[
  {
    "path": ".gitignore",
    "content": "*.xcodeproj/project.xcworkspace\n*.xcodeproj/xcuserdata\n*.xcworkspace\nbuild/\nIRCCloud/config.h\nIRCCloud/InfoPlist.h\nIRCCloud/GoogleService-Info.plist\n/*.png\n/*.sh\n/*.mobileprovision\n/*.ipa\ninfer-out/\nPreview.html\n/*.dSYM.zip\nfastlane/report.xml\nfastlane/.env\nscreenshots/\nGemfile.lock\nPodfile.lock\nPods/\n.env\nIRCCloud.app\nIRCCloud.pkg\n"
  },
  {
    "path": "ARChromeActivity/ARChromeActivity.h",
    "content": "/*\n  ARChromeActivity.h\n  Copyright (c) 2012 Alex Robinson\n  \n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n \n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n \n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n\n#import <UIKit/UIKit.h>\n\n@interface ARChromeActivity : UIActivity\n\n/// Uses the \"CFBundleName\" from your Info.plist by default.\n@property (strong, nonatomic, nonnull) NSString *callbackSource;\n\n/// The text beneath the icon. Defaults to \"Open in Chrome\".\n@property (strong, nonatomic, nonnull) NSString *activityTitle;\n\n/// Empty by default. Either set this in the initializer, or set this property. For iOS 9+, make sure you register the Chrome URL scheme in your Info.plist. See the demo project.\n@property (strong, nonatomic, nullable) NSURL *callbackURL;\n\n- (nonnull id)initWithCallbackURL:(nullable NSURL *)callbackURL;\n\n@end\n"
  },
  {
    "path": "ARChromeActivity/ARChromeActivity.m",
    "content": "/*\n  ARChromeActivity.m\n\n  Copyright (c) 2012 Alex Robinson\n \n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n \n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n \n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n\n#import \"ARChromeActivity.h\"\n\n@implementation ARChromeActivity {\n    NSURL *_activityURL;\n}\n@synthesize activityTitle = _title;\n\nstatic NSString *encodeByAddingPercentEscapes(NSString *input) {\n    return [input stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@\"!*'();:@&=+$,/?%#[] \"].invertedSet];\n}\n\n- (void)commonInit {\n    _callbackSource = [[NSBundle mainBundle]objectForInfoDictionaryKey:@\"CFBundleName\"];\n    _title = @\"Open in Chrome\";\n}\n\n- (NSString *)activityTitle\n{\n    return _title;\n}\n\n- (id)init {\n    self = [super init];\n    if (self) {\n        [self commonInit];\n    }\n    return self;\n}\n\n- (id)initWithCallbackURL:(NSURL *)callbackURL {\n    self = [super init];\n    if (self) {\n        [self commonInit];\n        _callbackURL = callbackURL;\n    }\n    return self;\n}\n\n- (UIImage *)activityImage {\n    if ([[UIImage class] respondsToSelector:@selector(imageNamed:inBundle:compatibleWithTraitCollection:)]) {\n        return [UIImage imageNamed:@\"ARChromeActivity\" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil];\n    } else {\n        return [UIImage imageNamed:@\"ARChromeActivity\"];\n    }\n}\n\n- (NSString *)activityType {\n    return NSStringFromClass([self class]);\n}\n\n- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems {\n    if (![[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@\"googlechrome://\"]]) {\n        return NO;\n    }\n    if (_callbackURL && ![[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@\"googlechrome-x-callback://\"]]) {\n        return NO;\n    }\n    for (id item in activityItems){\n        if ([item isKindOfClass:NSURL.class]){\n            NSURL *url = (NSURL *)item;\n            if ([url.scheme isEqualToString:@\"http\"] || [url.scheme isEqualToString:@\"https\"]) {\n                return YES;\n            }\n        }\n    }\n    return NO;\n}\n\n- (void)prepareWithActivityItems:(NSArray *)activityItems {\n    for (id item in activityItems) {\n        if ([item isKindOfClass:NSURL.class]) {\n            NSURL *url = (NSURL *)item;\n            if ([url.scheme isEqualToString:@\"http\"] || [url.scheme isEqualToString:@\"https\"]) {\n                _activityURL = (NSURL *)item;\n                return;\n            }\n            \n        }\n    }\n}\n\n- (void)performActivity {\n    \n    BOOL success = NO;\n    \n    if (_activityURL != nil) {\n        \n        if (self.callbackURL && self.callbackSource) {\n            NSString *openingURL = encodeByAddingPercentEscapes(_activityURL.absoluteString);\n            NSString *callbackURL = encodeByAddingPercentEscapes(self.callbackURL.absoluteString);\n            NSString *sourceName = encodeByAddingPercentEscapes(self.callbackSource);\n            \n            NSURL *activityURL = [NSURL URLWithString:[NSString stringWithFormat:@\"googlechrome-x-callback://x-callback-url/open/?url=%@&x-success=%@&x-source=%@\", openingURL, callbackURL, sourceName]];\n            [[UIApplication sharedApplication] openURL:activityURL options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n            success = YES;\n        } else {\n            \n            NSString *scheme = _activityURL.scheme;\n            \n            NSString *chromeScheme = nil;\n            if ([scheme isEqualToString:@\"http\"]) {\n                chromeScheme = @\"googlechrome\";\n            } else if ([scheme isEqualToString:@\"https\"]) {\n                chromeScheme = @\"googlechromes\";\n            }\n            \n            if (chromeScheme) {\n                NSString *absoluteString = [_activityURL absoluteString];\n                NSRange rangeForScheme = [absoluteString rangeOfString:@\":\"];\n                NSString *urlNoScheme = [absoluteString substringFromIndex:rangeForScheme.location];\n                NSString *chromeURLString = [chromeScheme stringByAppendingString:urlNoScheme];\n                NSURL *chromeURL = [NSURL URLWithString:chromeURLString];\n                \n                [[UIApplication sharedApplication] openURL:chromeURL options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n                success = YES;\n            }\n        }\n    }\n    \n    [self activityDidFinish:success];\n}\n\n@end\n"
  },
  {
    "path": "CSURITemplate/CSURITemplate.h",
    "content": "//\n//  CSURITemplate.h\n//  CSURITemplate\n//\n//  Created by Will Harris on 26/02/2013.\n//  Copyright (c) 2013 Cogenta Systems Ltd. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n/**\n The domain of errors returned by `CSURITemplate` objects.\n */\nextern NSString *const CSURITemplateErrorDomain;\n\ntypedef NS_ENUM(NSInteger, CSURITemplateError) {\n    // Parsing Errors\n    CSURITemplateErrorExpressionClosedButNeverOpened    = 100,\n    CSURITemplateErrorExpressionOpenedButNeverClosed    = 101,\n    CSURITemplateErrorInvalidOperator                   = 102,\n    CSURITemplateErrorUnknownOperator                   = 103,\n    CSURITemplateErrorInvalidVariableKey                = 104,\n    CSURITemplateErrorInvalidVariableModifier           = 105,\n    \n    // Expansion Errors\n    CSURITemplateErrorNoVariables                       = 200,\n    CSURITemplateErrorInvalidExpansionValue             = 201\n};\n\n/**\n An `NSNumber` value in the `userInfo` dictionary of errors returned while parsing a URI template that indicates \n the position in the string at which the error was encountered.\n */\nextern NSString *const CSURITemplateErrorScanLocationErrorKey;\n\n/**\n Expand URI Templates.\n \n This class implements Level 4 of the URI Template specification, defined by\n [RFC6570: URI Template](http://tools.ietf.org/html/rfc6570). URI Templates are\n a compact string representation of a set of URIs.\n \n Each CSURITemplate instance has a single URI Template. The URI template can be\n expanded into a URI reference by invoking the instance's URIWithVariables: with\n a dictionary of variables.\n \n For example:\n \n     NSError *error = nil;\n     CSURITemplate *template = [CSURITemplate URITemplateWithString:@\"/search{?q}\" error:&error];\n     NSString *uri1 = [template relativeStringWithVariables:@{@\"q\": @\"hateoas\"}];\n     NSString *uri2 = [template relativeStringWithVariables:@{@\"q\": @\"hal\"}];\n     assert([uri1 isEqualToString:@\"/search?q=hateoas\"]);\n     assert([uri2 isEqualToString:@\"/search?q=hal\"]);\n \n */\n@interface CSURITemplate : NSObject\n\n///---------------------------------\n/// @name Initializing URI Templates\n///---------------------------------\n\n/**\n Creates and returns a URI template object initialized with the given template string.\n \n @param templateString The RFC6570 conformant string with which to initialize the URI template object.\n @param error A pointer to an `NSError` object. If parsing the URI template string fails then the error will \n    be set to an instance of `NSError` that describes the problem.\n @return A new URI template object, or `nil` if the template string could not be parsed.\n */\n+ (instancetype)URITemplateWithString:(NSString *)templateString error:(NSError **)error;\n\n/**\n The URI template string that was used to initialize the receiver.\n */\n@property (nonatomic, copy, readonly) NSString *templateString;\n\n/**\n *  The keys of the variable terms in the receiver\n */\n@property (nonatomic, readonly) NSArray *keysOfVariables;\n\n///--------------------------------------------\n/// @name Expanding the Template with Variables\n///--------------------------------------------\n\n/** \n Expands the template with the given variables.\n \n This method expands the URI template using the variables provided and returns a string.\n If the URI template is valid but has no valid expansion for the given variables, then `nil` is returned and an `error` is set.\n For example, if the URI template is `\"{keys:1}\"` and `variables` is `{@\"semi\":@\";\",@\"dot\":@\".\",@\"comma\":@\",\"}`, \n this method will return nil because the prefix modifier is not applicable to composite values.\n \n @param variables a dictionary of variables to use when expanding the template.\n @param error A pointer to an `NSError` object. If an error occurs while expanding the template then the error will\n    be set to an instance of `NSError` that describes the problem.\n @returns A string containing the expanded URI reference, or nil if an error was encountered.\n */\n- (NSString *)relativeStringWithVariables:(NSDictionary *)variables error:(NSError **)error;\n\n/**\n Expands the template with the given variables and constructs a new URL relative to the given base URL.\n \n This method expands the URI template using the variables provided and then constructs a new URL object relative to \n the base URL provided. If the URI template is valid but has no valid expansion for the given variables, then `nil` is returned \n and an `error` is set. For example, if the URI template is `\"{keys:1}\"` and `variables` is `{@\"semi\":@\";\",@\"dot\":@\".\",@\"comma\":@\",\"}`,\n this method will return nil because the prefix modifier is not applicable to composite values.\n \n @param variables a dictionary of variables to use when expanding the template.\n @param error A pointer to an `NSError` object. If an error occurs while expanding the template then the error will\n    be set to an instance of `NSError` that describes the problem.\n @returns A URL constructed by evaluating the expanded template relative to the given baseURL, or nil if an error was encountered.\n */\n- (NSURL *)URLWithVariables:(NSDictionary *)variables relativeToBaseURL:(NSURL *)baseURL error:(NSError **)error;\n\n@end\n\n@interface CSURITemplate (Deprecations)\n- (id)initWithURITemplate:(NSString *)URITemplate __attribute__((deprecated (\"Use `URITemplateWithString:error:` instead\")));\n- (NSString *)URIWithVariables:(NSDictionary *)variables __attribute__((deprecated (\"Use `relativeStringWithVariables:error:` instead\")));;\n@end\n"
  },
  {
    "path": "CSURITemplate/CSURITemplate.m",
    "content": "//\n//  CSURITemplate.m\n//  CSURITemplate\n//\n//  Created by Will Harris on 26/02/2013.\n//  Copyright (c) 2013 Cogenta Systems Ltd. All rights reserved.\n//\n\n#import \"CSURITemplate.h\"\n\nNSString *const CSURITemplateErrorDomain = @\"com.cogenta.CSURITemplate.errors\";\nNSString *const CSURITemplateErrorScanLocationErrorKey = @\"location\";\n\n@protocol CSURITemplateTerm <NSObject>\n\n- (NSString *)expandWithVariables:(NSDictionary *)variables error:(NSError **)error;\n\n@end\n\n@protocol CSURITemplateEscaper <NSObject>\n\n- (NSString *)escapeItem:(id)item;\n\n@end\n\n@protocol CSURITemplateVariable <NSObject>\n\n@property (nonatomic, readonly) NSString *key;\n- (NSArray *)valuesWithVariables:(NSDictionary *)variables escaper:(id<CSURITemplateEscaper>)escaper error:(NSError **)error;\n- (BOOL)enumerateKeyValuesWithVariables:(NSDictionary *)variables\n                                escaper:(id<CSURITemplateEscaper>)escaper\n                                  error:(NSError **)error\n                                  block:(void (^)(NSString *key, NSString *value))block;\n\n@end\n\n@interface CSURITemplateEscaping : NSObject\n\n+ (NSObject<CSURITemplateEscaper> *)uriEscaper;\n+ (NSObject<CSURITemplateEscaper> *)fragmentEscaper;\n\n@end\n\n@interface CSURITemplateURIEscaper : NSObject <CSURITemplateEscaper>\n\n@end\n\n@interface CSURITemplateFragmentEscaper : NSObject <CSURITemplateEscaper>\n\n@end\n\n@implementation CSURITemplateEscaping\n\n+ (NSObject<CSURITemplateEscaper> *)uriEscaper\n{\n    return [[CSURITemplateURIEscaper alloc] init];\n}\n\n+ (NSObject<CSURITemplateEscaper> *)fragmentEscaper\n{\n    return [[CSURITemplateFragmentEscaper alloc] init];\n}\n\n@end\n\n@interface NSObject (URITemplateAdditions)\n\n- (NSString *)csuri_stringEscapedForURI;\n- (NSString *)csuri_stringEscapedForFragment;\n- (NSString *)csuri_basicString;\n- (NSArray *)csuri_explodedItems;\n- (NSArray *)csuri_explodedItemsEscapedWithEscaper:(id<CSURITemplateEscaper>)escaper;\n- (NSString *)csuri_escapeWithEscaper:(id<CSURITemplateEscaper>)escaper;\n- (void)csuri_enumerateExplodedItemsEscapedWithEscaper:(id<CSURITemplateEscaper>)escaper\n                                      defaultKey:(NSString *)key\n                                           block:(void (^)(NSString *key, NSString *value))block;\n@end\n\n@implementation CSURITemplateURIEscaper\n\n- (NSString *)escapeItem:(NSObject *)item\n{\n    return [item csuri_stringEscapedForURI];\n}\n\n@end\n\n@implementation CSURITemplateFragmentEscaper\n\n- (NSString *)escapeItem:(NSObject *)item\n{\n    return [item csuri_stringEscapedForFragment];\n}\n\n@end\n\n@implementation NSObject (URITemplateAdditions)\n\n- (NSString *)csuri_escapeWithEscaper:(id<CSURITemplateEscaper>)escaper\n{\n    return [escaper escapeItem:self];\n}\n\n- (NSString *)csuri_stringEscapedForURI\n{\n    return [[self csuri_basicString] csuri_stringEscapedForURI];\n}\n\n- (NSString *)csuri_stringEscapedForFragment\n{\n    return [[self csuri_basicString] csuri_stringEscapedForFragment];\n}\n\n- (NSString *)csuri_basicString\n{\n    return [self description];\n}\n\n- (NSArray *)csuri_explodedItems\n{\n    return [NSArray arrayWithObject:self];\n}\n\n- (NSArray *)csuri_explodedItemsEscapedWithEscaper:(id<CSURITemplateEscaper>)escaper\n{\n    NSMutableArray *result = [NSMutableArray array];\n    for (id value in [self csuri_explodedItems]) {\n        [result addObject:[value csuri_escapeWithEscaper:escaper]];\n    }\n    return [NSArray arrayWithArray:result];\n}\n\n- (void)csuri_enumerateExplodedItemsEscapedWithEscaper:(id<CSURITemplateEscaper>)escaper\n                                      defaultKey:(NSString *)key\n                                           block:(void (^)(NSString *, NSString *))block\n{\n    for (NSString *value in [self csuri_explodedItemsEscapedWithEscaper:escaper]) {\n        block(key, value);\n    }\n}\n\n@end\n\n@implementation NSString (URITemplateAdditions)\n\n- (NSString *)csuri_stringEscapedForURI\n{\n    return [self stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLPathAllowedCharacterSet];\n}\n\n- (NSString *)csuri_stringEscapedForFragment\n{\n    return [self stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLFragmentAllowedCharacterSet];\n}\n\n- (NSString *)csuri_basicString\n{\n    return self;\n}\n\n@end\n\n@implementation NSArray (URITemplateAdditions)\n\n- (NSString *)csuri_stringEscapedForURI\n{\n    NSMutableArray *result = [NSMutableArray array];\n    for (id item in self) {\n        [result addObject:[item csuri_stringEscapedForURI]];\n    }\n    return [result componentsJoinedByString:@\",\"];\n}\n\n\n- (NSString *)csuri_stringEscapedForFragment\n{\n    NSMutableArray *result = [NSMutableArray array];\n    for (id item in self) {\n        [result addObject:[item csuri_stringEscapedForFragment]];\n    }\n    return [result componentsJoinedByString:@\",\"];\n}\n\n- (NSString *)csuri_basicString\n{\n    NSMutableArray *result = [NSMutableArray array];\n    for (id item in self) {\n        [result addObject:[item csuri_basicString]];\n    }\n    return [result componentsJoinedByString:@\",\"];\n}\n\n- (NSArray *)csuri_explodedItems\n{\n    return self;\n}\n\n@end\n\n@implementation NSDictionary (URITemplateAdditions)\n\n- (NSString *)csuri_stringEscapedForURI\n{\n    NSMutableArray *result = [NSMutableArray array];\n    [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {\n        [result addObject:[key csuri_stringEscapedForURI]];\n        [result addObject:[obj csuri_stringEscapedForURI]];\n    }];\n    return [result componentsJoinedByString:@\",\"];\n}\n\n- (NSString *)csuri_stringEscapedForFragment\n{\n    NSMutableArray *result = [NSMutableArray array];\n    [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {\n        [result addObject:[key csuri_stringEscapedForFragment]];\n        [result addObject:[obj csuri_stringEscapedForFragment]];\n    }];\n    return [result componentsJoinedByString:@\",\"];\n}\n\n- (NSString *)csuri_basicString\n{\n    NSMutableArray *result = [NSMutableArray array];\n    [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {\n        [result addObject:[key csuri_basicString]];\n        [result addObject:[obj csuri_basicString]];\n    }];\n    return [result componentsJoinedByString:@\",\"];\n}\n\n- (NSArray *)csuri_explodedItems\n{\n    NSMutableArray *result = [NSMutableArray array];\n    [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {\n        [result addObject:key];\n        [result addObject:obj];\n    }];\n    return [NSArray arrayWithArray:result];\n}\n\n- (NSArray *)csuri_explodedItemsEscapedWithEscaper:(id<CSURITemplateEscaper>)escaper\n{\n    NSMutableArray *result = [NSMutableArray array];\n    [self csuri_enumerateExplodedItemsEscapedWithEscaper:escaper\n                                        defaultKey:nil\n                                             block:^(NSString *k, NSString *v)\n    {\n        [result addObject:[NSString stringWithFormat:@\"%@=%@\", k, v]];\n    }];\n    return [NSArray arrayWithArray:result];\n}\n\n- (void)csuri_enumerateExplodedItemsEscapedWithEscaper:(id<CSURITemplateEscaper>)escaper\n                                      defaultKey:(NSString *)defaultKey\n                                           block:(void (^)(NSString *, NSString *))block\n{\n    [self enumerateKeysAndObjectsUsingBlock:^(id k, id obj, BOOL *stop) {\n        block([k csuri_escapeWithEscaper:escaper],\n              [obj csuri_escapeWithEscaper:escaper]);\n    }];\n}\n\n@end\n\n@implementation NSNull (URITemplateDescriptions)\n\n- (NSArray *)csuri_explodedItems\n{\n    return [NSArray array];\n}\n\n@end\n\n#pragma mark -\n\n@interface CSURITemplateLiteralTerm : NSObject <CSURITemplateTerm>\n\n@property (nonatomic, strong) NSString *literal;\n\n- (id)initWithLiteral:(NSString *)literal;\n\n@end\n\n@implementation CSURITemplateLiteralTerm\n\n@synthesize literal;\n\n- (id)initWithLiteral:(NSString *)aLiteral\n{\n    self = [super init];\n    if (self) {\n        literal = aLiteral;\n    }\n    return self;\n}\n\n- (NSString *)expandWithVariables:(NSDictionary *)variables error:(NSError *__autoreleasing *)error\n{\n    return literal;\n}\n\n@end\n\n@interface CSURITemplateInfixExpressionTerm : NSObject <CSURITemplateTerm>\n\n@property (nonatomic, strong) NSArray *variablesExpression;\n- (id)initWithVariables:(NSArray *)variables;\n- (NSString *)infix;\n- (NSString *)prepend;\n\n@end\n\n@implementation CSURITemplateInfixExpressionTerm\n\n@synthesize variablesExpression;\n\n- (id)initWithVariables:(NSArray *)theVariables\n{\n    self = [super init];\n    if (self) {\n        variablesExpression = theVariables;\n    }\n    return self;\n}\n\n- (id<CSURITemplateEscaper>)escaper\n{\n    return [CSURITemplateEscaping uriEscaper];\n}\n\n- (NSString *)prepend\n{\n    return @\"\";\n}\n\n- (NSString *)infix\n{\n    return @\"\";\n}\n\n- (NSString *)expandWithVariables:(NSDictionary *)variables error:(NSError *__autoreleasing *)error\n{\n    BOOL isFirst = YES;\n    NSMutableString *result = [NSMutableString string];\n    for (NSObject<CSURITemplateVariable> *variable in variablesExpression) {\n        NSArray *values = [variable valuesWithVariables:variables\n                                                escaper:[self escaper]\n                                                  error:error];\n        if ( ! values) {\n            // An error was encountered expanding the variable.\n            return nil;\n        }\n        \n        for (NSString *value in values) {\n            if (isFirst) {\n                isFirst = NO;\n                [result appendString:[self prepend]];\n            } else {\n                [result appendString:[self infix]];\n            }\n            \n            [result appendString:value];\n        }\n    }\n    \n    return [NSString stringWithString:result];\n}\n\n@end\n\n@interface CSURITemplateCommaExpressionTerm : CSURITemplateInfixExpressionTerm\n\n@end\n\n@implementation CSURITemplateCommaExpressionTerm\n\n- (NSString *)infix\n{\n    return @\",\";\n}\n\n@end\n\n@interface CSURITemplatePrependExpressionTerm : NSObject <CSURITemplateTerm>\n\n@property (nonatomic, strong) NSArray *variablesExpression;\n\n- (id)initWithVariables:(NSArray *)variables;\n\n@end\n\n@implementation CSURITemplatePrependExpressionTerm\n\n@synthesize variablesExpression;\n\n- (id)initWithVariables:(NSArray *)theVariables\n{\n    self = [super init];\n    if (self) {\n        variablesExpression = theVariables;\n    }\n    return self;\n}\n\n- (NSString *)prepend\n{\n    return @\"\";\n}\n\n- (id<CSURITemplateEscaper>)escaper\n{\n    return [CSURITemplateEscaping uriEscaper];\n}\n\n- (NSString *)expandWithVariables:(NSDictionary *)variables error:(NSError *__autoreleasing *)error\n{\n    NSMutableString *result = [NSMutableString string];\n    for (NSObject<CSURITemplateVariable> *variable in variablesExpression) {\n        for (NSString *value in [variable valuesWithVariables:variables\n                                                      escaper:[self escaper]\n                                                        error:error]) {\n            [result appendString:[self prepend]];\n            [result appendString:value];\n        }\n    }\n    \n    return [NSString stringWithString:result];\n}\n\n\n@end\n\n@interface CSURITemplateSolidusExpressionTerm : CSURITemplatePrependExpressionTerm\n\n@end\n\n@implementation CSURITemplateSolidusExpressionTerm\n\n- (NSString *)prepend\n{\n    return @\"/\";\n}\n\n@end\n\n\n@interface CSURITemplateDotExpressionTerm : CSURITemplatePrependExpressionTerm\n\n@end\n\n@implementation CSURITemplateDotExpressionTerm\n\n- (NSString *)prepend\n{\n    return @\".\";\n}\n\n@end\n\n\n@interface CSURITemplateHashExpressionTerm : CSURITemplateCommaExpressionTerm\n\n@end\n\n@implementation CSURITemplateHashExpressionTerm\n\n- (NSString *)prepend\n{\n    return @\"#\";\n}\n\n- (id<CSURITemplateEscaper>)escaper\n{\n    return [CSURITemplateEscaping fragmentEscaper];\n}\n\n@end\n\n@interface CSURITemplateQueryExpressionTerm : NSObject <CSURITemplateTerm>\n\n@property (nonatomic, strong) NSArray *variablesExpression;\n- (id)initWithVariables:(NSArray *)variables;\n- (NSString *)prepend;\n\n@end\n\n@implementation CSURITemplateQueryExpressionTerm\n\n@synthesize variablesExpression;\n\n- (id)initWithVariables:(NSArray *)theVariables\n{\n    self = [super init];\n    if (self) {\n        variablesExpression = theVariables;\n    }\n    return self;\n}\n\n- (id<CSURITemplateEscaper>)escaper\n{\n    return [CSURITemplateEscaping uriEscaper];\n}\n\n- (NSString *)prepend\n{\n    return @\"?\";\n}\n\n- (NSString *)expandWithVariables:(NSDictionary *)variables error:(NSError *__autoreleasing *)error\n{\n    __block BOOL isFirst = YES;\n    NSMutableString *result = [NSMutableString string];\n    for (NSObject<CSURITemplateVariable> *variable in variablesExpression) {\n        BOOL success = [variable enumerateKeyValuesWithVariables:variables\n                                                         escaper:[self escaper]\n                                                           error:error\n                                                           block:^(NSString *key, NSString *value) {\n            \n            if (isFirst) {\n                isFirst = NO;\n                [result appendString:[self prepend]];\n            } else {\n                [result appendString:@\"&\"];\n            }\n            \n            [result appendString:key];\n            [result appendString:@\"=\"];\n            [result appendString:value];\n        }];\n        \n        if ( ! success) return nil;\n    }\n    \n    return [NSString stringWithString:result];\n}\n\n@end\n\n@interface CSURITemplateParameterExpressionTerm : NSObject <CSURITemplateTerm>\n\n@property (nonatomic, strong) NSArray *variablesExpression;\n- (id)initWithVariables:(NSArray *)variables;\n\n@end\n\n@implementation CSURITemplateParameterExpressionTerm\n\n@synthesize variablesExpression;\n\n- (id)initWithVariables:(NSArray *)theVariables\n{\n    self = [super init];\n    if (self) {\n        variablesExpression = theVariables;\n    }\n    return self;\n}\n\n- (id<CSURITemplateEscaper>)escaper\n{\n    return [CSURITemplateEscaping uriEscaper];\n}\n\n- (NSString *)expandWithVariables:(NSDictionary *)variables error:(NSError *__autoreleasing *)error\n{\n    NSMutableString *result = [NSMutableString string];\n    for (NSObject<CSURITemplateVariable> *variable in variablesExpression) {\n        BOOL success = [variable enumerateKeyValuesWithVariables:variables escaper:[self escaper] error:error block:^(NSString *key, NSString *value) {\n             [result appendString:@\";\"];\n             \n             [result appendString:key];\n             \n             if ( ! [value isEqualToString:@\"\"]) {\n                 [result appendString:@\"=\"];\n                 [result appendString:value];\n             }\n         }];\n        \n        if ( ! success) return nil;\n    }\n    \n    return [NSString stringWithString:result];\n}\n\n@end\n\n@interface CSURITemplateReservedExpressionTerm : CSURITemplateCommaExpressionTerm\n\n@end\n\n@implementation CSURITemplateReservedExpressionTerm\n\n- (id<CSURITemplateEscaper>)escaper\n{\n    return [CSURITemplateEscaping fragmentEscaper];\n}\n\n@end\n\n@interface CSURITemplateQueryContinuationExpressionTerm : CSURITemplateQueryExpressionTerm\n\n@end\n\n@implementation CSURITemplateQueryContinuationExpressionTerm\n\n- (NSString *)prepend\n{\n    return @\"&\";\n}\n\n@end\n\n#pragma mark -\n\n@interface CSURITemplateUnmodifiedVariable : NSObject <CSURITemplateVariable>\n\n- (id)initWithKey:(NSString *)key;\n\n@end\n\n@implementation CSURITemplateUnmodifiedVariable\n\n@synthesize key;\n\n- (id)initWithKey:(NSString *)aKey\n{\n    self = [super init];\n    if (self) {\n        key = aKey;\n    }\n    return self;\n}\n\n- (NSArray *)valuesWithVariables:(NSDictionary *)variables escaper:(id<CSURITemplateEscaper>)escaper error:(NSError *__autoreleasing *)error\n{\n    id value = [variables objectForKey:key];\n    if ( ! value || (NSNull *) value == [NSNull null]) {\n        return [NSArray array];\n    }\n    \n    if ([value isKindOfClass:[NSArray class]] && [(NSArray *)value count] == 0) {\n        return [NSArray array];\n    }\n    \n    NSMutableArray *result = [NSMutableArray array];\n    NSString *escaped = [value csuri_escapeWithEscaper:escaper];\n    [result addObject:escaped];\n    \n    return [NSArray arrayWithArray:result];\n}\n\n- (BOOL)enumerateKeyValuesWithVariables:(NSDictionary *)variables\n                                escaper:(id<CSURITemplateEscaper>)escaper\n                                  error:(NSError *__autoreleasing *)error\n                                  block:(void (^)(NSString *, NSString *))block\n{\n    id value = [variables objectForKey:key];\n    if ( ! value || (NSNull *) value == [NSNull null]) {\n        return YES;\n    }\n    \n    if ([value isEqual:@[]]) {\n        block(key, @\"\");\n        return YES;\n    }\n    \n    NSString *escaped = [value csuri_escapeWithEscaper:escaper];\n    block(key, escaped);\n    return YES;\n}\n\n@end\n\n@interface CSURITemplateExplodedVariable : NSObject <CSURITemplateVariable>\n\n- (id)initWithKey:(NSString *)key;\n\n@end\n\n@implementation CSURITemplateExplodedVariable\n\n@synthesize key;\n\n- (id)initWithKey:(NSString *)aKey\n{\n    self = [super init];\n    if (self) {\n        key = aKey;\n    }\n    return self;\n}\n\n- (NSArray *)valuesWithVariables:(NSDictionary *)variables escaper:(id<CSURITemplateEscaper>)escaper error:(NSError *__autoreleasing *)error\n{\n    id values = [variables objectForKey:key];\n    if ( ! values) {\n        return [NSArray array];\n    }\n    \n    NSMutableArray *result = [NSMutableArray array];\n    \n    for (id value in [values csuri_explodedItemsEscapedWithEscaper:escaper]) {\n        [result addObject:value];\n    }\n    \n    return [NSArray arrayWithArray:result];\n}\n\n- (BOOL)enumerateKeyValuesWithVariables:(NSDictionary *)variables\n                                escaper:(id<CSURITemplateEscaper>)escaper\n                                  error:(NSError *__autoreleasing *)error\n                                  block:(void (^)(NSString *, NSString *))block\n{\n    id values = [variables objectForKey:key];\n    if ( ! values) {\n        return YES;\n    }\n    \n    [values csuri_enumerateExplodedItemsEscapedWithEscaper:escaper\n                                          defaultKey:key\n                                               block:block];\n    return YES;\n}\n\n@end\n\n@interface CSURITemplatePrefixedVariable : NSObject <CSURITemplateVariable>\n\n@property (nonatomic, assign) NSUInteger maxLength;\n\n- (id)initWithKey:(NSString *)key maxLength:(NSUInteger)maxLength;\n\n@end\n\n@implementation CSURITemplatePrefixedVariable\n\n@synthesize key;\n@synthesize maxLength;\n\n- (id)initWithKey:(NSString *)aKey maxLength:(NSUInteger)aMaxLength\n{\n    self = [super init];\n    if (self) {\n        key = aKey;\n        maxLength = aMaxLength;\n    }\n    return self;\n}\n\n- (NSArray *)valuesWithVariables:(NSDictionary *)variables escaper:(id<CSURITemplateEscaper>)escaper error:(NSError *__autoreleasing *)error\n{\n    id value = [variables objectForKey:key];\n    \n    if ( ! [value isKindOfClass:[NSString class]]) {\n        NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@\"Variables with a maximum length modifier can only be expanded with string values, but a value of type '%@' given.\", nil), [value class]];\n        NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"An unexpandable value was given for a template variable.\", nil), NSLocalizedFailureReasonErrorKey: failureReason };\n        if (error) *error = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorInvalidExpansionValue userInfo:userInfo];\n        return nil;\n    }\n    \n    if ( ! value || (NSNull *) value == [NSNull null]) {\n        return [NSArray array];\n    }\n\n    NSMutableArray *result = [NSMutableArray array];\n    NSString *description = [value csuri_basicString];\n    if (maxLength <= [description length]) {\n        description = [description substringToIndex:maxLength];\n    }\n    \n    [result addObject:[description csuri_escapeWithEscaper:escaper]];\n    \n    return [NSArray arrayWithArray:result];\n}\n\n- (BOOL)enumerateKeyValuesWithVariables:(NSDictionary *)variables\n                                escaper:(id<CSURITemplateEscaper>)escaper\n                                  error:(NSError *__autoreleasing *)error\n                                  block:(void (^)(NSString *, NSString *))block\n{\n    NSArray *values = [self valuesWithVariables:variables escaper:escaper error:error];\n    if ( ! values) {\n        // An error was encountered expanding the variables.\n        return NO;\n    }\n    \n    for (NSString *value in values) {\n        block(key, value);\n    }\n    return YES;\n}\n\n@end\n\n#pragma mark -\n\n@interface CSURITemplate ()\n\n@property (nonatomic, copy, readwrite) NSString *templateString;\n@property (nonatomic, copy, readwrite) NSURL *baseURL;\n@property (nonatomic, strong) NSMutableArray *terms;\n\n@end\n\n@implementation CSURITemplate\n\n+ (instancetype)URITemplateWithString:(NSString *)templateString error:(NSError **)error\n{\n    CSURITemplate *URITemplate = [[self alloc] initWithTemplateString:templateString];\n    BOOL success = [URITemplate parseTemplate:error];\n    return success ? URITemplate : nil;\n}\n\n+ (instancetype)URITemplateWithString:(NSString *)templateString relativeToURL:(NSURL *)baseURL error:(NSError **)error\n{\n    CSURITemplate *URITemplate = [self URITemplateWithString:templateString error:error];\n    URITemplate.baseURL = baseURL;\n    return URITemplate;\n}\n\n- (id)initWithTemplateString:(NSString *)templateString\n{\n    self = [super init];\n    if (self) {\n        self.templateString = templateString;\n        self.terms = [NSMutableArray array];\n    }\n    return self;\n}\n\n- (id)init\n{\n    @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@\"Failed to call designated initializer. Invoke `URITemplateWithString:error:` or `URITemplateWithString:relativeToURL:error:` instead\" userInfo:nil];\n}\n\n- (NSObject<CSURITemplateVariable> *)variableWithVarspec:(NSString *)varspec error:(NSError **)error\n{\n    NSParameterAssert(varspec);\n    NSParameterAssert(error);\n    if ([varspec rangeOfString:@\"$\"].location != NSNotFound) {\n        // Varspec contains a forbidden character.\n        NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"The template contains an invalid variable key.\", nil),\n                                    NSLocalizedFailureReasonErrorKey: NSLocalizedString(@\"A variable key containing the forbidden character '$' was encountered.\", nil) };\n        *error = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorInvalidVariableKey userInfo:userInfo];\n        return nil;\n    }\n    NSMutableCharacterSet *varchars = [NSMutableCharacterSet alphanumericCharacterSet];\n    [varchars addCharactersInString:@\"._%\"];\n                                \n    NSCharacterSet *modifierStartCharacters = [NSCharacterSet characterSetWithCharactersInString:@\":*\"];\n    NSScanner *scanner = [NSScanner scannerWithString:varspec];\n    [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@\"\"]];\n    NSString *key = nil;\n    [scanner scanCharactersFromSet:varchars intoString:&key];\n    \n    NSString *modifierStart = nil;\n    [scanner scanCharactersFromSet:modifierStartCharacters intoString:&modifierStart];\n    \n    if ([modifierStart isEqualToString:@\"*\"]) {\n        // Modifier is explode.\n\n        if ( ! [scanner isAtEnd]) {\n            // There were extra characters after the explode modifier.\n            NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@\"Extra characters were found after the explode modifier ('*') for the variable '%@'.\", nil), key];\n            NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"The template contains an invalid variable modifier.\", nil),\n                                        NSLocalizedFailureReasonErrorKey: failureReason };\n            *error = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorInvalidVariableModifier userInfo:userInfo];\n            return nil;\n        }\n        \n        return [[CSURITemplateExplodedVariable alloc] initWithKey:key];\n    } else if ([modifierStart isEqualToString:@\":\"]) {\n        // Modifier is prefix.\n        NSCharacterSet *oneToNine = [NSCharacterSet characterSetWithCharactersInString:@\"123456789\"];\n        NSCharacterSet *zeroToNine = [NSCharacterSet decimalDigitCharacterSet];\n        NSString *firstDigit = @\"\";\n        if ( ! [scanner scanCharactersFromSet:oneToNine intoString:&firstDigit]) {\n            // The max-chars does not start with a valid digit.\n            NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@\"The variable '%@' was followed by the maximum length modifier (':'), but the maximum length argument was prefixed with an invalid character.\", nil), key];\n            NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"The template contains an invalid variable modifier.\", nil),\n                                        NSLocalizedFailureReasonErrorKey: failureReason };\n            *error = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorInvalidVariableModifier userInfo:userInfo];\n            return nil;\n        }\n        NSString *restDigits = @\"\";\n        [scanner scanCharactersFromSet:zeroToNine intoString:&restDigits];\n        NSString *digits = [firstDigit stringByAppendingString:restDigits];\n        \n        if ( ! [scanner isAtEnd]) {\n            // The max-chars is not entirely digits.\n            NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@\"The variable '%@' was followed by the maximum length modifier (':'), but the maximum length argument is not numeric.\", nil), key];\n            NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"The template contains an invalid variable modifier.\", nil),\n                                        NSLocalizedFailureReasonErrorKey: failureReason };\n            *error = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorInvalidVariableModifier userInfo:userInfo];\n            return nil;\n        }\n\n        NSUInteger maxLength = (NSUInteger)ABS([digits integerValue]);\n        return [[CSURITemplatePrefixedVariable alloc] initWithKey:key\n                                                        maxLength:maxLength];\n    } else {\n        // No modifier.\n        \n        if ( ! [scanner isAtEnd]) {\n            // There were extra characters after the key.\n            NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@\"The variable key '%@' is invalid.\", nil), varspec];\n            NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"The template contains an invalid variable key.\", nil),\n                                        NSLocalizedFailureReasonErrorKey: failureReason };\n            *error = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorInvalidVariableKey userInfo:userInfo];\n            return nil;\n        }\n        \n        return [[CSURITemplateUnmodifiedVariable alloc] initWithKey:key];\n    }\n    \n    return nil;\n}\n\n- (NSArray *)variablesWithVariableList:(NSString *)variableList error:(NSError **)error\n{\n    NSParameterAssert(variableList);\n    NSParameterAssert(error);\n    NSMutableArray *variables = [NSMutableArray array];\n    NSScanner *scanner = [NSScanner scannerWithString:variableList];\n    [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@\"\"]];\n\n    while ( ! [scanner isAtEnd]) {\n        NSString *varspec = nil;\n        [scanner scanUpToString:@\",\" intoString:&varspec];\n        [scanner scanString:@\",\" intoString:NULL];\n        NSObject<CSURITemplateVariable> *variable = [self variableWithVarspec:varspec error:error];\n        if ( ! variable) {\n            // An error was encountered parsing the varspec.\n            return nil;\n        }\n        [variables addObject:variable];\n    }\n    return variables;\n}\n\n- (NSObject<CSURITemplateTerm> *)termWithOperator:(NSString *)operator\n                                     variableList:(NSString *)variableList\n                                            error:(NSError **)error\n{\n    NSParameterAssert(variableList);\n    NSParameterAssert(error);\n    if ([operator length] > 1) {\n        // The term has an invalid operator.\n        NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@\"An operator was encountered with a length greater than 1 character ('%@').\", nil), operator];\n        NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"An invalid operator was encountered.\", nil),\n                                    NSLocalizedFailureReasonErrorKey : failureReason };\n        *error = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorInvalidOperator userInfo:userInfo];\n        return nil;\n    }\n    \n    NSArray *variables = [self variablesWithVariableList:variableList error:error];\n    if ( ! variables) {\n        // An error was encountered parsing a variable.\n        return nil;\n    }\n    \n    if ([operator isEqualToString:@\"/\"]) {\n        return [[CSURITemplateSolidusExpressionTerm alloc] initWithVariables:variables];\n    } else if ([operator isEqualToString:@\".\"]) {\n        return [[CSURITemplateDotExpressionTerm alloc] initWithVariables:variables];\n    } else if ([operator isEqualToString:@\"#\"]) {\n        return [[CSURITemplateHashExpressionTerm alloc] initWithVariables:variables];\n    } else if ([operator isEqualToString:@\"?\"]) {\n        return [[CSURITemplateQueryExpressionTerm alloc] initWithVariables:variables];\n    } else if ([operator isEqualToString:@\";\"]) {\n        return [[CSURITemplateParameterExpressionTerm alloc] initWithVariables:variables];\n    } else if ([operator isEqualToString:@\"+\"]) {\n        return [[CSURITemplateReservedExpressionTerm alloc] initWithVariables:variables];\n    } else if ([operator isEqualToString:@\"&\"]) {\n        return [[CSURITemplateQueryContinuationExpressionTerm alloc] initWithVariables:variables];\n    } else if ( ! operator) {\n        return [[CSURITemplateCommaExpressionTerm alloc] initWithVariables:variables];\n    } else {\n        // The operator is unknown or reserved.\n        NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@\"The URI template specification does not include an operator for the character '%@'.\", nil), operator];\n        NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"An unknown operator was encountered.\", nil),\n                                    NSLocalizedFailureReasonErrorKey : failureReason };\n        *error = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorUnknownOperator userInfo:userInfo];\n        return nil;\n    }\n}\n\n- (NSObject<CSURITemplateTerm> *)termWithExpression:(NSString *)expression error:(NSError **)error\n{\n    NSCharacterSet *operators = [NSCharacterSet characterSetWithCharactersInString:@\"+#./;?&=,!@|\"];\n    NSScanner *scanner = [NSScanner scannerWithString:expression];\n    [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@\"\"]];\n\n    NSString *operator = nil;\n    [scanner scanCharactersFromSet:operators intoString:&operator];\n    return [self termWithOperator:operator\n                     variableList:[expression substringFromIndex:scanner.scanLocation]\n                            error:error];\n}\n\n- (BOOL)parseTemplate:(NSError **)error\n{\n    NSError *parsingError = nil;\n    NSScanner *scanner = [NSScanner scannerWithString:self.templateString];\n    [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@\"\"]];\n    while ( ! [scanner isAtEnd]) {\n        NSCharacterSet *curlyBrackets = [NSCharacterSet\n                                         characterSetWithCharactersInString:@\"{}\"];\n        NSString *literal = nil;\n        if ([scanner scanUpToCharactersFromSet:curlyBrackets\n                                    intoString:&literal]) {\n            CSURITemplateLiteralTerm *term = [[CSURITemplateLiteralTerm alloc]\n                                                 initWithLiteral:literal];\n            [self.terms addObject:term];\n        }\n        \n        NSString *curlyBracket = nil;\n        [scanner scanCharactersFromSet:curlyBrackets intoString:&curlyBracket];\n        if ([curlyBracket isEqualToString:@\"}\"]) {\n            // An expression was closed but not opened.\n            NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"An expression was closed that was never opened.\", nil),\n                                        NSLocalizedFailureReasonErrorKey : NSLocalizedString(@\"A closing '}' character was encountered that was not preceeded by an opening '{' character.\", nil),\n                                        CSURITemplateErrorScanLocationErrorKey: @(scanner.scanLocation) };\n            parsingError = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorExpressionClosedButNeverOpened userInfo:userInfo];\n            break;\n        }\n        \n        NSString *expression = nil;\n        if ([scanner scanUpToString:@\"}\" intoString:&expression]) {\n            if ( ! [scanner scanString:@\"}\" intoString:NULL]) {\n                // An expression was opened not closed.\n                NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"An expression was opened but never closed.\", nil),\n                                            NSLocalizedFailureReasonErrorKey : NSLocalizedString(@\"An opening '{' character was never terminated by  '}' character.\", nil),\n                                            CSURITemplateErrorScanLocationErrorKey: @(scanner.scanLocation) };\n                parsingError = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorExpressionOpenedButNeverClosed userInfo:userInfo];\n                break;\n            }\n            \n            NSObject<CSURITemplateTerm> *term = [self termWithExpression:expression error:&parsingError];\n            if ( ! term) {\n                // An error was encountered parsing the term expression. Include the scan location in the error\n                NSMutableDictionary *mutableUserInfo = [[parsingError userInfo] mutableCopy];\n                mutableUserInfo[CSURITemplateErrorScanLocationErrorKey] = @(scanner.scanLocation);\n                break;\n            }\n            \n            [self.terms addObject:term];\n        }\n    }\n    \n    if (parsingError && error) *error = parsingError;\n    return parsingError ? NO : YES;\n}\n\n- (NSString *)relativeStringWithVariables:(NSDictionary *)variables error:(NSError **)error\n{\n    NSError *expansionError = nil;\n    if ( ! variables) {\n        NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@\"A template cannot be expanded without a dictionary of variables.\", nil) };\n        expansionError = [NSError errorWithDomain:CSURITemplateErrorDomain code:CSURITemplateErrorNoVariables userInfo:userInfo];\n        if (error) *error = expansionError;\n        return nil;\n    }\n    NSMutableString *result = [NSMutableString string];\n    BOOL errorEncountered = NO;\n    for (NSObject<CSURITemplateTerm> *term in self.terms) {\n        NSString *value = [term expandWithVariables:variables error:&expansionError];\n        if ( ! value) {\n            // An error was encountered expanding the term.\n            errorEncountered = YES;\n            break;\n        }\n        [result appendString:value];\n    }\n    if (expansionError && error) *error = expansionError;\n    return errorEncountered ? nil : [result copy];\n}\n\n- (NSURL *)URLWithVariables:(NSDictionary *)variables relativeToBaseURL:(NSURL *)baseURL error:(NSError **)error\n{\n    NSString *expandedTemplate = [self relativeStringWithVariables:variables error:error];\n    if ( ! expandedTemplate) return nil;\n    return [NSURL URLWithString:expandedTemplate relativeToURL:baseURL];\n}\n\n- (NSArray *)keysOfVariables\n{\n    NSMutableArray *keys = [NSMutableArray arrayWithCapacity:self.terms.count];\n    for (id <CSURITemplateTerm> term in self.terms) {\n        if (![term respondsToSelector:@selector(variablesExpression)]) continue;\n        for (id <CSURITemplateVariable> variable in [term performSelector:@selector(variablesExpression)]) {\n            [keys addObject:variable.key];\n        }\n    }\n    return keys;\n}\n\n- (NSString *)description\n{\n    return [NSString stringWithFormat:@\"<%@: %p templateString=\\\"%@\\\"\", self.class, self, self.templateString];\n}\n\n@end\n\n@implementation CSURITemplate (Deprecations)\n\n- (id)initWithURITemplate:(NSString *)URITemplate\n{\n    self = [self initWithTemplateString:URITemplate];\n    BOOL success = [self parseTemplate:nil];\n    return success ? self : nil;\n}\n\n- (NSString *)URIWithVariables:(NSDictionary *)variables\n{\n    return [self relativeStringWithVariables:variables ?: @{} error:nil];\n}\n\n@end\n"
  },
  {
    "path": "ECSlidingViewController/ECSlidingViewController.h",
    "content": "//\n//  ECSlidingViewController.h\n//  ECSlidingViewController\n//\n//  Created by Michael Enriquez on 1/23/12.\n//  Copyright (c) 2012 EdgeCase. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"UIImage+ImageWithUIView.h\"\n\n/** Notification that gets posted when the underRight view will appear */\nextern NSString *const ECSlidingViewUnderRightWillAppear;\n\n/** Notification that gets posted when the underLeft view will appear */\nextern NSString *const ECSlidingViewUnderLeftWillAppear;\n\n/** Notification that gets posted when the underLeft view will disappear */\nextern NSString *const ECSlidingViewUnderLeftWillDisappear;\n\n/** Notification that gets posted when the underRight view will disappear */\nextern NSString *const ECSlidingViewUnderRightWillDisappear;\n\n/** Notification that gets posted when the top view is anchored to the left side of the screen */\nextern NSString *const ECSlidingViewTopDidAnchorLeft;\n\n/** Notification that gets posted when the top view is anchored to the right side of the screen */\nextern NSString *const ECSlidingViewTopDidAnchorRight;\n\n/** Notification that gets posted when the top view will be centered on the screen */\nextern NSString *const ECSlidingViewTopWillReset;\n\n/** Notification that gets posted when the top view is centered on the screen */\nextern NSString *const ECSlidingViewTopDidReset;\n\n/** @constant ECViewWidthLayout width of under views */\ntypedef enum {\n  /** Under view will take up the full width of the screen */\n  ECFullWidth,\n  /** Under view will have a fixed width equal to anchorRightRevealAmount or anchorLeftRevealAmount. */\n  ECFixedRevealWidth,\n  /** Under view will have a variable width depending on rotation equal to the screen's width - anchorRightPeekAmount or anchorLeftPeekAmount. */\n  ECVariableRevealWidth\n} ECViewWidthLayout;\n\n/** @constant ECSide side of screen */\ntypedef enum {\n  /** Left side of screen */\n  ECLeft,\n  /** Right side of screen */\n  ECRight\n} ECSide;\n\n/** @constant ECResetStrategy top view behavior while anchored. */\ntypedef enum {\n  /** No reset strategy will be used */\n  ECNone = 0,\n  /** Tapping the top view will reset it */\n  ECTapping = 1 << 0,\n  /** Panning will be enabled on the top view. If it is panned and released towards the reset position it will reset, otherwise it will slide towards the anchored position. */\n  ECPanning = 1 << 1\n} ECResetStrategy;\n\n/** ECSlidingViewController is a view controller container that presents its child view controllers in two layers. The top layer can be panned to reveal the layers below it. */\n@interface ECSlidingViewController : UIViewController<UIGestureRecognizerDelegate> {\n  CGPoint startTouchPosition;\n  BOOL topViewHasFocus;\n}\n\n/** Returns the view controller that will be visible when the top view is slide to the right.\n \n This view controller is typically a menu or top-level view that switches out the top view controller.\n */\n@property (nonatomic, strong) UIViewController *underLeftViewController;\n\n/** Returns the view controller that will be visible when the top view is slide to the left.\n \n This view controller is typically a supplemental view to the top view.\n */\n@property (nonatomic, strong) UIViewController *underRightViewController;\n\n/** Returns the top view controller.\n \n This is the main view controller that is presented above the other view controllers.\n */\n@property (nonatomic, strong) UIViewController *topViewController;\n\n/** Returns the number of points the top view is visible when the top view is anchored to the left side.\n \n This value is fixed after rotation. If the number of points to reveal needs to be fixed, use anchorLeftRevealAmount.\n \n @see anchorLeftRevealAmount\n */\n@property (nonatomic, assign) CGFloat anchorLeftPeekAmount;\n\n/** Returns the number of points the top view is visible when the top view is anchored to the right side.\n \n This value is fixed after rotation. If the number of points to reveal needs to be fixed, use anchorRightRevealAmount.\n \n @see anchorRightRevealAmount\n */\n@property (nonatomic, assign) CGFloat anchorRightPeekAmount;\n\n/** Returns the number of points the under right view is visible when the top view is anchored to the left side.\n \n This value is fixed after rotation. If the number of points to peek needs to be fixed, use anchorLeftPeekAmount.\n \n @see anchorLeftPeekAmount\n */\n@property (nonatomic, assign) CGFloat anchorLeftRevealAmount;\n\n/** Returns the number of points the under left view is visible when the top view is anchored to the right side.\n \n This value is fixed after rotation. If the number of points to peek needs to be fixed, use anchorRightPeekAmount.\n \n @see anchorRightPeekAmount\n */\n@property (nonatomic, assign) CGFloat anchorRightRevealAmount;\n\n/** Specifies whether or not the top view can be panned past the anchor point.\n \n Set to NO if you don't want to show the empty space behind the top and under view.\n \n By defaut, this is set to YES\n */\n@property (nonatomic, assign) BOOL shouldAllowPanningPastAnchor;\n\n/** Specifies if the user should be able to interact with the top view when it is anchored.\n \n By default, this is set to NO\n */\n@property (nonatomic, assign) BOOL shouldAllowUserInteractionsWhenAnchored;\n\n/** Specifies if the top view snapshot requires a pan gesture recognizer.\n \n This is useful when panGesture is added to the navigation bar instead of the main view.\n \n By default, this is set to NO\n */\n@property (nonatomic, assign) BOOL shouldAddPanGestureRecognizerToTopViewSnapshot;\n\n/** Specifies the behavior for the under left width\n \n By default, this is set to ECFullWidth\n */\n@property (nonatomic, assign) ECViewWidthLayout underLeftWidthLayout;\n\n/** Specifies the behavior for the under right width\n \n By default, this is set to ECFullWidth\n */\n@property (nonatomic, assign) ECViewWidthLayout underRightWidthLayout;\n\n/** Returns the strategy for resetting the top view when it is anchored.\n \n By default, this is set to ECPanning | ECTapping to allow both panning and tapping to reset the top view.\n \n If this is set to ECNone, then there must be a custom way to reset the top view otherwise it will stay anchored.\n */\n@property (nonatomic, assign) ECResetStrategy resetStrategy;\n\n/** Returns a horizontal panning gesture for moving the top view.\n \n This is typically added to the top view or a top view's navigation bar.\n */\n- (UIPanGestureRecognizer *)panGesture;\n\n/** Slides the top view in the direction of the specified side.\n \n A peek amount or reveal amount must be set for the given side. The top view will anchor to one of those specified values.\n \n @param side The side for the top view to slide towards.\n */\n- (void)anchorTopViewTo:(ECSide)side;\n\n/** Slides the top view in the direction of the specified side.\n \n A peek amount or reveal amount must be set for the given side. The top view will anchor to one of those specified values.\n \n @param side The side for the top view to slide towards.\n @param animations Perform changes to properties that will be animated while top view is moved off screen. Can be nil.\n @param onComplete Executed after the animation is completed. Can be nil.\n */\n- (void)anchorTopViewTo:(ECSide)side animations:(void(^)(void))animations onComplete:(void(^)(void))onComplete;\n\n/** Slides the top view off of the screen in the direction of the specified side.\n \n @param side The side for the top view to slide off the screen towards.\n */\n- (void)anchorTopViewOffScreenTo:(ECSide)side;\n\n/** Slides the top view off of the screen in the direction of the specified side.\n \n @param side The side for the top view to slide off the screen towards.\n @param animations Perform changes to properties that will be animated while top view is moved off screen. Can be nil.\n @param onComplete Executed after the animation is completed. Can be nil.\n */\n- (void)anchorTopViewOffScreenTo:(ECSide)side animations:(void(^)(void))animations onComplete:(void(^)(void))onComplete;\n\n/** Slides the top view back to the center. */\n- (void)resetTopView;\n\n/** Slides the top view back to the center.\n\n @param animations Perform changes to properties that will be animated while top view is moved back to the center of the screen. Can be nil.\n @param onComplete Executed after the animation is completed. Can be nil.\n */\n- (void)resetTopViewWithAnimations:(void(^)(void))animations onComplete:(void(^)(void))onComplete;\n\n/** Returns true if the underLeft view is showing (even partially) */\n- (BOOL)underLeftShowing;\n\n/** Returns true if the underRight view is showing (even partially) */\n- (BOOL)underRightShowing;\n\n/** Returns true if the top view is completely off the screen */\n- (BOOL)topViewIsOffScreen;\n\n-(void)updateUnderLeftLayout;\n-(void)updateUnderRightLayout;\n-(BOOL)topViewHasFocus;\n-(void)adjustLayout;\n@end\n\n/** UIViewController extension */\n@interface UIViewController(SlidingViewExtension)\n/** Convience method for getting access to the ECSlidingViewController instance */\n- (ECSlidingViewController *)slidingViewController;\n@end\n"
  },
  {
    "path": "ECSlidingViewController/ECSlidingViewController.m",
    "content": "//\n//  ECSlidingViewController.m\n//  ECSlidingViewController\n//\n//  Created by Michael Enriquez on 1/23/12.\n//  Copyright (c) 2012 EdgeCase. All rights reserved.\n//\n\n#import \"ECSlidingViewController.h\"\n\nNSString *const ECSlidingViewUnderRightWillAppear    = @\"ECSlidingViewUnderRightWillAppear\";\nNSString *const ECSlidingViewUnderLeftWillAppear     = @\"ECSlidingViewUnderLeftWillAppear\";\nNSString *const ECSlidingViewUnderLeftWillDisappear  = @\"ECSlidingViewUnderLeftWillDisappear\";\nNSString *const ECSlidingViewUnderRightWillDisappear = @\"ECSlidingViewUnderRightWillDisappear\";\nNSString *const ECSlidingViewTopDidAnchorLeft        = @\"ECSlidingViewTopDidAnchorLeft\";\nNSString *const ECSlidingViewTopDidAnchorRight       = @\"ECSlidingViewTopDidAnchorRight\";\nNSString *const ECSlidingViewTopWillReset            = @\"ECSlidingViewTopWillReset\";\nNSString *const ECSlidingViewTopDidReset             = @\"ECSlidingViewTopDidReset\";\n\n@interface ECSlidingViewController()\n\n@property (nonatomic, strong) UIView *topViewSnapshot;\n@property (nonatomic, assign) CGFloat initialTouchPositionX;\n@property (nonatomic, assign) CGFloat initialHoizontalCenter;\n@property (nonatomic, strong) UIPanGestureRecognizer *panGesture;\n@property (nonatomic, strong) UITapGestureRecognizer *resetTapGesture;\n@property (nonatomic, strong) UIPanGestureRecognizer *topViewSnapshotPanGesture;\n@property (nonatomic, assign) BOOL underLeftShowing;\n@property (nonatomic, assign) BOOL underRightShowing;\n@property (nonatomic, assign) BOOL topViewIsOffScreen;\n\n- (NSUInteger)autoResizeToFillScreen;\n- (UIView *)topView;\n- (UIView *)underLeftView;\n- (UIView *)underRightView;\n- (void)adjustLayout;\n- (void)updateTopViewHorizontalCenterWithRecognizer:(UIPanGestureRecognizer *)recognizer;\n- (void)updateTopViewHorizontalCenter:(CGFloat)newHorizontalCenter;\n- (void)topViewHorizontalCenterWillChange:(CGFloat)newHorizontalCenter;\n- (void)topViewHorizontalCenterDidChange:(CGFloat)newHorizontalCenter;\n- (void)addTopViewSnapshot;\n- (void)removeTopViewSnapshot;\n- (CGFloat)anchorRightTopViewCenter;\n- (CGFloat)anchorLeftTopViewCenter;\n- (CGFloat)resettedCenter;\n- (void)underLeftWillAppear;\n- (void)underRightWillAppear;\n- (void)topDidReset;\n- (BOOL)topViewHasFocus;\n- (void)updateUnderLeftLayout;\n- (void)updateUnderRightLayout;\n\n@end\n\n@implementation UIViewController(SlidingViewExtension)\n\n- (ECSlidingViewController *)slidingViewController\n{\n  UIViewController *viewController = self.parentViewController;\n  while (!(viewController == nil || [viewController isKindOfClass:[ECSlidingViewController class]])) {\n    viewController = viewController.parentViewController;\n  }\n  \n  return (ECSlidingViewController *)viewController;\n}\n\n@end\n\n@implementation ECSlidingViewController\n\n// public properties\n@synthesize underLeftViewController  = _underLeftViewController;\n@synthesize underRightViewController = _underRightViewController;\n@synthesize topViewController        = _topViewController;\n@synthesize anchorLeftPeekAmount;\n@synthesize anchorRightPeekAmount;\n@synthesize anchorLeftRevealAmount;\n@synthesize anchorRightRevealAmount;\n@synthesize underRightWidthLayout = _underRightWidthLayout;\n@synthesize underLeftWidthLayout  = _underLeftWidthLayout;\n@synthesize shouldAllowPanningPastAnchor;\n@synthesize shouldAllowUserInteractionsWhenAnchored;\n@synthesize shouldAddPanGestureRecognizerToTopViewSnapshot;\n@synthesize resetStrategy = _resetStrategy;\n\n// category properties\n@synthesize topViewSnapshot;\n@synthesize initialTouchPositionX;\n@synthesize initialHoizontalCenter;\n@synthesize panGesture = _panGesture;\n@synthesize resetTapGesture;\n@synthesize underLeftShowing   = _underLeftShowing;\n@synthesize underRightShowing  = _underRightShowing;\n@synthesize topViewIsOffScreen = _topViewIsOffScreen;\n@synthesize topViewSnapshotPanGesture = _topViewSnapshotPanGesture;\n\n-(void)applicationDidResume {\n    //We do our own layout higher up in the stack, so override this to prevent a crash on iOS 8\n}\n\n- (void)setTopViewController:(UIViewController *)theTopViewController\n{\n  CGRect topViewFrame = _topViewController ? _topViewController.view.frame : self.view.bounds;\n  \n  [self removeTopViewSnapshot];\n  [_topViewController.view removeFromSuperview];\n  [_topViewController willMoveToParentViewController:nil];\n  [_topViewController removeFromParentViewController];\n  \n  _topViewController = theTopViewController;\n  \n  [self addChildViewController:self.topViewController];\n  [self.topViewController didMoveToParentViewController:self];\n  \n  [_topViewController.view setAutoresizingMask:self.autoResizeToFillScreen];\n  [_topViewController.view setFrame:topViewFrame];\n  _topViewController.view.layer.shadowOffset = CGSizeZero;\n  _topViewController.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.layer.bounds].CGPath;\n  \n  [self.view addSubview:_topViewController.view];\n}\n\n- (void)setUnderLeftViewController:(UIViewController *)theUnderLeftViewController\n{\n  [_underLeftViewController.view removeFromSuperview];\n  [_underLeftViewController willMoveToParentViewController:nil];\n  [_underLeftViewController removeFromParentViewController];\n  \n  _underLeftViewController = theUnderLeftViewController;\n  \n  if (_underLeftViewController) {\n    _underLeftViewController.view.hidden = YES;\n    @try {\n        [self addChildViewController:self.underLeftViewController];\n    } @catch (NSException *e) {\n    }\n    @try {\n        [self.view insertSubview:_underLeftViewController.view belowSubview:self.topView];\n    } @catch (NSException *e) {\n    }\n    @try {\n        [self addChildViewController:self.underLeftViewController];\n    } @catch (NSException *e) {\n    }\n    [self.underLeftViewController didMoveToParentViewController:self];\n    [self updateUnderLeftLayout];\n  }\n}\n\n- (void)setUnderRightViewController:(UIViewController *)theUnderRightViewController\n{\n  [_underRightViewController.view removeFromSuperview];\n  [_underRightViewController willMoveToParentViewController:nil];\n  [_underRightViewController removeFromParentViewController];\n  \n  _underRightViewController = theUnderRightViewController;\n  \n  if (_underRightViewController) {\n    _underRightViewController.view.hidden = YES;\n    [self.view insertSubview:_underRightViewController.view belowSubview:self.topView];\n    [self updateUnderRightLayout];\n    [self addChildViewController:self.underRightViewController];\n    [self.underRightViewController didMoveToParentViewController:self];\n  }\n}\n\n- (void)setUnderLeftWidthLayout:(ECViewWidthLayout)underLeftWidthLayout\n{\n  if (underLeftWidthLayout == ECVariableRevealWidth && self.anchorRightPeekAmount <= 0) {\n    [NSException raise:@\"Invalid Width Layout\" format:@\"anchorRightPeekAmount must be set\"];\n  } else if (underLeftWidthLayout == ECFixedRevealWidth && self.anchorRightRevealAmount <= 0) {\n    [NSException raise:@\"Invalid Width Layout\" format:@\"anchorRightRevealAmount must be set\"];\n  }\n  \n  _underLeftWidthLayout = underLeftWidthLayout;\n}\n\n- (void)setUnderRightWidthLayout:(ECViewWidthLayout)underRightWidthLayout\n{\n  if (underRightWidthLayout == ECVariableRevealWidth && self.anchorLeftPeekAmount <= 0) {\n    [NSException raise:@\"Invalid Width Layout\" format:@\"anchorLeftPeekAmount must be set\"];\n  } else if (underRightWidthLayout == ECFixedRevealWidth && self.anchorLeftRevealAmount <= 0) {\n    [NSException raise:@\"Invalid Width Layout\" format:@\"anchorLeftRevealAmount must be set\"];\n  }\n  \n  _underRightWidthLayout = underRightWidthLayout;\n}\n\n- (void)viewDidLoad\n{\n  [super viewDidLoad];\n  self.shouldAllowPanningPastAnchor = YES;\n  self.shouldAllowUserInteractionsWhenAnchored = NO;\n  self.shouldAddPanGestureRecognizerToTopViewSnapshot = NO;\n  self.resetTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(resetTopView)];\n  _panGesture          = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(updateTopViewHorizontalCenterWithRecognizer:)];\n  _panGesture.delegate = self;\n    _panGesture.maximumNumberOfTouches = 1;\n  self.resetTapGesture.enabled = NO;\n  self.resetStrategy = ECTapping | ECPanning;\n  \n  self.topViewSnapshot = [[UIView alloc] initWithFrame:self.topView.bounds];\n  [self.topViewSnapshot setAutoresizingMask:self.autoResizeToFillScreen];\n  [self.topViewSnapshot addGestureRecognizer:self.resetTapGesture];\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    if([self.topViewController isKindOfClass:[UINavigationController class]])\n        return [((UINavigationController *)self.topViewController).topViewController supportedInterfaceOrientations];\n    else\n        return [self.topViewController supportedInterfaceOrientations];\n}\n\n- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)recognizer {\n    CGPoint velocity = [recognizer velocityInView:self.view];\n    return ABS(velocity.x) > ABS(velocity.y);\n}\n\n- (void)viewWillAppear:(BOOL)animated\n{\n  [super viewWillAppear:animated];\n  self.topView.layer.shadowOffset = CGSizeZero;\n  self.topView.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.layer.bounds].CGPath;\n  [self adjustLayout];\n}\n\n-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {\n    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];\n    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n        self.topView.layer.shadowPath = nil;\n        self.topView.layer.shouldRasterize = YES;\n        \n        if(![self topViewHasFocus]){\n            [self removeTopViewSnapshot];\n        }\n        \n        [self adjustLayout];\n    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n        self.topView.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.layer.bounds].CGPath;\n        self.topView.layer.shouldRasterize = NO;\n        \n        if(![self topViewHasFocus]){\n            [self addTopViewSnapshot];\n        }\n    }\n     ];\n}\n\n- (void)setResetStrategy:(ECResetStrategy)theResetStrategy\n{\n  _resetStrategy = theResetStrategy;\n  if (_resetStrategy & ECTapping) {\n    self.resetTapGesture.enabled = YES;\n  } else {\n    self.resetTapGesture.enabled = NO;\n  }\n}\n\n- (void)adjustLayout\n{\n  if(@available(iOS 13, *)) {\n      BOOL hasGestureBar = NO;\n      hasGestureBar = self.view.window.safeAreaInsets.bottom > 0 && [[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPad;\n      if(!hasGestureBar) {\n        int sbheight = [UIApplication sharedApplication].statusBarFrame.size.height;\n        if(sbheight > 20 && [[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPad)\n          sbheight -= 20;\n        if(self.view.window.safeAreaInsets.bottom) {\n            sbheight = self.view.window.safeAreaInsets.top;\n        }\n#if !TARGET_OS_MACCATALYST\n        if (@available(iOS 14.0, *)) {\n          if([NSProcessInfo processInfo].isiOSAppOnMac) {\n              sbheight = 0;\n          }\n        }\n#endif\n        CGRect frame = self.topView.frame;\n        frame.origin.y = sbheight;\n        frame.size.height = self.view.bounds.size.height - sbheight;\n        if([UIApplication sharedApplication].statusBarFrame.size.height > 20 && [[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPad)\n          frame.size.height += 20;\n        if([[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPad && self.view.window.safeAreaInsets.bottom) {\n          frame.size.height -= self.view.window.safeAreaInsets.bottom;\n        }\n        self.topView.frame = frame;\n        _topViewController.view.layer.shadowOffset = CGSizeZero;\n        _topViewController.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.bounds].CGPath;\n      }\n  }\n\n  self.topViewSnapshot.frame = self.topView.bounds;\n    \n  if ([self underRightShowing] && ![self topViewIsOffScreen]) {\n    [self updateUnderRightLayout];\n    [self updateTopViewHorizontalCenter:self.anchorLeftTopViewCenter];\n  } else if ([self underRightShowing] && [self topViewIsOffScreen]) {\n    [self updateUnderRightLayout];\n    [self updateTopViewHorizontalCenter:-self.resettedCenter];\n  } else if ([self underLeftShowing] && ![self topViewIsOffScreen]) {\n    [self updateUnderLeftLayout];\n    [self updateTopViewHorizontalCenter:self.anchorRightTopViewCenter];\n  } else if ([self underLeftShowing] && [self topViewIsOffScreen]) {\n    [self updateUnderLeftLayout];\n    [self updateTopViewHorizontalCenter:self.view.bounds.size.width + self.resettedCenter];\n  }\n}\n\n- (void)updateTopViewHorizontalCenterWithRecognizer:(UIPanGestureRecognizer *)recognizer\n{\n    static BOOL underLeftWasShowing = NO;\n    static BOOL underRightWasShowing = NO;\n  CGPoint currentTouchPoint     = [recognizer locationInView:self.view];\n  CGFloat currentTouchPositionX = currentTouchPoint.x;\n  \n  if (recognizer.state == UIGestureRecognizerStateBegan) {\n    self.initialTouchPositionX = currentTouchPositionX;\n    self.initialHoizontalCenter = self.topView.center.x;\n  } else if (recognizer.state == UIGestureRecognizerStateChanged) {\n    CGFloat panAmount = self.initialTouchPositionX - currentTouchPositionX;\n    CGFloat newCenterPosition = self.initialHoizontalCenter - panAmount;\n    \n    if ((newCenterPosition < self.resettedCenter && (self.anchorLeftTopViewCenter == NSNotFound || self.underRightViewController == nil)) ||\n        (newCenterPosition > self.resettedCenter && (self.anchorRightTopViewCenter == NSNotFound || self.underLeftViewController == nil))) {\n      newCenterPosition = self.resettedCenter;\n    }\n    \n      if((newCenterPosition > self.resettedCenter && underRightWasShowing) || (newCenterPosition < self.resettedCenter && underLeftWasShowing)) {\n          newCenterPosition = self.resettedCenter;\n      }\n          \n      \n    BOOL newCenterPositionIsOutsideAnchor = newCenterPosition < self.anchorLeftTopViewCenter || self.anchorRightTopViewCenter < newCenterPosition;\n    \n    if (newCenterPosition != self.topView.center.x && ((newCenterPositionIsOutsideAnchor && self.shouldAllowPanningPastAnchor) || !newCenterPositionIsOutsideAnchor)) {\n      [self topViewHorizontalCenterWillChange:newCenterPosition];\n      [self updateTopViewHorizontalCenter:newCenterPosition];\n      [self topViewHorizontalCenterDidChange:newCenterPosition];\n        if(self.underLeftShowing)\n            underLeftWasShowing = self.underLeftShowing;\n        \n        if(self.underRightShowing)\n            underRightWasShowing = self.underRightShowing;\n    }\n  } else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) {\n      underLeftWasShowing = NO;\n      underRightWasShowing = NO;\n    CGFloat panAmount            = currentTouchPositionX - self.initialTouchPositionX;\n    CGPoint currentVelocityPoint = [recognizer velocityInView:self.view];\n    CGFloat currentVelocityX     = currentVelocityPoint.x;\n        \n    if ([self underLeftShowing] && (currentVelocityX > 50 || (currentVelocityX >= 0 && panAmount >= anchorRightRevealAmount/6.0f))) {\n      [self anchorTopViewTo:ECRight];\n    } else if ([self underRightShowing] && (currentVelocityX < -50 || (currentVelocityX <= 0 && panAmount <= -anchorLeftRevealAmount/6.0))) {\n      [self anchorTopViewTo:ECLeft];\n    } else {\n      [self resetTopView];\n    }\n  }\n}\n\n- (UIPanGestureRecognizer *)panGesture\n{\n  return _panGesture;\n}\n\n- (void)anchorTopViewTo:(ECSide)side\n{\n  [self anchorTopViewTo:side animations:nil onComplete:nil];\n}\n\n- (void)anchorTopViewTo:(ECSide)side animations:(void (^)(void))animations onComplete:(void (^)(void))complete\n{\n  CGFloat newCenter = self.topView.center.x;\n  \n  if (side == ECLeft) {\n    newCenter = self.anchorLeftTopViewCenter;\n  } else if (side == ECRight) {\n    newCenter = self.anchorRightTopViewCenter;\n  }\n  \n  [self topViewHorizontalCenterWillChange:newCenter];\n  \n  [UIView animateWithDuration:0.15f animations:^{\n    if (animations) {\n      animations();\n    }\n    [self updateTopViewHorizontalCenter:newCenter];\n  } completion:^(BOOL finished){\n      if (self->_resetStrategy & ECPanning) {\n      self.panGesture.enabled = YES;\n    } else {\n      self.panGesture.enabled = NO;\n    }\n    if (complete) {\n      complete();\n    }\n      self->_topViewIsOffScreen = NO;\n    [self addTopViewSnapshot];\n    dispatch_async(dispatch_get_main_queue(), ^{\n      NSString *key = (side == ECLeft) ? ECSlidingViewTopDidAnchorLeft : ECSlidingViewTopDidAnchorRight;\n      [[NSNotificationCenter defaultCenter] postNotificationName:key object:self userInfo:nil];\n        (side == ECRight) ? [self->_underLeftViewController viewDidAppear:NO] : [self->_underRightViewController viewDidAppear:NO];\n    });\n  }];\n}\n\n- (void)anchorTopViewOffScreenTo:(ECSide)side\n{\n  [self anchorTopViewOffScreenTo:side animations:nil onComplete:nil];\n}\n\n- (void)anchorTopViewOffScreenTo:(ECSide)side animations:(void(^)(void))animations onComplete:(void(^)(void))complete\n{\n  CGFloat newCenter = self.topView.center.x;\n  \n  if (side == ECLeft) {\n    newCenter = -self.resettedCenter;\n  } else if (side == ECRight) {\n    newCenter = self.view.bounds.size.width + self.resettedCenter;\n  }\n  \n  [self topViewHorizontalCenterWillChange:newCenter];\n  \n  [UIView animateWithDuration:0.15f animations:^{\n    if (animations) {\n      animations();\n    }\n    [self updateTopViewHorizontalCenter:newCenter];\n  } completion:^(BOOL finished){\n    if (complete) {\n      complete();\n    }\n      self->_topViewIsOffScreen = YES;\n    [self addTopViewSnapshot];\n    dispatch_async(dispatch_get_main_queue(), ^{\n      NSString *key = (side == ECLeft) ? ECSlidingViewTopDidAnchorLeft : ECSlidingViewTopDidAnchorRight;\n      [[NSNotificationCenter defaultCenter] postNotificationName:key object:self userInfo:nil];\n    });\n  }];\n}\n\n- (void)resetTopView\n{\n  dispatch_async(dispatch_get_main_queue(), ^{\n    [[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewTopWillReset object:self userInfo:nil];\n  });\n  [self resetTopViewWithAnimations:nil onComplete:nil];\n}\n\n- (void)resetTopViewWithAnimations:(void(^)(void))animations onComplete:(void(^)(void))complete\n{\n    if(self.topView.center.x != self.resettedCenter) {\n      [self topViewHorizontalCenterWillChange:self.resettedCenter];\n      \n      [UIView animateWithDuration:0.15f animations:^{\n        if (animations) {\n          animations();\n        }\n        [self updateTopViewHorizontalCenter:self.resettedCenter];\n      } completion:^(BOOL finished) {\n        [self topViewHorizontalCenterDidChange:self.resettedCenter];\n        if (complete) {\n          complete();\n        }\n      }];\n    } else {\n        if (complete) {\n            complete();\n        }\n    }\n}\n\n- (NSUInteger)autoResizeToFillScreen\n{\n  return (UIViewAutoresizingFlexibleWidth |\n          UIViewAutoresizingFlexibleHeight);\n}\n\n- (UIView *)topView\n{\n  return self.topViewController.view;\n}\n\n- (UIView *)underLeftView\n{\n  return self.underLeftViewController.view;\n}\n\n- (UIView *)underRightView\n{\n  return self.underRightViewController.view;\n}\n\n- (void)updateTopViewHorizontalCenter:(CGFloat)newHorizontalCenter\n{\n  CGPoint center = self.topView.center;\n  center.x = newHorizontalCenter;\n  self.topView.layer.position = center;\n}\n\n- (void)topViewHorizontalCenterWillChange:(CGFloat)newHorizontalCenter\n{\n  CGPoint center = self.topView.center;\n  \n\tif (center.x >= self.resettedCenter && newHorizontalCenter == self.resettedCenter) {\n\t\tdispatch_async(dispatch_get_main_queue(), ^{\n\t\t\t[[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewUnderLeftWillDisappear object:self userInfo:nil];\n\t\t});\n\t}\n\t\n\tif (center.x <= self.resettedCenter && newHorizontalCenter == self.resettedCenter) {\n\t\tdispatch_async(dispatch_get_main_queue(), ^{\n\t\t\t[[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewUnderRightWillDisappear object:self userInfo:nil];\n\t\t});\n\t}\n\t\n  if (center.x <= self.resettedCenter && newHorizontalCenter > self.resettedCenter) {\n    [self underLeftWillAppear];\n  } else if (center.x >= self.resettedCenter && newHorizontalCenter < self.resettedCenter) {\n    [self underRightWillAppear];\n  }\n    \n    [self.view sendSubviewToBack:self.underLeftView];\n    [self.view sendSubviewToBack:self.underRightView];\n}\n\n- (void)topViewHorizontalCenterDidChange:(CGFloat)newHorizontalCenter\n{\n  if (newHorizontalCenter == self.resettedCenter) {\n    [self topDidReset];\n  }\n}\n\n- (void)addTopViewSnapshot\n{\n  if (!self.topViewSnapshot.superview && !self.shouldAllowUserInteractionsWhenAnchored) {\n    //topViewSnapshot.layer.contents = (id)[UIImage imageWithUIView:self.topView].CGImage;\n    \n    if (self.shouldAddPanGestureRecognizerToTopViewSnapshot && (_resetStrategy & ECPanning)) {\n      if (!_topViewSnapshotPanGesture) {\n        _topViewSnapshotPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(updateTopViewHorizontalCenterWithRecognizer:)];\n      }\n      [topViewSnapshot addGestureRecognizer:_topViewSnapshotPanGesture];\n    }\n    self.topViewSnapshot.frame = self.topView.bounds;\n    [self.topView addSubview:self.topViewSnapshot];\n  }\n}\n\n- (void)removeTopViewSnapshot\n{\n  if (self.topViewSnapshot.superview) {\n    [self.topViewSnapshot removeFromSuperview];\n  }\n}\n\n- (CGFloat)anchorRightTopViewCenter\n{\n  if (self.anchorRightPeekAmount) {\n    return self.view.bounds.size.width + self.resettedCenter - self.anchorRightPeekAmount;\n  } else if (self.anchorRightRevealAmount) {\n    return self.resettedCenter + self.anchorRightRevealAmount;\n  } else {\n    return NSNotFound;\n  }\n}\n\n- (CGFloat)anchorLeftTopViewCenter\n{\n  if (self.anchorLeftPeekAmount) {\n    return -self.resettedCenter + self.anchorLeftPeekAmount;\n  } else if (self.anchorLeftRevealAmount) {\n    return -self.resettedCenter + (self.view.bounds.size.width - self.anchorLeftRevealAmount);\n  } else {\n    return NSNotFound;\n  }\n}\n\n- (CGFloat)resettedCenter\n{\n  return (self.view.bounds.size.width / 2);\n}\n\n- (void)underLeftWillAppear\n{\n  dispatch_async(dispatch_get_main_queue(), ^{\n    [[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewUnderLeftWillAppear object:self userInfo:nil];\n  });\n  [self updateUnderLeftLayout];\n  self.underRightView.hidden = YES;\n  self.underLeftView.hidden = NO;\n  _underLeftShowing  = YES;\n  _underRightShowing = NO;\n}\n\n- (void)underRightWillAppear\n{\n  dispatch_async(dispatch_get_main_queue(), ^{\n    [[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewUnderRightWillAppear object:self userInfo:nil];\n  });\n  [self updateUnderRightLayout];\n  self.underRightView.hidden = NO;\n  self.underLeftView.hidden = YES;\n  _underLeftShowing  = NO;\n  _underRightShowing = YES;\n}\n\n- (void)topDidReset\n{\n  dispatch_async(dispatch_get_main_queue(), ^{\n    [[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewTopDidReset object:self userInfo:nil];\n    if([self.topViewController isKindOfClass:UINavigationController.class]) {\n      [((UINavigationController *)self.topViewController).visibleViewController viewDidAppear:NO];\n    } else {\n      [self.topViewController viewDidAppear:NO];\n    }\n  });\n  [self.topView removeGestureRecognizer:self.resetTapGesture];\n  [self removeTopViewSnapshot];\n  self.panGesture.enabled = YES;\n  self.underRightView.hidden = YES;\n  self.underLeftView.hidden = YES;\n  _underLeftShowing   = NO;\n  _underRightShowing  = NO;\n  _topViewIsOffScreen = NO;\n}\n\n- (BOOL)topViewHasFocus\n{\n  return !_underLeftShowing && !_underRightShowing && !_topViewIsOffScreen;\n}\n\n- (void)updateUnderLeftLayout\n{\n    if (self.underLeftWidthLayout == ECFullWidth) {\n        [self.underLeftView setAutoresizingMask:self.autoResizeToFillScreen];\n        [self.underLeftView setFrame:self.view.bounds];\n    } else if (self.underLeftWidthLayout == ECVariableRevealWidth && !self.topViewIsOffScreen) {\n        CGRect frame = self.view.bounds;\n\n        frame.size.width = frame.size.width - self.anchorRightPeekAmount;\n        self.underLeftView.frame = frame;\n    } else if (self.underLeftWidthLayout == ECFixedRevealWidth) {\n        CGRect frame = self.view.bounds;\n\n        frame.size.width = self.anchorRightRevealAmount;\n        self.underLeftView.frame = frame;\n    } else {\n        [NSException raise:@\"Invalid Width Layout\" format:@\"underLeftWidthLayout must be a valid ECViewWidthLayout\"];\n    }\n    int sbheight = [UIApplication sharedApplication].statusBarFrame.size.height;\n    if(sbheight > 20 && [[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPad)\n        sbheight -= 20;\n#if TARGET_OS_MACCATALYST\n    sbheight = self.view.window.safeAreaInsets.top;\n#else\n    if(self.view.window.safeAreaInsets.bottom) {\n        sbheight = self.view.window.safeAreaInsets.top;\n    }\n    if (@available(iOS 14.0, *)) {\n        if([NSProcessInfo processInfo].isiOSAppOnMac) {\n            sbheight = 0;\n        }\n    }\n#endif\n    CGRect frame = self.underLeftView.frame;\n    frame.origin.y = sbheight;\n    frame.size.height = self.view.bounds.size.height - sbheight;\n    if([UIApplication sharedApplication].statusBarFrame.size.height > 20 && [[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPad)\n        frame.size.height += 20;\n    self.underLeftView.frame = frame;\n}\n\n- (void)updateUnderRightLayout\n{\n    if (self.underRightWidthLayout == ECFullWidth) {\n        [self.underRightViewController.view setAutoresizingMask:self.autoResizeToFillScreen];\n        self.underRightView.frame = self.view.bounds;\n    } else if (self.underRightWidthLayout == ECVariableRevealWidth) {\n        CGRect frame = self.view.bounds;\n\n        CGFloat newLeftEdge;\n        CGFloat newWidth = frame.size.width;\n\n        if (self.topViewIsOffScreen) {\n          newLeftEdge = 0;\n        } else {\n          newLeftEdge = self.anchorLeftPeekAmount;\n          newWidth   -= self.anchorLeftPeekAmount;\n        }\n\n        frame.origin.x   = newLeftEdge;\n        frame.size.width = newWidth;\n\n        self.underRightView.frame = frame;\n    } else if (self.underRightWidthLayout == ECFixedRevealWidth) {\n        CGRect frame = self.view.bounds;\n\n        CGFloat newLeftEdge = frame.size.width - self.anchorLeftRevealAmount;\n        CGFloat newWidth = self.anchorLeftRevealAmount;\n\n        frame.origin.x   = newLeftEdge;\n        frame.size.width = newWidth;\n\n        self.underRightView.frame = frame;\n    } else {\n        [NSException raise:@\"Invalid Width Layout\" format:@\"underRightWidthLayout must be a valid ECViewWidthLayout\"];\n    }\n    int sbheight = [UIApplication sharedApplication].statusBarFrame.size.height;\n    if(sbheight > 20)\n        sbheight -= 20;\n#if TARGET_OS_MACCATALYST\n    sbheight = self.view.window.safeAreaInsets.top;\n#else\n    if(self.view.window.safeAreaInsets.bottom) {\n        sbheight = self.view.window.safeAreaInsets.top;\n    }\n    if (@available(iOS 14.0, *)) {\n        if([NSProcessInfo processInfo].isiOSAppOnMac) {\n            sbheight = 0;\n        }\n    }\n#endif\n    CGRect frame = self.underRightView.frame;\n    frame.origin.y = sbheight;\n    frame.size.height = self.view.bounds.size.height - sbheight;\n    if([UIApplication sharedApplication].statusBarFrame.size.height > 20 && [[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPad)\n        frame.size.height += 20;\n    self.underRightView.frame = frame;\n}\n\n-(UIStatusBarStyle)preferredStatusBarStyle {\n    if(self.topViewController)\n        return self.topViewController.childViewControllerForStatusBarStyle ? self.topViewController.childViewControllerForStatusBarStyle.preferredStatusBarStyle : self.topViewController.preferredStatusBarStyle;\n    else\n        return UIStatusBarStyleDefault;\n}\n\n-(BOOL)prefersStatusBarHidden {\n    if(self.topViewController)\n        return self.topViewController.childViewControllerForStatusBarHidden ? self.topViewController.childViewControllerForStatusBarHidden.prefersStatusBarHidden : self.topViewController.prefersStatusBarHidden;\n    else\n        return NO;\n}\n@end\n"
  },
  {
    "path": "ECSlidingViewController/UIImage+ImageWithUIView.h",
    "content": "//\n//  UIImage+ImageWithUIView.h\n//\n\n#import <UIKit/UIKit.h>\n#import <QuartzCore/QuartzCore.h>\n\n@interface UIImage (ImageWithUIView)\n+ (UIImage *)imageWithUIView:(UIView *)view;\n@end"
  },
  {
    "path": "ECSlidingViewController/UIImage+ImageWithUIView.m",
    "content": "//\n//  UIImage+ImageWithUIView.m\n//\n\n#import \"UIImage+ImageWithUIView.h\"\n\n@implementation UIImage (ImageWithUIView)\n#pragma mark -\n#pragma mark TakeScreenShot\n\n+ (UIImage *)imageWithUIView:(UIView *)view\n{\n  CGSize screenShotSize = view.bounds.size;\n  UIImage *img;  \n  UIGraphicsBeginImageContext(screenShotSize);\n  CGContextRef ctx = UIGraphicsGetCurrentContext();\n  [view drawLayer:view.layer inContext:ctx];\n  img = UIGraphicsGetImageFromCurrentImageContext();\n  UIGraphicsEndImageContext();\n  \n  return img;\n}\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputColorView.h",
    "content": "//\n//  FLEXArgumentInputColorView.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/30/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputView.h\"\n\n@interface FLEXArgumentInputColorView : FLEXArgumentInputView\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m",
    "content": "//\n//  FLEXArgumentInputColorView.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/30/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputColorView.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXRuntimeUtility.h\"\n\n@protocol FLEXColorComponentInputViewDelegate;\n\n@interface FLEXColorComponentInputView : UIView\n\n@property (nonatomic, strong) UISlider *slider;\n@property (nonatomic, strong) UILabel *valueLabel;\n\n@property (nonatomic, weak) id <FLEXColorComponentInputViewDelegate> delegate;\n\n@end\n\n@protocol FLEXColorComponentInputViewDelegate <NSObject>\n\n- (void)colorComponentInputViewValueDidChange:(FLEXColorComponentInputView *)colorComponentInputView;\n\n@end\n\n\n@implementation FLEXColorComponentInputView\n\n- (id)initWithFrame:(CGRect)frame\n{\n    self = [super initWithFrame:frame];\n    if (self) {\n        self.slider = [[UISlider alloc] init];\n        self.slider.backgroundColor = self.backgroundColor;\n        [self.slider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];\n        [self addSubview:self.slider];\n        \n        self.valueLabel = [[UILabel alloc] init];\n        self.valueLabel.backgroundColor = self.backgroundColor;\n        self.valueLabel.font = [FLEXUtility defaultFontOfSize:14.0];\n        self.valueLabel.textAlignment = NSTextAlignmentRight;\n        [self addSubview:self.valueLabel];\n        \n        [self updateValueLabel];\n    }\n    return self;\n}\n\n- (void)setBackgroundColor:(UIColor *)backgroundColor\n{\n    [super setBackgroundColor:backgroundColor];\n    self.slider.backgroundColor = backgroundColor;\n    self.valueLabel.backgroundColor = backgroundColor;\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    \n    const CGFloat kValueLabelWidth = 50.0;\n    \n    [self.slider sizeToFit];\n    CGFloat sliderWidth = self.bounds.size.width - kValueLabelWidth;\n    self.slider.frame = CGRectMake(0, 0, sliderWidth, self.slider.frame.size.height);\n    \n    [self.valueLabel sizeToFit];\n    CGFloat valueLabelOriginX = CGRectGetMaxX(self.slider.frame);\n    CGFloat valueLabelOriginY = FLEXFloor((self.slider.frame.size.height - self.valueLabel.frame.size.height) / 2.0);\n    self.valueLabel.frame = CGRectMake(valueLabelOriginX, valueLabelOriginY, kValueLabelWidth, self.valueLabel.frame.size.height);\n}\n\n- (void)sliderChanged:(id)sender\n{\n    [self.delegate colorComponentInputViewValueDidChange:self];\n    [self updateValueLabel];\n}\n\n- (void)updateValueLabel\n{\n    self.valueLabel.text = [NSString stringWithFormat:@\"%.3f\", self.slider.value];\n}\n\n- (CGSize)sizeThatFits:(CGSize)size\n{\n    CGFloat height = [self.slider sizeThatFits:size].height;\n    return CGSizeMake(size.width, height);\n}\n\n@end\n\n@interface FLEXColorPreviewBox : UIView\n\n@property (nonatomic, strong) UIColor *color;\n\n@property (nonatomic, strong) UIView *colorOverlayView;\n\n@end\n\n@implementation FLEXColorPreviewBox\n\n- (id)initWithFrame:(CGRect)frame\n{\n    self = [super initWithFrame:frame];\n    if (self) {\n        self.layer.borderWidth = 1.0;\n        self.layer.borderColor = [[UIColor blackColor] CGColor];\n        self.backgroundColor = [UIColor colorWithPatternImage:[[self class] backgroundPatternImage]];\n        \n        self.colorOverlayView = [[UIView alloc] initWithFrame:self.bounds];\n        self.colorOverlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n        self.colorOverlayView.backgroundColor = [UIColor clearColor];\n        [self addSubview:self.colorOverlayView];\n    }\n    return self;\n}\n\n- (void)setColor:(UIColor *)color\n{\n    self.colorOverlayView.backgroundColor = color;\n}\n\n- (UIColor *)color\n{\n    return self.colorOverlayView.backgroundColor;\n}\n\n+ (UIImage *)backgroundPatternImage\n{\n    const CGFloat kSquareDimension = 5.0;\n    CGSize squareSize = CGSizeMake(kSquareDimension, kSquareDimension);\n    CGSize imageSize = CGSizeMake(2.0 * kSquareDimension, 2.0 * kSquareDimension);\n    \n    UIGraphicsBeginImageContextWithOptions(imageSize, YES, [[UIScreen mainScreen] scale]);\n    \n    [[UIColor whiteColor] setFill];\n    UIRectFill(CGRectMake(0, 0, imageSize.width, imageSize.height));\n    \n    [[UIColor grayColor] setFill];\n    UIRectFill(CGRectMake(squareSize.width, 0, squareSize.width, squareSize.height));\n    UIRectFill(CGRectMake(0, squareSize.height, squareSize.width, squareSize.height));\n    \n    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();\n    UIGraphicsEndImageContext();\n    \n    return image;\n}\n\n@end\n\n@interface FLEXArgumentInputColorView () <FLEXColorComponentInputViewDelegate>\n\n@property (nonatomic, strong) FLEXColorPreviewBox *colorPreviewBox;\n@property (nonatomic, strong) UILabel *hexLabel;\n@property (nonatomic, strong) FLEXColorComponentInputView *alphaInput;\n@property (nonatomic, strong) FLEXColorComponentInputView *redInput;\n@property (nonatomic, strong) FLEXColorComponentInputView *greenInput;\n@property (nonatomic, strong) FLEXColorComponentInputView *blueInput;\n\n@end\n\n@implementation FLEXArgumentInputColorView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        self.colorPreviewBox = [[FLEXColorPreviewBox alloc] init];\n        [self addSubview:self.colorPreviewBox];\n        \n        self.hexLabel = [[UILabel alloc] init];\n        self.hexLabel.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.9];\n        self.hexLabel.textAlignment = NSTextAlignmentCenter;\n        self.hexLabel.font = [FLEXUtility defaultFontOfSize:12.0];\n        [self addSubview:self.hexLabel];\n        \n        self.alphaInput = [[FLEXColorComponentInputView alloc] init];\n        self.alphaInput.slider.minimumTrackTintColor = [UIColor blackColor];\n        self.alphaInput.delegate = self;\n        [self addSubview:self.alphaInput];\n        \n        self.redInput = [[FLEXColorComponentInputView alloc] init];\n        self.redInput.slider.minimumTrackTintColor = [UIColor redColor];\n        self.redInput.delegate = self;\n        [self addSubview:self.redInput];\n        \n        self.greenInput = [[FLEXColorComponentInputView alloc] init];\n        self.greenInput.slider.minimumTrackTintColor = [UIColor greenColor];\n        self.greenInput.delegate = self;\n        [self addSubview:self.greenInput];\n        \n        self.blueInput = [[FLEXColorComponentInputView alloc] init];\n        self.blueInput.slider.minimumTrackTintColor = [UIColor blueColor];\n        self.blueInput.delegate = self;\n        [self addSubview:self.blueInput];\n    }\n    return self;\n}\n\n- (void)setBackgroundColor:(UIColor *)backgroundColor\n{\n    [super setBackgroundColor:backgroundColor];\n    self.alphaInput.backgroundColor = backgroundColor;\n    self.redInput.backgroundColor = backgroundColor;\n    self.greenInput.backgroundColor = backgroundColor;\n    self.blueInput.backgroundColor = backgroundColor;\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    \n    CGFloat runningOriginY = 0;\n    CGSize constrainSize = CGSizeMake(self.bounds.size.width, CGFLOAT_MAX);\n    \n    self.colorPreviewBox.frame = CGRectMake(0, runningOriginY, self.bounds.size.width, [[self class] colorPreviewBoxHeight]);\n    runningOriginY = CGRectGetMaxY(self.colorPreviewBox.frame) + [[self class] inputViewVerticalPadding];\n    \n    [self.hexLabel sizeToFit];\n    const CGFloat kLabelVerticalOutsetAmount = 0.0;\n    const CGFloat kLabelHorizonalOutsetAmount = 2.0;\n    UIEdgeInsets labelOutset = UIEdgeInsetsMake(-kLabelVerticalOutsetAmount, -kLabelHorizonalOutsetAmount, -kLabelVerticalOutsetAmount, -kLabelHorizonalOutsetAmount);\n    self.hexLabel.frame = UIEdgeInsetsInsetRect(self.hexLabel.frame, labelOutset);\n    CGFloat hexLabelOriginX = self.colorPreviewBox.layer.borderWidth;\n    CGFloat hexLabelOriginY = CGRectGetMaxY(self.colorPreviewBox.frame) - self.colorPreviewBox.layer.borderWidth - self.hexLabel.frame.size.height;\n    self.hexLabel.frame = CGRectMake(hexLabelOriginX, hexLabelOriginY, self.hexLabel.frame.size.width, self.hexLabel.frame.size.height);\n    \n    NSArray<FLEXColorComponentInputView *> *colorComponentInputViews = @[self.alphaInput, self.redInput, self.greenInput, self.blueInput];\n    for (FLEXColorComponentInputView *inputView in colorComponentInputViews) {\n        CGSize fitSize = [inputView sizeThatFits:constrainSize];\n        inputView.frame = CGRectMake(0, runningOriginY, fitSize.width, fitSize.height);\n        runningOriginY = CGRectGetMaxY(inputView.frame) + [[self class] inputViewVerticalPadding];\n    }\n}\n\n- (void)setInputValue:(id)inputValue\n{\n    if ([inputValue isKindOfClass:[UIColor class]]) {\n        [self updateWithColor:inputValue];\n    } else if ([inputValue isKindOfClass:[NSValue class]]) {\n        const char *type = [inputValue objCType];\n        if (strcmp(type, @encode(CGColorRef)) == 0) {\n            CGColorRef colorRef;\n            [inputValue getValue:&colorRef];\n            UIColor *color = [[UIColor alloc] initWithCGColor:colorRef];\n            [self updateWithColor:color];\n        }\n    }\n}\n\n- (id)inputValue\n{\n    return [UIColor colorWithRed:self.redInput.slider.value green:self.greenInput.slider.value blue:self.blueInput.slider.value alpha:self.alphaInput.slider.value];\n}\n\n- (void)colorComponentInputViewValueDidChange:(FLEXColorComponentInputView *)colorComponentInputView\n{\n    [self updateColorPreview];\n}\n\n- (void)updateWithColor:(UIColor *)color\n{\n    CGFloat red, green, blue, white, alpha;\n    if ([color getRed:&red green:&green blue:&blue alpha:&alpha]) {\n        self.alphaInput.slider.value = alpha;\n        [self.alphaInput updateValueLabel];\n        self.redInput.slider.value = red;\n        [self.redInput updateValueLabel];\n        self.greenInput.slider.value = green;\n        [self.greenInput updateValueLabel];\n        self.blueInput.slider.value = blue;\n        [self.blueInput updateValueLabel];\n    } else if ([color getWhite:&white alpha:&alpha]) {\n        self.alphaInput.slider.value = alpha;\n        [self.alphaInput updateValueLabel];\n        self.redInput.slider.value = white;\n        [self.redInput updateValueLabel];\n        self.greenInput.slider.value = white;\n        [self.greenInput updateValueLabel];\n        self.blueInput.slider.value = white;\n        [self.blueInput updateValueLabel];\n    }\n    [self updateColorPreview];\n}\n\n- (void)updateColorPreview\n{\n    self.colorPreviewBox.color = self.inputValue;\n    unsigned char redByte = self.redInput.slider.value * 255;\n    unsigned char greenByte = self.greenInput.slider.value * 255;\n    unsigned char blueByte = self.blueInput.slider.value * 255;\n    self.hexLabel.text = [NSString stringWithFormat:@\"#%02X%02X%02X\", redByte, greenByte, blueByte];\n    [self setNeedsLayout];\n}\n\n- (CGSize)sizeThatFits:(CGSize)size\n{\n    CGFloat height = 0;\n    height += [[self class] colorPreviewBoxHeight];\n    height += [[self class] inputViewVerticalPadding];\n    height += [self.alphaInput sizeThatFits:size].height;\n    height += [[self class] inputViewVerticalPadding];\n    height += [self.redInput sizeThatFits:size].height;\n    height += [[self class] inputViewVerticalPadding];\n    height += [self.greenInput sizeThatFits:size].height;\n    height += [[self class] inputViewVerticalPadding];\n    height += [self.blueInput sizeThatFits:size].height;\n    return CGSizeMake(size.width, height);\n}\n\n+ (CGFloat)inputViewVerticalPadding\n{\n    return 10.0;\n}\n\n+ (CGFloat)colorPreviewBoxHeight\n{\n    return 40.0;\n}\n\n+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value\n{\n    return (type && (strcmp(type, @encode(CGColorRef)) == 0 || strcmp(type, FLEXEncodeClass(UIColor)) == 0)) || [value isKindOfClass:[UIColor class]];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputDateView.h",
    "content": "//\n//  FLEXArgumentInputDataView.h\n//  Flipboard\n//\n//  Created by Daniel Rodriguez Troitino on 2/14/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputView.h\"\n\n@interface FLEXArgumentInputDateView : FLEXArgumentInputView\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m",
    "content": "//\n//  FLEXArgumentInputDataView.m\n//  Flipboard\n//\n//  Created by Daniel Rodriguez Troitino on 2/14/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputDateView.h\"\n#import \"FLEXRuntimeUtility.h\"\n\n@interface FLEXArgumentInputDateView ()\n\n@property (nonatomic, strong) UIDatePicker *datePicker;\n\n@end\n\n@implementation FLEXArgumentInputDateView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        self.datePicker = [[UIDatePicker alloc] init];\n        self.datePicker.datePickerMode = UIDatePickerModeDateAndTime;\n        // Using UTC, because that's what the NSDate description prints\n        self.datePicker.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];\n        self.datePicker.timeZone = [NSTimeZone timeZoneWithAbbreviation:@\"UTC\"];\n        [self addSubview:self.datePicker];\n    }\n    return self;\n}\n\n- (void)setInputValue:(id)inputValue\n{\n    if ([inputValue isKindOfClass:[NSDate class]]) {\n        self.datePicker.date = inputValue;\n    }\n}\n\n- (id)inputValue\n{\n    return self.datePicker.date;\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    self.datePicker.frame = self.bounds;\n}\n\n- (CGSize)sizeThatFits:(CGSize)size\n{\n    CGFloat height = [self.datePicker sizeThatFits:size].height;\n    return CGSizeMake(size.width, height);\n}\n\n+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value\n{\n    return (type && (strcmp(type, FLEXEncodeClass(NSDate)) == 0)) || [value isKindOfClass:[NSDate class]];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontView.h",
    "content": "//\n//  FLEXArgumentInputFontView.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/28/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputView.h\"\n\n@interface FLEXArgumentInputFontView : FLEXArgumentInputView\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontView.m",
    "content": "//\n//  FLEXArgumentInputFontView.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/28/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputFontView.h\"\n#import \"FLEXArgumentInputViewFactory.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXArgumentInputFontsPickerView.h\"\n\n@interface FLEXArgumentInputFontView ()\n\n@property (nonatomic, strong) FLEXArgumentInputView *fontNameInput;\n@property (nonatomic, strong) FLEXArgumentInputView *pointSizeInput;\n\n@end\n\n@implementation FLEXArgumentInputFontView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        self.fontNameInput = [[FLEXArgumentInputFontsPickerView alloc] initWithArgumentTypeEncoding:FLEXEncodeClass(NSString)];\n        self.fontNameInput.backgroundColor = self.backgroundColor;\n        self.fontNameInput.targetSize = FLEXArgumentInputViewSizeSmall;\n        self.fontNameInput.title = @\"Font Name:\";\n        [self addSubview:self.fontNameInput];\n        \n        self.pointSizeInput = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:@encode(CGFloat)];\n        self.pointSizeInput.backgroundColor = self.backgroundColor;\n        self.pointSizeInput.targetSize = FLEXArgumentInputViewSizeSmall;\n        self.pointSizeInput.title = @\"Point Size:\";\n        [self addSubview:self.pointSizeInput];\n    }\n    return self;\n}\n\n- (void)setBackgroundColor:(UIColor *)backgroundColor\n{\n    [super setBackgroundColor:backgroundColor];\n    self.fontNameInput.backgroundColor = backgroundColor;\n    self.pointSizeInput.backgroundColor = backgroundColor;\n}\n\n- (void)setInputValue:(id)inputValue\n{\n    if ([inputValue isKindOfClass:[UIFont class]]) {\n        UIFont *font = (UIFont *)inputValue;\n        self.fontNameInput.inputValue = font.fontName;\n        self.pointSizeInput.inputValue = @(font.pointSize);\n    }\n}\n\n- (id)inputValue\n{\n    CGFloat pointSize = 0;\n    if ([self.pointSizeInput.inputValue isKindOfClass:[NSValue class]]) {\n        NSValue *pointSizeValue = (NSValue *)self.pointSizeInput.inputValue;\n        if (strcmp([pointSizeValue objCType], @encode(CGFloat)) == 0) {\n            [pointSizeValue getValue:&pointSize];\n        }\n    }\n    return [UIFont fontWithName:self.fontNameInput.inputValue size:pointSize];\n}\n\n- (BOOL)inputViewIsFirstResponder\n{\n    return [self.fontNameInput inputViewIsFirstResponder] || [self.pointSizeInput inputViewIsFirstResponder];\n}\n\n\n#pragma mark - Layout and Sizing\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    \n    CGFloat runningOriginY = self.topInputFieldVerticalLayoutGuide;\n    \n    CGSize fontNameFitSize = [self.fontNameInput sizeThatFits:self.bounds.size];\n    self.fontNameInput.frame = CGRectMake(0, runningOriginY, fontNameFitSize.width, fontNameFitSize.height);\n    runningOriginY = CGRectGetMaxY(self.fontNameInput.frame) + [[self class] verticalPaddingBetweenFields];\n    \n    CGSize pointSizeFitSize = [self.pointSizeInput sizeThatFits:self.bounds.size];\n    self.pointSizeInput.frame = CGRectMake(0, runningOriginY, pointSizeFitSize.width, pointSizeFitSize.height);\n}\n\n+ (CGFloat)verticalPaddingBetweenFields\n{\n    return 10.0;\n}\n\n- (CGSize)sizeThatFits:(CGSize)size\n{\n    CGSize fitSize = [super sizeThatFits:size];\n    \n    CGSize constrainSize = CGSizeMake(size.width, CGFLOAT_MAX);\n    \n    CGFloat height = fitSize.height;\n    height += [self.fontNameInput sizeThatFits:constrainSize].height;\n    height += [[self class] verticalPaddingBetweenFields];\n    height += [self.pointSizeInput sizeThatFits:constrainSize].height;\n    \n    return CGSizeMake(fitSize.width, height);\n}\n\n\n#pragma mark -\n\n+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value\n{\n    BOOL supported = type && strcmp(type, FLEXEncodeClass(UIFont)) == 0;\n    supported = supported || (value && [value isKindOfClass:[UIFont class]]);\n    return supported;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.h",
    "content": "//\n//  FLEXArgumentInputFontsPickerView.h\n//  UICatalog\n//\n//  Created by 啟倫 陳 on 2014/7/27.\n//  Copyright (c) 2014年 f. All rights reserved.\n//\n\n#import \"FLEXArgumentInputTextView.h\"\n\n@interface FLEXArgumentInputFontsPickerView : FLEXArgumentInputTextView <UIPickerViewDataSource, UIPickerViewDelegate>\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m",
    "content": "//\n//  FLEXArgumentInputFontsPickerView.m\n//  UICatalog\n//\n//  Created by 啟倫 陳 on 2014/7/27.\n//  Copyright (c) 2014年 f. All rights reserved.\n//\n\n#import \"FLEXArgumentInputFontsPickerView.h\"\n#import \"FLEXRuntimeUtility.h\"\n\n@interface FLEXArgumentInputFontsPickerView ()\n\n@property (nonatomic, strong) NSMutableArray<NSString *> *availableFonts;\n\n@end\n\n\n@implementation FLEXArgumentInputFontsPickerView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        self.targetSize = FLEXArgumentInputViewSizeSmall;\n        [self createAvailableFonts];\n        self.inputTextView.inputView = [self createFontsPicker];\n    }\n    return self;\n}\n\n- (void)setInputValue:(id)inputValue\n{\n    self.inputTextView.text = inputValue;\n    if ([self.availableFonts indexOfObject:inputValue] == NSNotFound) {\n        [self.availableFonts insertObject:inputValue atIndex:0];\n    }\n    [(UIPickerView *)self.inputTextView.inputView selectRow:[self.availableFonts indexOfObject:inputValue] inComponent:0 animated:NO];\n}\n\n- (id)inputValue\n{\n    return [self.inputTextView.text length] > 0 ? [self.inputTextView.text copy] : nil;\n}\n\n#pragma mark - private\n\n- (UIPickerView*)createFontsPicker\n{\n    UIPickerView *fontsPicker = [UIPickerView new];\n    fontsPicker.dataSource = self;\n    fontsPicker.delegate = self;\n    fontsPicker.showsSelectionIndicator = YES;\n    return fontsPicker;\n}\n\n- (void)createAvailableFonts\n{\n    NSMutableArray<NSString *> *unsortedFontsArray = [NSMutableArray array];\n    for (NSString *eachFontFamily in [UIFont familyNames]) {\n        for (NSString *eachFontName in [UIFont fontNamesForFamilyName:eachFontFamily]) {\n            [unsortedFontsArray addObject:eachFontName];\n        }\n    }\n    self.availableFonts = [NSMutableArray arrayWithArray:[unsortedFontsArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]];\n}\n\n#pragma mark - UIPickerViewDataSource\n\n- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView\n{\n    return 1;\n}\n\n- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component\n{\n    return [self.availableFonts count];\n}\n\n#pragma mark - UIPickerViewDelegate\n\n- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view\n{\n    UILabel *fontLabel;\n    if (!view) {\n        fontLabel = [UILabel new];\n        fontLabel.backgroundColor = [UIColor clearColor];\n        fontLabel.textAlignment = NSTextAlignmentCenter;\n    } else {\n        fontLabel = (UILabel*)view;\n    }\n    UIFont *font = [UIFont fontWithName:self.availableFonts[row] size:15.0];\n    NSDictionary<NSString *, id> *attributesDictionary = [NSDictionary<NSString *, id> dictionaryWithObject:font forKey:NSFontAttributeName];\n    NSAttributedString *attributesString = [[NSAttributedString alloc] initWithString:self.availableFonts[row] attributes:attributesDictionary];\n    fontLabel.attributedText = attributesString;\n    [fontLabel sizeToFit];\n    return fontLabel;\n}\n\n- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component\n{\n    self.inputTextView.text = self.availableFonts[row];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputJSONObjectView.h",
    "content": "//\n//  FLEXArgumentInputJSONObjectView.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/15/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputTextView.h\"\n\n@interface FLEXArgumentInputJSONObjectView : FLEXArgumentInputTextView\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputJSONObjectView.m",
    "content": "//\n//  FLEXArgumentInputJSONObjectView.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/15/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputJSONObjectView.h\"\n#import \"FLEXRuntimeUtility.h\"\n\n@implementation FLEXArgumentInputJSONObjectView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        // Start with the numbers and punctuation keyboard since quotes, curly braces, or\n        // square brackets are likely to be the first characters type for the JSON.\n        self.inputTextView.keyboardType = UIKeyboardTypeNumbersAndPunctuation;\n        self.targetSize = FLEXArgumentInputViewSizeLarge;\n    }\n    return self;\n}\n\n- (void)setInputValue:(id)inputValue\n{\n    self.inputTextView.text = [FLEXRuntimeUtility editableJSONStringForObject:inputValue];\n}\n\n- (id)inputValue\n{\n    return [FLEXRuntimeUtility objectValueFromEditableJSONString:self.inputTextView.text];\n}\n\n+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value\n{\n    // Must be object type.\n    BOOL supported = type && type[0] == '@';\n    \n    if (supported) {\n        if (value) {\n            // If there's a current value, it must be serializable to JSON\n            supported = [FLEXRuntimeUtility editableJSONStringForObject:value] != nil;\n        } else {\n            // Otherwise, see if we have more type information than just 'id'.\n            // If we do, make sure the encoding is something serializable to JSON.\n            // Properties and ivars keep more detailed type encoding information than method arguments.\n            if (strcmp(type, @encode(id)) != 0) {\n                BOOL isJSONSerializableType = NO;\n                // Note: we can't use @encode(NSString) here because that drops the string information and just goes to @encode(id).\n                isJSONSerializableType = isJSONSerializableType || strcmp(type, FLEXEncodeClass(NSString)) == 0;\n                isJSONSerializableType = isJSONSerializableType || strcmp(type, FLEXEncodeClass(NSNumber)) == 0;\n                isJSONSerializableType = isJSONSerializableType || strcmp(type, FLEXEncodeClass(NSArray)) == 0;\n                isJSONSerializableType = isJSONSerializableType || strcmp(type, FLEXEncodeClass(NSDictionary)) == 0;\n                \n                supported = isJSONSerializableType;\n            }\n        }\n    }\n    \n    return supported;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNotSupportedView.h",
    "content": "//\n//  FLEXArgumentInputNotSupportedView.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/18/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputTextView.h\"\n\n@interface FLEXArgumentInputNotSupportedView : FLEXArgumentInputTextView\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNotSupportedView.m",
    "content": "//\n//  FLEXArgumentInputNotSupportedView.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/18/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputNotSupportedView.h\"\n\n@implementation FLEXArgumentInputNotSupportedView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        self.inputTextView.userInteractionEnabled = NO;\n        self.inputTextView.backgroundColor = [UIColor colorWithWhite:0.8 alpha:1.0];\n        self.inputTextView.text = @\"nil\";\n        self.targetSize = FLEXArgumentInputViewSizeSmall;\n    }\n    return self;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.h",
    "content": "//\n//  FLEXArgumentInputNumberView.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/15/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputTextView.h\"\n\n@interface FLEXArgumentInputNumberView : FLEXArgumentInputTextView\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m",
    "content": "//\n//  FLEXArgumentInputNumberView.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/15/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputNumberView.h\"\n#import \"FLEXRuntimeUtility.h\"\n\n@implementation FLEXArgumentInputNumberView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        self.inputTextView.keyboardType = UIKeyboardTypeNumbersAndPunctuation;\n        self.targetSize = FLEXArgumentInputViewSizeSmall;\n    }\n    return self;\n}\n\n- (void)setInputValue:(id)inputValue\n{\n    if ([inputValue respondsToSelector:@selector(stringValue)]) {\n        self.inputTextView.text = [inputValue stringValue];\n    }\n}\n\n- (id)inputValue\n{\n    return [FLEXRuntimeUtility valueForNumberWithObjCType:[self.typeEncoding UTF8String] fromInputString:self.inputTextView.text];\n}\n\n+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value\n{\n    static NSArray<NSString *> *primitiveTypes = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        primitiveTypes = @[@(@encode(char)),\n                           @(@encode(int)),\n                           @(@encode(short)),\n                           @(@encode(long)),\n                           @(@encode(long long)),\n                           @(@encode(unsigned char)),\n                           @(@encode(unsigned int)),\n                           @(@encode(unsigned short)),\n                           @(@encode(unsigned long)),\n                           @(@encode(unsigned long long)),\n                           @(@encode(float)),\n                           @(@encode(double))];\n    });\n    return type && [primitiveTypes containsObject:@(type)];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStringView.h",
    "content": "//\n//  FLEXArgumentInputStringView.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/28/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputTextView.h\"\n\n@interface FLEXArgumentInputStringView : FLEXArgumentInputTextView\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m",
    "content": "//\n//  FLEXArgumentInputStringView.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/28/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputStringView.h\"\n#import \"FLEXRuntimeUtility.h\"\n\n@implementation FLEXArgumentInputStringView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        self.targetSize = FLEXArgumentInputViewSizeLarge;\n    }\n    return self;\n}\n\n- (void)setInputValue:(id)inputValue\n{\n    self.inputTextView.text = inputValue;\n}\n\n- (id)inputValue\n{\n    // Interpret empty string as nil. We loose the ablitiy to set empty string as a string value,\n    // but we accept that tradeoff in exchange for not having to type quotes for every string.\n    return [self.inputTextView.text length] > 0 ? [self.inputTextView.text copy] : nil;\n}\n\n\n#pragma mark -\n\n+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value\n{\n    BOOL supported = type && strcmp(type, FLEXEncodeClass(NSString)) == 0;\n    supported = supported || (value && [value isKindOfClass:[NSString class]]);\n    return supported;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStructView.h",
    "content": "//\n//  FLEXArgumentInputStructView.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputView.h\"\n\n@interface FLEXArgumentInputStructView : FLEXArgumentInputView\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m",
    "content": "//\n//  FLEXArgumentInputStructView.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputStructView.h\"\n#import \"FLEXArgumentInputViewFactory.h\"\n#import \"FLEXRuntimeUtility.h\"\n\n@interface FLEXArgumentInputStructView ()\n\n@property (nonatomic, strong) NSArray<FLEXArgumentInputView *> *argumentInputViews;\n\n@end\n\n@implementation FLEXArgumentInputStructView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        NSMutableArray<FLEXArgumentInputView *> *inputViews = [NSMutableArray array];\n        NSArray<NSString *> *customTitles = [[self class] customFieldTitlesForTypeEncoding:typeEncoding];\n        [FLEXRuntimeUtility enumerateTypesInStructEncoding:typeEncoding usingBlock:^(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset) {\n            \n            FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:fieldTypeEncoding];\n            inputView.backgroundColor = self.backgroundColor;\n            inputView.targetSize = FLEXArgumentInputViewSizeSmall;\n            \n            if (fieldIndex < [customTitles count]) {\n                inputView.title = customTitles[fieldIndex];\n            } else {\n                inputView.title = [NSString stringWithFormat:@\"%@ field %lu (%@)\", structName, (unsigned long)fieldIndex, prettyTypeEncoding];\n            }\n\n            [inputViews addObject:inputView];\n            [self addSubview:inputView];\n        }];\n        self.argumentInputViews = inputViews;\n    }\n    return self;\n}\n\n\n#pragma mark - Superclass Overrides\n\n- (void)setBackgroundColor:(UIColor *)backgroundColor\n{\n    [super setBackgroundColor:backgroundColor];\n    for (FLEXArgumentInputView *inputView in self.argumentInputViews) {\n        inputView.backgroundColor = backgroundColor;\n    }\n}\n\n- (void)setInputValue:(id)inputValue\n{\n    if ([inputValue isKindOfClass:[NSValue class]]) {\n        const char *structTypeEncoding = [inputValue objCType];\n        if (strcmp([self.typeEncoding UTF8String], structTypeEncoding) == 0) {\n            NSUInteger valueSize = 0;\n            @try {\n                // NSGetSizeAndAlignment barfs on type encoding for bitfields.\n                NSGetSizeAndAlignment(structTypeEncoding, &valueSize, NULL);\n            } @catch (NSException *exception) { }\n            \n            if (valueSize > 0) {\n                void *unboxedValue = malloc(valueSize);\n                [inputValue getValue:unboxedValue];\n                [FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset) {\n                    \n                    void *fieldPointer = unboxedValue + fieldOffset;\n                    FLEXArgumentInputView *inputView = self.argumentInputViews[fieldIndex];\n                    \n                    if (fieldTypeEncoding[0] == @encode(id)[0] || fieldTypeEncoding[0] == @encode(Class)[0]) {\n                        inputView.inputValue = (__bridge id)fieldPointer;\n                    } else {\n                        NSValue *boxedField = [FLEXRuntimeUtility valueForPrimitivePointer:fieldPointer objCType:fieldTypeEncoding];\n                        inputView.inputValue = boxedField;\n                    }\n                }];\n                free(unboxedValue);\n            }\n        }\n    }\n}\n\n- (id)inputValue\n{\n    NSValue *boxedStruct = nil;\n    const char *structTypeEncoding = [self.typeEncoding UTF8String];\n    NSUInteger structSize = 0;\n    @try {\n        // NSGetSizeAndAlignment barfs on type encoding for bitfields.\n        NSGetSizeAndAlignment(structTypeEncoding, &structSize, NULL);\n    } @catch (NSException *exception) { }\n    \n    if (structSize > 0) {\n        void *unboxedStruct = malloc(structSize);\n        [FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset) {\n            \n            void *fieldPointer = unboxedStruct + fieldOffset;\n            FLEXArgumentInputView *inputView = self.argumentInputViews[fieldIndex];\n            \n            if (fieldTypeEncoding[0] == @encode(id)[0] || fieldTypeEncoding[0] == @encode(Class)[0]) {\n                // Object fields\n                memcpy(fieldPointer, (__bridge void *)inputView.inputValue, sizeof(id));\n            } else {\n                // Boxed primitive/struct fields\n                id inputValue = inputView.inputValue;\n                if ([inputValue isKindOfClass:[NSValue class]] && strcmp([inputValue objCType], fieldTypeEncoding) == 0) {\n                    [inputValue getValue:fieldPointer];\n                }\n            }\n        }];\n        \n        boxedStruct = [NSValue value:unboxedStruct withObjCType:structTypeEncoding];\n        free(unboxedStruct);\n    }\n    \n    return boxedStruct;\n}\n\n- (BOOL)inputViewIsFirstResponder\n{\n    BOOL isFirstResponder = NO;\n    for (FLEXArgumentInputView *inputView in self.argumentInputViews) {\n        if ([inputView inputViewIsFirstResponder]) {\n            isFirstResponder = YES;\n            break;\n        }\n    }\n    return isFirstResponder;\n}\n\n\n#pragma mark - Layout and Sizing\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    \n    CGFloat runningOriginY = self.topInputFieldVerticalLayoutGuide;\n    \n    for (FLEXArgumentInputView *inputView in self.argumentInputViews) {\n        CGSize inputFitSize = [inputView sizeThatFits:self.bounds.size];\n        inputView.frame = CGRectMake(0, runningOriginY, inputFitSize.width, inputFitSize.height);\n        runningOriginY = CGRectGetMaxY(inputView.frame) + [[self class] verticalPaddingBetweenFields];\n    }\n}\n\n+ (CGFloat)verticalPaddingBetweenFields\n{\n    return 10.0;\n}\n\n- (CGSize)sizeThatFits:(CGSize)size\n{\n    CGSize fitSize = [super sizeThatFits:size];\n    \n    CGSize constrainSize = CGSizeMake(size.width, CGFLOAT_MAX);\n    CGFloat height = fitSize.height;\n    \n    for (FLEXArgumentInputView *inputView in self.argumentInputViews) {\n        height += [inputView sizeThatFits:constrainSize].height;\n        height += [[self class] verticalPaddingBetweenFields];\n    }\n    \n    return CGSizeMake(fitSize.width, height);\n}\n\n\n#pragma mark - Class Helpers\n\n+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value\n{\n    return type && type[0] == '{';\n}\n\n+ (NSArray<NSString *> *)customFieldTitlesForTypeEncoding:(const char *)typeEncoding\n{\n    NSArray<NSString *> *customTitles = nil;\n    if (strcmp(typeEncoding, @encode(CGRect)) == 0) {\n        customTitles = @[@\"CGPoint origin\", @\"CGSize size\"];\n    } else if (strcmp(typeEncoding, @encode(CGPoint)) == 0) {\n        customTitles = @[@\"CGFloat x\", @\"CGFloat y\"];\n    } else if (strcmp(typeEncoding, @encode(CGSize)) == 0) {\n        customTitles = @[@\"CGFloat width\", @\"CGFloat height\"];\n    } else if (strcmp(typeEncoding, @encode(UIEdgeInsets)) == 0) {\n        customTitles = @[@\"CGFloat top\", @\"CGFloat left\", @\"CGFloat bottom\", @\"CGFloat right\"];\n    } else if (strcmp(typeEncoding, @encode(UIOffset)) == 0) {\n        customTitles = @[@\"CGFloat horizontal\", @\"CGFloat vertical\"];\n    } else if (strcmp(typeEncoding, @encode(NSRange)) == 0) {\n        customTitles = @[@\"NSUInteger location\", @\"NSUInteger length\"];\n    } else if (strcmp(typeEncoding, @encode(CATransform3D)) == 0) {\n        customTitles = @[@\"CGFloat m11\", @\"CGFloat m12\", @\"CGFloat m13\", @\"CGFloat m14\",\n                         @\"CGFloat m21\", @\"CGFloat m22\", @\"CGFloat m23\", @\"CGFloat m24\",\n                         @\"CGFloat m31\", @\"CGFloat m32\", @\"CGFloat m33\", @\"CGFloat m34\",\n                         @\"CGFloat m41\", @\"CGFloat m42\", @\"CGFloat m43\", @\"CGFloat m44\"];\n    } else if (strcmp(typeEncoding, @encode(CGAffineTransform)) == 0) {\n        customTitles = @[@\"CGFloat a\", @\"CGFloat b\",\n                         @\"CGFloat c\", @\"CGFloat d\",\n                         @\"CGFloat tx\", @\"CGFloat ty\"];\n    }\n    return customTitles;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.h",
    "content": "//\n//  FLEXArgumentInputSwitchView.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputView.h\"\n\n@interface FLEXArgumentInputSwitchView : FLEXArgumentInputView\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m",
    "content": "//\n//  FLEXArgumentInputSwitchView.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputSwitchView.h\"\n\n@interface FLEXArgumentInputSwitchView ()\n\n@property (nonatomic, strong) UISwitch *inputSwitch;\n\n@end\n\n@implementation FLEXArgumentInputSwitchView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        self.inputSwitch = [[UISwitch alloc] init];\n        [self.inputSwitch addTarget:self action:@selector(switchValueDidChange:) forControlEvents:UIControlEventValueChanged];\n        [self.inputSwitch sizeToFit];\n        [self addSubview:self.inputSwitch];\n    }\n    return self;\n}\n\n\n#pragma mark Input/Output\n\n- (void)setInputValue:(id)inputValue\n{\n    BOOL on = NO;\n    if ([inputValue isKindOfClass:[NSNumber class]]) {\n        NSNumber *number = (NSNumber *)inputValue;\n        on = [number boolValue];\n    } else if ([inputValue isKindOfClass:[NSValue class]]) {\n        NSValue *value = (NSValue *)inputValue;\n        if (strcmp([value objCType], @encode(BOOL)) == 0) {\n            [value getValue:&on];\n        }\n    }\n    self.inputSwitch.on = on;\n}\n\n- (id)inputValue\n{\n    BOOL isOn = [self.inputSwitch isOn];\n    NSValue *boxedBool = [NSValue value:&isOn withObjCType:@encode(BOOL)];\n    return boxedBool;\n}\n\n- (void)switchValueDidChange:(id)sender\n{\n    [self.delegate argumentInputViewValueDidChange:self];\n}\n\n\n#pragma mark - Layout and Sizing\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    \n    self.inputSwitch.frame = CGRectMake(0, self.topInputFieldVerticalLayoutGuide, self.inputSwitch.frame.size.width, self.inputSwitch.frame.size.height);\n}\n\n- (CGSize)sizeThatFits:(CGSize)size\n{\n    CGSize fitSize = [super sizeThatFits:size];\n    fitSize.height += self.inputSwitch.frame.size.height;\n    return fitSize;\n}\n\n\n#pragma mark - Class Helpers\n\n+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value\n{\n    // Only BOOLs. Current value is irrelevant.\n    return type && strcmp(type, @encode(BOOL)) == 0;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h",
    "content": "//\n//  FLEXArgumentInputTextView.h\n//  FLEXInjected\n//\n//  Created by Ryan Olson on 6/15/14.\n//\n//\n\n#import \"FLEXArgumentInputView.h\"\n\n@interface FLEXArgumentInputTextView : FLEXArgumentInputView\n\n// For subclass eyes only\n\n@property (nonatomic, strong, readonly) UITextView *inputTextView;\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputTextView.m",
    "content": "//\n//  FLEXArgumentInputTextView.m\n//  FLEXInjected\n//\n//  Created by Ryan Olson on 6/15/14.\n//\n//\n\n#import \"FLEXArgumentInputTextView.h\"\n#import \"FLEXUtility.h\"\n\n@interface FLEXArgumentInputTextView () <UITextViewDelegate>\n\n@property (nonatomic, strong) UITextView *inputTextView;\n@property (nonatomic, readonly) NSUInteger numberOfInputLines;\n\n@end\n\n@implementation FLEXArgumentInputTextView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithArgumentTypeEncoding:typeEncoding];\n    if (self) {\n        self.inputTextView = [[UITextView alloc] init];\n        self.inputTextView.font = [[self class] inputFont];\n        self.inputTextView.backgroundColor = [UIColor whiteColor];\n        self.inputTextView.layer.borderColor = [[UIColor blackColor] CGColor];\n        self.inputTextView.layer.borderWidth = 1.0;\n        self.inputTextView.autocapitalizationType = UITextAutocapitalizationTypeNone;\n        self.inputTextView.autocorrectionType = UITextAutocorrectionTypeNo;\n        self.inputTextView.delegate = self;\n        self.inputTextView.inputAccessoryView = [self createToolBar];\n        [self addSubview:self.inputTextView];\n    }\n    return self;\n}\n\n#pragma mark - private\n\n- (UIToolbar*)createToolBar\n{\n    UIToolbar *toolBar = [UIToolbar new];\n    [toolBar sizeToFit];\n    UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];\n    UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(textViewDone)];\n    toolBar.items = @[spaceItem, doneItem];\n    return toolBar;\n}\n\n- (void)textViewDone\n{\n    [self.inputTextView resignFirstResponder];\n}\n\n\n#pragma mark - Text View Changes\n\n- (void)textViewDidChange:(UITextView *)textView\n{\n    [self.delegate argumentInputViewValueDidChange:self];\n}\n\n\n#pragma mark - Superclass Overrides\n\n- (BOOL)inputViewIsFirstResponder\n{\n    return self.inputTextView.isFirstResponder;\n}\n\n\n#pragma mark - Layout and Sizing\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    \n    self.inputTextView.frame = CGRectMake(0, self.topInputFieldVerticalLayoutGuide, self.bounds.size.width, [self inputTextViewHeight]);\n}\n\n- (NSUInteger)numberOfInputLines\n{\n    NSUInteger numberOfInputLines = 0;\n    switch (self.targetSize) {\n        case FLEXArgumentInputViewSizeDefault:\n            numberOfInputLines = 2;\n            break;\n            \n        case FLEXArgumentInputViewSizeSmall:\n            numberOfInputLines = 1;\n            break;\n            \n        case FLEXArgumentInputViewSizeLarge:\n            numberOfInputLines = 8;\n            break;\n    }\n    return numberOfInputLines;\n}\n\n- (CGFloat)inputTextViewHeight\n{\n    return ceil([[self class] inputFont].lineHeight * self.numberOfInputLines) + 16.0;\n}\n\n- (CGSize)sizeThatFits:(CGSize)size\n{\n    CGSize fitSize = [super sizeThatFits:size];\n    fitSize.height += [self inputTextViewHeight];\n    return fitSize;\n}\n\n\n#pragma mark - Class Helpers\n\n+ (UIFont *)inputFont\n{\n    return [FLEXUtility defaultFontOfSize:14.0];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputView.h",
    "content": "//\n//  FLEXArgumentInputView.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/30/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\ntypedef NS_ENUM(NSUInteger, FLEXArgumentInputViewSize) {\n    FLEXArgumentInputViewSizeDefault = 0,\n    FLEXArgumentInputViewSizeSmall,\n    FLEXArgumentInputViewSizeLarge\n};\n\n@protocol FLEXArgumentInputViewDelegate;\n\n@interface FLEXArgumentInputView : UIView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding;\n\n/// The name of the field. Optional (can be nil).\n@property (nonatomic, copy) NSString *title;\n\n/// To populate the filed with an initial value, set this property.\n/// To reteive the value input by the user, access the property.\n/// Primitive types and structs should/will be boxed in NSValue containers.\n/// Concrete subclasses *must* override both the setter and getter for this property.\n@property (nonatomic) id inputValue;\n\n/// Setting this value to large will make some argument input views increase the size of their input field(s).\n/// Useful to increase the use of space if there is only one input view on screen (i.e. for property and ivar editing).\n@property (nonatomic, assign) FLEXArgumentInputViewSize targetSize;\n\n/// Users of the input view can get delegate callbacks for incremental changes in user input.\n@property (nonatomic, weak) id <FLEXArgumentInputViewDelegate> delegate;\n\n// Subclasses can override\n\n/// If the input view has one or more text views, returns YES when one of them is focused.\n@property (nonatomic, readonly) BOOL inputViewIsFirstResponder;\n\n/// For subclasses to indicate that they can handle editing a field the give type and value.\n/// Used by FLEXArgumentInputViewFactory to create appropriate input views.\n+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value;\n\n// For subclass eyes only\n\n@property (nonatomic, strong, readonly) UILabel *titleLabel;\n@property (nonatomic, strong, readonly) NSString *typeEncoding;\n@property (nonatomic, readonly) CGFloat topInputFieldVerticalLayoutGuide;\n\n@end\n\n@protocol FLEXArgumentInputViewDelegate <NSObject>\n\n- (void)argumentInputViewValueDidChange:(FLEXArgumentInputView *)argumentInputView;\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputView.m",
    "content": "//\n//  FLEXArgumentInputView.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/30/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArgumentInputView.h\"\n#import \"FLEXUtility.h\"\n\n@interface FLEXArgumentInputView ()\n\n@property (nonatomic, strong) UILabel *titleLabel;\n@property (nonatomic, strong) NSString *typeEncoding;\n\n@end\n\n@implementation FLEXArgumentInputView\n\n- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding\n{\n    self = [super initWithFrame:CGRectZero];\n    if (self) {\n        self.typeEncoding = typeEncoding != NULL ? @(typeEncoding) : nil;\n    }\n    return self;\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    \n    if (self.showsTitle) {\n        CGSize constrainSize = CGSizeMake(self.bounds.size.width, CGFLOAT_MAX);\n        CGSize labelSize = [self.titleLabel sizeThatFits:constrainSize];\n        self.titleLabel.frame = CGRectMake(0, 0, labelSize.width, labelSize.height);\n    }\n}\n\n- (void)setBackgroundColor:(UIColor *)backgroundColor\n{\n    [super setBackgroundColor:backgroundColor];\n    self.titleLabel.backgroundColor = backgroundColor;\n}\n\n- (void)setTitle:(NSString *)title\n{\n    if (![_title isEqual:title]) {\n        _title = title;\n        self.titleLabel.text = title;\n        [self setNeedsLayout];\n    }\n}\n\n- (UILabel *)titleLabel\n{\n    if (!_titleLabel) {\n        _titleLabel = [[UILabel alloc] init];\n        _titleLabel.font = [[self class] titleFont];\n        _titleLabel.backgroundColor = self.backgroundColor;\n        _titleLabel.textColor = [UIColor colorWithWhite:0.3 alpha:1.0];\n        _titleLabel.numberOfLines = 0;\n        [self addSubview:_titleLabel];\n    }\n    return _titleLabel;\n}\n\n- (BOOL)showsTitle\n{\n    return [self.title length] > 0;\n}\n\n- (CGFloat)topInputFieldVerticalLayoutGuide\n{\n    CGFloat verticalLayoutGuide = 0;\n    if (self.showsTitle) {\n        CGFloat titleHeight = [self.titleLabel sizeThatFits:self.bounds.size].height;\n        verticalLayoutGuide = titleHeight + [[self class] titleBottomPadding];\n    }\n    return verticalLayoutGuide;\n}\n\n\n#pragma mark - Subclasses Can Override\n\n- (BOOL)inputViewIsFirstResponder\n{\n    return NO;\n}\n\n- (void)setInputValue:(id)inputValue\n{\n    // Subclasses should override.\n}\n\n- (id)inputValue\n{\n    // Subclasses should override.\n    return nil;\n}\n\n+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value\n{\n    return NO;\n}\n\n\n#pragma mark - Class Helpers\n\n+ (UIFont *)titleFont\n{\n    return [FLEXUtility defaultFontOfSize:12.0];\n}\n\n+ (CGFloat)titleBottomPadding\n{\n    return 4.0;\n}\n\n\n#pragma mark - Sizing\n\n- (CGSize)sizeThatFits:(CGSize)size\n{\n    CGFloat height = 0;\n    \n    if ([self.title length] > 0) {\n        CGSize constrainSize = CGSizeMake(size.width, CGFLOAT_MAX);\n        height += ceil([self.titleLabel sizeThatFits:constrainSize].height);\n        height += [[self class] titleBottomPadding];\n    }\n    \n    return CGSizeMake(size.width, height);\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputViewFactory.h",
    "content": "//\n//  FLEXArgumentInputViewFactory.h\n//  FLEXInjected\n//\n//  Created by Ryan Olson on 6/15/14.\n//\n//\n\n#import <Foundation/Foundation.h>\n\n@class FLEXArgumentInputView;\n\n@interface FLEXArgumentInputViewFactory : NSObject\n\n/// Forwards to argumentInputViewForTypeEncoding:currentValue: with a nil currentValue.\n+ (FLEXArgumentInputView *)argumentInputViewForTypeEncoding:(const char *)typeEncoding;\n\n/// The main factory method for making argument input view subclasses that are the best fit for the type.\n+ (FLEXArgumentInputView *)argumentInputViewForTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue;\n\n/// A way to check if we should try editing a filed given its type encoding and value.\n/// Useful when deciding whether to edit or explore a property, ivar, or NSUserDefaults value.\n+ (BOOL)canEditFieldWithTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue;\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/ArgumentInputViews/FLEXArgumentInputViewFactory.m",
    "content": "//\n//  FLEXArgumentInputViewFactory.m\n//  FLEXInjected\n//\n//  Created by Ryan Olson on 6/15/14.\n//\n//\n\n#import \"FLEXArgumentInputViewFactory.h\"\n#import \"FLEXArgumentInputView.h\"\n#import \"FLEXArgumentInputJSONObjectView.h\"\n#import \"FLEXArgumentInputNumberView.h\"\n#import \"FLEXArgumentInputSwitchView.h\"\n#import \"FLEXArgumentInputStructView.h\"\n#import \"FLEXArgumentInputNotSupportedView.h\"\n#import \"FLEXArgumentInputStringView.h\"\n#import \"FLEXArgumentInputFontView.h\"\n#import \"FLEXArgumentInputColorView.h\"\n#import \"FLEXArgumentInputDateView.h\"\n\n@implementation FLEXArgumentInputViewFactory\n\n+ (FLEXArgumentInputView *)argumentInputViewForTypeEncoding:(const char *)typeEncoding\n{\n    return [self argumentInputViewForTypeEncoding:typeEncoding currentValue:nil];\n}\n\n+ (FLEXArgumentInputView *)argumentInputViewForTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue\n{\n    Class subclass = [self argumentInputViewSubclassForTypeEncoding:typeEncoding currentValue:currentValue];\n    if (!subclass) {\n        // Fall back to a FLEXArgumentInputNotSupportedView if we can't find a subclass that fits the type encoding.\n        // The unsupported view shows \"nil\" and does not allow user input.\n        subclass = [FLEXArgumentInputNotSupportedView class];\n    }\n    return [[subclass alloc] initWithArgumentTypeEncoding:typeEncoding];\n}\n\n+ (Class)argumentInputViewSubclassForTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue\n{\n    Class argumentInputViewSubclass = nil;\n    \n    // Note that order is important here since multiple subclasses may support the same type.\n    // An example is the number subclass and the bool subclass for the type @encode(BOOL).\n    // Both work, but we'd prefer to use the bool subclass.\n    if ([FLEXArgumentInputColorView supportsObjCType:typeEncoding withCurrentValue:currentValue]) {\n        argumentInputViewSubclass = [FLEXArgumentInputColorView class];\n    } else if ([FLEXArgumentInputFontView supportsObjCType:typeEncoding withCurrentValue:currentValue]) {\n        argumentInputViewSubclass = [FLEXArgumentInputFontView class];\n    } else if ([FLEXArgumentInputStringView supportsObjCType:typeEncoding withCurrentValue:currentValue]) {\n        argumentInputViewSubclass = [FLEXArgumentInputStringView class];\n    } else if ([FLEXArgumentInputStructView supportsObjCType:typeEncoding withCurrentValue:currentValue]) {\n        argumentInputViewSubclass = [FLEXArgumentInputStructView class];\n    } else if ([FLEXArgumentInputSwitchView supportsObjCType:typeEncoding withCurrentValue:currentValue]) {\n        argumentInputViewSubclass = [FLEXArgumentInputSwitchView class];\n    } else if ([FLEXArgumentInputDateView supportsObjCType:typeEncoding withCurrentValue:currentValue]) {\n        argumentInputViewSubclass = [FLEXArgumentInputDateView class];\n    } else if ([FLEXArgumentInputNumberView supportsObjCType:typeEncoding withCurrentValue:currentValue]) {\n        argumentInputViewSubclass = [FLEXArgumentInputNumberView class];\n    } else if ([FLEXArgumentInputJSONObjectView supportsObjCType:typeEncoding withCurrentValue:currentValue]) {\n        argumentInputViewSubclass = [FLEXArgumentInputJSONObjectView class];\n    }\n    \n    return argumentInputViewSubclass;\n}\n\n+ (BOOL)canEditFieldWithTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue\n{\n    return [self argumentInputViewSubclassForTypeEncoding:typeEncoding currentValue:currentValue] != nil;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXDefaultEditorViewController.h",
    "content": "//\n//  FLEXDefaultEditorViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/23/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXFieldEditorViewController.h\"\n\n@interface FLEXDefaultEditorViewController : FLEXFieldEditorViewController\n\n- (id)initWithDefaults:(NSUserDefaults *)defaults key:(NSString *)key;\n\n+ (BOOL)canEditDefaultWithValue:(id)currentValue;\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXDefaultEditorViewController.m",
    "content": "//\n//  FLEXDefaultEditorViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/23/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXDefaultEditorViewController.h\"\n#import \"FLEXFieldEditorView.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXArgumentInputView.h\"\n#import \"FLEXArgumentInputViewFactory.h\"\n\n@interface FLEXDefaultEditorViewController ()\n\n@property (nonatomic, readonly) NSUserDefaults *defaults;\n@property (nonatomic, strong) NSString *key;\n\n@end\n\n@implementation FLEXDefaultEditorViewController\n\n- (id)initWithDefaults:(NSUserDefaults *)defaults key:(NSString *)key\n{\n    self = [super initWithTarget:defaults];\n    if (self) {\n        self.key = key;\n        self.title = @\"Edit Default\";\n    }\n    return self;\n}\n\n- (NSUserDefaults *)defaults\n{\n    return [self.target isKindOfClass:[NSUserDefaults class]] ? self.target : nil;\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.fieldEditorView.fieldDescription = self.key;\n\n    id currentValue = [self.defaults objectForKey:self.key];\n    FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:@encode(id) currentValue:currentValue];\n    inputView.backgroundColor = self.view.backgroundColor;\n    inputView.inputValue = currentValue;\n    self.fieldEditorView.argumentInputViews = @[inputView];\n}\n\n- (void)actionButtonPressed:(id)sender\n{\n    [super actionButtonPressed:sender];\n    \n    id value = self.firstInputView.inputValue;\n    if (value) {\n        [self.defaults setObject:value forKey:self.key];\n    } else {\n        [self.defaults removeObjectForKey:self.key];\n    }\n    [self.defaults synchronize];\n\n    self.firstInputView.inputValue = [self.defaults objectForKey:self.key];\n}\n\n+ (BOOL)canEditDefaultWithValue:(id)currentValue\n{\n    return [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:@encode(id) currentValue:currentValue];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXFieldEditorView.h",
    "content": "//\n//  FLEXFieldEditorView.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@class FLEXArgumentInputView;\n\n@interface FLEXFieldEditorView : UIView\n\n@property (nonatomic, copy) NSString *targetDescription;\n@property (nonatomic, copy) NSString *fieldDescription;\n\n@property (nonatomic, strong) NSArray<FLEXArgumentInputView *> *argumentInputViews;\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXFieldEditorView.m",
    "content": "//\n//  FLEXFieldEditorView.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXFieldEditorView.h\"\n#import \"FLEXArgumentInputView.h\"\n#import \"FLEXUtility.h\"\n\n@interface FLEXFieldEditorView ()\n\n@property (nonatomic, strong) UILabel *targetDescriptionLabel;\n@property (nonatomic, strong) UIView *targetDescriptionDivider;\n@property (nonatomic, strong) UILabel *fieldDescriptionLabel;\n@property (nonatomic, strong) UIView *fieldDescriptionDivider;\n\n@end\n\n@implementation FLEXFieldEditorView\n\n- (id)initWithFrame:(CGRect)frame\n{\n    self = [super initWithFrame:frame];\n    if (self) {\n        self.targetDescriptionLabel = [[UILabel alloc] init];\n        self.targetDescriptionLabel.numberOfLines = 0;\n        self.targetDescriptionLabel.font = [[self class] labelFont];\n        [self addSubview:self.targetDescriptionLabel];\n        \n        self.targetDescriptionDivider = [[self class] dividerView];\n        [self addSubview:self.targetDescriptionDivider];\n        \n        self.fieldDescriptionLabel = [[UILabel alloc] init];\n        self.fieldDescriptionLabel.numberOfLines = 0;\n        self.fieldDescriptionLabel.font = [[self class] labelFont];\n        [self addSubview:self.fieldDescriptionLabel];\n        \n        self.fieldDescriptionDivider = [[self class] dividerView];\n        [self addSubview:self.fieldDescriptionDivider];\n    }\n    return self;\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    \n    CGFloat horizontalPadding = [[self class] horizontalPadding];\n    CGFloat verticalPadding = [[self class] verticalPadding];\n    CGFloat dividerLineHeight = [[self class] dividerLineHeight];\n    \n    CGFloat originY = verticalPadding;\n    CGFloat originX = horizontalPadding;\n    CGFloat contentWidth = self.bounds.size.width - 2.0 * horizontalPadding;\n    CGSize constrainSize = CGSizeMake(contentWidth, CGFLOAT_MAX);\n    \n    CGSize instanceDescriptionSize = [self.targetDescriptionLabel sizeThatFits:constrainSize];\n    self.targetDescriptionLabel.frame = CGRectMake(originX, originY, instanceDescriptionSize.width, instanceDescriptionSize.height);\n    originY = CGRectGetMaxY(self.targetDescriptionLabel.frame) + verticalPadding;\n    \n    self.targetDescriptionDivider.frame = CGRectMake(originX, originY, contentWidth, dividerLineHeight);\n    originY = CGRectGetMaxY(self.targetDescriptionDivider.frame) + verticalPadding;\n    \n    CGSize fieldDescriptionSize = [self.fieldDescriptionLabel sizeThatFits:constrainSize];\n    self.fieldDescriptionLabel.frame = CGRectMake(originX, originY, fieldDescriptionSize.width, fieldDescriptionSize.height);\n    originY = CGRectGetMaxY(self.fieldDescriptionLabel.frame) + verticalPadding;\n    \n    self.fieldDescriptionDivider.frame = CGRectMake(originX, originY, contentWidth, dividerLineHeight);\n    originY = CGRectGetMaxY(self.fieldDescriptionDivider.frame) + verticalPadding;\n\n    for (UIView *argumentInputView in self.argumentInputViews) {\n        CGSize inputViewSize = [argumentInputView sizeThatFits:constrainSize];\n        argumentInputView.frame = CGRectMake(originX, originY, inputViewSize.width, inputViewSize.height);\n        originY = CGRectGetMaxY(argumentInputView.frame) + verticalPadding;\n    }\n}\n\n- (void)setBackgroundColor:(UIColor *)backgroundColor\n{\n    [super setBackgroundColor:backgroundColor];\n    self.targetDescriptionLabel.backgroundColor = backgroundColor;\n    self.fieldDescriptionLabel.backgroundColor = backgroundColor;\n}\n\n- (void)setTargetDescription:(NSString *)targetDescription\n{\n    if (![_targetDescription isEqual:targetDescription]) {\n        _targetDescription = targetDescription;\n        self.targetDescriptionLabel.text = targetDescription;\n        [self setNeedsLayout];\n    }\n}\n\n- (void)setFieldDescription:(NSString *)fieldDescription\n{\n    if (![_fieldDescription isEqual:fieldDescription]) {\n        _fieldDescription = fieldDescription;\n        self.fieldDescriptionLabel.text = fieldDescription;\n        [self setNeedsLayout];\n    }\n}\n\n- (void)setArgumentInputViews:(NSArray<FLEXArgumentInputView *> *)argumentInputViews\n{\n    if (![_argumentInputViews isEqual:argumentInputViews]) {\n        \n        for (FLEXArgumentInputView *inputView in _argumentInputViews) {\n            [inputView removeFromSuperview];\n        }\n        \n        _argumentInputViews = argumentInputViews;\n        \n        for (FLEXArgumentInputView *newInputView in argumentInputViews) {\n            [self addSubview:newInputView];\n        }\n        \n        [self setNeedsLayout];\n    }\n}\n\n+ (UIView *)dividerView\n{\n    UIView *dividerView = [[UIView alloc] init];\n    dividerView.backgroundColor = [self dividerColor];\n    return dividerView;\n}\n\n+ (UIColor *)dividerColor\n{\n    return [UIColor lightGrayColor];\n}\n\n+ (CGFloat)horizontalPadding\n{\n    return 10.0;\n}\n\n+ (CGFloat)verticalPadding\n{\n    return 20.0;\n}\n\n+ (UIFont *)labelFont\n{\n    return [FLEXUtility defaultFontOfSize:14.0];\n}\n\n+ (CGFloat)dividerLineHeight\n{\n    return 1.0;\n}\n\n- (CGSize)sizeThatFits:(CGSize)size\n{\n    CGFloat horizontalPadding = [[self class] horizontalPadding];\n    CGFloat verticalPadding = [[self class] verticalPadding];\n    CGFloat dividerLineHeight = [[self class] dividerLineHeight];\n    \n    CGFloat height = 0;\n    CGFloat availableWidth = size.width - 2.0 * horizontalPadding;\n    CGSize constrainSize = CGSizeMake(availableWidth, CGFLOAT_MAX);\n    \n    height += verticalPadding;\n    height += ceil([self.targetDescriptionLabel sizeThatFits:constrainSize].height);\n    height += verticalPadding;\n    height += dividerLineHeight;\n    height += verticalPadding;\n    height += ceil([self.fieldDescriptionLabel sizeThatFits:constrainSize].height);\n    height += verticalPadding;\n    height += dividerLineHeight;\n    height += verticalPadding;\n    \n    for (FLEXArgumentInputView *inputView in self.argumentInputViews) {\n        height += [inputView sizeThatFits:constrainSize].height;\n        height += verticalPadding;\n    }\n    \n    return CGSizeMake(size.width, height);\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXFieldEditorViewController.h",
    "content": "//\n//  FLEXFieldEditorViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@class FLEXFieldEditorView;\n@class FLEXArgumentInputView;\n\n@interface FLEXFieldEditorViewController : UIViewController\n\n- (id)initWithTarget:(id)target;\n\n// Convenience accessor since many subclasses only use one input view\n@property (nonatomic, readonly) FLEXArgumentInputView *firstInputView;\n\n// For subclass use only.\n@property (nonatomic, strong, readonly) id target;\n@property (nonatomic, strong, readonly) FLEXFieldEditorView *fieldEditorView;\n@property (nonatomic, strong, readonly) UIBarButtonItem *setterButton;\n- (void)actionButtonPressed:(id)sender;\n- (NSString *)titleForActionButton;\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXFieldEditorViewController.m",
    "content": "//\n//  FLEXFieldEditorViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXFieldEditorViewController.h\"\n#import \"FLEXFieldEditorView.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXArgumentInputView.h\"\n#import \"FLEXArgumentInputViewFactory.h\"\n\n@interface FLEXFieldEditorViewController () <UIScrollViewDelegate>\n\n@property (nonatomic, strong) UIScrollView *scrollView;\n\n@property (nonatomic, strong, readwrite) id target;\n@property (nonatomic, strong, readwrite) FLEXFieldEditorView *fieldEditorView;\n@property (nonatomic, strong, readwrite) UIBarButtonItem *setterButton;\n\n@end\n\n@implementation FLEXFieldEditorViewController\n\n- (id)initWithTarget:(id)target\n{\n    self = [super initWithNibName:nil bundle:nil];\n    if (self) {\n        self.target = target;\n        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];\n        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];\n    }\n    return self;\n}\n\n- (void)dealloc\n{\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n- (void)keyboardDidShow:(NSNotification *)notification\n{\n    CGRect keyboardRectInWindow = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];\n    CGSize keyboardSize = [self.view convertRect:keyboardRectInWindow fromView:nil].size;\n    UIEdgeInsets scrollInsets = self.scrollView.contentInset;\n    scrollInsets.bottom = keyboardSize.height;\n    self.scrollView.contentInset = scrollInsets;\n    self.scrollView.scrollIndicatorInsets = scrollInsets;\n    \n    // Find the active input view and scroll to make sure it's visible.\n    for (FLEXArgumentInputView *argumentInputView in self.fieldEditorView.argumentInputViews) {\n        if (argumentInputView.inputViewIsFirstResponder) {\n            CGRect scrollToVisibleRect = [self.scrollView convertRect:argumentInputView.bounds fromView:argumentInputView];\n            [self.scrollView scrollRectToVisible:scrollToVisibleRect animated:YES];\n            break;\n        }\n    }\n}\n\n- (void)keyboardWillHide:(NSNotification *)notification\n{\n    UIEdgeInsets scrollInsets = self.scrollView.contentInset;\n    scrollInsets.bottom = 0.0;\n    self.scrollView.contentInset = scrollInsets;\n    self.scrollView.scrollIndicatorInsets = scrollInsets;\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.view.backgroundColor = [FLEXUtility scrollViewGrayColor];\n    \n    self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];\n    self.scrollView.backgroundColor = self.view.backgroundColor;\n    self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    self.scrollView.delegate = self;\n    [self.view addSubview:self.scrollView];\n    \n    self.fieldEditorView = [[FLEXFieldEditorView alloc] init];\n    self.fieldEditorView.backgroundColor = self.view.backgroundColor;\n    self.fieldEditorView.targetDescription = [NSString stringWithFormat:@\"%@ %p\", [self.target class], self.target];\n    [self.scrollView addSubview:self.fieldEditorView];\n    \n    self.setterButton = [[UIBarButtonItem alloc] initWithTitle:[self titleForActionButton] style:UIBarButtonItemStyleDone target:self action:@selector(actionButtonPressed:)];\n    self.navigationItem.rightBarButtonItem = self.setterButton;\n}\n\n- (void)viewWillLayoutSubviews\n{\n    CGSize constrainSize = CGSizeMake(self.scrollView.bounds.size.width, CGFLOAT_MAX);\n    CGSize fieldEditorSize = [self.fieldEditorView sizeThatFits:constrainSize];\n    self.fieldEditorView.frame = CGRectMake(0, 0, fieldEditorSize.width, fieldEditorSize.height);\n    self.scrollView.contentSize = fieldEditorSize;\n}\n\n- (FLEXArgumentInputView *)firstInputView\n{\n    return [[self.fieldEditorView argumentInputViews] firstObject];\n}\n\n- (void)actionButtonPressed:(id)sender\n{\n    // Subclasses can override\n    [self.fieldEditorView endEditing:YES];\n}\n\n- (NSString *)titleForActionButton\n{\n    // Subclasses can override.\n    return @\"Set\";\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXIvarEditorViewController.h",
    "content": "//\n//  FLEXIvarEditorViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/23/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXFieldEditorViewController.h\"\n#import <objc/runtime.h>\n\n@interface FLEXIvarEditorViewController : FLEXFieldEditorViewController\n\n- (id)initWithTarget:(id)target ivar:(Ivar)ivar;\n\n+ (BOOL)canEditIvar:(Ivar)ivar currentValue:(id)value;\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXIvarEditorViewController.m",
    "content": "//\n//  FLEXIvarEditorViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/23/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXIvarEditorViewController.h\"\n#import \"FLEXFieldEditorView.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXArgumentInputView.h\"\n#import \"FLEXArgumentInputViewFactory.h\"\n#import \"FLEXArgumentInputSwitchView.h\"\n\n@interface FLEXIvarEditorViewController () <FLEXArgumentInputViewDelegate>\n\n@property (nonatomic, assign) Ivar ivar;\n\n@end\n\n@implementation FLEXIvarEditorViewController\n\n- (id)initWithTarget:(id)target ivar:(Ivar)ivar\n{\n    self = [super initWithTarget:target];\n    if (self) {\n        self.ivar = ivar;\n        self.title = @\"Instance Variable\";\n    }\n    return self;\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.fieldEditorView.fieldDescription = [FLEXRuntimeUtility prettyNameForIvar:self.ivar];\n    \n    FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:ivar_getTypeEncoding(self.ivar)];\n    inputView.backgroundColor = self.view.backgroundColor;\n    inputView.inputValue = [FLEXRuntimeUtility valueForIvar:self.ivar onObject:self.target];\n    inputView.delegate = self;\n    self.fieldEditorView.argumentInputViews = @[inputView];\n    \n    // Don't show a \"set\" button for switches. Set the ivar when the switch toggles.\n    if ([inputView isKindOfClass:[FLEXArgumentInputSwitchView class]]) {\n        self.navigationItem.rightBarButtonItem = nil;\n    }\n}\n\n- (void)actionButtonPressed:(id)sender\n{\n    [super actionButtonPressed:sender];\n    \n    [FLEXRuntimeUtility setValue:self.firstInputView.inputValue forIvar:self.ivar onObject:self.target];\n    self.firstInputView.inputValue = [FLEXRuntimeUtility valueForIvar:self.ivar onObject:self.target];\n}\n\n- (void)argumentInputViewValueDidChange:(FLEXArgumentInputView *)argumentInputView\n{\n    if ([argumentInputView isKindOfClass:[FLEXArgumentInputSwitchView class]]) {\n        [self actionButtonPressed:nil];\n    }\n}\n\n+ (BOOL)canEditIvar:(Ivar)ivar currentValue:(id)value\n{\n    return [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:ivar_getTypeEncoding(ivar) currentValue:value];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXMethodCallingViewController.h",
    "content": "//\n//  FLEXMethodCallingViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/23/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXFieldEditorViewController.h\"\n#import <objc/runtime.h>\n\n@interface FLEXMethodCallingViewController : FLEXFieldEditorViewController\n\n- (id)initWithTarget:(id)target method:(Method)method;\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXMethodCallingViewController.m",
    "content": "//\n//  FLEXMethodCallingViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/23/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXMethodCallingViewController.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXFieldEditorView.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXObjectExplorerViewController.h\"\n#import \"FLEXArgumentInputView.h\"\n#import \"FLEXArgumentInputViewFactory.h\"\n\n@interface FLEXMethodCallingViewController ()\n\n@property (nonatomic, assign) Method method;\n\n@end\n\n@implementation FLEXMethodCallingViewController\n\n- (id)initWithTarget:(id)target method:(Method)method\n{\n    self = [super initWithTarget:target];\n    if (self) {\n        self.method = method;\n        self.title = [self isClassMethod] ? @\"Class Method\" : @\"Method\";\n    }\n    return self;\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.fieldEditorView.fieldDescription = [FLEXRuntimeUtility prettyNameForMethod:self.method isClassMethod:[self isClassMethod]];\n    \n    NSArray<NSString *> *methodComponents = [FLEXRuntimeUtility prettyArgumentComponentsForMethod:self.method];\n    NSMutableArray<FLEXArgumentInputView *> *argumentInputViews = [NSMutableArray array];\n    unsigned int argumentIndex = kFLEXNumberOfImplicitArgs;\n    for (NSString *methodComponent in methodComponents) {\n        char *argumentTypeEncoding = method_copyArgumentType(self.method, argumentIndex);\n        FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:argumentTypeEncoding];\n        free(argumentTypeEncoding);\n        \n        inputView.backgroundColor = self.view.backgroundColor;\n        inputView.title = methodComponent;\n        [argumentInputViews addObject:inputView];\n        argumentIndex++;\n    }\n    self.fieldEditorView.argumentInputViews = argumentInputViews;\n}\n\n- (BOOL)isClassMethod\n{\n    return self.target && self.target == [self.target class];\n}\n\n- (NSString *)titleForActionButton\n{\n    return @\"Call\";\n}\n\n- (void)actionButtonPressed:(id)sender\n{\n    [super actionButtonPressed:sender];\n    \n    NSMutableArray *arguments = [NSMutableArray array];\n    for (FLEXArgumentInputView *inputView in self.fieldEditorView.argumentInputViews) {\n        id argumentValue = inputView.inputValue;\n        if (!argumentValue) {\n            // Use NSNulls as placeholders in the array. They will be interpreted as nil arguments.\n            argumentValue = [NSNull null];\n        }\n        [arguments addObject:argumentValue];\n    }\n    \n    NSError *error = nil;\n    id returnedObject = [FLEXRuntimeUtility performSelector:method_getName(self.method) onObject:self.target withArguments:arguments error:&error];\n    \n    if (error) {\n        NSString *title = @\"Method Call Failed\";\n        NSString *message = [error localizedDescription];\n        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@\"OK\" otherButtonTitles:nil];\n        [alert show];\n    } else if (returnedObject) {\n        // For non-nil (or void) return types, push an explorer view controller to display the returned object\n        FLEXObjectExplorerViewController *explorerViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:returnedObject];\n        [self.navigationController pushViewController:explorerViewController animated:YES];\n    } else {\n        // If we didn't get a returned object but the method call succeeded,\n        // pop this view controller off the stack to indicate that the call went through.\n        [self.navigationController popViewControllerAnimated:YES];\n    }\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXPropertyEditorViewController.h",
    "content": "//\n//  FLEXPropertyEditorViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/20/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXFieldEditorViewController.h\"\n#import <objc/runtime.h>\n\n@interface FLEXPropertyEditorViewController : FLEXFieldEditorViewController\n\n- (id)initWithTarget:(id)target property:(objc_property_t)property;\n\n+ (BOOL)canEditProperty:(objc_property_t)property currentValue:(id)value;\n\n@end\n"
  },
  {
    "path": "FLEX/Editing/FLEXPropertyEditorViewController.m",
    "content": "//\n//  FLEXPropertyEditorViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/20/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXPropertyEditorViewController.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXFieldEditorView.h\"\n#import \"FLEXArgumentInputView.h\"\n#import \"FLEXArgumentInputViewFactory.h\"\n#import \"FLEXArgumentInputSwitchView.h\"\n\n@interface FLEXPropertyEditorViewController () <FLEXArgumentInputViewDelegate>\n\n@property (nonatomic, assign) objc_property_t property;\n\n@end\n\n@implementation FLEXPropertyEditorViewController\n\n- (id)initWithTarget:(id)target property:(objc_property_t)property\n{\n    self = [super initWithTarget:target];\n    if (self) {\n        self.property = property;\n        self.title = @\"Property\";\n    }\n    return self;\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.fieldEditorView.fieldDescription = [FLEXRuntimeUtility fullDescriptionForProperty:self.property];\n    id currentValue = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target];\n    self.setterButton.enabled = [[self class] canEditProperty:self.property currentValue:currentValue];\n    \n    const char *typeEncoding = [[FLEXRuntimeUtility typeEncodingForProperty:self.property] UTF8String];\n    FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:typeEncoding];\n    inputView.backgroundColor = self.view.backgroundColor;\n    inputView.inputValue = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target];\n    inputView.delegate = self;\n    self.fieldEditorView.argumentInputViews = @[inputView];\n    \n    // Don't show a \"set\" button for switches - just call the setter immediately after the switch toggles.\n    if ([inputView isKindOfClass:[FLEXArgumentInputSwitchView class]]) {\n        self.navigationItem.rightBarButtonItem = nil;\n    }\n}\n\n- (void)actionButtonPressed:(id)sender\n{\n    [super actionButtonPressed:sender];\n    \n    id userInputObject = self.firstInputView.inputValue;\n    NSArray *arguments = userInputObject ? @[userInputObject] : nil;\n    SEL setterSelector = [FLEXRuntimeUtility setterSelectorForProperty:self.property];\n    NSError *error = nil;\n    [FLEXRuntimeUtility performSelector:setterSelector onObject:self.target withArguments:arguments error:&error];\n    if (error) {\n        NSString *title = @\"Property Setter Failed\";\n        NSString *message = [error localizedDescription];\n        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@\"OK\" otherButtonTitles:nil];\n        [alert show];\n        self.firstInputView.inputValue = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target];\n    } else {\n        // If the setter was called without error, pop the view controller to indicate that and make the user's life easier.\n        // Don't do this for simulated taps on the action button (i.e. from switch/BOOL editors). The experience is weird there.\n        if (sender) {\n            [self.navigationController popViewControllerAnimated:YES];\n        }\n    }\n}\n\n- (void)argumentInputViewValueDidChange:(FLEXArgumentInputView *)argumentInputView\n{\n    if ([argumentInputView isKindOfClass:[FLEXArgumentInputSwitchView class]]) {\n        [self actionButtonPressed:nil];\n    }\n}\n\n+ (BOOL)canEditProperty:(objc_property_t)property currentValue:(id)value\n{\n    const char *typeEncoding = [[FLEXRuntimeUtility typeEncodingForProperty:property] UTF8String];\n    BOOL canEditType = [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:typeEncoding currentValue:value];\n    BOOL isReadonly = [FLEXRuntimeUtility isReadonlyProperty:property];\n    return canEditType && !isReadonly;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ExplorerInterface/FLEXExplorerViewController.h",
    "content": "//\n//  FLEXExplorerViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/4/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@protocol FLEXExplorerViewControllerDelegate;\n\n@interface FLEXExplorerViewController : UIViewController\n\n@property (nonatomic, weak) id <FLEXExplorerViewControllerDelegate> delegate;\n\n- (BOOL)shouldReceiveTouchAtWindowPoint:(CGPoint)pointInWindowCoordinates;\n- (BOOL)wantsWindowToBecomeKey;\n\n/// @brief Used to present (or dismiss) a modal view controller (\"tool\"), typically triggered by pressing a button in the toolbar.\n///\n/// If a tool is already presented, this method simply dismisses it and calls the completion block.\n/// If no tool is presented, @code future() @endcode is presented and the completion block is called.\n- (void)toggleToolWithViewControllerProvider:(UIViewController *(^)(void))future completion:(void(^)(void))completion;\n\n// Keyboard shortcut helpers\n\n- (void)toggleSelectTool;\n- (void)toggleMoveTool;\n- (void)toggleViewsTool;\n- (void)toggleMenuTool;\n- (void)handleDownArrowKeyPressed;\n- (void)handleUpArrowKeyPressed;\n- (void)handleRightArrowKeyPressed;\n- (void)handleLeftArrowKeyPressed;\n\n@end\n\n@protocol FLEXExplorerViewControllerDelegate <NSObject>\n\n- (void)explorerViewControllerDidFinish:(FLEXExplorerViewController *)explorerViewController;\n\n@end\n"
  },
  {
    "path": "FLEX/ExplorerInterface/FLEXExplorerViewController.m",
    "content": "//\n//  FLEXExplorerViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/4/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXExplorerViewController.h\"\n#import \"FLEXExplorerToolbar.h\"\n#import \"FLEXToolbarItem.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXHierarchyTableViewController.h\"\n#import \"FLEXGlobalsTableViewController.h\"\n#import \"FLEXObjectExplorerViewController.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXNetworkHistoryTableViewController.h\"\n\nstatic NSString *const kFLEXToolbarTopMarginDefaultsKey = @\"com.flex.FLEXToolbar.topMargin\";\n\ntypedef NS_ENUM(NSUInteger, FLEXExplorerMode) {\n    FLEXExplorerModeDefault,\n    FLEXExplorerModeSelect,\n    FLEXExplorerModeMove\n};\n\n@interface FLEXExplorerViewController () <FLEXHierarchyTableViewControllerDelegate, FLEXGlobalsTableViewControllerDelegate>\n\n@property (nonatomic, strong) FLEXExplorerToolbar *explorerToolbar;\n\n/// Tracks the currently active tool/mode\n@property (nonatomic, assign) FLEXExplorerMode currentMode;\n\n/// Gesture recognizer for dragging a view in move mode\n@property (nonatomic, strong) UIPanGestureRecognizer *movePanGR;\n\n/// Gesture recognizer for showing additional details on the selected view\n@property (nonatomic, strong) UITapGestureRecognizer *detailsTapGR;\n\n/// Only valid while a move pan gesture is in progress.\n@property (nonatomic, assign) CGRect selectedViewFrameBeforeDragging;\n\n/// Only valid while a toolbar drag pan gesture is in progress.\n@property (nonatomic, assign) CGRect toolbarFrameBeforeDragging;\n\n/// Borders of all the visible views in the hierarchy at the selection point.\n/// The keys are NSValues with the correponding view (nonretained).\n@property (nonatomic, strong) NSDictionary<NSValue *, UIView *> *outlineViewsForVisibleViews;\n\n/// The actual views at the selection point with the deepest view last.\n@property (nonatomic, strong) NSArray<UIView *> *viewsAtTapPoint;\n\n/// The view that we're currently highlighting with an overlay and displaying details for.\n@property (nonatomic, strong) UIView *selectedView;\n\n/// A colored transparent overlay to indicate that the view is selected.\n@property (nonatomic, strong) UIView *selectedViewOverlay;\n\n/// Tracked so we can restore the key window after dismissing a modal.\n/// We need to become key after modal presentation so we can correctly capture intput.\n/// If we're just showing the toolbar, we want the main app's window to remain key so that we don't interfere with input, status bar, etc.\n@property (nonatomic, strong) UIWindow *previousKeyWindow;\n\n/// Similar to the previousKeyWindow property above, we need to track status bar styling if\n/// the app doesn't use view controller based status bar management. When we present a modal,\n/// we want to change the status bar style to UIStausBarStyleDefault. Before changing, we stash\n/// the current style. On dismissal, we return the staus bar to the style that the app was using previously.\n@property (nonatomic, assign) UIStatusBarStyle previousStatusBarStyle;\n\n/// All views that we're KVOing. Used to help us clean up properly.\n@property (nonatomic, strong) NSMutableSet<UIView *> *observedViews;\n\n@end\n\n@implementation FLEXExplorerViewController\n\n- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil\n{\n    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];\n    if (self) {\n        self.observedViews = [NSMutableSet set];\n    }\n    return self;\n}\n\n-(void)dealloc\n{\n    for (UIView *view in _observedViews) {\n        [self stopObservingView:view];\n    }\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n\t\n    // Toolbar\n    self.explorerToolbar = [[FLEXExplorerToolbar alloc] init];\n\n    // Start the toolbar off below any bars that may be at the top of the view.\n    id toolbarOriginYDefault = [[NSUserDefaults standardUserDefaults] objectForKey:kFLEXToolbarTopMarginDefaultsKey];\n    CGFloat toolbarOriginY = toolbarOriginYDefault ? [toolbarOriginYDefault doubleValue] : 100;\n\n    CGRect safeArea = [self viewSafeArea];\n    CGSize toolbarSize = [self.explorerToolbar sizeThatFits:CGSizeMake(CGRectGetWidth(self.view.bounds), CGRectGetHeight(safeArea))];\n    [self updateToolbarPositionWithUnconstrainedFrame:CGRectMake(CGRectGetMinX(safeArea), toolbarOriginY, toolbarSize.width, toolbarSize.height)];\n    self.explorerToolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;\n    [self.view addSubview:self.explorerToolbar];\n    [self setupToolbarActions];\n    [self setupToolbarGestures];\n    \n    // View selection\n    UITapGestureRecognizer *selectionTapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSelectionTap:)];\n    [self.view addGestureRecognizer:selectionTapGR];\n    \n    // View moving\n    self.movePanGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleMovePan:)];\n    self.movePanGR.enabled = self.currentMode == FLEXExplorerModeMove;\n    [self.view addGestureRecognizer:self.movePanGR];\n}\n\n- (void)viewWillAppear:(BOOL)animated\n{\n    [super viewWillAppear:animated];\n    \n    [self updateButtonStates];\n}\n\n\n#pragma mark - Rotation\n\n- (UIViewController *)viewControllerForRotationAndOrientation\n{\n    UIWindow *window = self.previousKeyWindow ?: [[UIApplication sharedApplication] keyWindow];\n    UIViewController *viewController = window.rootViewController;\n    NSString *viewControllerSelectorString = [@[@\"_vie\", @\"wContro\", @\"llerFor\", @\"Supported\", @\"Interface\", @\"Orientations\"] componentsJoinedByString:@\"\"];\n    SEL viewControllerSelector = NSSelectorFromString(viewControllerSelectorString);\n    if ([viewController respondsToSelector:viewControllerSelector]) {\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Warc-performSelector-leaks\"\n        viewController = [viewController performSelector:viewControllerSelector];\n#pragma clang diagnostic pop\n    }\n    return viewController;\n}\n\n- (UIInterfaceOrientationMask)supportedInterfaceOrientations\n{\n    UIViewController *viewControllerToAsk = [self viewControllerForRotationAndOrientation];\n    UIInterfaceOrientationMask supportedOrientations = [FLEXUtility infoPlistSupportedInterfaceOrientationsMask];\n    if (viewControllerToAsk && viewControllerToAsk != self) {\n        supportedOrientations = [viewControllerToAsk supportedInterfaceOrientations];\n    }\n    \n    // The UIViewController docs state that this method must not return zero.\n    // If we weren't able to get a valid value for the supported interface orientations, default to all supported.\n    if (supportedOrientations == 0) {\n        supportedOrientations = UIInterfaceOrientationMaskAll;\n    }\n    \n    return supportedOrientations;\n}\n\n- (BOOL)shouldAutorotate\n{\n    UIViewController *viewControllerToAsk = [self viewControllerForRotationAndOrientation];\n    BOOL shouldAutorotate = YES;\n    if (viewControllerToAsk && viewControllerToAsk != self) {\n        shouldAutorotate = [viewControllerToAsk shouldAutorotate];\n    }\n    return shouldAutorotate;\n}\n\n- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator\n{\n    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n         for (UIView *outlineView in [self.outlineViewsForVisibleViews allValues]) {\n             outlineView.hidden = YES;\n         }\n         self.selectedViewOverlay.hidden = YES;\n     } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n         for (UIView *view in self.viewsAtTapPoint) {\n             NSValue *key = [NSValue valueWithNonretainedObject:view];\n             UIView *outlineView = self.outlineViewsForVisibleViews[key];\n             outlineView.frame = [self frameInLocalCoordinatesForView:view];\n             if (self.currentMode == FLEXExplorerModeSelect) {\n                 outlineView.hidden = NO;\n             }\n         }\n\n         if (self.selectedView) {\n             self.selectedViewOverlay.frame = [self frameInLocalCoordinatesForView:self.selectedView];\n             self.selectedViewOverlay.hidden = NO;\n         }\n     }];\n}\n\n#pragma mark - Setter Overrides\n\n- (void)setSelectedView:(UIView *)selectedView\n{\n    if (![_selectedView isEqual:selectedView]) {\n        if (![self.viewsAtTapPoint containsObject:_selectedView]) {\n            [self stopObservingView:_selectedView];\n        }\n        \n        _selectedView = selectedView;\n        \n        [self beginObservingView:selectedView];\n\n        // Update the toolbar and selected overlay\n        self.explorerToolbar.selectedViewDescription = [FLEXUtility descriptionForView:selectedView includingFrame:YES];\n        self.explorerToolbar.selectedViewOverlayColor = [FLEXUtility consistentRandomColorForObject:selectedView];\n\n        if (selectedView) {\n            if (!self.selectedViewOverlay) {\n                self.selectedViewOverlay = [[UIView alloc] init];\n                [self.view addSubview:self.selectedViewOverlay];\n                self.selectedViewOverlay.layer.borderWidth = 1.0;\n            }\n            UIColor *outlineColor = [FLEXUtility consistentRandomColorForObject:selectedView];\n            self.selectedViewOverlay.backgroundColor = [outlineColor colorWithAlphaComponent:0.2];\n            self.selectedViewOverlay.layer.borderColor = [outlineColor CGColor];\n            self.selectedViewOverlay.frame = [self.view convertRect:selectedView.bounds fromView:selectedView];\n            \n            // Make sure the selected overlay is in front of all the other subviews except the toolbar, which should always stay on top.\n            [self.view bringSubviewToFront:self.selectedViewOverlay];\n            [self.view bringSubviewToFront:self.explorerToolbar];\n        } else {\n            [self.selectedViewOverlay removeFromSuperview];\n            self.selectedViewOverlay = nil;\n        }\n        \n        // Some of the button states depend on whether we have a selected view.\n        [self updateButtonStates];\n    }\n}\n\n- (void)setViewsAtTapPoint:(NSArray<UIView *> *)viewsAtTapPoint\n{\n    if (![_viewsAtTapPoint isEqual:viewsAtTapPoint]) {\n        for (UIView *view in _viewsAtTapPoint) {\n            if (view != self.selectedView) {\n                [self stopObservingView:view];\n            }\n        }\n        \n        _viewsAtTapPoint = viewsAtTapPoint;\n        \n        for (UIView *view in viewsAtTapPoint) {\n            [self beginObservingView:view];\n        }\n    }\n}\n\n- (void)setCurrentMode:(FLEXExplorerMode)currentMode\n{\n    if (_currentMode != currentMode) {\n        _currentMode = currentMode;\n        switch (currentMode) {\n            case FLEXExplorerModeDefault:\n                [self removeAndClearOutlineViews];\n                self.viewsAtTapPoint = nil;\n                self.selectedView = nil;\n                break;\n                \n            case FLEXExplorerModeSelect:\n                // Make sure the outline views are unhidden in case we came from the move mode.\n                for (NSValue *key in self.outlineViewsForVisibleViews) {\n                    UIView *outlineView = self.outlineViewsForVisibleViews[key];\n                    outlineView.hidden = NO;\n                }\n                break;\n                \n            case FLEXExplorerModeMove:\n                // Hide all the outline views to focus on the selected view, which is the only one that will move.\n                for (NSValue *key in self.outlineViewsForVisibleViews) {\n                    UIView *outlineView = self.outlineViewsForVisibleViews[key];\n                    outlineView.hidden = YES;\n                }\n                break;\n        }\n        self.movePanGR.enabled = currentMode == FLEXExplorerModeMove;\n        [self updateButtonStates];\n    }\n}\n\n\n#pragma mark - View Tracking\n\n- (void)beginObservingView:(UIView *)view\n{\n    // Bail if we're already observing this view or if there's nothing to observe.\n    if (!view || [self.observedViews containsObject:view]) {\n        return;\n    }\n    \n    for (NSString *keyPath in [[self class] viewKeyPathsToTrack]) {\n        [view addObserver:self forKeyPath:keyPath options:0 context:NULL];\n    }\n    \n    [self.observedViews addObject:view];\n}\n\n- (void)stopObservingView:(UIView *)view\n{\n    if (!view) {\n        return;\n    }\n    \n    for (NSString *keyPath in [[self class] viewKeyPathsToTrack]) {\n        [view removeObserver:self forKeyPath:keyPath];\n    }\n    \n    [self.observedViews removeObject:view];\n}\n\n+ (NSArray<NSString *> *)viewKeyPathsToTrack\n{\n    static NSArray<NSString *> *trackedViewKeyPaths = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        NSString *frameKeyPath = NSStringFromSelector(@selector(frame));\n        trackedViewKeyPaths = @[frameKeyPath];\n    });\n    return trackedViewKeyPaths;\n}\n\n- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context\n{\n    [self updateOverlayAndDescriptionForObjectIfNeeded:object];\n}\n\n- (void)updateOverlayAndDescriptionForObjectIfNeeded:(id)object\n{\n    NSUInteger indexOfView = [self.viewsAtTapPoint indexOfObject:object];\n    if (indexOfView != NSNotFound) {\n        UIView *view = self.viewsAtTapPoint[indexOfView];\n        NSValue *key = [NSValue valueWithNonretainedObject:view];\n        UIView *outline = self.outlineViewsForVisibleViews[key];\n        if (outline) {\n            outline.frame = [self frameInLocalCoordinatesForView:view];\n        }\n    }\n    if (object == self.selectedView) {\n        // Update the selected view description since we show the frame value there.\n        self.explorerToolbar.selectedViewDescription = [FLEXUtility descriptionForView:self.selectedView includingFrame:YES];\n        CGRect selectedViewOutlineFrame = [self frameInLocalCoordinatesForView:self.selectedView];\n        self.selectedViewOverlay.frame = selectedViewOutlineFrame;\n    }\n}\n\n- (CGRect)frameInLocalCoordinatesForView:(UIView *)view\n{\n    // First convert to window coordinates since the view may be in a different window than our view.\n    CGRect frameInWindow = [view convertRect:view.bounds toView:nil];\n    // Then convert from the window to our view's coordinate space.\n    return [self.view convertRect:frameInWindow fromView:nil];\n}\n\n\n#pragma mark - Toolbar Buttons\n\n- (void)setupToolbarActions\n{\n    [self.explorerToolbar.selectItem addTarget:self action:@selector(selectButtonTapped:) forControlEvents:UIControlEventTouchUpInside];\n    [self.explorerToolbar.hierarchyItem addTarget:self action:@selector(hierarchyButtonTapped:) forControlEvents:UIControlEventTouchUpInside];\n    [self.explorerToolbar.moveItem addTarget:self action:@selector(moveButtonTapped:) forControlEvents:UIControlEventTouchUpInside];\n    [self.explorerToolbar.globalsItem addTarget:self action:@selector(globalsButtonTapped:) forControlEvents:UIControlEventTouchUpInside];\n    [self.explorerToolbar.closeItem addTarget:self action:@selector(closeButtonTapped:) forControlEvents:UIControlEventTouchUpInside];\n}\n\n- (void)selectButtonTapped:(FLEXToolbarItem *)sender\n{\n    [self toggleSelectTool];\n}\n\n- (void)hierarchyButtonTapped:(FLEXToolbarItem *)sender\n{\n    [self toggleViewsTool];\n}\n\n- (NSArray<UIView *> *)allViewsInHierarchy\n{\n    NSMutableArray<UIView *> *allViews = [NSMutableArray array];\n    NSArray<UIWindow *> *windows = [FLEXUtility allWindows];\n    for (UIWindow *window in windows) {\n        if (window != self.view.window) {\n            [allViews addObject:window];\n            [allViews addObjectsFromArray:[self allRecursiveSubviewsInView:window]];\n        }\n    }\n    return allViews;\n}\n\n- (UIWindow *)statusWindow\n{\n    NSString *statusBarString = [NSString stringWithFormat:@\"%@arWindow\", @\"_statusB\"];\n    return [[UIApplication sharedApplication] valueForKey:statusBarString];\n}\n\n- (void)moveButtonTapped:(FLEXToolbarItem *)sender\n{\n    [self toggleMoveTool];\n}\n\n- (void)globalsButtonTapped:(FLEXToolbarItem *)sender\n{\n    [self toggleMenuTool];\n}\n\n- (void)closeButtonTapped:(FLEXToolbarItem *)sender\n{\n    self.currentMode = FLEXExplorerModeDefault;\n    [self.delegate explorerViewControllerDidFinish:self];\n}\n\n- (void)updateButtonStates\n{\n    // Move and details only active when an object is selected.\n    BOOL hasSelectedObject = self.selectedView != nil;\n    self.explorerToolbar.moveItem.enabled = hasSelectedObject;\n    self.explorerToolbar.selectItem.selected = self.currentMode == FLEXExplorerModeSelect;\n    self.explorerToolbar.moveItem.selected = self.currentMode == FLEXExplorerModeMove;\n}\n\n\n#pragma mark - Toolbar Dragging\n\n- (void)setupToolbarGestures\n{\n    // Pan gesture for dragging.\n    UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleToolbarPanGesture:)];\n    [self.explorerToolbar.dragHandle addGestureRecognizer:panGR];\n    \n    // Tap gesture for hinting.\n    UITapGestureRecognizer *hintTapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleToolbarHintTapGesture:)];\n    [self.explorerToolbar.dragHandle addGestureRecognizer:hintTapGR];\n    \n    // Tap gesture for showing additional details\n    self.detailsTapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleToolbarDetailsTapGesture:)];\n    [self.explorerToolbar.selectedViewDescriptionContainer addGestureRecognizer:self.detailsTapGR];\n}\n\n- (void)handleToolbarPanGesture:(UIPanGestureRecognizer *)panGR\n{\n    switch (panGR.state) {\n        case UIGestureRecognizerStateBegan:\n            self.toolbarFrameBeforeDragging = self.explorerToolbar.frame;\n            [self updateToolbarPostionWithDragGesture:panGR];\n            break;\n            \n        case UIGestureRecognizerStateChanged:\n        case UIGestureRecognizerStateEnded:\n            [self updateToolbarPostionWithDragGesture:panGR];\n            break;\n            \n        default:\n            break;\n    }\n}\n\n- (void)updateToolbarPostionWithDragGesture:(UIPanGestureRecognizer *)panGR\n{\n    CGPoint translation = [panGR translationInView:self.view];\n    CGRect newToolbarFrame = self.toolbarFrameBeforeDragging;\n    newToolbarFrame.origin.y += translation.y;\n    \n    [self updateToolbarPositionWithUnconstrainedFrame:newToolbarFrame];\n}\n\n- (void)updateToolbarPositionWithUnconstrainedFrame:(CGRect)unconstrainedFrame\n{\n    CGRect safeArea = [self viewSafeArea];\n    // We only constrain the Y-axis because We want the toolbar to handle the X-axis safeArea layout by itself\n    CGFloat minY = CGRectGetMinY(safeArea);\n    CGFloat maxY = CGRectGetMaxY(safeArea) - unconstrainedFrame.size.height;\n    if (unconstrainedFrame.origin.y < minY) {\n        unconstrainedFrame.origin.y = minY;\n    } else if (unconstrainedFrame.origin.y > maxY) {\n        unconstrainedFrame.origin.y = maxY;\n    }\n\n    self.explorerToolbar.frame = unconstrainedFrame;\n\n    [[NSUserDefaults standardUserDefaults] setDouble:unconstrainedFrame.origin.y forKey:kFLEXToolbarTopMarginDefaultsKey];\n}\n\n- (void)handleToolbarHintTapGesture:(UITapGestureRecognizer *)tapGR\n{\n    // Bounce the toolbar to indicate that it is draggable.\n    // TODO: make it bouncier.\n    if (tapGR.state == UIGestureRecognizerStateRecognized) {\n        CGRect originalToolbarFrame = self.explorerToolbar.frame;\n        const NSTimeInterval kHalfwayDuration = 0.2;\n        const CGFloat kVerticalOffset = 30.0;\n        [UIView animateWithDuration:kHalfwayDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{\n            CGRect newToolbarFrame = self.explorerToolbar.frame;\n            newToolbarFrame.origin.y += kVerticalOffset;\n            self.explorerToolbar.frame = newToolbarFrame;\n        } completion:^(BOOL finished) {\n            [UIView animateWithDuration:kHalfwayDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{\n                self.explorerToolbar.frame = originalToolbarFrame;\n            } completion:nil];\n        }];\n    }\n}\n\n- (void)handleToolbarDetailsTapGesture:(UITapGestureRecognizer *)tapGR\n{\n    if (tapGR.state == UIGestureRecognizerStateRecognized && self.selectedView) {\n        FLEXObjectExplorerViewController *selectedViewExplorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:self.selectedView];\n        selectedViewExplorer.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(selectedViewExplorerFinished:)];\n        UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:selectedViewExplorer];\n        [self makeKeyAndPresentViewController:navigationController animated:YES completion:nil];\n    }\n}\n\n\n#pragma mark - View Selection\n\n- (void)handleSelectionTap:(UITapGestureRecognizer *)tapGR\n{\n    // Only if we're in selection mode\n    if (self.currentMode == FLEXExplorerModeSelect && tapGR.state == UIGestureRecognizerStateRecognized) {\n        // Note that [tapGR locationInView:nil] is broken in iOS 8, so we have to do a two step conversion to window coordinates.\n        // Thanks to @lascorbe for finding this: https://github.com/Flipboard/FLEX/pull/31\n        CGPoint tapPointInView = [tapGR locationInView:self.view];\n        CGPoint tapPointInWindow = [self.view convertPoint:tapPointInView toView:nil];\n        [self updateOutlineViewsForSelectionPoint:tapPointInWindow];\n    }\n}\n\n- (void)updateOutlineViewsForSelectionPoint:(CGPoint)selectionPointInWindow\n{\n    [self removeAndClearOutlineViews];\n    \n    // Include hidden views in the \"viewsAtTapPoint\" array so we can show them in the hierarchy list.\n    self.viewsAtTapPoint = [self viewsAtPoint:selectionPointInWindow skipHiddenViews:NO];\n    \n    // For outlined views and the selected view, only use visible views.\n    // Outlining hidden views adds clutter and makes the selection behavior confusing.\n    NSArray<UIView *> *visibleViewsAtTapPoint = [self viewsAtPoint:selectionPointInWindow skipHiddenViews:YES];\n    NSMutableDictionary<NSValue *, UIView *> *newOutlineViewsForVisibleViews = [NSMutableDictionary dictionary];\n    for (UIView *view in visibleViewsAtTapPoint) {\n        UIView *outlineView = [self outlineViewForView:view];\n        [self.view addSubview:outlineView];\n        NSValue *key = [NSValue valueWithNonretainedObject:view];\n        [newOutlineViewsForVisibleViews setObject:outlineView forKey:key];\n    }\n    self.outlineViewsForVisibleViews = newOutlineViewsForVisibleViews;\n    self.selectedView = [self viewForSelectionAtPoint:selectionPointInWindow];\n    \n    // Make sure the explorer toolbar doesn't end up behind the newly added outline views.\n    [self.view bringSubviewToFront:self.explorerToolbar];\n    \n    [self updateButtonStates];\n}\n\n- (UIView *)outlineViewForView:(UIView *)view\n{\n    CGRect outlineFrame = [self frameInLocalCoordinatesForView:view];\n    UIView *outlineView = [[UIView alloc] initWithFrame:outlineFrame];\n    outlineView.backgroundColor = [UIColor clearColor];\n    outlineView.layer.borderColor = [[FLEXUtility consistentRandomColorForObject:view] CGColor];\n    outlineView.layer.borderWidth = 1.0;\n    return outlineView;\n}\n\n- (void)removeAndClearOutlineViews\n{\n    for (NSValue *key in self.outlineViewsForVisibleViews) {\n        UIView *outlineView = self.outlineViewsForVisibleViews[key];\n        [outlineView removeFromSuperview];\n    }\n    self.outlineViewsForVisibleViews = nil;\n}\n\n- (NSArray<UIView *> *)viewsAtPoint:(CGPoint)tapPointInWindow skipHiddenViews:(BOOL)skipHidden\n{\n    NSMutableArray<UIView *> *views = [NSMutableArray array];\n    for (UIWindow *window in [FLEXUtility allWindows]) {\n        // Don't include the explorer's own window or subviews.\n        if (window != self.view.window && [window pointInside:tapPointInWindow withEvent:nil]) {\n            [views addObject:window];\n            [views addObjectsFromArray:[self recursiveSubviewsAtPoint:tapPointInWindow inView:window skipHiddenViews:skipHidden]];\n        }\n    }\n    return views;\n}\n\n- (UIView *)viewForSelectionAtPoint:(CGPoint)tapPointInWindow\n{\n    // Select in the window that would handle the touch, but don't just use the result of hitTest:withEvent: so we can still select views with interaction disabled.\n    // Default to the the application's key window if none of the windows want the touch.\n    UIWindow *windowForSelection = [[UIApplication sharedApplication] keyWindow];\n    for (UIWindow *window in [[FLEXUtility allWindows] reverseObjectEnumerator]) {\n        // Ignore the explorer's own window.\n        if (window != self.view.window) {\n            if ([window hitTest:tapPointInWindow withEvent:nil]) {\n                windowForSelection = window;\n                break;\n            }\n        }\n    }\n    \n    // Select the deepest visible view at the tap point. This generally corresponds to what the user wants to select.\n    return [[self recursiveSubviewsAtPoint:tapPointInWindow inView:windowForSelection skipHiddenViews:YES] lastObject];\n}\n\n- (NSArray<UIView *> *)recursiveSubviewsAtPoint:(CGPoint)pointInView inView:(UIView *)view skipHiddenViews:(BOOL)skipHidden\n{\n    NSMutableArray<UIView *> *subviewsAtPoint = [NSMutableArray array];\n    for (UIView *subview in view.subviews) {\n        BOOL isHidden = subview.hidden || subview.alpha < 0.01;\n        if (skipHidden && isHidden) {\n            continue;\n        }\n        \n        BOOL subviewContainsPoint = CGRectContainsPoint(subview.frame, pointInView);\n        if (subviewContainsPoint) {\n            [subviewsAtPoint addObject:subview];\n        }\n        \n        // If this view doesn't clip to its bounds, we need to check its subviews even if it doesn't contain the selection point.\n        // They may be visible and contain the selection point.\n        if (subviewContainsPoint || !subview.clipsToBounds) {\n            CGPoint pointInSubview = [view convertPoint:pointInView toView:subview];\n            [subviewsAtPoint addObjectsFromArray:[self recursiveSubviewsAtPoint:pointInSubview inView:subview skipHiddenViews:skipHidden]];\n        }\n    }\n    return subviewsAtPoint;\n}\n\n- (NSArray<UIView *> *)allRecursiveSubviewsInView:(UIView *)view\n{\n    NSMutableArray<UIView *> *subviews = [NSMutableArray array];\n    for (UIView *subview in view.subviews) {\n        [subviews addObject:subview];\n        [subviews addObjectsFromArray:[self allRecursiveSubviewsInView:subview]];\n    }\n    return subviews;\n}\n\n- (NSDictionary<NSValue *, NSNumber *> *)hierarchyDepthsForViews:(NSArray<UIView *> *)views\n{\n    NSMutableDictionary<NSValue *, NSNumber *> *hierarchyDepths = [NSMutableDictionary dictionary];\n    for (UIView *view in views) {\n        NSInteger depth = 0;\n        UIView *tryView = view;\n        while (tryView.superview) {\n            tryView = tryView.superview;\n            depth++;\n        }\n        [hierarchyDepths setObject:@(depth) forKey:[NSValue valueWithNonretainedObject:view]];\n    }\n    return hierarchyDepths;\n}\n\n\n#pragma mark - Selected View Moving\n\n- (void)handleMovePan:(UIPanGestureRecognizer *)movePanGR\n{\n    switch (movePanGR.state) {\n        case UIGestureRecognizerStateBegan:\n            self.selectedViewFrameBeforeDragging = self.selectedView.frame;\n            [self updateSelectedViewPositionWithDragGesture:movePanGR];\n            break;\n            \n        case UIGestureRecognizerStateChanged:\n        case UIGestureRecognizerStateEnded:\n            [self updateSelectedViewPositionWithDragGesture:movePanGR];\n            break;\n            \n        default:\n            break;\n    }\n}\n\n- (void)updateSelectedViewPositionWithDragGesture:(UIPanGestureRecognizer *)movePanGR\n{\n    CGPoint translation = [movePanGR translationInView:self.selectedView.superview];\n    CGRect newSelectedViewFrame = self.selectedViewFrameBeforeDragging;\n    newSelectedViewFrame.origin.x = FLEXFloor(newSelectedViewFrame.origin.x + translation.x);\n    newSelectedViewFrame.origin.y = FLEXFloor(newSelectedViewFrame.origin.y + translation.y);\n    self.selectedView.frame = newSelectedViewFrame;\n}\n\n\n#pragma mark - Safe Area Handling\n\n- (CGRect)viewSafeArea\n{\n    CGRect safeArea = self.view.bounds;\n#if FLEX_AT_LEAST_IOS11_SDK\n    if (@available(iOS 11, *)) {\n        safeArea = UIEdgeInsetsInsetRect(self.view.bounds, self.view.safeAreaInsets);\n    }\n#endif\n    return safeArea;\n}\n\n#if FLEX_AT_LEAST_IOS11_SDK\n- (void)viewSafeAreaInsetsDidChange\n{\n  if (@available(iOS 11, *)) {\n    [super viewSafeAreaInsetsDidChange];\n  }\n\n  CGRect safeArea = [self viewSafeArea];\n  CGSize toolbarSize = [self.explorerToolbar sizeThatFits:CGSizeMake(CGRectGetWidth(self.view.bounds), CGRectGetHeight(safeArea))];\n  [self updateToolbarPositionWithUnconstrainedFrame:CGRectMake(CGRectGetMinX(self.explorerToolbar.frame), CGRectGetMinY(self.explorerToolbar.frame), toolbarSize.width, toolbarSize.height)];\n}\n#endif\n\n\n#pragma mark - Touch Handling\n\n- (BOOL)shouldReceiveTouchAtWindowPoint:(CGPoint)pointInWindowCoordinates\n{\n    BOOL shouldReceiveTouch = NO;\n    \n    CGPoint pointInLocalCoordinates = [self.view convertPoint:pointInWindowCoordinates fromView:nil];\n    \n    // Always if it's on the toolbar\n    if (CGRectContainsPoint(self.explorerToolbar.frame, pointInLocalCoordinates)) {\n        shouldReceiveTouch = YES;\n    }\n    \n    // Always if we're in selection mode\n    if (!shouldReceiveTouch && self.currentMode == FLEXExplorerModeSelect) {\n        shouldReceiveTouch = YES;\n    }\n    \n    // Always in move mode too\n    if (!shouldReceiveTouch && self.currentMode == FLEXExplorerModeMove) {\n        shouldReceiveTouch = YES;\n    }\n    \n    // Always if we have a modal presented\n    if (!shouldReceiveTouch && self.presentedViewController) {\n        shouldReceiveTouch = YES;\n    }\n    \n    return shouldReceiveTouch;\n}\n\n\n#pragma mark - FLEXHierarchyTableViewControllerDelegate\n\n- (void)hierarchyViewController:(FLEXHierarchyTableViewController *)hierarchyViewController didFinishWithSelectedView:(UIView *)selectedView\n{\n    // Note that we need to wait until the view controller is dismissed to calculated the frame of the outline view.\n    // Otherwise the coordinate conversion doesn't give the correct result.\n    [self toggleViewsToolWithCompletion:^{\n        // If the selected view is outside of the tap point array (selected from \"Full Hierarchy\"),\n        // then clear out the tap point array and remove all the outline views.\n        if (![self.viewsAtTapPoint containsObject:selectedView]) {\n            self.viewsAtTapPoint = nil;\n            [self removeAndClearOutlineViews];\n        }\n        \n        // If we now have a selected view and we didn't have one previously, go to \"select\" mode.\n        if (self.currentMode == FLEXExplorerModeDefault && selectedView) {\n            self.currentMode = FLEXExplorerModeSelect;\n        }\n        \n        // The selected view setter will also update the selected view overlay appropriately.\n        self.selectedView = selectedView;\n    }];\n}\n\n\n#pragma mark - FLEXGlobalsViewControllerDelegate\n\n- (void)globalsViewControllerDidFinish:(FLEXGlobalsTableViewController *)globalsViewController\n{\n    [self resignKeyAndDismissViewControllerAnimated:YES completion:nil];\n}\n\n\n#pragma mark - FLEXObjectExplorerViewController Done Action\n\n- (void)selectedViewExplorerFinished:(id)sender\n{\n    [self resignKeyAndDismissViewControllerAnimated:YES completion:nil];\n}\n\n\n#pragma mark - Modal Presentation and Window Management\n\n- (void)makeKeyAndPresentViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void (^)(void))completion\n{\n    // Save the current key window so we can restore it following dismissal.\n    self.previousKeyWindow = [[UIApplication sharedApplication] keyWindow];\n    \n    // Make our window key to correctly handle input.\n    [self.view.window makeKeyWindow];\n    \n    // Move the status bar on top of FLEX so we can get scroll to top behavior for taps.\n    [[self statusWindow] setWindowLevel:self.view.window.windowLevel + 1.0];\n    \n    // If this app doesn't use view controller based status bar management and we're on iOS 7+,\n    // make sure the status bar style is UIStatusBarStyleDefault. We don't actully have to check\n    // for view controller based management because the global methods no-op if that is turned on.\n    self.previousStatusBarStyle = [[UIApplication sharedApplication] statusBarStyle];\n    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];\n    \n    // Show the view controller.\n    [self presentViewController:viewController animated:animated completion:completion];\n}\n\n- (void)resignKeyAndDismissViewControllerAnimated:(BOOL)animated completion:(void (^)(void))completion\n{\n    UIWindow *previousKeyWindow = self.previousKeyWindow;\n    self.previousKeyWindow = nil;\n    [previousKeyWindow makeKeyWindow];\n    [[previousKeyWindow rootViewController] setNeedsStatusBarAppearanceUpdate];\n    \n    // Restore the status bar window's normal window level.\n    // We want it above FLEX while a modal is presented for scroll to top, but below FLEX otherwise for exploration.\n    [[self statusWindow] setWindowLevel:UIWindowLevelStatusBar];\n    \n    // Restore the stauts bar style if the app is using global status bar management.\n    [[UIApplication sharedApplication] setStatusBarStyle:self.previousStatusBarStyle];\n    \n    [self dismissViewControllerAnimated:animated completion:completion];\n}\n\n- (BOOL)wantsWindowToBecomeKey\n{\n    return self.previousKeyWindow != nil;\n}\n\n- (void)toggleToolWithViewControllerProvider:(UIViewController *(^)(void))future completion:(void(^)(void))completion\n{\n    if (self.presentedViewController) {\n        [self resignKeyAndDismissViewControllerAnimated:YES completion:completion];\n    } else {\n        [self makeKeyAndPresentViewController:future() animated:YES completion:completion];\n    }\n}\n\n#pragma mark - Keyboard Shortcut Helpers\n\n- (void)toggleSelectTool\n{\n    if (self.currentMode == FLEXExplorerModeSelect) {\n        self.currentMode = FLEXExplorerModeDefault;\n    } else {\n        self.currentMode = FLEXExplorerModeSelect;\n    }\n}\n\n- (void)toggleMoveTool\n{\n    if (self.currentMode == FLEXExplorerModeMove) {\n        self.currentMode = FLEXExplorerModeDefault;\n    } else {\n        self.currentMode = FLEXExplorerModeMove;\n    }\n}\n\n- (void)toggleViewsTool\n{\n    [self toggleViewsToolWithCompletion:nil];\n}\n\n- (void)toggleViewsToolWithCompletion:(void(^)(void))completion\n{\n    [self toggleToolWithViewControllerProvider:^UIViewController *{\n        NSArray<UIView *> *allViews = [self allViewsInHierarchy];\n        NSDictionary *depthsForViews = [self hierarchyDepthsForViews:allViews];\n        FLEXHierarchyTableViewController *hierarchyTVC = [[FLEXHierarchyTableViewController alloc] initWithViews:allViews viewsAtTap:self.viewsAtTapPoint selectedView:self.selectedView depths:depthsForViews];\n        hierarchyTVC.delegate = self;\n        return [[UINavigationController alloc] initWithRootViewController:hierarchyTVC];\n    } completion:^{\n        if (completion) {\n            completion();\n        }\n    }];\n}\n\n- (void)toggleMenuTool\n{\n    [self toggleToolWithViewControllerProvider:^UIViewController *{\n        FLEXGlobalsTableViewController *globalsViewController = [[FLEXGlobalsTableViewController alloc] init];\n        globalsViewController.delegate = self;\n        [FLEXGlobalsTableViewController setApplicationWindow:[[UIApplication sharedApplication] keyWindow]];\n        return [[UINavigationController alloc] initWithRootViewController:globalsViewController];\n    } completion:nil];\n}\n\n- (void)handleDownArrowKeyPressed\n{\n    if (self.currentMode == FLEXExplorerModeMove) {\n        CGRect frame = self.selectedView.frame;\n        frame.origin.y += 1.0 / [[UIScreen mainScreen] scale];\n        self.selectedView.frame = frame;\n    } else if (self.currentMode == FLEXExplorerModeSelect && [self.viewsAtTapPoint count] > 0) {\n        NSInteger selectedViewIndex = [self.viewsAtTapPoint indexOfObject:self.selectedView];\n        if (selectedViewIndex > 0) {\n            self.selectedView = [self.viewsAtTapPoint objectAtIndex:selectedViewIndex - 1];\n        }\n    }\n}\n\n- (void)handleUpArrowKeyPressed\n{\n    if (self.currentMode == FLEXExplorerModeMove) {\n        CGRect frame = self.selectedView.frame;\n        frame.origin.y -= 1.0 / [[UIScreen mainScreen] scale];\n        self.selectedView.frame = frame;\n    } else if (self.currentMode == FLEXExplorerModeSelect && [self.viewsAtTapPoint count] > 0) {\n        NSInteger selectedViewIndex = [self.viewsAtTapPoint indexOfObject:self.selectedView];\n        if (selectedViewIndex < [self.viewsAtTapPoint count] - 1) {\n            self.selectedView = [self.viewsAtTapPoint objectAtIndex:selectedViewIndex + 1];\n        }\n    }\n}\n\n- (void)handleRightArrowKeyPressed\n{\n    if (self.currentMode == FLEXExplorerModeMove) {\n        CGRect frame = self.selectedView.frame;\n        frame.origin.x += 1.0 / [[UIScreen mainScreen] scale];\n        self.selectedView.frame = frame;\n    }\n}\n\n- (void)handleLeftArrowKeyPressed\n{\n    if (self.currentMode == FLEXExplorerModeMove) {\n        CGRect frame = self.selectedView.frame;\n        frame.origin.x -= 1.0 / [[UIScreen mainScreen] scale];\n        self.selectedView.frame = frame;\n    }\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ExplorerInterface/FLEXWindow.h",
    "content": "//\n//  FLEXWindow.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/13/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@protocol FLEXWindowEventDelegate;\n\n@interface FLEXWindow : UIWindow\n\n@property (nonatomic, weak) id <FLEXWindowEventDelegate> eventDelegate;\n\n@end\n\n@protocol FLEXWindowEventDelegate <NSObject>\n\n- (BOOL)shouldHandleTouchAtPoint:(CGPoint)pointInWindow;\n- (BOOL)canBecomeKeyWindow;\n\n@end\n"
  },
  {
    "path": "FLEX/ExplorerInterface/FLEXWindow.m",
    "content": "//\n//  FLEXWindow.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/13/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXWindow.h\"\n#import <objc/runtime.h>\n\n@implementation FLEXWindow\n\n- (id)initWithFrame:(CGRect)frame\n{\n    self = [super initWithFrame:frame];\n    if (self) {\n        self.backgroundColor = [UIColor clearColor];\n        // Some apps have windows at UIWindowLevelStatusBar + n.\n        // If we make the window level too high, we block out UIAlertViews.\n        // There's a balance between staying above the app's windows and staying below alerts.\n        // UIWindowLevelStatusBar + 100 seems to hit that balance.\n        self.windowLevel = UIWindowLevelStatusBar + 100.0;\n    }\n    return self;\n}\n\n- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event\n{\n    BOOL pointInside = NO;\n    if ([self.eventDelegate shouldHandleTouchAtPoint:point]) {\n        pointInside = [super pointInside:point withEvent:event];\n    }\n    return pointInside;\n}\n\n- (BOOL)shouldAffectStatusBarAppearance\n{\n    return [self isKeyWindow];\n}\n\n- (BOOL)canBecomeKeyWindow\n{\n    return [self.eventDelegate canBecomeKeyWindow];\n}\n\n+ (void)initialize\n{\n    // This adds a method (superclass override) at runtime which gives us the status bar behavior we want.\n    // The FLEX window is intended to be an overlay that generally doesn't affect the app underneath.\n    // Most of the time, we want the app's main window(s) to be in control of status bar behavior.\n    // Done at runtime with an obfuscated selector because it is private API. But you shoudn't ship this to the App Store anyways...\n    NSString *canAffectSelectorString = [@[@\"_can\", @\"Affect\", @\"Status\", @\"Bar\", @\"Appearance\"] componentsJoinedByString:@\"\"];\n    SEL canAffectSelector = NSSelectorFromString(canAffectSelectorString);\n    Method shouldAffectMethod = class_getInstanceMethod(self, @selector(shouldAffectStatusBarAppearance));\n    IMP canAffectImplementation = method_getImplementation(shouldAffectMethod);\n    class_addMethod(self, canAffectSelector, canAffectImplementation, method_getTypeEncoding(shouldAffectMethod));\n\n    // One more...\n    NSString *canBecomeKeySelectorString = [NSString stringWithFormat:@\"_%@\", NSStringFromSelector(@selector(canBecomeKeyWindow))];\n    SEL canBecomeKeySelector = NSSelectorFromString(canBecomeKeySelectorString);\n    Method canBecomeKeyMethod = class_getInstanceMethod(self, @selector(canBecomeKeyWindow));\n    IMP canBecomeKeyImplementation = method_getImplementation(canBecomeKeyMethod);\n    class_addMethod(self, canBecomeKeySelector, canBecomeKeyImplementation, method_getTypeEncoding(canBecomeKeyMethod));\n}\n\n@end\n"
  },
  {
    "path": "FLEX/FLEX.h",
    "content": "//\n//  FLEX.h\n//  FLEX\n//\n//  Created by Eric Horacek on 7/18/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import <FLEX/FLEXManager.h>\n"
  },
  {
    "path": "FLEX/FLEXManager.h",
    "content": "//\n//  FLEXManager.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/4/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n\n@interface FLEXManager : NSObject\n\n+ (instancetype)sharedManager;\n\n@property (nonatomic, readonly) BOOL isHidden;\n\n- (void)showExplorer;\n- (void)hideExplorer;\n- (void)toggleExplorer;\n\n#pragma mark - Network Debugging\n\n/// If this property is set to YES, FLEX will swizzle NSURLConnection*Delegate and NSURLSession*Delegate methods\n/// on classes that conform to the protocols. This allows you to view network activity history from the main FLEX menu.\n/// Full responses are kept temporarily in a size-limited cache and may be pruned under memory pressure.\n@property (nonatomic, assign, getter=isNetworkDebuggingEnabled) BOOL networkDebuggingEnabled;\n\n/// Defaults to 25 MB if never set. Values set here are presisted across launches of the app.\n/// The response cache uses an NSCache, so it may purge prior to hitting the limit when the app is under memory pressure.\n@property (nonatomic, assign) NSUInteger networkResponseCacheByteLimit;\n\n/// Requests whose host ends with one of the blacklisted entries in this array will be not be recorded (eg. google.com).\n/// Wildcard or subdomain entries are not required (eg. google.com will match any subdomain under google.com).\n/// Useful to remove requests that are typically noisy, such as analytics requests that you aren't interested in tracking.\n@property (nonatomic, copy) NSArray<NSString *> *networkRequestHostBlacklist;\n\n\n#pragma mark - Keyboard Shortcuts\n\n/// Simulator keyboard shortcuts are enabled by default.\n/// The shortcuts will not fire when there is an active text field, text view, or other responder accepting key input.\n/// You can disable keyboard shortcuts if you have existing keyboard shortcuts that conflict with FLEX, or if you like doing things the hard way ;)\n/// Keyboard shortcuts are always disabled (and support is compiled out) in non-simulator builds\n@property (nonatomic, assign) BOOL simulatorShortcutsEnabled;\n\n/// Adds an action to run when the specified key & modifier combination is pressed\n/// @param key A single character string matching a key on the keyboard\n/// @param modifiers Modifier keys such as shift, command, or alt/option\n/// @param action The block to run on the main thread when the key & modifier combination is recognized.\n/// @param description Shown the the keyboard shortcut help menu, which is accessed via the '?' key.\n/// @note The action block will be retained for the duration of the application. You may want to use weak references.\n/// @note FLEX registers several default keyboard shortcuts. Use the '?' key to see a list of shortcuts.\n- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description;\n\n#pragma mark - Extensions\n\n/// Default database password is @c nil by default.\n/// Set this to the password you want the databases to open with.\n@property (copy, nonatomic) NSString *defaultSqliteDatabasePassword;\n\n/// Adds an entry at the bottom of the list of Global State items. Call this method before this view controller is displayed.\n/// @param entryName The string to be displayed in the cell.\n/// @param objectFutureBlock When you tap on the row, information about the object returned by this block will be displayed.\n/// Passing a block that returns an object allows you to display information about an object whose actual pointer may change at runtime (e.g. +currentUser)\n/// @note This method must be called from the main thread.\n/// The objectFutureBlock will be invoked from the main thread and may return nil.\n/// @note The passed block will be copied and retain for the duration of the application, you may want to use __weak references.\n- (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock;\n\n/// Adds an entry at the bottom of the list of Global State items. Call this method before this view controller is displayed.\n/// @param entryName The string to be displayed in the cell.\n/// @param viewControllerFutureBlock When you tap on the row, view controller returned by this block will be pushed on the navigation controller stack.\n/// @note This method must be called from the main thread.\n/// The viewControllerFutureBlock will be invoked from the main thread and may not return nil.\n/// @note The passed block will be copied and retain for the duration of the application, you may want to use __weak references.\n- (void)registerGlobalEntryWithName:(NSString *)entryName\n          viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXDatabaseManager.h",
    "content": "//\n//  PTDatabaseManager.h\n//  Derived from:\n//\n//  FMDatabase.h\n//  FMDB( https://github.com/ccgus/fmdb )\n//\n//  Created by Peng Tao on 15/11/23.\n//\n//  Licensed to Flying Meat Inc. under one or more contributor license agreements.\n//  See the LICENSE file distributed with this work for the terms under\n//  which Flying Meat Inc. licenses this file to you.\n\n#import <Foundation/Foundation.h>\n\n@protocol FLEXDatabaseManager <NSObject>\n\n@required\n- (instancetype)initWithPath:(NSString*)path;\n\n- (BOOL)open;\n- (NSArray<NSDictionary<NSString *, id> *> *)queryAllTables;\n- (NSArray<NSString *> *)queryAllColumnsWithTableName:(NSString *)tableName;\n- (NSArray<NSDictionary<NSString *, id> *> *)queryAllDataWithTableName:(NSString *)tableName;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.h",
    "content": "//\n//  PTMultiColumnTableView.h\n//  PTMultiColumnTableViewDemo\n//\n//  Created by Peng Tao on 15/11/16.\n//  Copyright © 2015年 Peng Tao. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FLEXTableColumnHeader.h\"\n\n@class FLEXMultiColumnTableView;\n\n@protocol FLEXMultiColumnTableViewDelegate <NSObject>\n\n@required\n- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didTapLabelWithText:(NSString *)text;\n- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didTapHeaderWithText:(NSString *)text sortType:(FLEXTableColumnHeaderSortType)sortType;\n\n@end\n\n@protocol FLEXMultiColumnTableViewDataSource <NSObject>\n\n@required\n\n- (NSInteger)numberOfColumnsInTableView:(FLEXMultiColumnTableView *)tableView;\n- (NSInteger)numberOfRowsInTableView:(FLEXMultiColumnTableView *)tableView;\n- (NSString *)columnNameInColumn:(NSInteger)column;\n- (NSString *)rowNameInRow:(NSInteger)row;\n- (NSString *)contentAtColumn:(NSInteger)column row:(NSInteger)row;\n- (NSArray *)contentAtRow:(NSInteger)row;\n\n- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView widthForContentCellInColumn:(NSInteger)column;\n- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView heightForContentCellInRow:(NSInteger)row;\n- (CGFloat)heightForTopHeaderInTableView:(FLEXMultiColumnTableView *)tableView;\n- (CGFloat)widthForLeftHeaderInTableView:(FLEXMultiColumnTableView *)tableView;\n\n@end\n\n\n@interface FLEXMultiColumnTableView : UIView\n\n@property (nonatomic, weak) id<FLEXMultiColumnTableViewDataSource>dataSource;\n@property (nonatomic, weak) id<FLEXMultiColumnTableViewDelegate>delegate;\n\n- (void)reloadData;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m",
    "content": "//\n//  PTMultiColumnTableView.m\n//  PTMultiColumnTableViewDemo\n//\n//  Created by Peng Tao on 15/11/16.\n//  Copyright © 2015年 Peng Tao. All rights reserved.\n//\n\n#import \"FLEXMultiColumnTableView.h\"\n#import \"FLEXTableContentCell.h\"\n#import \"FLEXTableLeftCell.h\"\n\n@interface FLEXMultiColumnTableView ()\n<UITableViewDataSource, UITableViewDelegate,UIScrollViewDelegate, FLEXTableContentCellDelegate>\n\n@property (nonatomic, strong) UIScrollView *contentScrollView;\n@property (nonatomic, strong) UIScrollView *headerScrollView;\n@property (nonatomic, strong) UITableView  *leftTableView;\n@property (nonatomic, strong) UITableView  *contentTableView;\n@property (nonatomic, strong) UIView       *leftHeader;\n\n@property (nonatomic, strong) NSDictionary<NSString *, NSNumber *> *sortStatusDict;\n@property (nonatomic, strong) NSArray *rowData;\n@end\n\nstatic const CGFloat kColumnMargin = 1;\n\n@implementation FLEXMultiColumnTableView\n\n\n- (instancetype)initWithFrame:(CGRect)frame\n{\n    self = [super initWithFrame:frame];\n    if (self) {\n        [self loadUI];\n    }\n    return self;\n}\n\n- (void)didMoveToSuperview\n{\n    [super didMoveToSuperview];\n    [self reloadData];\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    \n    CGFloat width  = self.frame.size.width;\n    CGFloat height = self.frame.size.height;\n    CGFloat topheaderHeight = [self topHeaderHeight];\n    CGFloat leftHeaderWidth = [self leftHeaderWidth];\n    \n    CGFloat contentWidth = 0.0;\n    NSInteger rowsCount = [self numberOfColumns];\n    for (int i = 0; i < rowsCount; i++) {\n        contentWidth += [self contentWidthForColumn:i];\n    }\n    \n    self.leftTableView.frame           = CGRectMake(0, topheaderHeight, leftHeaderWidth, height - topheaderHeight);\n    self.headerScrollView.frame        = CGRectMake(leftHeaderWidth, 0, width - leftHeaderWidth, topheaderHeight);\n    self.headerScrollView.contentSize  = CGSizeMake( self.contentTableView.frame.size.width, self.headerScrollView.frame.size.height);\n    self.contentTableView.frame        = CGRectMake(0, 0, contentWidth + [self numberOfColumns] * [self columnMargin] , height - topheaderHeight);\n    self.contentScrollView.frame       = CGRectMake(leftHeaderWidth, topheaderHeight, width - leftHeaderWidth, height - topheaderHeight);\n    self.contentScrollView.contentSize = self.contentTableView.frame.size;\n    self.leftHeader.frame              = CGRectMake(0, 0, [self leftHeaderWidth], [self topHeaderHeight]);\n}\n\n\n- (void)loadUI\n{\n    [self loadHeaderScrollView];\n    [self loadContentScrollView];\n    [self loadLeftView];\n}\n\n- (void)reloadData\n{\n    [self loadLeftViewData];\n    [self loadContentData];\n    [self loadHeaderData];\n}\n\n#pragma mark - UI\n\n- (void)loadHeaderScrollView\n{\n    UIScrollView *headerScrollView = [[UIScrollView alloc] init];\n    headerScrollView.delegate      = self;\n    self.headerScrollView          = headerScrollView;\n    self.headerScrollView.backgroundColor =  [UIColor colorWithWhite:0.803 alpha:0.850];\n    \n    [self addSubview:headerScrollView];\n}\n\n- (void)loadContentScrollView\n{\n    \n    UIScrollView *scrollView = [[UIScrollView alloc] init];\n    scrollView.bounces       = NO;\n    scrollView.delegate      = self;\n    \n    UITableView *tableView   = [[UITableView alloc] init];\n    tableView.delegate       = self;\n    tableView.dataSource     = self;\n    tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    \n    [self addSubview:scrollView];\n    [scrollView addSubview:tableView];\n    \n    self.contentScrollView = scrollView;\n    self.contentTableView    = tableView;\n    \n}\n\n- (void)loadLeftView\n{\n    UITableView *leftTableView = [[UITableView alloc] init];\n    leftTableView.delegate       = self;\n    leftTableView.dataSource     = self;\n    leftTableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    self.leftTableView           = leftTableView;\n    [self addSubview:leftTableView];\n    \n    UIView *leftHeader = [[UIView alloc] init];\n    leftHeader.backgroundColor = [UIColor colorWithWhite:0.950 alpha:0.668];\n    self.leftHeader            = leftHeader;\n    [self addSubview:leftHeader];\n    \n}\n\n\n#pragma mark - Data\n\n- (void)loadHeaderData\n{\n    NSArray<UIView *> *subviews = self.headerScrollView.subviews;\n    \n    for (UIView *subview in subviews) {\n        [subview removeFromSuperview];\n    }\n    CGFloat x = 0.0;\n    CGFloat w = 0.0;\n    for (int i = 0; i < [self numberOfColumns] ; i++) {\n        w = [self contentWidthForColumn:i] + [self columnMargin];\n        \n        FLEXTableColumnHeader *cell = [[FLEXTableColumnHeader alloc] initWithFrame:CGRectMake(x, 0, w, [self topHeaderHeight] - 1)];\n        cell.label.text = [self columnTitleForColumn:i];\n        [self.headerScrollView addSubview:cell];\n        \n        FLEXTableColumnHeaderSortType type = [self.sortStatusDict[[self columnTitleForColumn:i]] integerValue];\n        [cell changeSortStatusWithType:type];\n        \n        UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self\n                                                                                  action:@selector(contentHeaderTap:)];\n        [cell addGestureRecognizer:gesture];\n        cell.userInteractionEnabled = YES;\n        \n        x = x + w;\n    }\n}\n\n- (void)contentHeaderTap:(UIGestureRecognizer *)gesture\n{\n    FLEXTableColumnHeader *header = (FLEXTableColumnHeader *)gesture.view;\n    NSString *string = header.label.text;\n    FLEXTableColumnHeaderSortType currentType = [self.sortStatusDict[string] integerValue];\n    FLEXTableColumnHeaderSortType newType ;\n    \n    switch (currentType) {\n        case FLEXTableColumnHeaderSortTypeNone:\n            newType = FLEXTableColumnHeaderSortTypeAsc;\n            break;\n        case FLEXTableColumnHeaderSortTypeAsc:\n            newType = FLEXTableColumnHeaderSortTypeDesc;\n            break;\n        case FLEXTableColumnHeaderSortTypeDesc:\n            newType = FLEXTableColumnHeaderSortTypeAsc;\n            break;\n    }\n    \n    self.sortStatusDict = @{header.label.text : @(newType)};\n    [header changeSortStatusWithType:newType];\n    [self.delegate multiColumnTableView:self didTapHeaderWithText:string sortType:newType];\n    \n}\n\n- (void)loadContentData\n{\n    [self.contentTableView reloadData];\n}\n\n- (void)loadLeftViewData\n{\n    [self.leftTableView reloadData];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView\n         cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    UIColor *backgroundColor = [UIColor whiteColor];\n    if (indexPath.row % 2 != 0) {\n        backgroundColor = [UIColor colorWithWhite:0.950 alpha:0.750];\n    }\n    \n    if (tableView != self.leftTableView) {\n        self.rowData = [self.dataSource contentAtRow:indexPath.row];\n        FLEXTableContentCell *cell = [FLEXTableContentCell cellWithTableView:tableView\n                                                                columnNumber:[self numberOfColumns]];\n        cell.contentView.backgroundColor = backgroundColor;\n        cell.delegate = self;\n        \n        for (int i = 0 ; i < cell.labels.count; i++) {\n            \n            UILabel *label  = cell.labels[i];\n            label.textColor = [UIColor blackColor];\n            \n            NSString *content = [NSString stringWithFormat:@\"%@\",self.rowData[i]];\n            if ([content isEqualToString:@\"<null>\"]) {\n                label.textColor = [UIColor lightGrayColor];\n                content = @\"NULL\";\n            }\n            label.text            = content;\n            label.backgroundColor = backgroundColor;\n        }\n        return cell;\n    }\n    else {\n        FLEXTableLeftCell *cell          = [FLEXTableLeftCell cellWithTableView:tableView];\n        cell.contentView.backgroundColor = backgroundColor;\n        cell.titlelabel.text             = [self rowTitleForRow:indexPath.row];\n        return cell;\n    }\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return [self.dataSource numberOfRowsInTableView:self];\n}\n\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    return [self.dataSource multiColumnTableView:self heightForContentCellInRow:indexPath.row];\n}\n\n\n- (void)scrollViewDidScroll:(UIScrollView *)scrollView\n{\n    if (scrollView == self.contentScrollView) {\n        self.headerScrollView.contentOffset = scrollView.contentOffset;\n    }\n    else if (scrollView == self.headerScrollView) {\n        self.contentScrollView.contentOffset = scrollView.contentOffset;\n    }\n    else if (scrollView == self.leftTableView) {\n        self.contentTableView.contentOffset = scrollView.contentOffset;\n    }\n    else if (scrollView == self.contentTableView) {\n        self.leftTableView.contentOffset = scrollView.contentOffset;\n    }\n}\n\n#pragma mark -\n#pragma mark UITableView Delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    if (tableView == self.leftTableView) {\n        [self.contentTableView selectRowAtIndexPath:indexPath\n                                           animated:NO\n                                     scrollPosition:UITableViewScrollPositionNone];\n    }\n    else if (tableView == self.contentTableView) {\n        [self.leftTableView selectRowAtIndexPath:indexPath\n                                        animated:NO\n                                  scrollPosition:UITableViewScrollPositionNone];\n    }\n}\n\n#pragma mark -\n#pragma mark DataSource Accessor\n\n- (NSInteger)numberOfrows\n{\n    return [self.dataSource numberOfRowsInTableView:self];\n}\n\n- (NSInteger)numberOfColumns\n{\n    return [self.dataSource numberOfColumnsInTableView:self];\n}\n\n- (NSString *)columnTitleForColumn:(NSInteger)column\n{\n    return [self.dataSource columnNameInColumn:column];\n}\n\n- (NSString *)rowTitleForRow:(NSInteger)row\n{\n    return [self.dataSource rowNameInRow:row];\n}\n\n- (NSString *)contentAtColumn:(NSInteger)column row:(NSInteger)row;\n{\n    return [self.dataSource contentAtColumn:column row:row];\n}\n\n- (CGFloat)contentWidthForColumn:(NSInteger)column\n{\n    return [self.dataSource multiColumnTableView:self widthForContentCellInColumn:column];\n}\n\n- (CGFloat)contentHeightForRow:(NSInteger)row\n{\n    return [self.dataSource multiColumnTableView:self heightForContentCellInRow:row];\n}\n\n- (CGFloat)topHeaderHeight\n{\n    return [self.dataSource heightForTopHeaderInTableView:self];\n}\n\n- (CGFloat)leftHeaderWidth\n{\n    return [self.dataSource widthForLeftHeaderInTableView:self];\n}\n\n- (CGFloat)columnMargin\n{\n    return kColumnMargin;\n}\n\n\n- (void)tableContentCell:(FLEXTableContentCell *)tableView labelDidTapWithText:(NSString *)text\n{\n    [self.delegate multiColumnTableView:self didTapLabelWithText:text];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.h",
    "content": "//\n//  FLEXRealmDatabaseManager.h\n//  FLEX\n//\n//  Created by Tim Oliver on 28/01/2016.\n//  Copyright © 2016 Realm. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"FLEXDatabaseManager.h\"\n\n@interface FLEXRealmDatabaseManager : NSObject <FLEXDatabaseManager>\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m",
    "content": "//\n//  FLEXRealmDatabaseManager.m\n//  FLEX\n//\n//  Created by Tim Oliver on 28/01/2016.\n//  Copyright © 2016 Realm. All rights reserved.\n//\n\n#import \"FLEXRealmDatabaseManager.h\"\n\n#if __has_include(<Realm/Realm.h>)\n#import <Realm/Realm.h>\n#import <Realm/RLMRealm_Dynamic.h>\n#else\n#import \"FLEXRealmDefines.h\"\n#endif\n\n@interface FLEXRealmDatabaseManager ()\n\n@property (nonatomic, copy) NSString *path;\n@property (nonatomic, strong) RLMRealm * realm;\n\n@end\n\n//#endif\n\n@implementation FLEXRealmDatabaseManager\n\n- (instancetype)initWithPath:(NSString*)aPath\n{\n    Class realmClass = NSClassFromString(@\"RLMRealm\");\n    if (realmClass == nil) {\n        return nil;\n    }\n    \n    self = [super init];\n    \n    if (self) {\n        _path = aPath;\n    }\n    return self;\n}\n\n- (BOOL)open\n{\n    Class realmClass = NSClassFromString(@\"RLMRealm\");\n    Class configurationClass = NSClassFromString(@\"RLMRealmConfiguration\");\n    \n    if (realmClass == nil || configurationClass == nil) {\n        return NO;\n    }\n    \n    NSError *error = nil;\n    id configuration = [[configurationClass alloc] init];\n    [(RLMRealmConfiguration *)configuration setFileURL:[NSURL fileURLWithPath:self.path]];\n    self.realm = [realmClass realmWithConfiguration:configuration error:&error];\n    return (error == nil);\n}\n\n- (NSArray<NSDictionary<NSString *, id> *> *)queryAllTables\n{\n    NSMutableArray<NSDictionary<NSString *, id> *> *allTables = [NSMutableArray array];\n    RLMSchema *schema = [self.realm schema];\n    \n    for (RLMObjectSchema *objectSchema in schema.objectSchema) {\n        if (objectSchema.className == nil) {\n            continue;\n        }\n        \n        NSDictionary<NSString *, id> *dictionary = @{@\"name\":objectSchema.className};\n        [allTables addObject:dictionary];\n    }\n    \n    return allTables;\n}\n\n- (NSArray<NSString *> *)queryAllColumnsWithTableName:(NSString *)tableName\n{\n    RLMObjectSchema *objectSchema = [[self.realm schema] schemaForClassName:tableName];\n    if (objectSchema == nil) {\n        return nil;\n    }\n    \n    NSMutableArray<NSString *> *columnNames = [NSMutableArray array];\n    for (RLMProperty *property in objectSchema.properties) {\n        [columnNames addObject:property.name];\n    }\n    \n    return columnNames;\n}\n\n- (NSArray<NSDictionary<NSString *, id> *> *)queryAllDataWithTableName:(NSString *)tableName\n{\n    RLMObjectSchema *objectSchema = [[self.realm schema] schemaForClassName:tableName];\n    RLMResults *results = [self.realm allObjects:tableName];\n    if (results.count == 0 || objectSchema == nil) {\n        return nil;\n    }\n    \n    NSMutableArray<NSDictionary<NSString *, id> *> *allDataEntries = [NSMutableArray array];\n    for (RLMObject *result in results) {\n        NSMutableDictionary<NSString *, id> *entry = [NSMutableDictionary dictionary];\n        for (RLMProperty *property in objectSchema.properties) {\n            id value = [result valueForKey:property.name];\n            entry[property.name] = (value) ? (value) : [NSNull null];\n        }\n        \n        [allDataEntries addObject:entry];\n    }\n    \n    return allDataEntries;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDefines.h",
    "content": "//\n//  Realm.h\n//  FLEX\n//\n//  Created by Tim Oliver on 16/02/2016.\n//  Copyright © 2016 Realm. All rights reserved.\n//\n\n#if __has_include(<Realm/Realm.h>)\n#else\n\n@class RLMObject, RLMResults, RLMRealm, RLMRealmConfiguration, RLMSchema, RLMObjectSchema, RLMProperty;\n\n@interface RLMRealmConfiguration : NSObject\n@property (nonatomic, copy) NSURL *fileURL;\n@end\n\n@interface RLMRealm : NSObject\n@property (nonatomic, readonly) RLMSchema *schema;\n+ (RLMRealm *)realmWithConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error;\n- (RLMResults *)allObjects:(NSString *)className;\n@end\n\n@interface RLMSchema : NSObject\n@property (nonatomic, readonly) NSArray<RLMObjectSchema *> *objectSchema;\n- (RLMObjectSchema *)schemaForClassName:(NSString *)className;\n@end\n\n@interface RLMObjectSchema : NSObject\n@property (nonatomic, readonly) NSString *className;\n@property (nonatomic, readonly) NSArray<RLMProperty *> *properties;\n@end\n\n@interface RLMProperty : NSString\n@property (nonatomic, readonly) NSString *name;\n@end\n\n@interface RLMResults : NSObject <NSFastEnumeration>\n@property (nonatomic, readonly) NSInteger count;\n@end\n\n@interface RLMObject : NSObject\n\n@end\n\n#endif\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.h",
    "content": "//\n//  PTDatabaseManager.h\n//  Derived from:\n//\n//  FMDatabase.h\n//  FMDB( https://github.com/ccgus/fmdb )\n//\n//  Created by Peng Tao on 15/11/23.\n//\n//  Licensed to Flying Meat Inc. under one or more contributor license agreements.\n//  See the LICENSE file distributed with this work for the terms under\n//  which Flying Meat Inc. licenses this file to you.\n\n#import <Foundation/Foundation.h>\n#import \"FLEXDatabaseManager.h\"\n\n@interface FLEXSQLiteDatabaseManager : NSObject <FLEXDatabaseManager>\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.m",
    "content": "//\n//  PTDatabaseManager.m\n//  PTDatabaseReader\n//\n//  Created by Peng Tao on 15/11/23.\n//  Copyright © 2015年 Peng Tao. All rights reserved.\n//\n\n#import \"FLEXSQLiteDatabaseManager.h\"\n#import \"FLEXManager.h\"\n#import <sqlite3.h>\n\n\nstatic NSString *const QUERY_TABLENAMES_SQL = @\"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name\";\n\n@implementation FLEXSQLiteDatabaseManager\n{\n    sqlite3* _db;\n    NSString* _databasePath;\n}\n\n- (instancetype)initWithPath:(NSString*)aPath\n{\n    self = [super init];\n    \n    if (self) {\n        _databasePath = [aPath copy];\n    }\n    return self;\n}\n\n- (BOOL)open {\n    if (_db) {\n        return YES;\n    }\n    int err = sqlite3_open([_databasePath UTF8String], &_db);\n\n#if SQLITE_HAS_CODEC\n    NSString *defaultSqliteDatabasePassword = [FLEXManager sharedManager].defaultSqliteDatabasePassword;\n\n    if (defaultSqliteDatabasePassword) {\n        const char *key = defaultSqliteDatabasePassword.UTF8String;\n\n        sqlite3_key(_db, key, (int)strlen(key));\n    }\n#endif\n\n    if(err != SQLITE_OK) {\n        NSLog(@\"error opening!: %d\", err);\n        return NO;\n    }\n    return YES;\n}\n\n- (BOOL)close {\n    if (!_db) {\n        return YES;\n    }\n    \n    int  rc;\n    BOOL retry;\n    BOOL triedFinalizingOpenStatements = NO;\n    \n    do {\n        retry   = NO;\n        rc      = sqlite3_close(_db);\n        if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {\n            if (!triedFinalizingOpenStatements) {\n                triedFinalizingOpenStatements = YES;\n                sqlite3_stmt *pStmt;\n                while ((pStmt = sqlite3_next_stmt(_db, nil)) !=0) {\n                    NSLog(@\"Closing leaked statement\");\n                    sqlite3_finalize(pStmt);\n                    retry = YES;\n                }\n            }\n        }\n        else if (SQLITE_OK != rc) {\n            NSLog(@\"error closing!: %d\", rc);\n        }\n    }\n    while (retry);\n    \n    _db = nil;\n    return YES;\n}\n\n\n- (NSArray<NSDictionary<NSString *, id> *> *)queryAllTables\n{\n    return [self executeQuery:QUERY_TABLENAMES_SQL];\n}\n\n- (NSArray<NSString *> *)queryAllColumnsWithTableName:(NSString *)tableName\n{\n    NSString *sql = [NSString stringWithFormat:@\"PRAGMA table_info('%@')\",tableName];\n    NSArray<NSDictionary<NSString *, id> *> *resultArray =  [self executeQuery:sql];\n    NSMutableArray<NSString *> *array = [NSMutableArray array];\n    for (NSDictionary<NSString *, id> *dict in resultArray) {\n        NSString *columnName = (NSString *)dict[@\"name\"] ?: @\"\";\n        [array addObject:columnName];\n    }\n    return array;\n}\n\n- (NSArray<NSDictionary<NSString *, id> *> *)queryAllDataWithTableName:(NSString *)tableName\n{\n    NSString *sql = [NSString stringWithFormat:@\"SELECT * FROM %@\",tableName];\n    return [self executeQuery:sql];\n}\n\n#pragma mark -\n#pragma mark - Private\n\n- (NSArray<NSDictionary<NSString *, id> *> *)executeQuery:(NSString *)sql\n{\n    [self open];\n    NSMutableArray<NSDictionary<NSString *, id> *> *resultArray = [NSMutableArray array];\n    sqlite3_stmt *pstmt;\n    if (sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pstmt, 0) == SQLITE_OK) {\n        while (sqlite3_step(pstmt) == SQLITE_ROW) {\n            NSUInteger num_cols = (NSUInteger)sqlite3_data_count(pstmt);\n            if (num_cols > 0) {\n                NSMutableDictionary<NSString *, id> *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols];\n                \n                int columnCount = sqlite3_column_count(pstmt);\n                \n                int columnIdx = 0;\n                for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {\n                    \n                    NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name(pstmt, columnIdx)];\n                    id objectValue = [self objectForColumnIndex:columnIdx stmt:pstmt];\n                    [dict setObject:objectValue forKey:columnName];\n                }\n                [resultArray addObject:dict];\n            }\n        }\n    }\n    [self close];\n    return resultArray;\n}\n\n\n- (id)objectForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt*)stmt {\n    int columnType = sqlite3_column_type(stmt, columnIdx);\n    \n    id returnValue = nil;\n    \n    if (columnType == SQLITE_INTEGER) {\n        returnValue =  [NSNumber numberWithLongLong:sqlite3_column_int64(stmt, columnIdx)];\n    }\n    else if (columnType == SQLITE_FLOAT) {\n        returnValue = [NSNumber numberWithDouble:sqlite3_column_double(stmt, columnIdx)];\n    }\n    else if (columnType == SQLITE_BLOB) {\n        returnValue = [self dataForColumnIndex:columnIdx stmt:stmt];\n    }\n    else {\n        //default to a string for everything else\n        returnValue = [self stringForColumnIndex:columnIdx stmt:stmt];\n    }\n    \n    if (returnValue == nil) {\n        returnValue = [NSNull null];\n    }\n    \n    return returnValue;\n}\n\n- (NSString *)stringForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt *)stmt {\n    \n    if (sqlite3_column_type(stmt, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {\n        return nil;\n    }\n    \n    const char *c = (const char *)sqlite3_column_text(stmt, columnIdx);\n    \n    if (!c) {\n        // null row.\n        return nil;\n    }\n    \n    return [NSString stringWithUTF8String:c];\n}\n\n- (NSData *)dataForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt *)stmt{\n    \n    if (sqlite3_column_type(stmt, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {\n        return nil;\n    }\n    \n    const char *dataBuffer = sqlite3_column_blob(stmt, columnIdx);\n    int dataSize = sqlite3_column_bytes(stmt, columnIdx);\n    \n    if (dataBuffer == NULL) {\n        return nil;\n    }\n    \n    return [NSData dataWithBytes:(const void *)dataBuffer length:(NSUInteger)dataSize];\n}\n\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.h",
    "content": "//\n//  FLEXTableContentHeaderCell.h\n//  UICatalog\n//\n//  Created by Peng Tao on 15/11/26.\n//  Copyright © 2015年 f. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\ntypedef NS_ENUM(NSUInteger, FLEXTableColumnHeaderSortType) {\n    FLEXTableColumnHeaderSortTypeNone = 0,\n    FLEXTableColumnHeaderSortTypeAsc,\n    FLEXTableColumnHeaderSortTypeDesc,\n};\n\n@interface FLEXTableColumnHeader : UIView\n\n@property (nonatomic, strong) UILabel *label;\n\n- (void)changeSortStatusWithType:(FLEXTableColumnHeaderSortType)type;\n\n@end\n\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.m",
    "content": "//\n//  FLEXTableContentHeaderCell.m\n//  UICatalog\n//\n//  Created by Peng Tao on 15/11/26.\n//  Copyright © 2015年 f. All rights reserved.\n//\n\n#import \"FLEXTableColumnHeader.h\"\n\n@implementation FLEXTableColumnHeader\n{\n    UILabel *_arrowLabel;\n}\n\n\n- (instancetype)initWithFrame:(CGRect)frame\n{\n    self = [super initWithFrame:frame];\n    if (self) {\n        self.backgroundColor = [UIColor whiteColor];\n        \n        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, frame.size.width - 25, frame.size.height)];\n        label.font = [UIFont systemFontOfSize:13.0];\n        [self addSubview:label];\n        self.label = label;\n        \n        \n        _arrowLabel = [[UILabel alloc] initWithFrame:CGRectMake(frame.size.width - 20, 0, 20, frame.size.height)];\n        _arrowLabel.font = [UIFont systemFontOfSize:13.0];\n        [self addSubview:_arrowLabel];\n        \n        UIView *line = [[UIView alloc] initWithFrame:CGRectMake(frame.size.width - 1, 2, 1, frame.size.height - 4)];\n        line.backgroundColor = [UIColor colorWithWhite:0.803 alpha:0.850];\n        [self addSubview:line];\n        \n    }\n    return self;\n}\n\n- (void)changeSortStatusWithType:(FLEXTableColumnHeaderSortType)type\n{\n    switch (type) {\n        case FLEXTableColumnHeaderSortTypeNone:\n            _arrowLabel.text = @\"\";\n            break;\n        case FLEXTableColumnHeaderSortTypeAsc:\n            _arrowLabel.text = @\"⬆️\";\n            break;\n        case FLEXTableColumnHeaderSortTypeDesc:\n            _arrowLabel.text = @\"⬇️\";\n            break;\n    }\n}\n\n\n\n\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentCell.h",
    "content": "//\n//  FLEXTableContentCell.h\n//  UICatalog\n//\n//  Created by Peng Tao on 15/11/24.\n//  Copyright © 2015年 f. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@class FLEXTableContentCell;\n@protocol FLEXTableContentCellDelegate <NSObject>\n\n@optional\n- (void)tableContentCell:(FLEXTableContentCell *)tableView labelDidTapWithText:(NSString *)text;\n\n@end\n\n@interface FLEXTableContentCell : UITableViewCell\n\n@property (nonatomic, strong) NSArray<UILabel *> *labels;\n\n@property (nonatomic, weak) id<FLEXTableContentCellDelegate> delegate;\n\n+ (instancetype)cellWithTableView:(UITableView *)tableView columnNumber:(NSInteger)number;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentCell.m",
    "content": "//\n//  FLEXTableContentCell.m\n//  UICatalog\n//\n//  Created by Peng Tao on 15/11/24.\n//  Copyright © 2015年 f. All rights reserved.\n//\n\n#import \"FLEXTableContentCell.h\"\n#import \"FLEXMultiColumnTableView.h\"\n\n@interface FLEXTableContentCell ()\n\n@end\n\n@implementation FLEXTableContentCell\n\n+ (instancetype)cellWithTableView:(UITableView *)tableView columnNumber:(NSInteger)number;\n{\n    static NSString *identifier = @\"FLEXTableContentCell\";\n    FLEXTableContentCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];\n    if (!cell) {\n        cell = [[FLEXTableContentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];\n        NSMutableArray<UILabel *> *labels = [NSMutableArray array];\n        for (int i = 0; i < number ; i++) {\n            UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];\n            label.backgroundColor = [UIColor whiteColor];\n            label.font            = [UIFont systemFontOfSize:13.0];\n            label.textAlignment   = NSTextAlignmentLeft;\n            label.backgroundColor = [UIColor greenColor];\n            [labels addObject:label];\n            \n            UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:cell\n                                                                                      action:@selector(labelDidTap:)];\n            [label addGestureRecognizer:gesture];\n            label.userInteractionEnabled = YES;\n            \n            [cell.contentView addSubview:label];\n            cell.contentView.backgroundColor = [UIColor whiteColor];\n        }\n        cell.labels = labels;\n    }\n    return cell;\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    CGFloat labelWidth  = self.contentView.frame.size.width / self.labels.count;\n    CGFloat labelHeight = self.contentView.frame.size.height;\n    for (int i = 0; i < self.labels.count; i++) {\n        UILabel *label = self.labels[i];\n        label.frame = CGRectMake(labelWidth * i + 5, 0, (labelWidth - 10), labelHeight);\n    }\n}\n\n\n- (void)labelDidTap:(UIGestureRecognizer *)gesture\n{\n    UILabel *label = (UILabel *)gesture.view;\n    if ([self.delegate respondsToSelector:@selector(tableContentCell:labelDidTapWithText:)]) {\n        [self.delegate tableContentCell:self labelDidTapWithText:label.text];\n    }\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.h",
    "content": "//\n//  PTTableContentViewController.h\n//  PTDatabaseReader\n//\n//  Created by Peng Tao on 15/11/23.\n//  Copyright © 2015年 Peng Tao. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXTableContentViewController : UIViewController\n\n@property (nonatomic, strong) NSArray<NSString *> *columnsArray;\n@property (nonatomic, strong) NSArray<NSDictionary<NSString *, id> *> *contentsArray;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m",
    "content": "//\n//  PTTableContentViewController.m\n//  PTDatabaseReader\n//\n//  Created by Peng Tao on 15/11/23.\n//  Copyright © 2015年 Peng Tao. All rights reserved.\n//\n\n#import \"FLEXTableContentViewController.h\"\n#import \"FLEXMultiColumnTableView.h\"\n#import \"FLEXWebViewController.h\"\n\n\n@interface FLEXTableContentViewController ()<FLEXMultiColumnTableViewDataSource, FLEXMultiColumnTableViewDelegate>\n\n@property (nonatomic, strong) FLEXMultiColumnTableView *multiColumView;\n\n@end\n\n@implementation FLEXTableContentViewController\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.edgesForExtendedLayout = UIRectEdgeNone;\n    [self.view addSubview:self.multiColumView];\n}\n\n- (void)viewWillAppear:(BOOL)animated\n{\n    [super viewWillAppear:animated];\n    [self.multiColumView reloadData];\n}\n\n#pragma mark -\n\n#pragma mark init SubView\n- (FLEXMultiColumnTableView *)multiColumView {\n    if (!_multiColumView) {\n        _multiColumView = [[FLEXMultiColumnTableView alloc] initWithFrame:\n                           CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];\n        \n        _multiColumView.autoresizingMask          = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin;\n        _multiColumView.backgroundColor           = [UIColor whiteColor];\n        _multiColumView.dataSource                = self;\n        _multiColumView.delegate                  = self;\n    }\n    return _multiColumView;\n}\n#pragma mark MultiColumnTableView DataSource\n\n- (NSInteger)numberOfColumnsInTableView:(FLEXMultiColumnTableView *)tableView\n{\n    return self.columnsArray.count;\n}\n- (NSInteger)numberOfRowsInTableView:(FLEXMultiColumnTableView *)tableView\n{\n    return self.contentsArray.count;\n}\n\n\n- (NSString *)columnNameInColumn:(NSInteger)column\n{\n    return self.columnsArray[column];\n}\n\n\n- (NSString *)rowNameInRow:(NSInteger)row\n{\n    return [NSString stringWithFormat:@\"%ld\",(long)row];\n}\n\n- (NSString *)contentAtColumn:(NSInteger)column row:(NSInteger)row\n{\n    if (self.contentsArray.count > row) {\n        NSDictionary<NSString *, id> *dic = self.contentsArray[row];\n        if (self.contentsArray.count > column) {\n            return [NSString stringWithFormat:@\"%@\",[dic objectForKey:self.columnsArray[column]]];\n        }\n    }\n    return @\"\";\n}\n\n- (NSArray *)contentAtRow:(NSInteger)row\n{\n    NSMutableArray *result = [NSMutableArray array];\n    if (self.contentsArray.count > row) {\n        NSDictionary<NSString *, id> *dic = self.contentsArray[row];\n        for (int i = 0; i < self.columnsArray.count; i ++) {\n            [result addObject:dic[self.columnsArray[i]]];\n        }\n        return result;\n    }\n    return nil;\n}\n\n- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView\n      heightForContentCellInRow:(NSInteger)row\n{\n    return 40;\n}\n\n- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView\n    widthForContentCellInColumn:(NSInteger)column\n{\n    return 120;\n}\n\n- (CGFloat)heightForTopHeaderInTableView:(FLEXMultiColumnTableView *)tableView\n{\n    return 40;\n}\n\n- (CGFloat)widthForLeftHeaderInTableView:(FLEXMultiColumnTableView *)tableView\n{\n    NSString *str = [NSString stringWithFormat:@\"%lu\",(unsigned long)self.contentsArray.count];\n    NSDictionary<NSString *, id> *attrs = @{@\"NSFontAttributeName\":[UIFont systemFontOfSize:17.0]};\n    CGSize size =   [str boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, 14)\n                                      options:NSStringDrawingUsesLineFragmentOrigin\n                                   attributes:attrs context:nil].size;\n    return size.width + 20;\n}\n\n#pragma mark -\n#pragma mark MultiColumnTableView Delegate\n\n\n- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didTapLabelWithText:(NSString *)text\n{\n    FLEXWebViewController * detailViewController = [[FLEXWebViewController alloc] initWithText:text];\n    [self.navigationController pushViewController:detailViewController animated:YES];\n}\n\n- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didTapHeaderWithText:(NSString *)text sortType:(FLEXTableColumnHeaderSortType)sortType\n{\n    \n    NSArray<NSDictionary<NSString *, id> *> *sortContentData = [self.contentsArray sortedArrayUsingComparator:^NSComparisonResult(NSDictionary<NSString *, id> * obj1, NSDictionary<NSString *, id> * obj2) {\n        \n        if ([obj1 objectForKey:text] == [NSNull null]) {\n            return NSOrderedAscending;\n        }\n        if ([obj2 objectForKey:text] == [NSNull null]) {\n            return NSOrderedDescending;\n        }\n        \n        if (![[obj1 objectForKey:text] respondsToSelector:@selector(compare:)] && ![[obj2 objectForKey:text] respondsToSelector:@selector(compare:)]) {\n            return NSOrderedSame;\n        }\n        \n        NSComparisonResult result =  [[obj1 objectForKey:text] compare:[obj2 objectForKey:text]];\n        \n        return result;\n    }];\n    if (sortType == FLEXTableColumnHeaderSortTypeDesc) {\n        NSEnumerator *contentReverseEvumerator = [sortContentData reverseObjectEnumerator];\n        sortContentData = [NSArray arrayWithArray:[contentReverseEvumerator allObjects]];\n    }\n    \n    self.contentsArray = sortContentData;\n    [self.multiColumView reloadData];\n}\n\n#pragma mark -\n#pragma mark About Transition\n\n- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection\n              withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator\n{\n    [super willTransitionToTraitCollection:newCollection\n                 withTransitionCoordinator:coordinator];\n    [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) {\n        if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {\n            \n            self->_multiColumView.frame = CGRectMake(0, 32, self.view.frame.size.width, self.view.frame.size.height - 32);\n        }\n        else {\n            self->_multiColumView.frame = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64);\n        }\n        [self.view setNeedsLayout];\n    } completion:nil];\n}\n\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.h",
    "content": "//\n//  FLEXTableLeftCell.h\n//  UICatalog\n//\n//  Created by Peng Tao on 15/11/24.\n//  Copyright © 2015年 f. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXTableLeftCell : UITableViewCell\n\n@property (nonatomic, strong) UILabel *titlelabel;\n\n+ (instancetype)cellWithTableView:(UITableView *)tableView;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.m",
    "content": "//\n//  FLEXTableLeftCell.m\n//  UICatalog\n//\n//  Created by Peng Tao on 15/11/24.\n//  Copyright © 2015年 f. All rights reserved.\n//\n\n#import \"FLEXTableLeftCell.h\"\n\n@implementation FLEXTableLeftCell\n\n+ (instancetype)cellWithTableView:(UITableView *)tableView\n{\n    static NSString *identifier = @\"FLEXTableLeftCell\";\n    FLEXTableLeftCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];\n    \n    if (!cell) {\n        cell = [[FLEXTableLeftCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];\n        UILabel *textLabel               = [[UILabel alloc] initWithFrame:CGRectZero];\n        textLabel.textAlignment          = NSTextAlignmentCenter;\n        textLabel.font                   = [UIFont systemFontOfSize:13.0];\n        textLabel.backgroundColor = [UIColor clearColor];\n        [cell.contentView addSubview:textLabel];\n        cell.titlelabel = textLabel;\n    }\n    return cell;\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    self.titlelabel.frame = self.contentView.frame;\n}\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.h",
    "content": "//\n//  PTTableListViewController.h\n//  PTDatabaseReader\n//\n//  Created by Peng Tao on 15/11/23.\n//  Copyright © 2015年 Peng Tao. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXTableListViewController : UITableViewController\n\n+ (BOOL)supportsExtension:(NSString *)extension;\n- (instancetype)initWithPath:(NSString *)path;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m",
    "content": "//\n//  PTTableListViewController.m\n//  PTDatabaseReader\n//\n//  Created by Peng Tao on 15/11/23.\n//  Copyright © 2015年 Peng Tao. All rights reserved.\n//\n\n#import \"FLEXTableListViewController.h\"\n\n#import \"FLEXDatabaseManager.h\"\n#import \"FLEXSQLiteDatabaseManager.h\"\n#import \"FLEXRealmDatabaseManager.h\"\n\n#import \"FLEXTableContentViewController.h\"\n\n@interface FLEXTableListViewController ()\n{\n    id<FLEXDatabaseManager> _dbm;\n    NSString *_databasePath;\n}\n\n@property (nonatomic, strong) NSArray<NSString *> *tables;\n\n+ (NSArray<NSString *> *)supportedSQLiteExtensions;\n+ (NSArray<NSString *> *)supportedRealmExtensions;\n\n@end\n\n@implementation FLEXTableListViewController\n\n- (instancetype)initWithPath:(NSString *)path\n{\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        _databasePath = [path copy];\n        _dbm = [self databaseManagerForFileAtPath:_databasePath];\n        [_dbm open];\n        [self getAllTables];\n    }\n    return self;\n}\n\n- (id<FLEXDatabaseManager>)databaseManagerForFileAtPath:(NSString *)path\n{\n    NSString *pathExtension = path.pathExtension.lowercaseString;\n    \n    NSArray<NSString *> *sqliteExtensions = [FLEXTableListViewController supportedSQLiteExtensions];\n    if ([sqliteExtensions indexOfObject:pathExtension] != NSNotFound) {\n        return [[FLEXSQLiteDatabaseManager alloc] initWithPath:path];\n    }\n    \n    NSArray<NSString *> *realmExtensions = [FLEXTableListViewController supportedRealmExtensions];\n    if (realmExtensions != nil && [realmExtensions indexOfObject:pathExtension] != NSNotFound) {\n        return [[FLEXRealmDatabaseManager alloc] initWithPath:path];\n    }\n    \n    return nil;\n}\n\n- (void)getAllTables\n{\n    NSArray<NSDictionary<NSString *, id> *> *resultArray = [_dbm queryAllTables];\n    NSMutableArray<NSString *> *array = [NSMutableArray array];\n    for (NSDictionary<NSString *, id> *dict in resultArray) {\n        NSString *columnName = (NSString *)dict[@\"name\"] ?: @\"\";\n        [array addObject:columnName];\n    }\n    self.tables = array;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return self.tables.count;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"FLEXTableListViewControllerCell\"];\n    if (!cell) {\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault\n                                      reuseIdentifier:@\"FLEXTableListViewControllerCell\"];\n    }\n    cell.textLabel.text = self.tables[indexPath.row];\n    return cell;\n}\n\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXTableContentViewController *contentViewController = [[FLEXTableContentViewController alloc] init];\n    \n    contentViewController.contentsArray = [_dbm queryAllDataWithTableName:self.tables[indexPath.row]];\n    contentViewController.columnsArray = [_dbm queryAllColumnsWithTableName:self.tables[indexPath.row]];\n    \n    contentViewController.title = self.tables[indexPath.row];\n    [self.navigationController pushViewController:contentViewController animated:YES];\n}\n\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section\n{\n    return [NSString stringWithFormat:@\"%lu tables\", (unsigned long)self.tables.count];\n}\n\n+ (BOOL)supportsExtension:(NSString *)extension\n{\n    extension = extension.lowercaseString;\n    \n    NSArray<NSString *> *sqliteExtensions = [FLEXTableListViewController supportedSQLiteExtensions];\n    if (sqliteExtensions.count > 0 && [sqliteExtensions indexOfObject:extension] != NSNotFound) {\n        return YES;\n    }\n    \n    NSArray<NSString *> *realmExtensions = [FLEXTableListViewController supportedRealmExtensions];\n    if (realmExtensions.count > 0 && [realmExtensions indexOfObject:extension] != NSNotFound) {\n        return YES;\n    }\n    \n    return NO;\n}\n\n+ (NSArray<NSString *> *)supportedSQLiteExtensions\n{\n    return @[@\"db\", @\"sqlite\", @\"sqlite3\"];\n}\n\n+ (NSArray<NSString *> *)supportedRealmExtensions\n{\n    if (NSClassFromString(@\"RLMRealm\") == nil) {\n        return nil;\n    }\n    \n    return @[@\"realm\"];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/DatabaseBrowser/LICENSE",
    "content": "\nFMDB\nCopyright (c) 2008-2014 Flying Meat Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXClassesTableViewController.h",
    "content": "//\n//  FLEXClassesTableViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-03.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXClassesTableViewController : UITableViewController\n\n@property (nonatomic, copy) NSString *binaryImageName;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXClassesTableViewController.m",
    "content": "//\n//  FLEXClassesTableViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-03.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXClassesTableViewController.h\"\n#import \"FLEXObjectExplorerViewController.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXUtility.h\"\n#import <objc/runtime.h>\n\n@interface FLEXClassesTableViewController () <UISearchBarDelegate>\n\n@property (nonatomic, strong) NSArray<NSString *> *classNames;\n@property (nonatomic, strong) NSArray<NSString *> *filteredClassNames;\n@property (nonatomic, strong) UISearchBar *searchBar;\n\n@end\n\n@implementation FLEXClassesTableViewController\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.searchBar = [[UISearchBar alloc] init];\n    self.searchBar.placeholder = [FLEXUtility searchBarPlaceholderText];\n    self.searchBar.delegate = self;\n    [self.searchBar sizeToFit];\n    self.tableView.tableHeaderView = self.searchBar;\n}\n\n- (void)setBinaryImageName:(NSString *)binaryImageName\n{\n    if (![_binaryImageName isEqual:binaryImageName]) {\n        _binaryImageName = binaryImageName;\n        [self loadClassNames];\n        [self updateTitle];\n    }\n}\n\n- (void)setClassNames:(NSArray<NSString *> *)classNames\n{\n    _classNames = classNames;\n    self.filteredClassNames = classNames;\n}\n\n- (void)loadClassNames\n{\n    unsigned int classNamesCount = 0;\n    const char **classNames = objc_copyClassNamesForImage([self.binaryImageName UTF8String], &classNamesCount);\n    if (classNames) {\n        NSMutableArray<NSString *> *classNameStrings = [NSMutableArray array];\n        for (unsigned int i = 0; i < classNamesCount; i++) {\n            const char *className = classNames[i];\n            NSString *classNameString = [NSString stringWithUTF8String:className];\n            [classNameStrings addObject:classNameString];\n        }\n        \n        self.classNames = [classNameStrings sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];\n        \n        free(classNames);\n    }\n}\n\n- (void)updateTitle\n{\n    NSString *shortImageName = self.binaryImageName.lastPathComponent;\n    self.title = [NSString stringWithFormat:@\"%@ Classes (%lu)\", shortImageName, (unsigned long)[self.filteredClassNames count]];\n}\n\n\n#pragma mark - Search\n\n- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText\n{\n    if ([searchText length] > 0) {\n        NSPredicate *searchPreidcate = [NSPredicate predicateWithFormat:@\"SELF CONTAINS[cd] %@\", searchText];\n        self.filteredClassNames = [self.classNames filteredArrayUsingPredicate:searchPreidcate];\n    } else {\n        self.filteredClassNames = self.classNames;\n    }\n    [self updateTitle];\n    [self.tableView reloadData];\n}\n\n- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar\n{\n    [searchBar resignFirstResponder];\n}\n\n- (void)scrollViewDidScroll:(UIScrollView *)scrollView\n{\n    // Dismiss the keyboard when interacting with filtered results.\n    [self.searchBar endEditing:YES];\n}\n\n\n#pragma mark - Table View Data Source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return [self.filteredClassNames count];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    static NSString *CellIdentifier = @\"Cell\";\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];\n    if (!cell) {\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];\n        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;\n        cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n    }\n    \n    cell.textLabel.text = self.filteredClassNames[indexPath.row];\n    \n    return cell;\n}\n\n\n#pragma mark - Table View Delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    NSString *className = self.filteredClassNames[indexPath.row];\n    Class selectedClass = objc_getClass([className UTF8String]);\n    FLEXObjectExplorerViewController *objectExplorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:selectedClass];\n    [self.navigationController pushViewController:objectExplorer animated:YES];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXCookiesTableViewController.h",
    "content": "//\n//  FLEXCookiesTableViewController.h\n//  FLEX\n//\n//  Created by Rich Robinson on 19/10/2015.\n//  Copyright © 2015 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXCookiesTableViewController : UITableViewController\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXCookiesTableViewController.m",
    "content": "//\n//  FLEXCookiesTableViewController.m\n//  FLEX\n//\n//  Created by Rich Robinson on 19/10/2015.\n//  Copyright © 2015 Flipboard. All rights reserved.\n//\n\n#import \"FLEXCookiesTableViewController.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXUtility.h\"\n\n@interface FLEXCookiesTableViewController ()\n\n@property (nonatomic, strong) NSArray<NSHTTPCookie *> *cookies;\n\n@end\n\n@implementation FLEXCookiesTableViewController\n\n- (id)initWithStyle:(UITableViewStyle)style {\n    self = [super initWithStyle:style];\n    \n    if (self) {\n        self.title = @\"Cookies\";\n\n        NSSortDescriptor *nameSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@\"name\" ascending:YES selector:@selector(caseInsensitiveCompare:)];\n        _cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies sortedArrayUsingDescriptors:@[nameSortDescriptor]];\n    }\n    \n    return self;\n}\n\n- (NSHTTPCookie *)cookieForRowAtIndexPath:(NSIndexPath *)indexPath {\n    return self.cookies[indexPath.row];\n}\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return self.cookies.count;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    static NSString *CellIdentifier = @\"Cell\";\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];\n    if (!cell) {\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];\n        cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n        cell.detailTextLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n        cell.detailTextLabel.textColor = [UIColor grayColor];\n        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;\n    }\n    \n    NSHTTPCookie *cookie = [self cookieForRowAtIndexPath:indexPath];\n    cell.textLabel.text = [NSString stringWithFormat:@\"%@ (%@)\", cookie.name, cookie.value];\n    cell.detailTextLabel.text = cookie.domain;\n    \n    return cell;\n}\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSHTTPCookie *cookie = [self cookieForRowAtIndexPath:indexPath];\n    UIViewController *cookieViewController = (UIViewController *)[FLEXObjectExplorerFactory explorerViewControllerForObject:cookie];\n    \n    [self.navigationController pushViewController:cookieViewController animated:YES];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXFileBrowserFileOperationController.h",
    "content": "//\n//  FLEXFileBrowserFileOperationController.h\n//  Flipboard\n//\n//  Created by Daniel Rodriguez Troitino on 2/13/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@protocol FLEXFileBrowserFileOperationController;\n\n@protocol FLEXFileBrowserFileOperationControllerDelegate <NSObject>\n\n- (void)fileOperationControllerDidDismiss:(id<FLEXFileBrowserFileOperationController>)controller;\n\n@end\n\n@protocol FLEXFileBrowserFileOperationController <NSObject>\n\n@property (nonatomic, weak) id<FLEXFileBrowserFileOperationControllerDelegate> delegate;\n\n- (instancetype)initWithPath:(NSString *)path;\n\n- (void)show;\n\n@end\n\n@interface FLEXFileBrowserFileDeleteOperationController : NSObject <FLEXFileBrowserFileOperationController>\n@end\n\n@interface FLEXFileBrowserFileRenameOperationController : NSObject <FLEXFileBrowserFileOperationController>\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXFileBrowserFileOperationController.m",
    "content": "//\n//  FLEXFileBrowserFileOperationController.m\n//  Flipboard\n//\n//  Created by Daniel Rodriguez Troitino on 2/13/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import \"FLEXFileBrowserFileOperationController.h\"\n#import <UIKit/UIKit.h>\n\n@interface FLEXFileBrowserFileDeleteOperationController () <UIAlertViewDelegate>\n\n@property (nonatomic, copy, readonly) NSString *path;\n\n- (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;\n\n@end\n\n@implementation FLEXFileBrowserFileDeleteOperationController\n\n@synthesize delegate = _delegate;\n\n- (instancetype)init\n{\n    return [self initWithPath:nil];\n}\n\n- (instancetype)initWithPath:(NSString *)path\n{\n    self = [super init];\n    if (self) {\n        _path = path;\n    }\n\n    return self;\n}\n\n- (void)show\n{\n    BOOL isDirectory = NO;\n    BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:self.path isDirectory:&isDirectory];\n\n    if (stillExists) {\n        UIAlertView *deleteWarning = [[UIAlertView alloc]\n                                      initWithTitle:[NSString stringWithFormat:@\"Delete %@?\", self.path.lastPathComponent]\n                                      message:[NSString stringWithFormat:@\"The %@ will be deleted. This operation cannot be undone\", isDirectory ? @\"directory\" : @\"file\"]\n                                      delegate:self\n                                      cancelButtonTitle:@\"Cancel\"\n                                      otherButtonTitles:@\"Delete\", nil];\n        [deleteWarning show];\n    } else {\n        [[[UIAlertView alloc] initWithTitle:@\"File Removed\" message:@\"The file at the specified path no longer exists.\" delegate:nil cancelButtonTitle:@\"OK\" otherButtonTitles:nil] show];\n    }\n}\n\n#pragma mark - UIAlertViewDelegate\n\n- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex\n{\n    if (buttonIndex == alertView.cancelButtonIndex) {\n        // Nothing, just cancel\n    } else if (buttonIndex == alertView.firstOtherButtonIndex) {\n        [[NSFileManager defaultManager] removeItemAtPath:self.path error:NULL];\n    }\n}\n\n- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex\n{\n    [self.delegate fileOperationControllerDidDismiss:self];\n}\n\n@end\n\n@interface FLEXFileBrowserFileRenameOperationController () <UIAlertViewDelegate>\n\n@property (nonatomic, copy, readonly) NSString *path;\n\n- (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;\n\n@end\n\n@implementation FLEXFileBrowserFileRenameOperationController\n\n@synthesize delegate = _delegate;\n\n- (instancetype)init\n{\n    return [self initWithPath:nil];\n}\n\n- (instancetype)initWithPath:(NSString *)path\n{\n    self = [super init];\n    if (self) {\n        _path = path;\n    }\n\n    return self;\n}\n\n- (void)show\n{\n    BOOL isDirectory = NO;\n    BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:self.path isDirectory:&isDirectory];\n\n    if (stillExists) {\n        UIAlertView *renameDialog = [[UIAlertView alloc]\n                                     initWithTitle:[NSString stringWithFormat:@\"Rename %@?\", self.path.lastPathComponent]\n                                     message:nil\n                                     delegate:self\n                                     cancelButtonTitle:@\"Cancel\"\n                                     otherButtonTitles:@\"Rename\", nil];\n        renameDialog.alertViewStyle = UIAlertViewStylePlainTextInput;\n        UITextField *textField = [renameDialog textFieldAtIndex:0];\n        textField.placeholder = @\"New file name\";\n        textField.text = self.path.lastPathComponent;\n        [renameDialog show];\n    } else {\n        [[[UIAlertView alloc] initWithTitle:@\"File Removed\" message:@\"The file at the specified path no longer exists.\" delegate:nil cancelButtonTitle:@\"OK\" otherButtonTitles:nil] show];\n    }\n}\n\n#pragma mark - UIAlertViewDelegate\n\n- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex\n{\n    if (buttonIndex == alertView.cancelButtonIndex) {\n        // Nothing, just cancel\n    } else if (buttonIndex == alertView.firstOtherButtonIndex) {\n        NSString *newFileName = [alertView textFieldAtIndex:0].text;\n        NSString *newPath = [[self.path stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFileName];\n        [[NSFileManager defaultManager] moveItemAtPath:self.path toPath:newPath error:NULL];\n    }\n}\n\n- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex\n{\n    [self.delegate fileOperationControllerDidDismiss:self];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXFileBrowserSearchOperation.h",
    "content": "//\n//  FLEXFileBrowserSearchOperation.h\n//  UICatalog\n//\n//  Created by 啟倫 陳 on 2014/8/4.\n//  Copyright (c) 2014年 f. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@protocol FLEXFileBrowserSearchOperationDelegate;\n\n@interface FLEXFileBrowserSearchOperation : NSOperation\n\n@property (nonatomic, weak) id<FLEXFileBrowserSearchOperationDelegate> delegate;\n\n- (id)initWithPath:(NSString *)currentPath searchString:(NSString *)searchString;\n\n@end\n\n@protocol FLEXFileBrowserSearchOperationDelegate <NSObject>\n\n- (void)fileBrowserSearchOperationResult:(NSArray<NSString *> *)searchResult size:(uint64_t)size;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXFileBrowserSearchOperation.m",
    "content": "//\n//  FLEXFileBrowserSearchOperation.m\n//  UICatalog\n//\n//  Created by 啟倫 陳 on 2014/8/4.\n//  Copyright (c) 2014年 f. All rights reserved.\n//\n\n#import \"FLEXFileBrowserSearchOperation.h\"\n\n@implementation NSMutableArray (FLEXStack)\n\n- (void)flex_push:(id)anObject\n{\n    [self addObject:anObject];\n}\n\n- (id)flex_pop\n{\n    id anObject = [self lastObject];\n    [self removeLastObject];\n    return anObject;\n}\n\n@end\n\n@interface FLEXFileBrowserSearchOperation ()\n\n@property (nonatomic, strong) NSString *path;\n@property (nonatomic, strong) NSString *searchString;\n\n@end\n\n@implementation FLEXFileBrowserSearchOperation\n\n#pragma mark - private\n\n- (uint64_t)totalSizeAtPath:(NSString *)path\n{\n    NSFileManager *fileManager = [NSFileManager defaultManager];\n    NSDictionary<NSString *, id> *attributes = [fileManager attributesOfItemAtPath:path error:NULL];\n    uint64_t totalSize = [attributes fileSize];\n    \n    for (NSString *fileName in [fileManager enumeratorAtPath:path]) {\n        attributes = [fileManager attributesOfItemAtPath:[path stringByAppendingPathComponent:fileName] error:NULL];\n        totalSize += [attributes fileSize];\n    }\n    return totalSize;\n}\n\n#pragma mark - instance method\n\n- (id)initWithPath:(NSString *)currentPath searchString:(NSString *)searchString\n{\n    self = [super init];\n    if (self) {\n        self.path = currentPath;\n        self.searchString = searchString;\n    }\n    return self;\n}\n\n#pragma mark - methods to override\n\n- (void)main\n{\n    NSFileManager *fileManager = [NSFileManager defaultManager];\n    NSMutableArray<NSString *> *searchPaths = [NSMutableArray array];\n    NSMutableDictionary<NSString *, NSNumber *> *sizeMapping = [NSMutableDictionary dictionary];\n    uint64_t totalSize = 0;\n    NSMutableArray<NSString *> *stack = [NSMutableArray array];\n    [stack flex_push:self.path];\n    \n    //recursive found all match searchString paths, and precomputing there size\n    while ([stack count]) {\n        NSString *currentPath = [stack flex_pop];\n        NSArray<NSString *> *directoryPath = [fileManager contentsOfDirectoryAtPath:currentPath error:nil];\n        \n        for (NSString *subPath in directoryPath) {\n            NSString *fullPath = [currentPath stringByAppendingPathComponent:subPath];\n            \n            if ([[subPath lowercaseString] rangeOfString:[self.searchString lowercaseString]].location != NSNotFound) {\n                [searchPaths addObject:fullPath];\n                if (!sizeMapping[fullPath]) {\n                    uint64_t fullPathSize = [self totalSizeAtPath:fullPath];\n                    totalSize += fullPathSize;\n                    [sizeMapping setObject:@(fullPathSize) forKey:fullPath];\n                }\n            }\n            BOOL isDirectory;\n            if ([fileManager fileExistsAtPath:fullPath isDirectory:&isDirectory] && isDirectory) {\n                [stack flex_push:fullPath];\n            }\n            \n            if ([self isCancelled]) {\n                return;\n            }\n        }\n    }\n    \n    //sort\n    NSArray<NSString *> *sortedArray = [searchPaths sortedArrayUsingComparator:^NSComparisonResult(NSString *path1, NSString *path2) {\n        uint64_t pathSize1 = [sizeMapping[path1] unsignedLongLongValue];\n        uint64_t pathSize2 = [sizeMapping[path2] unsignedLongLongValue];\n        if (pathSize1 < pathSize2) {\n            return NSOrderedAscending;\n        } else if (pathSize1 > pathSize2) {\n            return NSOrderedDescending;\n        } else {\n            return NSOrderedSame;\n        }\n    }];\n    \n    if ([self isCancelled]) {\n        return;\n    }\n    \n    dispatch_async(dispatch_get_main_queue(), ^{\n        [self.delegate fileBrowserSearchOperationResult:sortedArray size:totalSize];\n    });\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXFileBrowserTableViewController.h",
    "content": "//\n//  FLEXFileBrowserTableViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/9/14.\n//  Based on previous work by Evan Doll\n//\n\n#import <UIKit/UIKit.h>\n\n#import \"FLEXFileBrowserSearchOperation.h\"\n\n@interface FLEXFileBrowserTableViewController : UITableViewController\n\n- (id)initWithPath:(NSString *)path;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXFileBrowserTableViewController.m",
    "content": "//\n//  FLEXFileBrowserTableViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/9/14.\n//\n//\n\n#import \"FLEXFileBrowserTableViewController.h\"\n#import \"FLEXFileBrowserFileOperationController.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXWebViewController.h\"\n#import \"FLEXImagePreviewViewController.h\"\n#import \"FLEXTableListViewController.h\"\n\n@interface FLEXFileBrowserTableViewCell : UITableViewCell\n@end\n\n@interface FLEXFileBrowserTableViewController () <FLEXFileBrowserFileOperationControllerDelegate, FLEXFileBrowserSearchOperationDelegate, UISearchResultsUpdating, UISearchControllerDelegate>\n\n@property (nonatomic, copy) NSString *path;\n@property (nonatomic, copy) NSArray<NSString *> *childPaths;\n@property (nonatomic, strong) NSArray<NSString *> *searchPaths;\n@property (nonatomic, strong) NSNumber *recursiveSize;\n@property (nonatomic, strong) NSNumber *searchPathsSize;\n@property (nonatomic, strong) UISearchController *searchController;\n@property (nonatomic) NSOperationQueue *operationQueue;\n@property (nonatomic, strong) UIDocumentInteractionController *documentController;\n@property (nonatomic, strong) id<FLEXFileBrowserFileOperationController> fileOperationController;\n\n@end\n\n@implementation FLEXFileBrowserTableViewController\n\n- (id)initWithStyle:(UITableViewStyle)style\n{\n    return [self initWithPath:NSHomeDirectory()];\n}\n\n- (id)initWithPath:(NSString *)path\n{\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        self.path = path;\n        self.title = [path lastPathComponent];\n        self.operationQueue = [NSOperationQueue new];\n\n        self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];\n        self.searchController.searchResultsUpdater = self;\n        self.searchController.delegate = self;\n        self.searchController.dimsBackgroundDuringPresentation = NO;\n        self.tableView.tableHeaderView = self.searchController.searchBar;\n\n        //computing path size\n        FLEXFileBrowserTableViewController *__weak weakSelf = self;\n        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n            NSFileManager *fileManager = [NSFileManager defaultManager];\n            NSDictionary<NSString *, id> *attributes = [fileManager attributesOfItemAtPath:path error:NULL];\n            uint64_t totalSize = [attributes fileSize];\n\n            for (NSString *fileName in [fileManager enumeratorAtPath:path]) {\n                attributes = [fileManager attributesOfItemAtPath:[path stringByAppendingPathComponent:fileName] error:NULL];\n                totalSize += [attributes fileSize];\n\n                // Bail if the interested view controller has gone away.\n                if (!weakSelf) {\n                    return;\n                }\n            }\n\n            dispatch_async(dispatch_get_main_queue(), ^{\n                FLEXFileBrowserTableViewController *__strong strongSelf = weakSelf;\n                strongSelf.recursiveSize = @(totalSize);\n                [strongSelf.tableView reloadData];\n            });\n        });\n\n        [self reloadChildPaths];\n    }\n    return self;\n}\n\n#pragma mark - UIViewController\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n\n}\n\n#pragma mark - FLEXFileBrowserSearchOperationDelegate\n\n- (void)fileBrowserSearchOperationResult:(NSArray<NSString *> *)searchResult size:(uint64_t)size\n{\n    self.searchPaths = searchResult;\n    self.searchPathsSize = @(size);\n    [self.tableView reloadData];\n}\n\n#pragma mark - UISearchResultsUpdating\n\n- (void)updateSearchResultsForSearchController:(UISearchController *)searchController\n{\n    [self reloadDisplayedPaths];\n}\n\n#pragma mark - UISearchControllerDelegate\n\n- (void)willDismissSearchController:(UISearchController *)searchController\n{\n    [self.operationQueue cancelAllOperations];\n    [self reloadChildPaths];\n    [self.tableView reloadData];\n}\n\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return self.searchController.isActive ? [self.searchPaths count] : [self.childPaths count];\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section\n{\n    BOOL isSearchActive = self.searchController.isActive;\n    NSNumber *currentSize = isSearchActive ? self.searchPathsSize : self.recursiveSize;\n    NSArray<NSString *> *currentPaths = isSearchActive ? self.searchPaths : self.childPaths;\n\n    NSString *sizeString = nil;\n    if (!currentSize) {\n        sizeString = @\"Computing size…\";\n    } else {\n        sizeString = [NSByteCountFormatter stringFromByteCount:[currentSize longLongValue] countStyle:NSByteCountFormatterCountStyleFile];\n    }\n\n    return [NSString stringWithFormat:@\"%lu files (%@)\", (unsigned long)[currentPaths count], sizeString];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    NSString *fullPath = [self filePathAtIndexPath:indexPath];\n    NSDictionary<NSString *, id> *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:NULL];\n    BOOL isDirectory = [[attributes fileType] isEqual:NSFileTypeDirectory];\n    NSString *subtitle = nil;\n    if (isDirectory) {\n        NSUInteger count = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:fullPath error:NULL] count];\n        subtitle = [NSString stringWithFormat:@\"%lu file%@\", (unsigned long)count, (count == 1 ? @\"\" : @\"s\")];\n    } else {\n        NSString *sizeString = [NSByteCountFormatter stringFromByteCount:[attributes fileSize] countStyle:NSByteCountFormatterCountStyleFile];\n        subtitle = [NSString stringWithFormat:@\"%@ - %@\", sizeString, [attributes fileModificationDate]];\n    }\n\n    static NSString *textCellIdentifier = @\"textCell\";\n    static NSString *imageCellIdentifier = @\"imageCell\";\n    UITableViewCell *cell = nil;\n\n    // Separate image and text only cells because otherwise the separator lines get out-of-whack on image cells reused with text only.\n    BOOL showImagePreview = [FLEXUtility isImagePathExtension:[fullPath pathExtension]];\n    NSString *cellIdentifier = showImagePreview ? imageCellIdentifier : textCellIdentifier;\n\n    if (!cell) {\n        cell = [[FLEXFileBrowserTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];\n        cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n        cell.detailTextLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n        cell.detailTextLabel.textColor = [UIColor grayColor];\n        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;\n    }\n    NSString *cellTitle = [fullPath lastPathComponent];\n    cell.textLabel.text = cellTitle;\n    cell.detailTextLabel.text = subtitle;\n\n    if (showImagePreview) {\n        cell.imageView.contentMode = UIViewContentModeScaleAspectFit;\n        cell.imageView.image = [UIImage imageWithContentsOfFile:fullPath];\n    }\n\n    return cell;\n}\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    NSString *fullPath = [self filePathAtIndexPath:indexPath];\n    NSString *subpath = [fullPath lastPathComponent];\n    NSString *pathExtension = [subpath pathExtension];\n\n    BOOL isDirectory = NO;\n    BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDirectory];\n    if (stillExists) {\n        UIViewController *drillInViewController = nil;\n        if (isDirectory) {\n            drillInViewController = [[[self class] alloc] initWithPath:fullPath];\n        } else if ([FLEXUtility isImagePathExtension:pathExtension]) {\n            UIImage *image = [UIImage imageWithContentsOfFile:fullPath];\n            drillInViewController = [[FLEXImagePreviewViewController alloc] initWithImage:image];\n        } else {\n            // Special case keyed archives, json, and plists to get more readable data.\n            NSString *prettyString = nil;\n            if ([pathExtension isEqual:@\"archive\"] || [pathExtension isEqual:@\"coded\"]) {\n                prettyString = [[NSKeyedUnarchiver unarchiveObjectWithFile:fullPath] description];\n            } else if ([pathExtension isEqualToString:@\"json\"]) {\n                prettyString = [FLEXUtility prettyJSONStringFromData:[NSData dataWithContentsOfFile:fullPath]];\n            } else if ([pathExtension isEqualToString:@\"plist\"]) {\n                NSData *fileData = [NSData dataWithContentsOfFile:fullPath];\n                prettyString = [[NSPropertyListSerialization propertyListWithData:fileData options:0 format:NULL error:NULL] description];\n            }\n\n            if ([prettyString length] > 0) {\n                drillInViewController = [[FLEXWebViewController alloc] initWithText:prettyString];\n            } else if ([FLEXWebViewController supportsPathExtension:pathExtension]) {\n                drillInViewController = [[FLEXWebViewController alloc] initWithURL:[NSURL fileURLWithPath:fullPath]];\n            } else if ([FLEXTableListViewController supportsExtension:subpath.pathExtension]) {\n                drillInViewController = [[FLEXTableListViewController alloc] initWithPath:fullPath];\n            }\n            else {\n                NSString *fileString = [NSString stringWithContentsOfFile:fullPath encoding:NSUTF8StringEncoding error:NULL];\n                if ([fileString length] > 0) {\n                    drillInViewController = [[FLEXWebViewController alloc] initWithText:fileString];\n                }\n            }\n        }\n\n        if (drillInViewController) {\n            drillInViewController.title = [subpath lastPathComponent];\n            [self.navigationController pushViewController:drillInViewController animated:YES];\n        } else {\n            [self openFileController:fullPath];\n            [self.tableView deselectRowAtIndexPath:indexPath animated:YES];\n        }\n    } else {\n        [[[UIAlertView alloc] initWithTitle:@\"File Removed\" message:@\"The file at the specified path no longer exists.\" delegate:nil cancelButtonTitle:@\"OK\" otherButtonTitles:nil] show];\n        [self reloadDisplayedPaths];\n    }\n}\n\n- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    UIMenuItem *renameMenuItem = [[UIMenuItem alloc] initWithTitle:@\"Rename\" action:@selector(fileBrowserRename:)];\n    UIMenuItem *deleteMenuItem = [[UIMenuItem alloc] initWithTitle:@\"Delete\" action:@selector(fileBrowserDelete:)];\n    NSMutableArray *menus = [NSMutableArray arrayWithObjects:renameMenuItem, deleteMenuItem, nil];\n\n    NSString *fullPath = [self filePathAtIndexPath:indexPath];\n    NSError *error = nil;\n    NSDictionary *attributes = [NSFileManager.defaultManager attributesOfItemAtPath:fullPath error:&error];\n    if (error == nil && [attributes fileType] != NSFileTypeDirectory) {\n        UIMenuItem *shareMenuItem = [[UIMenuItem alloc] initWithTitle:@\"Share\" action:@selector(fileBrowserShare:)];\n        [menus addObject:shareMenuItem];\n    }\n    [UIMenuController sharedMenuController].menuItems = menus;\n\n    return YES;\n}\n\n- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender\n{\n    return action == @selector(fileBrowserDelete:) || action == @selector(fileBrowserRename:) || action == @selector(fileBrowserShare:);\n}\n\n- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender\n{\n    // Empty, but has to exist for the menu to show\n    // The table view only calls this method for actions in the UIResponderStandardEditActions informal protocol.\n    // Since our actions are outside of that protocol, we need to manually handle the action forwarding from the cells.\n}\n\n#pragma mark - FLEXFileBrowserFileOperationControllerDelegate\n\n- (void)fileOperationControllerDidDismiss:(id<FLEXFileBrowserFileOperationController>)controller\n{\n    [self reloadDisplayedPaths];\n}\n\n- (void)openFileController:(NSString *)fullPath\n{\n    UIDocumentInteractionController *controller = [UIDocumentInteractionController new];\n    controller.URL = [[NSURL alloc] initFileURLWithPath:fullPath];\n\n    [controller presentOptionsMenuFromRect:self.view.bounds inView:self.view animated:YES];\n    self.documentController = controller;\n}\n\n- (void)fileBrowserRename:(UITableViewCell *)sender\n{\n    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];\n    NSString *fullPath = [self filePathAtIndexPath:indexPath];\n\n    self.fileOperationController = [[FLEXFileBrowserFileRenameOperationController alloc] initWithPath:fullPath];\n    self.fileOperationController.delegate = self;\n    [self.fileOperationController show];\n}\n\n- (void)fileBrowserDelete:(UITableViewCell *)sender\n{\n    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];\n    NSString *fullPath = [self filePathAtIndexPath:indexPath];\n\n    self.fileOperationController = [[FLEXFileBrowserFileDeleteOperationController alloc] initWithPath:fullPath];\n    self.fileOperationController.delegate = self;\n    [self.fileOperationController show];\n}\n\n- (void)fileBrowserShare:(UITableViewCell *)sender\n{\n    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];\n    NSString *fullPath = [self filePathAtIndexPath:indexPath];\n\n    UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[fullPath] applicationActivities:nil];\n    [self presentViewController:activityViewController animated:true completion:nil];\n}\n\n- (void)reloadDisplayedPaths\n{\n    if (self.searchController.isActive) {\n        [self reloadSearchPaths];\n    } else {\n        [self reloadChildPaths];\n    }\n    [self.tableView reloadData];\n}\n\n- (void)reloadChildPaths\n{\n    NSMutableArray<NSString *> *childPaths = [NSMutableArray array];\n    NSArray<NSString *> *subpaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.path error:NULL];\n    for (NSString *subpath in subpaths) {\n        [childPaths addObject:[self.path stringByAppendingPathComponent:subpath]];\n    }\n    self.childPaths = childPaths;\n}\n\n- (void)reloadSearchPaths\n{\n    self.searchPaths = nil;\n    self.searchPathsSize = nil;\n\n    //clear pre search request and start a new one\n    [self.operationQueue cancelAllOperations];\n    FLEXFileBrowserSearchOperation *newOperation = [[FLEXFileBrowserSearchOperation alloc] initWithPath:self.path searchString:self.searchController.searchBar.text];\n    newOperation.delegate = self;\n    [self.operationQueue addOperation:newOperation];\n}\n\n- (NSString *)filePathAtIndexPath:(NSIndexPath *)indexPath\n{\n    return self.searchController.isActive ? self.searchPaths[indexPath.row] : self.childPaths[indexPath.row];\n}\n\n@end\n\n\n@implementation FLEXFileBrowserTableViewCell\n\n- (void)fileBrowserRename:(UIMenuController *)sender\n{\n    id target = [self.nextResponder targetForAction:_cmd withSender:sender];\n    [[UIApplication sharedApplication] sendAction:_cmd to:target from:self forEvent:nil];\n}\n\n- (void)fileBrowserDelete:(UIMenuController *)sender\n{\n    id target = [self.nextResponder targetForAction:_cmd withSender:sender];\n    [[UIApplication sharedApplication] sendAction:_cmd to:target from:self forEvent:nil];\n}\n\n- (void)fileBrowserShare:(UIMenuController *)sender\n{\n    id target = [self.nextResponder targetForAction:_cmd withSender:sender];\n    [[UIApplication sharedApplication] sendAction:_cmd to:target from:self forEvent:nil];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXGlobalsTableViewController.h",
    "content": "//\n//  FLEXGlobalsTableViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-03.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@protocol FLEXGlobalsTableViewControllerDelegate;\n\n@interface FLEXGlobalsTableViewController : UITableViewController\n\n@property (nonatomic, weak) id <FLEXGlobalsTableViewControllerDelegate> delegate;\n\n/// We pretend that one of the app's windows is still the key window, even though the explorer window may have become key.\n/// We want to display debug state about the application, not about this tool.\n+ (void)setApplicationWindow:(UIWindow *)applicationWindow;\n\n@end\n\n@protocol FLEXGlobalsTableViewControllerDelegate <NSObject>\n\n- (void)globalsViewControllerDidFinish:(FLEXGlobalsTableViewController *)globalsViewController;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXGlobalsTableViewController.m",
    "content": "//\n//  FLEXGlobalsTableViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-03.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXGlobalsTableViewController.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXLibrariesTableViewController.h\"\n#import \"FLEXClassesTableViewController.h\"\n#import \"FLEXObjectExplorerViewController.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXLiveObjectsTableViewController.h\"\n#import \"FLEXFileBrowserTableViewController.h\"\n#import \"FLEXCookiesTableViewController.h\"\n#import \"FLEXGlobalsTableViewControllerEntry.h\"\n#import \"FLEXManager+Private.h\"\n#import \"FLEXSystemLogTableViewController.h\"\n#import \"FLEXNetworkHistoryTableViewController.h\"\n\nstatic __weak UIWindow *s_applicationWindow = nil;\n\ntypedef NS_ENUM(NSUInteger, FLEXGlobalsRow) {\n    FLEXGlobalsRowNetworkHistory,\n    FLEXGlobalsRowSystemLog,\n    FLEXGlobalsRowLiveObjects,\n    FLEXGlobalsRowFileBrowser,\n    FLEXGlobalsCookies,    \n    FLEXGlobalsRowSystemLibraries,\n    FLEXGlobalsRowAppClasses,\n    FLEXGlobalsRowAppDelegate,\n    FLEXGlobalsRowRootViewController,\n    FLEXGlobalsRowUserDefaults,\n    FLEXGlobalsRowApplication,\n    FLEXGlobalsRowKeyWindow,\n    FLEXGlobalsRowMainScreen,\n    FLEXGlobalsRowCurrentDevice,\n    FLEXGlobalsRowCount\n};\n\n@interface FLEXGlobalsTableViewController ()\n\n@property (nonatomic, readonly, copy) NSArray<FLEXGlobalsTableViewControllerEntry *> *entries;\n\n@end\n\n@implementation FLEXGlobalsTableViewController\n\n+ (NSArray<FLEXGlobalsTableViewControllerEntry *> *)defaultGlobalEntries\n{\n    NSMutableArray<FLEXGlobalsTableViewControllerEntry *> *defaultGlobalEntries = [NSMutableArray array];\n\n    for (FLEXGlobalsRow defaultRowIndex = 0; defaultRowIndex < FLEXGlobalsRowCount; defaultRowIndex++) {\n        FLEXGlobalsTableViewControllerEntryNameFuture titleFuture = nil;\n        FLEXGlobalsTableViewControllerViewControllerFuture viewControllerFuture = nil;\n\n        switch (defaultRowIndex) {\n            case FLEXGlobalsRowAppClasses:\n                titleFuture = ^NSString *{\n                    return [NSString stringWithFormat:@\"📕  %@ Classes\", [FLEXUtility applicationName]];\n                };\n                viewControllerFuture = ^UIViewController *{\n                    FLEXClassesTableViewController *classesViewController = [[FLEXClassesTableViewController alloc] init];\n                    classesViewController.binaryImageName = [FLEXUtility applicationImageName];\n\n                    return classesViewController;\n                };\n                break;\n\n            case FLEXGlobalsRowSystemLibraries: {\n                NSString *titleString = @\"📚  System Libraries\";\n                titleFuture = ^NSString *{\n                    return titleString;\n                };\n                viewControllerFuture = ^UIViewController *{\n                    FLEXLibrariesTableViewController *librariesViewController = [[FLEXLibrariesTableViewController alloc] init];\n                    librariesViewController.title = titleString;\n\n                    return librariesViewController;\n                };\n                break;\n            }\n\n            case FLEXGlobalsRowLiveObjects:\n                titleFuture = ^NSString *{\n                    return @\"💩  Heap Objects\";\n                };\n                viewControllerFuture = ^UIViewController *{\n                    return [[FLEXLiveObjectsTableViewController alloc] init];\n                };\n\n                break;\n\n            case FLEXGlobalsRowAppDelegate:\n                titleFuture = ^NSString *{\n                    return [NSString stringWithFormat:@\"👉  %@\", [[[UIApplication sharedApplication] delegate] class]];\n                };\n                viewControllerFuture = ^UIViewController *{\n                    id <UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];\n                    return [FLEXObjectExplorerFactory explorerViewControllerForObject:appDelegate];\n                };\n                break;\n\n            case FLEXGlobalsRowRootViewController:\n                titleFuture = ^NSString *{\n                    return [NSString stringWithFormat:@\"🌴  %@\", [[s_applicationWindow rootViewController] class]];\n                };\n                viewControllerFuture = ^UIViewController *{\n                    UIViewController *rootViewController = [s_applicationWindow rootViewController];\n                    return [FLEXObjectExplorerFactory explorerViewControllerForObject:rootViewController];\n                };\n                break;\n\n            case FLEXGlobalsRowUserDefaults:\n                titleFuture = ^NSString *{\n                    return @\"🚶  +[NSUserDefaults standardUserDefaults]\";\n                };\n                viewControllerFuture = ^UIViewController *{\n                    NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];\n                    return [FLEXObjectExplorerFactory explorerViewControllerForObject:standardUserDefaults];\n                };\n                break;\n\n            case FLEXGlobalsRowApplication:\n                titleFuture = ^NSString *{\n                    return @\"💾  +[UIApplication sharedApplication]\";\n                };\n                viewControllerFuture = ^UIViewController *{\n                    UIApplication *sharedApplication = [UIApplication sharedApplication];\n                    return [FLEXObjectExplorerFactory explorerViewControllerForObject:sharedApplication];\n                };\n                break;\n\n            case FLEXGlobalsRowKeyWindow:\n                titleFuture = ^NSString *{\n                    return @\"🔑  -[UIApplication keyWindow]\";\n                };\n                viewControllerFuture = ^UIViewController *{\n                    return [FLEXObjectExplorerFactory explorerViewControllerForObject:s_applicationWindow];\n                };\n                break;\n\n            case FLEXGlobalsRowMainScreen:\n                titleFuture = ^NSString *{\n                    return @\"💻  +[UIScreen mainScreen]\";\n                };\n                viewControllerFuture = ^UIViewController *{\n                    UIScreen *mainScreen = [UIScreen mainScreen];\n                    return [FLEXObjectExplorerFactory explorerViewControllerForObject:mainScreen];\n                };\n                break;\n\n            case FLEXGlobalsRowCurrentDevice:\n                titleFuture = ^NSString *{\n                    return @\"📱  +[UIDevice currentDevice]\";\n                };\n                viewControllerFuture = ^UIViewController *{\n                    UIDevice *currentDevice = [UIDevice currentDevice];\n                    return [FLEXObjectExplorerFactory explorerViewControllerForObject:currentDevice];\n                };\n                break;\n\n            case FLEXGlobalsCookies:\n                titleFuture = ^NSString *{\n                    return @\"🍪  Cookies\";\n                };\n                viewControllerFuture = ^UIViewController *{\n                    return [[FLEXCookiesTableViewController alloc] init];\n                };\n                break;                \n                \n            case FLEXGlobalsRowFileBrowser:\n                titleFuture = ^NSString *{\n                    return @\"📁  File Browser\";\n                };\n                viewControllerFuture = ^UIViewController *{\n                    return [[FLEXFileBrowserTableViewController alloc] init];\n                };\n                break;\n\n            case FLEXGlobalsRowSystemLog:\n                titleFuture = ^{\n                    return @\"⚠️  System Log\";\n                };\n                viewControllerFuture = ^{\n                    return [[FLEXSystemLogTableViewController alloc] init];\n                };\n                break;\n\n            case FLEXGlobalsRowNetworkHistory:\n                titleFuture = ^{\n                    return @\"📡  Network History\";\n                };\n                viewControllerFuture = ^{\n                    return [[FLEXNetworkHistoryTableViewController alloc] init];\n                };\n                break;\n            case FLEXGlobalsRowCount:\n                break;\n        }\n\n        NSParameterAssert(titleFuture);\n        NSParameterAssert(viewControllerFuture);\n\n        [defaultGlobalEntries addObject:[FLEXGlobalsTableViewControllerEntry entryWithNameFuture:titleFuture viewControllerFuture:viewControllerFuture]];\n    }\n\n    return defaultGlobalEntries;\n}\n\n- (id)initWithStyle:(UITableViewStyle)style\n{\n    self = [super initWithStyle:style];\n    if (self) {\n        self.title = @\"💪  FLEX\";\n        _entries = [[[self class] defaultGlobalEntries] arrayByAddingObjectsFromArray:[FLEXManager sharedManager].userGlobalEntries];\n    }\n    return self;\n}\n\n#pragma mark - Public\n\n+ (void)setApplicationWindow:(UIWindow *)applicationWindow\n{\n    s_applicationWindow = applicationWindow;\n}\n\n#pragma mark - UIViewController\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(donePressed:)];\n}\n\n#pragma mark -\n\n- (void)donePressed:(id)sender\n{\n    [self.delegate globalsViewControllerDidFinish:self];\n}\n\n#pragma mark - Table Data Helpers\n\n- (FLEXGlobalsTableViewControllerEntry *)globalEntryAtIndexPath:(NSIndexPath *)indexPath\n{\n    return self.entries[indexPath.row];\n}\n\n- (NSString *)titleForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXGlobalsTableViewControllerEntry *entry = [self globalEntryAtIndexPath:indexPath];\n\n    return entry.entryNameFuture();\n}\n\n- (UIViewController *)viewControllerToPushForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXGlobalsTableViewControllerEntry *entry = [self globalEntryAtIndexPath:indexPath];\n\n    return entry.viewControllerFuture();\n}\n\n#pragma mark - Table View Data Source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return [self.entries count];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    static NSString *CellIdentifier = @\"Cell\";\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];\n    if (!cell) {\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];\n        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;\n        cell.textLabel.font = [FLEXUtility defaultFontOfSize:14.0];\n    }\n\n    cell.textLabel.text = [self titleForRowAtIndexPath:indexPath];\n    \n    return cell;\n}\n\n\n#pragma mark - Table View Delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    UIViewController *viewControllerToPush = [self viewControllerToPushForRowAtIndexPath:indexPath];\n\n    [self.navigationController pushViewController:viewControllerToPush animated:YES];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXInstancesTableViewController.h",
    "content": "//\n//  FLEXInstancesTableViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/28/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXInstancesTableViewController : UITableViewController\n\n+ (instancetype)instancesTableViewControllerForClassName:(NSString *)className;\n+ (instancetype)instancesTableViewControllerForInstancesReferencingObject:(id)object;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXInstancesTableViewController.m",
    "content": "//\n//  FLEXInstancesTableViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/28/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXInstancesTableViewController.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXObjectExplorerViewController.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXHeapEnumerator.h\"\n#import \"FLEXObjectRef.h\"\n#import <malloc/malloc.h>\n\n\n@interface FLEXInstancesTableViewController ()\n\n/// Array of [[section], [section], ...]\n/// where [section] is [[\"row title\", instance], [\"row title\", instance], ...]\n@property (nonatomic) NSArray<FLEXObjectRef *> *instances;\n@property (nonatomic) NSArray<NSArray<FLEXObjectRef*>*> *sections;\n@property (nonatomic) NSArray<NSString *> *sectionTitles;\n@property (nonatomic) NSArray<NSPredicate *> *predicates;\n@property (nonatomic, readonly) NSInteger maxSections;\n\n@end\n\n@implementation FLEXInstancesTableViewController\n\n- (id)initWithReferences:(NSArray<FLEXObjectRef *> *)references {\n    return [self initWithReferences:references predicates:nil sectionTitles:nil];\n}\n\n- (id)initWithReferences:(NSArray<FLEXObjectRef *> *)references\n              predicates:(NSArray<NSPredicate *> *)predicates\n           sectionTitles:(NSArray<NSString *> *)sectionTitles {\n    NSParameterAssert(predicates.count == sectionTitles.count);\n\n    self = [super init];\n    if (self) {\n        self.instances = references;\n        self.predicates = predicates;\n        self.sectionTitles = sectionTitles;\n\n        if (predicates.count) {\n            [self buildSections];\n        } else {\n            self.sections = @[references];\n        }\n    }\n\n    return self;\n}\n\n+ (instancetype)instancesTableViewControllerForClassName:(NSString *)className\n{\n    const char *classNameCString = [className UTF8String];\n    NSMutableArray *instances = [NSMutableArray array];\n    [FLEXHeapEnumerator enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object, __unsafe_unretained Class actualClass) {\n        if (strcmp(classNameCString, class_getName(actualClass)) == 0) {\n            // Note: objects of certain classes crash when retain is called. It is up to the user to avoid tapping into instance lists for these classes.\n            // Ex. OS_dispatch_queue_specific_queue\n            // In the future, we could provide some kind of warning for classes that are known to be problematic.\n            if (malloc_size((__bridge const void *)(object)) > 0) {\n                [instances addObject:object];\n            }\n        }\n    }];\n    NSArray<FLEXObjectRef *> *references = [FLEXObjectRef referencingAll:instances];\n    FLEXInstancesTableViewController *viewController = [[self alloc] initWithReferences:references];\n    viewController.title = [NSString stringWithFormat:@\"%@ (%lu)\", className, (unsigned long)[instances count]];\n    return viewController;\n}\n\n+ (instancetype)instancesTableViewControllerForInstancesReferencingObject:(id)object\n{\n    NSMutableArray<FLEXObjectRef *> *instances = [NSMutableArray array];\n    [FLEXHeapEnumerator enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id tryObject, __unsafe_unretained Class actualClass) {\n        // Get all the ivars on the object. Start with the class and and travel up the inheritance chain.\n        // Once we find a match, record it and move on to the next object. There's no reason to find multiple matches within the same object.\n        Class tryClass = actualClass;\n        while (tryClass) {\n            unsigned int ivarCount = 0;\n            Ivar *ivars = class_copyIvarList(tryClass, &ivarCount);\n            for (unsigned int ivarIndex = 0; ivarIndex < ivarCount; ivarIndex++) {\n                Ivar ivar = ivars[ivarIndex];\n                const char *typeEncoding = ivar_getTypeEncoding(ivar);\n                if (typeEncoding[0] == @encode(id)[0] || typeEncoding[0] == @encode(Class)[0]) {\n                    ptrdiff_t offset = ivar_getOffset(ivar);\n                    uintptr_t *fieldPointer = (__bridge void *)tryObject + offset;\n                    if (*fieldPointer == (uintptr_t)(__bridge void *)object) {\n                        [instances addObject:[FLEXObjectRef referencing:tryObject ivar:@(ivar_getName(ivar))]];\n                        return;\n                    }\n                }\n            }\n            tryClass = class_getSuperclass(tryClass);\n        }\n    }];\n\n    NSArray<NSPredicate *> *predicates = [self defaultPredicates];\n    NSArray<NSString *> *sectionTitles = [self defaultSectionTitles];\n    FLEXInstancesTableViewController *viewController = [[self alloc] initWithReferences:instances\n                                                                             predicates:predicates\n                                                                          sectionTitles:sectionTitles];\n    viewController.title = [NSString stringWithFormat:@\"Referencing %@ %p\", NSStringFromClass(object_getClass(object)), object];\n    return viewController;\n}\n\n+ (NSPredicate *)defaultPredicateForSection:(NSInteger)section\n{\n    // These are the types of references that we typically don't care about.\n    // We want this list of \"object-ivar pairs\" split into two sections.\n    BOOL(^isObserver)(FLEXObjectRef *, NSDictionary *) = ^BOOL(FLEXObjectRef *ref, NSDictionary *bindings) {\n        NSString *row = ref.reference;\n        return [row isEqualToString:@\"__NSObserver object\"] ||\n               [row isEqualToString:@\"_CFXNotificationObjcObserverRegistration _object\"];\n    };\n\n    /// These are common AutoLayout related references we also rarely care about.\n    BOOL(^isConstraintRelated)(FLEXObjectRef *, NSDictionary *) = ^BOOL(FLEXObjectRef *ref, NSDictionary *bindings) {\n        static NSSet *ignored = nil;\n        static dispatch_once_t onceToken;\n        dispatch_once(&onceToken, ^{\n            ignored = [NSSet setWithArray:@[\n                @\"NSLayoutConstraint _container\",\n                @\"NSContentSizeLayoutConstraint _container\",\n                @\"NSAutoresizingMaskLayoutConstraint _container\",\n                @\"MASViewConstraint _installedView\",\n                @\"MASLayoutConstraint _container\",\n                @\"MASViewAttribute _view\"\n            ]];\n        });\n\n        NSString *row = ref.reference;\n        return ([row hasPrefix:@\"NSLayout\"] && [row hasSuffix:@\" _referenceItem\"]) ||\n               ([row hasPrefix:@\"NSIS\"] && [row hasSuffix:@\" _delegate\"])  ||\n               ([row hasPrefix:@\"_NSAutoresizingMask\"] && [row hasSuffix:@\" _referenceItem\"]) ||\n               [ignored containsObject:row];\n    };\n\n    BOOL(^isEssential)(FLEXObjectRef *, NSDictionary *) = ^BOOL(FLEXObjectRef *ref, NSDictionary *bindings) {\n        return !(isObserver(ref, bindings) || isConstraintRelated(ref, bindings));\n    };\n\n    switch (section) {\n        case 0: return [NSPredicate predicateWithBlock:isEssential];\n        case 1: return [NSPredicate predicateWithBlock:isConstraintRelated];\n        case 2: return [NSPredicate predicateWithBlock:isObserver];\n\n        default: return nil;\n    }\n}\n\n+ (NSArray<NSPredicate *> *)defaultPredicates {\n    return @[[self defaultPredicateForSection:0],\n             [self defaultPredicateForSection:1],\n             [self defaultPredicateForSection:2]];\n}\n\n+ (NSArray<NSString *> *)defaultSectionTitles {\n    return @[@\"\", @\"AutoLayout\", @\"Trivial\"];\n}\n\n- (void)buildSections\n{\n    NSInteger maxSections = self.maxSections;\n    NSMutableArray *sections = [NSMutableArray array];\n    for (NSInteger i = 0; i < maxSections; i++) {\n        NSPredicate *predicate = self.predicates[i];\n        [sections addObject:[self.instances filteredArrayUsingPredicate:predicate]];\n    }\n\n    self.sections = sections;\n}\n\n- (NSInteger)maxSections {\n    return self.predicates.count ?: 1;\n}\n\n\n#pragma mark - Table View Data Source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return self.maxSections;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return self.sections[section].count;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    static NSString *CellIdentifier = @\"Cell\";\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];\n    if (!cell) {\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];\n        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;\n        UIFont *cellFont = [FLEXUtility defaultTableViewCellLabelFont];\n        cell.textLabel.font = cellFont;\n        cell.detailTextLabel.font = cellFont;\n        cell.detailTextLabel.textColor = [UIColor grayColor];\n    }\n\n    FLEXObjectRef *row = self.sections[indexPath.section][indexPath.row];\n    cell.textLabel.text = row.reference;\n    cell.detailTextLabel.text = [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:row.object];\n    \n    return cell;\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section\n{\n    if (self.sectionTitles.count) {\n        // Return nil instead of empty strings\n        NSString *title = self.sectionTitles[section];\n        if (title.length) {\n            return title;\n        }\n    }\n\n    return nil;\n}\n\n\n#pragma mark - Table View Delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    id instance = self.instances[indexPath.row];\n    FLEXObjectExplorerViewController *drillInViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:instance];\n    [self.navigationController pushViewController:drillInViewController animated:YES];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXLibrariesTableViewController.h",
    "content": "//\n//  FLEXLibrariesTableViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-02.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXLibrariesTableViewController : UITableViewController\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXLibrariesTableViewController.m",
    "content": "//\n//  FLEXLibrariesTableViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-02.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXLibrariesTableViewController.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXClassesTableViewController.h\"\n#import \"FLEXClassExplorerViewController.h\"\n#import <objc/runtime.h>\n\n@interface FLEXLibrariesTableViewController () <UISearchBarDelegate>\n\n@property (nonatomic, strong) NSArray<NSString *> *imageNames;\n@property (nonatomic, strong) NSArray<NSString *> *filteredImageNames;\n\n@property (nonatomic, strong) UISearchBar *searchBar;\n@property (nonatomic, strong) Class foundClass;\n\n@end\n\n@implementation FLEXLibrariesTableViewController\n\n- (id)initWithStyle:(UITableViewStyle)style\n{\n    self = [super initWithStyle:style];\n    if (self) {\n        [self loadImageNames];\n    }\n    return self;\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.searchBar = [[UISearchBar alloc] init];\n    self.searchBar.delegate = self;\n    self.searchBar.placeholder = [FLEXUtility searchBarPlaceholderText];\n    [self.searchBar sizeToFit];\n    self.tableView.tableHeaderView = self.searchBar;\n}\n\n\n#pragma mark - Binary Images\n\n- (void)loadImageNames\n{\n    unsigned int imageNamesCount = 0;\n    const char **imageNames = objc_copyImageNames(&imageNamesCount);\n    if (imageNames) {\n        NSMutableArray<NSString *> *imageNameStrings = [NSMutableArray array];\n        NSString *appImageName = [FLEXUtility applicationImageName];\n        for (unsigned int i = 0; i < imageNamesCount; i++) {\n            const char *imageName = imageNames[i];\n            NSString *imageNameString = [NSString stringWithUTF8String:imageName];\n            // Skip the app's image. We're just showing system libraries and frameworks.\n            if (![imageNameString isEqual:appImageName]) {\n                [imageNameStrings addObject:imageNameString];\n            }\n        }\n        \n        // Sort alphabetically\n        self.imageNames = [imageNameStrings sortedArrayWithOptions:0 usingComparator:^NSComparisonResult(NSString *name1, NSString *name2) {\n            NSString *shortName1 = [self shortNameForImageName:name1];\n            NSString *shortName2 = [self shortNameForImageName:name2];\n            return [shortName1 caseInsensitiveCompare:shortName2];\n        }];\n        \n        free(imageNames);\n    }\n}\n\n- (NSString *)shortNameForImageName:(NSString *)imageName\n{\n    NSArray<NSString *> *components = [imageName componentsSeparatedByString:@\"/\"];\n    if (components.count >= 2) {\n        return [NSString stringWithFormat:@\"%@/%@\", components[components.count - 2], components[components.count - 1]];\n    }\n    return imageName.lastPathComponent;\n}\n\n- (void)setImageNames:(NSArray<NSString *> *)imageNames\n{\n    if (![_imageNames isEqual:imageNames]) {\n        _imageNames = imageNames;\n        self.filteredImageNames = imageNames;\n    }\n}\n\n\n#pragma mark - Filtering\n\n- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText\n{\n    if ([searchText length] > 0) {\n        NSPredicate *searchPreidcate = [NSPredicate predicateWithBlock:^BOOL(NSString *evaluatedObject, NSDictionary<NSString *, id> *bindings) {\n            BOOL matches = NO;\n            NSString *shortName = [self shortNameForImageName:evaluatedObject];\n            if ([shortName rangeOfString:searchText options:NSCaseInsensitiveSearch].length > 0) {\n                matches = YES;\n            }\n            return matches;\n        }];\n        self.filteredImageNames = [self.imageNames filteredArrayUsingPredicate:searchPreidcate];\n    } else {\n        self.filteredImageNames = self.imageNames;\n    }\n    \n    self.foundClass = NSClassFromString(searchText);\n    [self.tableView reloadData];\n}\n\n- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar\n{\n    [searchBar resignFirstResponder];\n}\n\n\n#pragma mark - Table View Data Source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return self.filteredImageNames.count + (self.foundClass ? 1 : 0);\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    static NSString *cellIdentifier = @\"Cell\";\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];\n    if (!cell) {\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];\n        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;\n        cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n    }\n    \n    NSString *executablePath;\n    if (self.foundClass) {\n        if (indexPath.row == 0) {\n            cell.textLabel.text = [NSString stringWithFormat:@\"Class \\\"%@\\\"\", self.searchBar.text];\n            return cell;\n        } else {\n            executablePath = self.filteredImageNames[indexPath.row-1];\n        }\n    } else {\n        executablePath = self.filteredImageNames[indexPath.row];\n    }\n    \n    cell.textLabel.text = [self shortNameForImageName:executablePath];\n    return cell;\n}\n\n\n#pragma mark - Table View Delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    if (indexPath.row == 0 && self.foundClass) {\n        FLEXClassExplorerViewController *objectExplorer = [FLEXClassExplorerViewController new];\n        objectExplorer.object = self.foundClass;\n        [self.navigationController pushViewController:objectExplorer animated:YES];\n    } else {\n        FLEXClassesTableViewController *classesViewController = [[FLEXClassesTableViewController alloc] init];\n        classesViewController.binaryImageName = self.filteredImageNames[self.foundClass ? indexPath.row-1 : indexPath.row];\n        [self.navigationController pushViewController:classesViewController animated:YES];\n    }\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXLiveObjectsTableViewController.h",
    "content": "//\n//  FLEXLiveObjectsTableViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/28/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXLiveObjectsTableViewController : UITableViewController\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m",
    "content": "//\n//  FLEXLiveObjectsTableViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/28/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXLiveObjectsTableViewController.h\"\n#import \"FLEXHeapEnumerator.h\"\n#import \"FLEXInstancesTableViewController.h\"\n#import \"FLEXUtility.h\"\n#import <objc/runtime.h>\n\nstatic const NSInteger kFLEXLiveObjectsSortAlphabeticallyIndex = 0;\nstatic const NSInteger kFLEXLiveObjectsSortByCountIndex = 1;\nstatic const NSInteger kFLEXLiveObjectsSortBySizeIndex = 2;\n\n@interface FLEXLiveObjectsTableViewController () <UISearchBarDelegate>\n\n@property (nonatomic, strong) NSDictionary<NSString *, NSNumber *> *instanceCountsForClassNames;\n@property (nonatomic, strong) NSDictionary<NSString *, NSNumber *> *instanceSizesForClassNames;\n@property (nonatomic, readonly) NSArray<NSString *> *allClassNames;\n@property (nonatomic, strong) NSArray<NSString *> *filteredClassNames;\n@property (nonatomic, strong) UISearchBar *searchBar;\n\n@end\n\n@implementation FLEXLiveObjectsTableViewController\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.searchBar = [[UISearchBar alloc] init];\n    self.searchBar.placeholder = [FLEXUtility searchBarPlaceholderText];\n    self.searchBar.delegate = self;\n    self.searchBar.showsScopeBar = YES;\n    self.searchBar.scopeButtonTitles = @[@\"Sort Alphabetically\", @\"Sort by Count\", @\"Sort by Size\"];\n    [self.searchBar sizeToFit];\n    self.tableView.tableHeaderView = self.searchBar;\n    \n    self.refreshControl = [[UIRefreshControl alloc] init];\n    [self.refreshControl addTarget:self action:@selector(refreshControlDidRefresh:) forControlEvents:UIControlEventValueChanged];\n    \n    [self reloadTableData];\n}\n\n- (NSArray<NSString *> *)allClassNames\n{\n    return [self.instanceCountsForClassNames allKeys];\n}\n\n- (void)reloadTableData\n{\n    // Set up a CFMutableDictionary with class pointer keys and NSUInteger values.\n    // We abuse CFMutableDictionary a little to have primitive keys through judicious casting, but it gets the job done.\n    // The dictionary is intialized with a 0 count for each class so that it doesn't have to expand during enumeration.\n    // While it might be a little cleaner to populate an NSMutableDictionary with class name string keys to NSNumber counts,\n    // we choose the CF/primitives approach because it lets us enumerate the objects in the heap without allocating any memory during enumeration.\n    // The alternative of creating one NSString/NSNumber per object on the heap ends up polluting the count of live objects quite a bit.\n    unsigned int classCount = 0;\n    Class *classes = objc_copyClassList(&classCount);\n    CFMutableDictionaryRef mutableCountsForClasses = CFDictionaryCreateMutable(NULL, classCount, NULL, NULL);\n    for (unsigned int i = 0; i < classCount; i++) {\n        CFDictionarySetValue(mutableCountsForClasses, (__bridge const void *)classes[i], (const void *)0);\n    }\n    \n    // Enumerate all objects on the heap to build the counts of instances for each class.\n    [FLEXHeapEnumerator enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object, __unsafe_unretained Class actualClass) {\n        NSUInteger instanceCount = (NSUInteger)CFDictionaryGetValue(mutableCountsForClasses, (__bridge const void *)actualClass);\n        instanceCount++;\n        CFDictionarySetValue(mutableCountsForClasses, (__bridge const void *)actualClass, (const void *)instanceCount);\n    }];\n    \n    // Convert our CF primitive dictionary into a nicer mapping of class name strings to counts that we will use as the table's model.\n    NSMutableDictionary<NSString *, NSNumber *> *mutableCountsForClassNames = [NSMutableDictionary dictionary];\n    NSMutableDictionary<NSString *, NSNumber *> *mutableSizesForClassNames = [NSMutableDictionary dictionary];\n    for (unsigned int i = 0; i < classCount; i++) {\n        Class class = classes[i];\n        NSUInteger instanceCount = (NSUInteger)CFDictionaryGetValue(mutableCountsForClasses, (__bridge const void *)(class));\n        NSString *className = @(class_getName(class));\n        if (instanceCount > 0) {\n            [mutableCountsForClassNames setObject:@(instanceCount) forKey:className];\n        }\n        [mutableSizesForClassNames setObject:@(class_getInstanceSize(class)) forKey:className];\n    }\n    free(classes);\n    \n    self.instanceCountsForClassNames = mutableCountsForClassNames;\n    self.instanceSizesForClassNames = mutableSizesForClassNames;\n    \n    [self updateTableDataForSearchFilter];\n}\n\n- (void)refreshControlDidRefresh:(id)sender\n{\n    [self reloadTableData];\n    [self.refreshControl endRefreshing];\n}\n\n- (void)updateTitle\n{\n    NSString *title = @\"Live Objects\";\n    \n    NSUInteger totalCount = 0;\n    NSUInteger totalSize = 0;\n    for (NSString *className in self.allClassNames) {\n        NSUInteger count = [self.instanceCountsForClassNames[className] unsignedIntegerValue];\n        totalCount += count;\n        totalSize += count * [self.instanceSizesForClassNames[className] unsignedIntegerValue];\n    }\n    NSUInteger filteredCount = 0;\n    NSUInteger filteredSize = 0;\n    for (NSString *className in self.filteredClassNames) {\n        NSUInteger count = [self.instanceCountsForClassNames[className] unsignedIntegerValue];\n        filteredCount += count;\n        filteredSize += count * [self.instanceSizesForClassNames[className] unsignedIntegerValue];\n    }\n    \n    if (filteredCount == totalCount) {\n        // Unfiltered\n        title = [title stringByAppendingFormat:@\" (%lu, %@)\", (unsigned long)totalCount,\n              [NSByteCountFormatter stringFromByteCount:totalSize countStyle:NSByteCountFormatterCountStyleFile]];\n    } else {\n        title = [title stringByAppendingFormat:@\" (filtered, %lu, %@)\", (unsigned long)filteredCount,\n              [NSByteCountFormatter stringFromByteCount:filteredSize countStyle:NSByteCountFormatterCountStyleFile]];\n    }\n    \n    self.title = title;\n}\n\n\n#pragma mark - Search\n\n- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText\n{\n    [self updateTableDataForSearchFilter];\n}\n\n- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar\n{\n    [searchBar resignFirstResponder];\n}\n\n- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope\n{\n    [self updateTableDataForSearchFilter];\n}\n\n- (void)scrollViewDidScroll:(UIScrollView *)scrollView\n{\n    // Dismiss the keyboard when interacting with filtered results.\n    [self.searchBar endEditing:YES];\n}\n\n- (void)updateTableDataForSearchFilter\n{\n    if ([self.searchBar.text length] > 0) {\n        NSPredicate *searchPreidcate = [NSPredicate predicateWithFormat:@\"SELF CONTAINS[cd] %@\", self.searchBar.text];\n        self.filteredClassNames = [self.allClassNames filteredArrayUsingPredicate:searchPreidcate];\n    } else {\n        self.filteredClassNames = self.allClassNames;\n    }\n    \n    if (self.searchBar.selectedScopeButtonIndex == kFLEXLiveObjectsSortAlphabeticallyIndex) {\n        self.filteredClassNames = [self.filteredClassNames sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];\n    } else if (self.searchBar.selectedScopeButtonIndex == kFLEXLiveObjectsSortByCountIndex) {\n        self.filteredClassNames = [self.filteredClassNames sortedArrayUsingComparator:^NSComparisonResult(NSString *className1, NSString *className2) {\n            NSNumber *count1 = self.instanceCountsForClassNames[className1];\n            NSNumber *count2 = self.instanceCountsForClassNames[className2];\n            // Reversed for descending counts.\n            return [count2 compare:count1];\n        }];\n    } else if (self.searchBar.selectedScopeButtonIndex == kFLEXLiveObjectsSortBySizeIndex) {\n        self.filteredClassNames = [self.filteredClassNames sortedArrayUsingComparator:^NSComparisonResult(NSString *className1, NSString *className2) {\n            NSNumber *count1 = self.instanceCountsForClassNames[className1];\n            NSNumber *count2 = self.instanceCountsForClassNames[className2];\n            NSNumber *size1 = self.instanceSizesForClassNames[className1];\n            NSNumber *size2 = self.instanceSizesForClassNames[className2];\n            // Reversed for descending sizes.\n            return [@(count2.integerValue * size2.integerValue) compare:@(count1.integerValue * size1.integerValue)];\n        }];\n    }\n    \n    [self updateTitle];\n    [self.tableView reloadData];\n}\n\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return [self.filteredClassNames count];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    static NSString *CellIdentifier = @\"Cell\";\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];\n    if (!cell) {\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];\n        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;\n        cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n    }\n    \n    NSString *className = self.filteredClassNames[indexPath.row];\n    NSNumber *count = self.instanceCountsForClassNames[className];\n    NSNumber *size = self.instanceSizesForClassNames[className];\n    unsigned long totalSize = count.unsignedIntegerValue * size.unsignedIntegerValue;\n    cell.textLabel.text = [NSString stringWithFormat:@\"%@ (%ld, %@)\", className, (long)[count integerValue],\n        [NSByteCountFormatter stringFromByteCount:totalSize countStyle:NSByteCountFormatterCountStyleFile]];\n    \n    return cell;\n}\n\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    NSString *className = self.filteredClassNames[indexPath.row];\n    FLEXInstancesTableViewController *instancesViewController = [FLEXInstancesTableViewController instancesTableViewControllerForClassName:className];\n    [self.navigationController pushViewController:instancesViewController animated:YES];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXObjectRef.h",
    "content": "//\n//  FLEXObjectRef.h\n//  FLEX\n//\n//  Created by Tanner Bennett on 7/24/18.\n//  Copyright (c) 2018 Flipboard. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface FLEXObjectRef : NSObject\n\n+ (instancetype)referencing:(id)object;\n+ (instancetype)referencing:(id)object ivar:(NSString *)ivarName;\n\n+ (NSArray<FLEXObjectRef *> *)referencingAll:(NSArray *)objects;\n\n/// For example, \"NSString 0x1d4085d0\" or \"NSLayoutConstraint _object\"\n@property (nonatomic, readonly) NSString *reference;\n@property (nonatomic, readonly) id object;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXObjectRef.m",
    "content": "//\n//  FLEXObjectRef.m\n//  FLEX\n//\n//  Created by Tanner Bennett on 7/24/18.\n//  Copyright (c) 2018 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectRef.h\"\n#import <objc/runtime.h>\n\n@implementation FLEXObjectRef\n\n+ (instancetype)referencing:(id)object {\n    return [[self alloc] initWithObject:object ivarName:nil];\n}\n\n+ (instancetype)referencing:(id)object ivar:(NSString *)ivarName {\n    return [[self alloc] initWithObject:object ivarName:ivarName];\n}\n\n+ (NSArray<FLEXObjectRef *> *)referencingAll:(NSArray *)objects {\n    NSMutableArray<FLEXObjectRef *> *refs = [NSMutableArray array];\n    for (id obj in objects) {\n        [refs addObject:[self referencing:obj]];\n    }\n\n    return refs;\n}\n\n- (id)initWithObject:(id)object ivarName:(NSString *)ivar {\n    self = [super init];\n    if (self) {\n        _object = object;\n\n        NSString *class = NSStringFromClass(object_getClass(object));\n        if (ivar) {\n            _reference = [NSString stringWithFormat:@\"%@ %@\", class, ivar];\n        } else {\n            _reference = [NSString stringWithFormat:@\"%@ %p\", class, object];\n        }\n    }\n\n    return self;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXWebViewController.h",
    "content": "//\n//  FLEXWebViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/10/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXWebViewController : UIViewController\n\n- (id)initWithURL:(NSURL *)url;\n- (id)initWithText:(NSString *)text;\n\n+ (BOOL)supportsPathExtension:(NSString *)extension;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/FLEXWebViewController.m",
    "content": "//\n//  FLEXWebViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/10/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXWebViewController.h\"\n#import \"FLEXUtility.h\"\n\n@interface FLEXWebViewController () <UIWebViewDelegate>\n\n@property (nonatomic, strong) UIWebView *webView;\n@property (nonatomic, strong) NSString *originalText;\n\n@end\n\n@implementation FLEXWebViewController\n\n- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil\n{\n    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];\n    if (self) {\n        self.webView = [[UIWebView alloc] init];\n        self.webView.delegate = self;\n        self.webView.dataDetectorTypes = UIDataDetectorTypeLink;\n        self.webView.scalesPageToFit = YES;\n    }\n    return self;\n}\n\n- (id)initWithText:(NSString *)text\n{\n    self = [self initWithNibName:nil bundle:nil];\n    if (self) {\n        self.originalText = text;\n        NSString *htmlString = [NSString stringWithFormat:@\"<head><meta name='viewport' content='initial-scale=1.0'></head><body><pre>%@</pre></body>\", [FLEXUtility stringByEscapingHTMLEntitiesInString:text]];\n        [self.webView loadHTMLString:htmlString baseURL:nil];\n    }\n    return self;\n}\n\n- (id)initWithURL:(NSURL *)url\n{\n    self = [self initWithNibName:nil bundle:nil];\n    if (self) {\n        NSURLRequest *request = [NSURLRequest requestWithURL:url];\n        [self.webView loadRequest:request];\n    }\n    return self;\n}\n\n- (void)dealloc\n{\n    // UIWebView's delegate is assign so we need to clear it manually.\n    if (_webView.delegate == self) {\n        _webView.delegate = nil;\n    }\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    [self.view addSubview:self.webView];\n    self.webView.frame = self.view.bounds;\n    self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    \n    if ([self.originalText length] > 0) {\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@\"Copy\" style:UIBarButtonItemStylePlain target:self action:@selector(copyButtonTapped:)];\n    }\n}\n\n- (void)copyButtonTapped:(id)sender\n{\n    [[UIPasteboard generalPasteboard] setString:self.originalText];\n}\n\n\n#pragma mark - UIWebView Delegate\n\n- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType\n{\n    BOOL shouldStart = NO;\n    if (navigationType == UIWebViewNavigationTypeOther) {\n        // Allow the initial load\n        shouldStart = YES;\n    } else {\n        // For clicked links, push another web view controller onto the navigation stack so that hitting the back button works as expected.\n        // Don't allow the current web view do handle the navigation.\n        FLEXWebViewController *webVC = [[[self class] alloc] initWithURL:[request URL]];\n        webVC.title = [[request URL] absoluteString];\n        [self.navigationController pushViewController:webVC animated:YES];\n    }\n    return shouldStart;\n}\n\n\n#pragma mark - Class Helpers\n\n+ (BOOL)supportsPathExtension:(NSString *)extension\n{\n    BOOL supported = NO;\n    NSSet<NSString *> *supportedExtensions = [self webViewSupportedPathExtensions];\n    if ([supportedExtensions containsObject:[extension lowercaseString]]) {\n        supported = YES;\n    }\n    return supported;\n}\n\n+ (NSSet<NSString *> *)webViewSupportedPathExtensions\n{\n    static NSSet<NSString *> *pathExtenstions = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        // Note that this is not exhaustive, but all these extensions should work well in the web view.\n        // See https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html#//apple_ref/doc/uid/TP40006482-SW7\n        pathExtenstions = [NSSet<NSString *> setWithArray:@[@\"jpg\", @\"jpeg\", @\"png\", @\"gif\", @\"pdf\", @\"svg\", @\"tiff\", @\"3gp\", @\"3gpp\", @\"3g2\",\n                                                            @\"3gp2\", @\"aiff\", @\"aif\", @\"aifc\", @\"cdda\", @\"amr\", @\"mp3\", @\"swa\", @\"mp4\", @\"mpeg\",\n                                                            @\"mpg\", @\"mp3\", @\"wav\", @\"bwf\", @\"m4a\", @\"m4b\", @\"m4p\", @\"mov\", @\"qt\", @\"mqv\", @\"m4v\"]];\n        \n    });\n    return pathExtenstions;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogMessage.h",
    "content": "//\n//  FLEXSystemLogMessage.h\n//  UICatalog\n//\n//  Created by Ryan Olson on 1/25/15.\n//  Copyright (c) 2015 f. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <asl.h>\n\n@interface FLEXSystemLogMessage : NSObject\n\n+ (instancetype)logMessageFromASLMessage:(aslmsg)aslMessage;\n\n@property (nonatomic, strong) NSDate *date;\n@property (nonatomic, copy) NSString *sender;\n@property (nonatomic, copy) NSString *messageText;\n@property (nonatomic, assign) long long messageID;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogMessage.m",
    "content": "//\n//  FLEXSystemLogMessage.m\n//  UICatalog\n//\n//  Created by Ryan Olson on 1/25/15.\n//  Copyright (c) 2015 f. All rights reserved.\n//\n\n#import \"FLEXSystemLogMessage.h\"\n\n@implementation FLEXSystemLogMessage\n\n+ (instancetype)logMessageFromASLMessage:(aslmsg)aslMessage\n{\n    FLEXSystemLogMessage *logMessage = [[FLEXSystemLogMessage alloc] init];\n\n    const char *timestamp = asl_get(aslMessage, ASL_KEY_TIME);\n    if (timestamp) {\n        NSTimeInterval timeInterval = [@(timestamp) integerValue];\n        const char *nanoseconds = asl_get(aslMessage, ASL_KEY_TIME_NSEC);\n        if (nanoseconds) {\n            timeInterval += [@(nanoseconds) doubleValue] / NSEC_PER_SEC;\n        }\n        logMessage.date = [NSDate dateWithTimeIntervalSince1970:timeInterval];\n    }\n\n    const char *sender = asl_get(aslMessage, ASL_KEY_SENDER);\n    if (sender) {\n        logMessage.sender = @(sender);\n    }\n\n    const char *messageText = asl_get(aslMessage, ASL_KEY_MSG);\n    if (messageText) {\n        logMessage.messageText = @(messageText);\n    }\n\n    const char *messageID = asl_get(aslMessage, ASL_KEY_MSG_ID);\n    if (messageID) {\n        logMessage.messageID = [@(messageID) longLongValue];\n    }\n\n    return logMessage;\n}\n\n- (BOOL)isEqual:(id)object\n{\n    return [object isKindOfClass:[FLEXSystemLogMessage class]] && self.messageID == [object messageID];\n}\n\n- (NSUInteger)hash\n{\n    return (NSUInteger)self.messageID;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.h",
    "content": "//\n//  FLEXSystemLogTableViewCell.h\n//  UICatalog\n//\n//  Created by Ryan Olson on 1/25/15.\n//  Copyright (c) 2015 f. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@class FLEXSystemLogMessage;\n\nextern NSString *const kFLEXSystemLogTableViewCellIdentifier;\n\n@interface FLEXSystemLogTableViewCell : UITableViewCell\n\n@property (nonatomic, strong) FLEXSystemLogMessage *logMessage;\n@property (nonatomic, copy) NSString *highlightedText;\n\n+ (NSString *)displayedTextForLogMessage:(FLEXSystemLogMessage *)logMessage;\n+ (CGFloat)preferredHeightForLogMessage:(FLEXSystemLogMessage *)logMessage inWidth:(CGFloat)width;\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m",
    "content": "//\n//  FLEXSystemLogTableViewCell.m\n//  UICatalog\n//\n//  Created by Ryan Olson on 1/25/15.\n//  Copyright (c) 2015 f. All rights reserved.\n//\n\n#import \"FLEXSystemLogTableViewCell.h\"\n#import \"FLEXSystemLogMessage.h\"\n\nNSString *const kFLEXSystemLogTableViewCellIdentifier = @\"FLEXSystemLogTableViewCellIdentifier\";\n\n@interface FLEXSystemLogTableViewCell ()\n\n@property (nonatomic, strong) UILabel *logMessageLabel;\n@property (nonatomic, strong) NSAttributedString *logMessageAttributedText;\n\n@end\n\n@implementation FLEXSystemLogTableViewCell\n\n- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier\n{\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.logMessageLabel = [[UILabel alloc] init];\n        self.logMessageLabel.numberOfLines = 0;\n        self.separatorInset = UIEdgeInsetsZero;\n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        [self.contentView addSubview:self.logMessageLabel];\n    }\n    return self;\n}\n\n- (void)setLogMessage:(FLEXSystemLogMessage *)logMessage\n{\n    if (![_logMessage isEqual:logMessage]) {\n        _logMessage = logMessage;\n        self.logMessageAttributedText = nil;\n        [self setNeedsLayout];\n    }\n}\n\n- (void)setHighlightedText:(NSString *)highlightedText\n{\n    if (![_highlightedText isEqual:highlightedText]) {\n        _highlightedText = highlightedText;\n        self.logMessageAttributedText = nil;\n        [self setNeedsLayout];\n    }\n}\n\n- (NSAttributedString *)logMessageAttributedText\n{\n    if (!_logMessageAttributedText) {\n        _logMessageAttributedText = [[self class] attributedTextForLogMessage:self.logMessage highlightedText:self.highlightedText];\n    }\n    return _logMessageAttributedText;\n}\n\nstatic const UIEdgeInsets kFLEXLogMessageCellInsets = {10.0, 10.0, 10.0, 10.0};\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n\n    self.logMessageLabel.attributedText = self.logMessageAttributedText;\n    self.logMessageLabel.frame = UIEdgeInsetsInsetRect(self.contentView.bounds, kFLEXLogMessageCellInsets);\n}\n\n#pragma mark - Stateless helpers\n\n+ (NSAttributedString *)attributedTextForLogMessage:(FLEXSystemLogMessage *)logMessage highlightedText:(NSString *)highlightedText\n{\n    NSString *text = [self displayedTextForLogMessage:logMessage];\n    NSDictionary<NSString *, id> *attributes = @{ NSFontAttributeName : [UIFont fontWithName:@\"CourierNewPSMT\" size:12.0] };\n    NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:attributes];\n\n    if ([highlightedText length] > 0) {\n        NSMutableAttributedString *mutableAttributedText = [attributedText mutableCopy];\n        NSMutableDictionary<NSString *, id> *highlightAttributes = [@{ NSBackgroundColorAttributeName : [UIColor yellowColor] } mutableCopy];\n        [highlightAttributes addEntriesFromDictionary:attributes];\n        \n        NSRange remainingSearchRange = NSMakeRange(0, text.length);\n        while (remainingSearchRange.location < text.length) {\n            remainingSearchRange.length = text.length - remainingSearchRange.location;\n            NSRange foundRange = [text rangeOfString:highlightedText options:NSCaseInsensitiveSearch range:remainingSearchRange];\n            if (foundRange.location != NSNotFound) {\n                remainingSearchRange.location = foundRange.location + foundRange.length;\n                [mutableAttributedText setAttributes:highlightAttributes range:foundRange];\n            } else {\n                break;\n            }\n        }\n        attributedText = mutableAttributedText;\n    }\n\n    return attributedText;\n}\n\n+ (NSString *)displayedTextForLogMessage:(FLEXSystemLogMessage *)logMessage\n{\n    return [NSString stringWithFormat:@\"%@: %@\", [self logTimeStringFromDate:logMessage.date], logMessage.messageText];\n}\n\n+ (CGFloat)preferredHeightForLogMessage:(FLEXSystemLogMessage *)logMessage inWidth:(CGFloat)width\n{\n    UIEdgeInsets insets = kFLEXLogMessageCellInsets;\n    CGFloat availableWidth = width - insets.left - insets.right;\n    NSAttributedString *attributedLogText = [self attributedTextForLogMessage:logMessage highlightedText:nil];\n    CGSize labelSize = [attributedLogText boundingRectWithSize:CGSizeMake(availableWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading context:nil].size;\n    return labelSize.height + insets.top + insets.bottom;\n}\n\n+ (NSString *)logTimeStringFromDate:(NSDate *)date\n{\n    static NSDateFormatter *formatter = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        formatter = [[NSDateFormatter alloc] init];\n        formatter.dateFormat = @\"yyyy-MM-dd HH:mm:ss.SSS\";\n    });\n\n    return [formatter stringFromDate:date];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewController.h",
    "content": "//\n//  FLEXSystemLogTableViewController.h\n//  UICatalog\n//\n//  Created by Ryan Olson on 1/19/15.\n//  Copyright (c) 2015 f. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXSystemLogTableViewController : UITableViewController\n\n@end\n"
  },
  {
    "path": "FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewController.m",
    "content": "//\n//  FLEXSystemLogTableViewController.m\n//  UICatalog\n//\n//  Created by Ryan Olson on 1/19/15.\n//  Copyright (c) 2015 f. All rights reserved.\n//\n\n#import \"FLEXSystemLogTableViewController.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXSystemLogMessage.h\"\n#import \"FLEXSystemLogTableViewCell.h\"\n#import <asl.h>\n\n@interface FLEXSystemLogTableViewController () <UISearchResultsUpdating, UISearchControllerDelegate>\n\n@property (nonatomic, strong) UISearchController *searchController;\n@property (nonatomic, readonly) NSMutableArray<FLEXSystemLogMessage *> *logMessages;\n@property (nonatomic, copy) NSArray<FLEXSystemLogMessage *> *filteredLogMessages;\n@property (nonatomic, strong) NSTimer *logUpdateTimer;\n@property (nonatomic, readonly) NSMutableIndexSet *logMessageIdentifiers;\n\n@end\n\n@implementation FLEXSystemLogTableViewController\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n\n    _logMessages = [NSMutableArray array];\n    _logMessageIdentifiers = [NSMutableIndexSet indexSet];\n\n    [self.tableView registerClass:[FLEXSystemLogTableViewCell class] forCellReuseIdentifier:kFLEXSystemLogTableViewCellIdentifier];\n    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    self.title = @\"Loading...\";\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@\" ⬇︎ \" style:UIBarButtonItemStylePlain target:self action:@selector(scrollToLastRow)];\n\n    self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];\n    self.searchController.delegate = self;\n    self.searchController.searchResultsUpdater = self;\n    self.searchController.dimsBackgroundDuringPresentation = NO;\n    self.tableView.tableHeaderView = self.searchController.searchBar;\n\n    [self updateLogMessages];\n}\n\n- (void)viewWillAppear:(BOOL)animated\n{\n    [super viewWillAppear:animated];\n\n    NSTimeInterval updateInterval = 1.0;\n\n#if TARGET_IPHONE_SIMULATOR\n    // Querrying the ASL is much slower in the simulator. We need a longer polling interval to keep things repsonsive.\n    updateInterval = 5.0;\n#endif\n\n    self.logUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:updateInterval target:self selector:@selector(updateLogMessages) userInfo:nil repeats:YES];\n}\n\n- (void)viewWillDisappear:(BOOL)animated\n{\n    [super viewWillDisappear:animated];\n\n    [self.logUpdateTimer invalidate];\n}\n\n- (void)updateLogMessages\n{\n    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n        NSArray<FLEXSystemLogMessage *> *newMessages = [self newLogMessagesForCurrentProcess];\n        if (!newMessages.count) {\n            return;\n        }\n\n        dispatch_async(dispatch_get_main_queue(), ^{\n            self.title = @\"System Log\";\n\n            [self.logMessages addObjectsFromArray:newMessages];\n            for (FLEXSystemLogMessage *message in newMessages) {\n                [self.logMessageIdentifiers addIndex:(NSUInteger)message.messageID];\n            }\n\n            // \"Follow\" the log as new messages stream in if we were previously near the bottom.\n            BOOL wasNearBottom = self.tableView.contentOffset.y >= self.tableView.contentSize.height - self.tableView.frame.size.height - 100.0;\n            [self.tableView reloadData];\n            if (wasNearBottom) {\n                [self scrollToLastRow];\n            }\n        });\n    });\n}\n\n- (void)scrollToLastRow\n{\n    NSInteger numberOfRows = [self.tableView numberOfRowsInSection:0];\n    if (numberOfRows > 0) {\n        NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:numberOfRows - 1 inSection:0];\n        [self.tableView scrollToRowAtIndexPath:lastIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];\n    }\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return self.searchController.isActive ? [self.filteredLogMessages count] : [self.logMessages count];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath \n{\n    FLEXSystemLogTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kFLEXSystemLogTableViewCellIdentifier forIndexPath:indexPath];\n    cell.logMessage = [self logMessageAtIndexPath:indexPath];\n    cell.highlightedText = self.searchController.searchBar.text;\n    \n    if (indexPath.row % 2 == 0) {\n        cell.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];\n    } else {\n        cell.backgroundColor = [UIColor whiteColor];\n    }\n    \n    return cell;\n}\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXSystemLogMessage *logMessage = [self logMessageAtIndexPath:indexPath];\n    return [FLEXSystemLogTableViewCell preferredHeightForLogMessage:logMessage inWidth:self.tableView.bounds.size.width];\n}\n\n#pragma mark - Copy on long press\n\n- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    return YES;\n}\n\n- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender\n{\n    return action == @selector(copy:);\n}\n\n- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender\n{\n    if (action == @selector(copy:)) {\n        FLEXSystemLogMessage *logMessage = [self logMessageAtIndexPath:indexPath];\n        NSString *stringToCopy = [FLEXSystemLogTableViewCell displayedTextForLogMessage:logMessage] ?: @\"\";\n        [[UIPasteboard generalPasteboard] setString:stringToCopy];\n    }\n}\n\n- (FLEXSystemLogMessage *)logMessageAtIndexPath:(NSIndexPath *)indexPath\n{\n    return self.searchController.isActive ? self.filteredLogMessages[indexPath.row] : self.logMessages[indexPath.row];\n}\n\n#pragma mark - UISearchResultsUpdating\n\n- (void)updateSearchResultsForSearchController:(UISearchController *)searchController\n{\n    NSString *searchString = searchController.searchBar.text;\n    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n        NSArray<FLEXSystemLogMessage *> *filteredLogMessages = [self.logMessages filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(FLEXSystemLogMessage *logMessage, NSDictionary<NSString *, id> *bindings) {\n            NSString *displayedText = [FLEXSystemLogTableViewCell displayedTextForLogMessage:logMessage];\n            return [displayedText rangeOfString:searchString options:NSCaseInsensitiveSearch].length > 0;\n        }]];\n        dispatch_async(dispatch_get_main_queue(), ^{\n            if ([searchController.searchBar.text isEqual:searchString]) {\n                self.filteredLogMessages = filteredLogMessages;\n                [self.tableView reloadData];\n            }\n        });\n    });\n}\n\n#pragma mark - Log Message Fetching\n\n- (NSArray<FLEXSystemLogMessage *> *)newLogMessagesForCurrentProcess\n{\n    if (!self.logMessages.count) {\n        return [[self class] allLogMessagesForCurrentProcess];\n    }\n\n    aslresponse response = [FLEXSystemLogTableViewController ASLMessageListForCurrentProcess];\n    aslmsg aslMessage = NULL;\n\n    NSMutableArray<FLEXSystemLogMessage *> *newMessages = [NSMutableArray array];\n\n    while ((aslMessage = asl_next(response))) {\n        NSUInteger messageID = (NSUInteger)atoll(asl_get(aslMessage, ASL_KEY_MSG_ID));\n        if (![self.logMessageIdentifiers containsIndex:messageID]) {\n            [newMessages addObject:[FLEXSystemLogMessage logMessageFromASLMessage:aslMessage]];\n        }\n    }\n\n    asl_release(response);\n    return newMessages;\n}\n\n+ (aslresponse)ASLMessageListForCurrentProcess\n{\n    static NSString *pidString = nil;\n    if (!pidString) {\n        pidString = @([[NSProcessInfo processInfo] processIdentifier]).stringValue;\n    }\n\n    // Create system log query object.\n    asl_object_t query = asl_new(ASL_TYPE_QUERY);\n\n    // Filter for messages from the current process.\n    // Note that this appears to happen by default on device, but is required in the simulator.\n    asl_set_query(query, ASL_KEY_PID, pidString.UTF8String, ASL_QUERY_OP_EQUAL);\n\n    return asl_search(NULL, query);\n}\n\n+ (NSArray<FLEXSystemLogMessage *> *)allLogMessagesForCurrentProcess\n{\n    aslresponse response = [self ASLMessageListForCurrentProcess];\n    aslmsg aslMessage = NULL;\n\n    NSMutableArray<FLEXSystemLogMessage *> *logMessages = [NSMutableArray array];\n    while ((aslMessage = asl_next(response))) {\n        [logMessages addObject:[FLEXSystemLogMessage logMessageFromASLMessage:aslMessage]];\n    }\n    asl_release(response);\n\n    return logMessages;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/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>$(PRODUCT_BUNDLE_IDENTIFIER)</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>FMWK</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>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>NSPrincipalClass</key>\n\t<string></string>\n</dict>\n</plist>\n"
  },
  {
    "path": "FLEX/Manager/FLEXManager+Private.h",
    "content": "//\n//  FLEXManager+Private.h\n//  PebbleApp\n//\n//  Created by Javier Soto on 7/26/14.\n//  Copyright (c) 2014 Pebble Technology. All rights reserved.\n//\n\n#import \"FLEXManager.h\"\n\n@class FLEXGlobalsTableViewControllerEntry;\n\n@interface FLEXManager ()\n\n/// An array of FLEXGlobalsTableViewControllerEntry objects that have been registered by the user.\n@property (nonatomic, readonly, strong) NSArray<FLEXGlobalsTableViewControllerEntry *> *userGlobalEntries;\n\n@end\n"
  },
  {
    "path": "FLEX/Manager/FLEXManager.m",
    "content": "//\n//  FLEXManager.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/4/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXManager.h\"\n#import \"FLEXExplorerViewController.h\"\n#import \"FLEXWindow.h\"\n#import \"FLEXGlobalsTableViewControllerEntry.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXObjectExplorerViewController.h\"\n#import \"FLEXNetworkObserver.h\"\n#import \"FLEXNetworkRecorder.h\"\n#import \"FLEXKeyboardShortcutManager.h\"\n#import \"FLEXFileBrowserTableViewController.h\"\n#import \"FLEXNetworkHistoryTableViewController.h\"\n#import \"FLEXKeyboardHelpViewController.h\"\n\n@interface FLEXManager () <FLEXWindowEventDelegate, FLEXExplorerViewControllerDelegate>\n\n@property (nonatomic, strong) FLEXWindow *explorerWindow;\n@property (nonatomic, strong) FLEXExplorerViewController *explorerViewController;\n\n@property (nonatomic, readonly, strong) NSMutableArray<FLEXGlobalsTableViewControllerEntry *> *userGlobalEntries;\n\n@end\n\n@implementation FLEXManager\n\n+ (instancetype)sharedManager\n{\n    static FLEXManager *sharedManager = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        sharedManager = [[[self class] alloc] init];\n    });\n    return sharedManager;\n}\n\n- (instancetype)init\n{\n    self = [super init];\n    if (self) {\n        _userGlobalEntries = [NSMutableArray array];\n    }\n    return self;\n}\n\n- (FLEXWindow *)explorerWindow\n{\n    NSAssert([NSThread isMainThread], @\"You must use %@ from the main thread only.\", NSStringFromClass([self class]));\n    \n    if (!_explorerWindow) {\n        _explorerWindow = [[FLEXWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];\n        _explorerWindow.eventDelegate = self;\n        _explorerWindow.rootViewController = self.explorerViewController;\n    }\n    \n    return _explorerWindow;\n}\n\n- (FLEXExplorerViewController *)explorerViewController\n{\n    if (!_explorerViewController) {\n        _explorerViewController = [[FLEXExplorerViewController alloc] init];\n        _explorerViewController.delegate = self;\n    }\n\n    return _explorerViewController;\n}\n\n- (void)showExplorer\n{\n    self.explorerWindow.hidden = NO;\n}\n\n- (void)hideExplorer\n{\n    self.explorerWindow.hidden = YES;\n}\n\n- (void)toggleExplorer {\n    if (self.explorerWindow.isHidden) {\n        [self showExplorer];\n    } else {\n        [self hideExplorer];\n    }\n}\n\n- (BOOL)isHidden\n{\n    return self.explorerWindow.isHidden;\n}\n\n- (BOOL)isNetworkDebuggingEnabled\n{\n    return [FLEXNetworkObserver isEnabled];\n}\n\n- (void)setNetworkDebuggingEnabled:(BOOL)networkDebuggingEnabled\n{\n    [FLEXNetworkObserver setEnabled:networkDebuggingEnabled];\n}\n\n- (NSUInteger)networkResponseCacheByteLimit\n{\n    return [[FLEXNetworkRecorder defaultRecorder] responseCacheByteLimit];\n}\n\n- (void)setNetworkResponseCacheByteLimit:(NSUInteger)networkResponseCacheByteLimit\n{\n    [[FLEXNetworkRecorder defaultRecorder] setResponseCacheByteLimit:networkResponseCacheByteLimit];\n}\n\n- (void)setNetworkRequestHostBlacklist:(NSArray<NSString *> *)networkRequestHostBlacklist\n{\n    [FLEXNetworkRecorder defaultRecorder].hostBlacklist = networkRequestHostBlacklist;\n}\n\n- (NSArray<NSString *> *)hostBlacklist\n{\n    return [FLEXNetworkRecorder defaultRecorder].hostBlacklist;\n}\n\n#pragma mark - FLEXWindowEventDelegate\n\n- (BOOL)shouldHandleTouchAtPoint:(CGPoint)pointInWindow\n{\n    // Ask the explorer view controller\n    return [self.explorerViewController shouldReceiveTouchAtWindowPoint:pointInWindow];\n}\n\n- (BOOL)canBecomeKeyWindow\n{\n    // Only when the explorer view controller wants it because it needs to accept key input & affect the status bar.\n    return [self.explorerViewController wantsWindowToBecomeKey];\n}\n\n\n#pragma mark - FLEXExplorerViewControllerDelegate\n\n- (void)explorerViewControllerDidFinish:(FLEXExplorerViewController *)explorerViewController\n{\n    [self hideExplorer];\n}\n\n#pragma mark - Simulator Shortcuts\n\n- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description\n{\n# if TARGET_OS_SIMULATOR\n    [[FLEXKeyboardShortcutManager sharedManager] registerSimulatorShortcutWithKey:key modifiers:modifiers action:action description:description];\n#endif\n}\n\n- (void)setSimulatorShortcutsEnabled:(BOOL)simulatorShortcutsEnabled\n{\n# if TARGET_OS_SIMULATOR\n    [[FLEXKeyboardShortcutManager sharedManager] setEnabled:simulatorShortcutsEnabled];\n#endif\n}\n\n- (BOOL)simulatorShortcutsEnabled\n{\n# if TARGET_OS_SIMULATOR\n    return [[FLEXKeyboardShortcutManager sharedManager] isEnabled];\n#else\n    return NO;\n#endif\n}\n\n- (void)registerDefaultSimulatorShortcuts\n{\n    [self registerSimulatorShortcutWithKey:@\"f\" modifiers:0 action:^{\n        [self toggleExplorer];\n    } description:@\"Toggle FLEX toolbar\"];\n    \n    [self registerSimulatorShortcutWithKey:@\"g\" modifiers:0 action:^{\n        [self showExplorerIfNeeded];\n        [self.explorerViewController toggleMenuTool];\n    } description:@\"Toggle FLEX globals menu\"];\n    \n    [self registerSimulatorShortcutWithKey:@\"v\" modifiers:0 action:^{\n        [self showExplorerIfNeeded];\n        [self.explorerViewController toggleViewsTool];\n    } description:@\"Toggle view hierarchy menu\"];\n    \n    [self registerSimulatorShortcutWithKey:@\"s\" modifiers:0 action:^{\n        [self showExplorerIfNeeded];\n        [self.explorerViewController toggleSelectTool];\n    } description:@\"Toggle select tool\"];\n    \n    [self registerSimulatorShortcutWithKey:@\"m\" modifiers:0 action:^{\n        [self showExplorerIfNeeded];\n        [self.explorerViewController toggleMoveTool];\n    } description:@\"Toggle move tool\"];\n    \n    [self registerSimulatorShortcutWithKey:@\"n\" modifiers:0 action:^{\n        [self toggleTopViewControllerOfClass:[FLEXNetworkHistoryTableViewController class]];\n    } description:@\"Toggle network history view\"];\n    \n    [self registerSimulatorShortcutWithKey:UIKeyInputDownArrow modifiers:0 action:^{\n        if ([self isHidden]) {\n            [self tryScrollDown];\n        } else {\n            [self.explorerViewController handleDownArrowKeyPressed];\n        }\n    } description:@\"Cycle view selection\\n\\t\\tMove view down\\n\\t\\tScroll down\"];\n    \n    [self registerSimulatorShortcutWithKey:UIKeyInputUpArrow modifiers:0 action:^{\n        if ([self isHidden]) {\n            [self tryScrollUp];\n        } else {\n            [self.explorerViewController handleUpArrowKeyPressed];\n        }\n    } description:@\"Cycle view selection\\n\\t\\tMove view up\\n\\t\\tScroll up\"];\n    \n    [self registerSimulatorShortcutWithKey:UIKeyInputRightArrow modifiers:0 action:^{\n        if (![self isHidden]) {\n            [self.explorerViewController handleRightArrowKeyPressed];\n        }\n    } description:@\"Move selected view right\"];\n    \n    [self registerSimulatorShortcutWithKey:UIKeyInputLeftArrow modifiers:0 action:^{\n        if ([self isHidden]) {\n            [self tryGoBack];\n        } else {\n            [self.explorerViewController handleLeftArrowKeyPressed];\n        }\n    } description:@\"Move selected view left\"];\n    \n    [self registerSimulatorShortcutWithKey:@\"?\" modifiers:0 action:^{\n        [self toggleTopViewControllerOfClass:[FLEXKeyboardHelpViewController class]];\n    } description:@\"Toggle (this) help menu\"];\n    \n    [self registerSimulatorShortcutWithKey:UIKeyInputEscape modifiers:0 action:^{\n        [[[self topViewController] presentingViewController] dismissViewControllerAnimated:YES completion:nil];\n    } description:@\"End editing text\\n\\t\\tDismiss top view controller\"];\n    \n    [self registerSimulatorShortcutWithKey:@\"o\" modifiers:UIKeyModifierCommand|UIKeyModifierShift action:^{\n        [self toggleTopViewControllerOfClass:[FLEXFileBrowserTableViewController class]];\n    } description:@\"Toggle file browser menu\"];\n}\n\n+ (void)load\n{\n    dispatch_async(dispatch_get_main_queue(), ^{\n        [[[self class] sharedManager] registerDefaultSimulatorShortcuts];\n    });\n}\n\n#pragma mark - Extensions\n\n- (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock\n{\n    NSParameterAssert(entryName);\n    NSParameterAssert(objectFutureBlock);\n    NSAssert([NSThread isMainThread], @\"This method must be called from the main thread.\");\n\n    entryName = entryName.copy;\n    FLEXGlobalsTableViewControllerEntry *entry = [FLEXGlobalsTableViewControllerEntry entryWithNameFuture:^NSString *{\n        return entryName;\n    } viewControllerFuture:^UIViewController *{\n        return [FLEXObjectExplorerFactory explorerViewControllerForObject:objectFutureBlock()];\n    }];\n\n    [self.userGlobalEntries addObject:entry];\n}\n\n- (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock\n{\n    NSParameterAssert(entryName);\n    NSParameterAssert(viewControllerFutureBlock);\n    NSAssert([NSThread isMainThread], @\"This method must be called from the main thread.\");\n\n    entryName = entryName.copy;\n    FLEXGlobalsTableViewControllerEntry *entry = [FLEXGlobalsTableViewControllerEntry entryWithNameFuture:^NSString *{\n        return entryName;\n    } viewControllerFuture:^UIViewController *{\n        UIViewController *viewController = viewControllerFutureBlock();\n        NSCAssert(viewController, @\"'%@' entry returned nil viewController. viewControllerFutureBlock should never return nil.\", entryName);\n        return viewController;\n    }];\n\n    [self.userGlobalEntries addObject:entry];\n}\n\n- (void)tryScrollDown\n{\n    UIScrollView *firstScrollView = [self firstScrollView];\n    CGPoint contentOffset = [firstScrollView contentOffset];\n    CGFloat distance = floor(firstScrollView.frame.size.height / 2.0);\n    CGFloat maxContentOffsetY = firstScrollView.contentSize.height + firstScrollView.contentInset.bottom - firstScrollView.frame.size.height;\n    distance = MIN(maxContentOffsetY - firstScrollView.contentOffset.y, distance);\n    contentOffset.y += distance;\n    [firstScrollView setContentOffset:contentOffset animated:YES];\n}\n\n- (void)tryScrollUp\n{\n    UIScrollView *firstScrollView = [self firstScrollView];\n    CGPoint contentOffset = [firstScrollView contentOffset];\n    CGFloat distance = floor(firstScrollView.frame.size.height / 2.0);\n    CGFloat minContentOffsetY = -firstScrollView.contentInset.top;\n    distance = MIN(firstScrollView.contentOffset.y - minContentOffsetY, distance);\n    contentOffset.y -= distance;\n    [firstScrollView setContentOffset:contentOffset animated:YES];\n}\n\n- (UIScrollView *)firstScrollView\n{\n    NSMutableArray<UIView *> *views = [[[[UIApplication sharedApplication] keyWindow] subviews] mutableCopy];\n    UIScrollView *scrollView = nil;\n    while ([views count] > 0) {\n        UIView *view = [views firstObject];\n        [views removeObjectAtIndex:0];\n        if ([view isKindOfClass:[UIScrollView class]]) {\n            scrollView = (UIScrollView *)view;\n            break;\n        } else {\n            [views addObjectsFromArray:[view subviews]];\n        }\n    }\n    return scrollView;\n}\n\n- (void)tryGoBack\n{\n    UINavigationController *navigationController = nil;\n    UIViewController *topViewController = [self topViewController];\n    if ([topViewController isKindOfClass:[UINavigationController class]]) {\n        navigationController = (UINavigationController *)topViewController;\n    } else {\n        navigationController = topViewController.navigationController;\n    }\n    [navigationController popViewControllerAnimated:YES];\n}\n\n- (UIViewController *)topViewController\n{\n    UIViewController *topViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];\n    while ([topViewController presentedViewController]) {\n        topViewController = [topViewController presentedViewController];\n    }\n    return topViewController;\n}\n\n- (void)toggleTopViewControllerOfClass:(Class)class\n{\n    UIViewController *topViewController = [self topViewController];\n    if ([topViewController isKindOfClass:[UINavigationController class]] && [[[(UINavigationController *)topViewController viewControllers] firstObject] isKindOfClass:[class class]]) {\n        [[topViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil];\n    } else {\n        id viewController = [[class alloc] init];\n        UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];\n        [topViewController presentViewController:navigationController animated:YES completion:nil];\n    }\n}\n\n- (void)showExplorerIfNeeded\n{\n    if ([self isHidden]) {\n        [self showExplorer];\n    }\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkCurlLogger.h",
    "content": "//\n// FLEXCurlLogger.h\n//\n//\n// Created by Ji Pei on 07/27/16\n//\n\n#import <Foundation/Foundation.h>\n\n@interface FLEXNetworkCurlLogger : NSObject\n\n/**\n * Generates a cURL command equivalent to the given request.\n *\n * @param request The request to be translated\n */\n+ (NSString *)curlCommandString:(NSURLRequest *)request;\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkCurlLogger.m",
    "content": "//\n// FLEXCurlLogger.m\n//\n//\n// Created by Ji Pei on 07/27/16\n//\n\n#import \"FLEXNetworkCurlLogger.h\"\n\n@implementation FLEXNetworkCurlLogger\n\n+ (NSString *)curlCommandString:(NSURLRequest *)request {\n    __block NSMutableString *curlCommandString = [NSMutableString stringWithFormat:@\"curl -v -X %@ \", request.HTTPMethod];\n\n    [curlCommandString appendFormat:@\"\\'%@\\' \", request.URL.absoluteString];\n\n    [request.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *val, BOOL *stop) {\n        [curlCommandString appendFormat:@\"-H \\'%@: %@\\' \", key, val];\n    }];\n\n    NSArray<NSHTTPCookie *> *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:request.URL];\n    if (cookies) {\n        [curlCommandString appendFormat:@\"-H \\'Cookie:\"];\n        for (NSHTTPCookie *cookie in cookies) {\n            [curlCommandString appendFormat:@\" %@=%@;\", cookie.name, cookie.value];\n        }\n        [curlCommandString appendFormat:@\"\\' \"];\n    }\n\n    if (request.HTTPBody) {\n        if ([request.allHTTPHeaderFields[@\"Content-Length\"] intValue] < 1024) {\n            [curlCommandString appendFormat:@\"-d \\'%@\\'\",\n             [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]];\n        } else {\n            [curlCommandString appendFormat:@\"[TOO MUCH DATA TO INCLUDE]\"];\n        }\n    }\n\n    return curlCommandString;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkHistoryTableViewController.h",
    "content": "//\n//  FLEXNetworkHistoryTableViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2/8/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXNetworkHistoryTableViewController : UITableViewController\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkHistoryTableViewController.m",
    "content": "//\n//  FLEXNetworkHistoryTableViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2/8/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import \"FLEXNetworkHistoryTableViewController.h\"\n#import \"FLEXNetworkTransaction.h\"\n#import \"FLEXNetworkTransactionTableViewCell.h\"\n#import \"FLEXNetworkRecorder.h\"\n#import \"FLEXNetworkTransactionDetailTableViewController.h\"\n#import \"FLEXNetworkObserver.h\"\n#import \"FLEXNetworkSettingsTableViewController.h\"\n\n@interface FLEXNetworkHistoryTableViewController () <UISearchResultsUpdating, UISearchControllerDelegate>\n\n/// Backing model\n@property (nonatomic, copy) NSArray<FLEXNetworkTransaction *> *networkTransactions;\n@property (nonatomic, assign) long long bytesReceived;\n@property (nonatomic, copy) NSArray<FLEXNetworkTransaction *> *filteredNetworkTransactions;\n@property (nonatomic, assign) long long filteredBytesReceived;\n\n@property (nonatomic, assign) BOOL rowInsertInProgress;\n@property (nonatomic, assign) BOOL isPresentingSearch;\n\n@property (nonatomic, strong) UISearchController *searchController;\n\n@end\n\n@implementation FLEXNetworkHistoryTableViewController\n\n- (instancetype)initWithStyle:(UITableViewStyle)style\n{\n    self = [super initWithStyle:style];\n    if (self) {\n        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNewTransactionRecordedNotification:) name:kFLEXNetworkRecorderNewTransactionNotification object:nil];\n        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTransactionUpdatedNotification:) name:kFLEXNetworkRecorderTransactionUpdatedNotification object:nil];\n        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTransactionsClearedNotification:) name:kFLEXNetworkRecorderTransactionsClearedNotification object:nil];\n        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNetworkObserverEnabledStateChangedNotification:) name:kFLEXNetworkObserverEnabledStateChangedNotification object:nil];\n        self.title = @\"📡  Network\";\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@\"Settings\" style:UIBarButtonItemStylePlain target:self action:@selector(settingsButtonTapped:)];\n\n        // Needed to avoid search bar showing over detail pages pushed on the nav stack\n        // see http://asciiwwdc.com/2014/sessions/228\n        self.definesPresentationContext = YES;\n    }\n    return self;\n}\n\n- (void)dealloc\n{\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n\n    [self.tableView registerClass:[FLEXNetworkTransactionTableViewCell class] forCellReuseIdentifier:kFLEXNetworkTransactionCellIdentifier];\n    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    self.tableView.rowHeight = [FLEXNetworkTransactionTableViewCell preferredCellHeight];\n\n    self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];\n    self.searchController.delegate = self;\n    self.searchController.searchResultsUpdater = self;\n    self.searchController.dimsBackgroundDuringPresentation = NO;\n    self.tableView.tableHeaderView = self.searchController.searchBar;\n\n    [self updateTransactions];\n}\n\n- (void)settingsButtonTapped:(id)sender\n{\n    FLEXNetworkSettingsTableViewController *settingsViewController = [[FLEXNetworkSettingsTableViewController alloc] init];\n    settingsViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(settingsViewControllerDoneTapped:)];\n    settingsViewController.title = @\"Network Debugging Settings\";\n    UINavigationController *wrapperNavigationController = [[UINavigationController alloc] initWithRootViewController:settingsViewController];\n    [self presentViewController:wrapperNavigationController animated:YES completion:nil];\n}\n\n- (void)settingsViewControllerDoneTapped:(id)sender\n{\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n- (void)updateTransactions\n{\n    self.networkTransactions = [[FLEXNetworkRecorder defaultRecorder] networkTransactions];\n}\n\n- (void)setNetworkTransactions:(NSArray<FLEXNetworkTransaction *> *)networkTransactions\n{\n    if (![_networkTransactions isEqual:networkTransactions]) {\n        _networkTransactions = networkTransactions;\n        [self updateBytesReceived];\n        [self updateFilteredBytesReceived];\n    }\n}\n\n- (void)updateBytesReceived\n{\n    long long bytesReceived = 0;\n    for (FLEXNetworkTransaction *transaction in self.networkTransactions) {\n        bytesReceived += transaction.receivedDataLength;\n    }\n    self.bytesReceived = bytesReceived;\n    [self updateFirstSectionHeader];\n}\n\n- (void)setFilteredNetworkTransactions:(NSArray<FLEXNetworkTransaction *> *)filteredNetworkTransactions\n{\n    if (![_filteredNetworkTransactions isEqual:filteredNetworkTransactions]) {\n        _filteredNetworkTransactions = filteredNetworkTransactions;\n        [self updateFilteredBytesReceived];\n    }\n}\n\n- (void)updateFilteredBytesReceived\n{\n    long long filteredBytesReceived = 0;\n    for (FLEXNetworkTransaction *transaction in self.filteredNetworkTransactions) {\n        filteredBytesReceived += transaction.receivedDataLength;\n    }\n    self.filteredBytesReceived = filteredBytesReceived;\n    [self updateFirstSectionHeader];\n}\n\n- (void)updateFirstSectionHeader\n{\n    UIView *view = [self.tableView headerViewForSection:0];\n    if ([view isKindOfClass:[UITableViewHeaderFooterView class]]) {\n        UITableViewHeaderFooterView *headerView = (UITableViewHeaderFooterView *)view;\n        headerView.textLabel.text = [self headerText];\n        [headerView setNeedsLayout];\n    }\n}\n\n- (NSString *)headerText\n{\n    NSString *headerText = nil;\n    if ([FLEXNetworkObserver isEnabled]) {\n        long long bytesReceived = 0;\n        NSInteger totalRequests = 0;\n        if (self.searchController.isActive) {\n            bytesReceived = self.filteredBytesReceived;\n            totalRequests = [self.filteredNetworkTransactions count];\n        } else {\n            bytesReceived = self.bytesReceived;\n            totalRequests = [self.networkTransactions count];\n        }\n        NSString *byteCountText = [NSByteCountFormatter stringFromByteCount:bytesReceived countStyle:NSByteCountFormatterCountStyleBinary];\n        NSString *requestsText = totalRequests == 1 ? @\"Request\" : @\"Requests\";\n        headerText = [NSString stringWithFormat:@\"%ld %@ (%@ received)\", (long)totalRequests, requestsText, byteCountText];\n    } else {\n        headerText = @\"⚠️  Debugging Disabled (Enable in Settings)\";\n    }\n    return headerText;\n}\n\n#pragma mark - Notification Handlers\n\n- (void)handleNewTransactionRecordedNotification:(NSNotification *)notification\n{\n    [self tryUpdateTransactions];\n}\n\n- (void)tryUpdateTransactions\n{\n    // Let the previous row insert animation finish before starting a new one to avoid stomping.\n    // We'll try calling the method again when the insertion completes, and we properly no-op if there haven't been changes.\n    if (self.rowInsertInProgress) {\n        return;\n    }\n    \n    if (self.searchController.isActive) {\n        [self updateTransactions];\n        [self updateSearchResults];\n        return;\n    }\n\n    NSInteger existingRowCount = [self.networkTransactions count];\n    [self updateTransactions];\n    NSInteger newRowCount = [self.networkTransactions count];\n    NSInteger addedRowCount = newRowCount - existingRowCount;\n\n    if (addedRowCount != 0 && !self.isPresentingSearch) {\n        // Insert animation if we're at the top.\n        if (self.tableView.contentOffset.y <= 0.0 && addedRowCount > 0) {\n            [CATransaction begin];\n            \n            self.rowInsertInProgress = YES;\n            [CATransaction setCompletionBlock:^{\n                self.rowInsertInProgress = NO;\n                [self tryUpdateTransactions];\n            }];\n\n            NSMutableArray<NSIndexPath *> *indexPathsToReload = [NSMutableArray array];\n            for (NSInteger row = 0; row < addedRowCount; row++) {\n                [indexPathsToReload addObject:[NSIndexPath indexPathForRow:row inSection:0]];\n            }\n            [self.tableView insertRowsAtIndexPaths:indexPathsToReload withRowAnimation:UITableViewRowAnimationAutomatic];\n\n            [CATransaction commit];\n        } else {\n            // Maintain the user's position if they've scrolled down.\n            CGSize existingContentSize = self.tableView.contentSize;\n            [self.tableView reloadData];\n            CGFloat contentHeightChange = self.tableView.contentSize.height - existingContentSize.height;\n            self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, self.tableView.contentOffset.y + contentHeightChange);\n        }\n    }\n}\n\n- (void)handleTransactionUpdatedNotification:(NSNotification *)notification\n{\n    [self updateBytesReceived];\n    [self updateFilteredBytesReceived];\n\n    FLEXNetworkTransaction *transaction = notification.userInfo[kFLEXNetworkRecorderUserInfoTransactionKey];\n\n    // Update both the main table view and search table view if needed.\n    for (FLEXNetworkTransactionTableViewCell *cell in [self.tableView visibleCells]) {\n        if ([cell.transaction isEqual:transaction]) {\n            // Using -[UITableView reloadRowsAtIndexPaths:withRowAnimation:] is overkill here and kicks off a lot of\n            // work that can make the table view somewhat unresponseive when lots of updates are streaming in.\n            // We just need to tell the cell that it needs to re-layout.\n            [cell setNeedsLayout];\n            break;\n        }\n    }\n    [self updateFirstSectionHeader];\n}\n\n- (void)handleTransactionsClearedNotification:(NSNotification *)notification\n{\n    [self updateTransactions];\n    [self.tableView reloadData];\n}\n\n- (void)handleNetworkObserverEnabledStateChangedNotification:(NSNotification *)notification\n{\n    // Update the header, which displays a warning when network debugging is disabled\n    [self updateFirstSectionHeader];\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return self.searchController.isActive ? [self.filteredNetworkTransactions count] : [self.networkTransactions count];\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section\n{\n    return [self headerText];\n}\n\n- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section\n{\n    if ([view isKindOfClass:[UITableViewHeaderFooterView class]]) {\n        UITableViewHeaderFooterView *headerView = (UITableViewHeaderFooterView *)view;\n        headerView.textLabel.font = [UIFont fontWithName:@\"HelveticaNeue-Medium\" size:14.0];\n        headerView.textLabel.textColor = [UIColor whiteColor];\n        headerView.contentView.backgroundColor = [UIColor colorWithWhite:0.5 alpha:1.0];\n    }\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXNetworkTransactionTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kFLEXNetworkTransactionCellIdentifier forIndexPath:indexPath];\n    cell.transaction = [self transactionAtIndexPath:indexPath inTableView:tableView];\n\n    // Since we insert from the top, assign background colors bottom up to keep them consistent for each transaction.\n    NSInteger totalRows = [tableView numberOfRowsInSection:indexPath.section];\n    if ((totalRows - indexPath.row) % 2 == 0) {\n        cell.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];\n    } else {\n        cell.backgroundColor = [UIColor whiteColor];\n    }\n\n    return cell;\n}\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXNetworkTransactionDetailTableViewController *detailViewController = [[FLEXNetworkTransactionDetailTableViewController alloc] init];\n    detailViewController.transaction = [self transactionAtIndexPath:indexPath inTableView:tableView];\n    [self.navigationController pushViewController:detailViewController animated:YES];\n}\n\n#pragma mark - Menu Actions\n\n- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    return YES;\n}\n\n- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender\n{\n    return action == @selector(copy:);\n}\n\n- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender\n{\n    if (action == @selector(copy:)) {\n        FLEXNetworkTransaction *transaction = [self transactionAtIndexPath:indexPath inTableView:tableView];\n        NSString *requestURLString = transaction.request.URL.absoluteString ?: @\"\";\n        [[UIPasteboard generalPasteboard] setString:requestURLString];\n    }\n}\n\n- (FLEXNetworkTransaction *)transactionAtIndexPath:(NSIndexPath *)indexPath inTableView:(UITableView *)tableView\n{\n    return self.searchController.isActive ? self.filteredNetworkTransactions[indexPath.row] : self.networkTransactions[indexPath.row];\n}\n\n#pragma mark - UISearchResultsUpdating\n\n- (void)updateSearchResultsForSearchController:(UISearchController *)searchController\n{\n    [self updateSearchResults];\n}\n\n- (void)updateSearchResults\n{\n    NSString *searchString = self.searchController.searchBar.text;\n    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n        NSArray<FLEXNetworkTransaction *> *filteredNetworkTransactions = [self.networkTransactions filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(FLEXNetworkTransaction *transaction, NSDictionary<NSString *, id> *bindings) {\n            return [[transaction.request.URL absoluteString] rangeOfString:searchString options:NSCaseInsensitiveSearch].length > 0;\n        }]];\n        dispatch_async(dispatch_get_main_queue(), ^{\n            if ([self.searchController.searchBar.text isEqual:searchString]) {\n                self.filteredNetworkTransactions = filteredNetworkTransactions;\n                [self.tableView reloadData];\n            }\n        });\n    });\n}\n\n#pragma mark - UISearchControllerDelegate\n\n- (void)willPresentSearchController:(UISearchController *)searchController\n{\n    self.isPresentingSearch = YES;\n}\n\n- (void)didPresentSearchController:(UISearchController *)searchController\n{\n    self.isPresentingSearch = NO;\n}\n\n- (void)willDismissSearchController:(UISearchController *)searchController\n{\n    [self.tableView reloadData];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkRecorder.h",
    "content": "//\n//  FLEXNetworkRecorder.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2/4/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n// Notifications posted when the record is updated\nextern NSString *const kFLEXNetworkRecorderNewTransactionNotification;\nextern NSString *const kFLEXNetworkRecorderTransactionUpdatedNotification;\nextern NSString *const kFLEXNetworkRecorderUserInfoTransactionKey;\nextern NSString *const kFLEXNetworkRecorderTransactionsClearedNotification;\n\n@class FLEXNetworkTransaction;\n\n@interface FLEXNetworkRecorder : NSObject\n\n/// In general, it only makes sense to have one recorder for the entire application.\n+ (instancetype)defaultRecorder;\n\n/// Defaults to 25 MB if never set. Values set here are presisted across launches of the app.\n@property (nonatomic, assign) NSUInteger responseCacheByteLimit;\n\n/// If NO, the recorder not cache will not cache response for content types with an \"image\", \"video\", or \"audio\" prefix.\n@property (nonatomic, assign) BOOL shouldCacheMediaResponses;\n\n@property (nonatomic, copy) NSArray<NSString *> *hostBlacklist;\n\n\n// Accessing recorded network activity\n\n/// Array of FLEXNetworkTransaction objects ordered by start time with the newest first.\n- (NSArray<FLEXNetworkTransaction *> *)networkTransactions;\n\n/// The full response data IFF it hasn't been purged due to memory pressure.\n- (NSData *)cachedResponseBodyForTransaction:(FLEXNetworkTransaction *)transaction;\n\n/// Dumps all network transactions and cached response bodies.\n- (void)clearRecordedActivity;\n\n\n// Recording network activity\n\n/// Call when app is about to send HTTP request.\n- (void)recordRequestWillBeSentWithRequestID:(NSString *)requestID request:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse;\n\n/// Call when HTTP response is available.\n- (void)recordResponseReceivedWithRequestID:(NSString *)requestID response:(NSURLResponse *)response;\n\n/// Call when data chunk is received over the network.\n- (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength;\n\n/// Call when HTTP request has finished loading.\n- (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(NSData *)responseBody;\n\n/// Call when HTTP request has failed to load.\n- (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error;\n\n/// Call to set the request mechanism anytime after recordRequestWillBeSent... has been called.\n/// This string can be set to anything useful about the API used to make the request.\n- (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID;\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkRecorder.m",
    "content": "//\n//  FLEXNetworkRecorder.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2/4/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import \"FLEXNetworkRecorder.h\"\n#import \"FLEXNetworkCurlLogger.h\"\n#import \"FLEXNetworkTransaction.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXResources.h\"\n\nNSString *const kFLEXNetworkRecorderNewTransactionNotification = @\"kFLEXNetworkRecorderNewTransactionNotification\";\nNSString *const kFLEXNetworkRecorderTransactionUpdatedNotification = @\"kFLEXNetworkRecorderTransactionUpdatedNotification\";\nNSString *const kFLEXNetworkRecorderUserInfoTransactionKey = @\"transaction\";\nNSString *const kFLEXNetworkRecorderTransactionsClearedNotification = @\"kFLEXNetworkRecorderTransactionsClearedNotification\";\n\nNSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @\"com.flex.responseCacheLimit\";\n\n@interface FLEXNetworkRecorder ()\n\n@property (nonatomic, strong) NSCache *responseCache;\n@property (nonatomic, strong) NSMutableArray<FLEXNetworkTransaction *> *orderedTransactions;\n@property (nonatomic, strong) NSMutableDictionary<NSString *, FLEXNetworkTransaction *> *networkTransactionsForRequestIdentifiers;\n@property (nonatomic, strong) dispatch_queue_t queue;\n\n@end\n\n@implementation FLEXNetworkRecorder\n\n- (instancetype)init\n{\n    self = [super init];\n    if (self) {\n        self.responseCache = [[NSCache alloc] init];\n        NSUInteger responseCacheLimit = [[[NSUserDefaults standardUserDefaults] objectForKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey] unsignedIntegerValue];\n        if (responseCacheLimit) {\n            [self.responseCache setTotalCostLimit:responseCacheLimit];\n        } else {\n            // Default to 25 MB max. The cache will purge earlier if there is memory pressure.\n            [self.responseCache setTotalCostLimit:25 * 1024 * 1024];\n        }\n        self.orderedTransactions = [NSMutableArray array];\n        self.networkTransactionsForRequestIdentifiers = [NSMutableDictionary dictionary];\n\n        // Serial queue used because we use mutable objects that are not thread safe\n        self.queue = dispatch_queue_create(\"com.flex.FLEXNetworkRecorder\", DISPATCH_QUEUE_SERIAL);\n    }\n    return self;\n}\n\n+ (instancetype)defaultRecorder\n{\n    static FLEXNetworkRecorder *defaultRecorder = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        defaultRecorder = [[[self class] alloc] init];\n    });\n    return defaultRecorder;\n}\n\n#pragma mark - Public Data Access\n\n- (NSUInteger)responseCacheByteLimit\n{\n    return [self.responseCache totalCostLimit];\n}\n\n- (void)setResponseCacheByteLimit:(NSUInteger)responseCacheByteLimit\n{\n    [self.responseCache setTotalCostLimit:responseCacheByteLimit];\n    [[NSUserDefaults standardUserDefaults] setObject:@(responseCacheByteLimit) forKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey];\n}\n\n- (NSArray<FLEXNetworkTransaction *> *)networkTransactions\n{\n    __block NSArray<FLEXNetworkTransaction *> *transactions = nil;\n    dispatch_sync(self.queue, ^{\n        transactions = [self.orderedTransactions copy];\n    });\n    return transactions;\n}\n\n- (NSData *)cachedResponseBodyForTransaction:(FLEXNetworkTransaction *)transaction\n{\n    return [self.responseCache objectForKey:transaction.requestID];\n}\n\n- (void)clearRecordedActivity\n{\n    dispatch_async(self.queue, ^{\n        [self.responseCache removeAllObjects];\n        [self.orderedTransactions removeAllObjects];\n        [self.networkTransactionsForRequestIdentifiers removeAllObjects];\n        dispatch_async(dispatch_get_main_queue(), ^{\n            [[NSNotificationCenter defaultCenter] postNotificationName:kFLEXNetworkRecorderTransactionsClearedNotification object:self];\n        });\n    });\n}\n\n#pragma mark - Network Events\n\n- (void)recordRequestWillBeSentWithRequestID:(NSString *)requestID request:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse\n{\n    for (NSString *host in self.hostBlacklist) {\n        if ([request.URL.host hasSuffix:host]) {\n            return;\n        }\n    }\n    \n    NSDate *startDate = [NSDate date];\n\n    if (redirectResponse) {\n        [self recordResponseReceivedWithRequestID:requestID response:redirectResponse];\n        [self recordLoadingFinishedWithRequestID:requestID responseBody:nil];\n    }\n\n    dispatch_async(self.queue, ^{\n        FLEXNetworkTransaction *transaction = [[FLEXNetworkTransaction alloc] init];\n        transaction.requestID = requestID;\n        transaction.request = request;\n        transaction.startTime = startDate;\n\n        [self.orderedTransactions insertObject:transaction atIndex:0];\n        [self.networkTransactionsForRequestIdentifiers setObject:transaction forKey:requestID];\n        transaction.transactionState = FLEXNetworkTransactionStateAwaitingResponse;\n\n        [self postNewTransactionNotificationWithTransaction:transaction];\n    });\n}\n\n- (void)recordResponseReceivedWithRequestID:(NSString *)requestID response:(NSURLResponse *)response\n{\n    NSDate *responseDate = [NSDate date];\n\n    dispatch_async(self.queue, ^{\n        FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];\n        if (!transaction) {\n            return;\n        }\n        transaction.response = response;\n        transaction.transactionState = FLEXNetworkTransactionStateReceivingData;\n        transaction.latency = -[transaction.startTime timeIntervalSinceDate:responseDate];\n\n        [self postUpdateNotificationForTransaction:transaction];\n    });\n}\n\n- (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength\n{\n    dispatch_async(self.queue, ^{\n        FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];\n        if (!transaction) {\n            return;\n        }\n        transaction.receivedDataLength += dataLength;\n\n        [self postUpdateNotificationForTransaction:transaction];\n    });\n}\n\n- (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(NSData *)responseBody\n{\n    NSDate *finishedDate = [NSDate date];\n\n    dispatch_async(self.queue, ^{\n        FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];\n        if (!transaction) {\n            return;\n        }\n        transaction.transactionState = FLEXNetworkTransactionStateFinished;\n        transaction.duration = -[transaction.startTime timeIntervalSinceDate:finishedDate];\n\n        BOOL shouldCache = [responseBody length] > 0;\n        if (!self.shouldCacheMediaResponses) {\n            NSArray<NSString *> *ignoredMIMETypePrefixes = @[ @\"audio\", @\"image\", @\"video\" ];\n            for (NSString *ignoredPrefix in ignoredMIMETypePrefixes) {\n                shouldCache = shouldCache && ![transaction.response.MIMEType hasPrefix:ignoredPrefix];\n            }\n        }\n        \n        if (shouldCache) {\n            [self.responseCache setObject:responseBody forKey:requestID cost:[responseBody length]];\n        }\n\n        NSString *mimeType = transaction.response.MIMEType;\n        if ([mimeType hasPrefix:@\"image/\"] && [responseBody length] > 0) {\n            // Thumbnail image previews on a separate background queue\n            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n                NSInteger maxPixelDimension = [[UIScreen mainScreen] scale] * 32.0;\n                transaction.responseThumbnail = [FLEXUtility thumbnailedImageWithMaxPixelDimension:maxPixelDimension fromImageData:responseBody];\n                [self postUpdateNotificationForTransaction:transaction];\n            });\n        } else if ([mimeType isEqual:@\"application/json\"]) {\n            transaction.responseThumbnail = [FLEXResources jsonIcon];\n        } else if ([mimeType isEqual:@\"text/plain\"]){\n            transaction.responseThumbnail = [FLEXResources textPlainIcon];\n        } else if ([mimeType isEqual:@\"text/html\"]) {\n            transaction.responseThumbnail = [FLEXResources htmlIcon];\n        } else if ([mimeType isEqual:@\"application/x-plist\"]) {\n            transaction.responseThumbnail = [FLEXResources plistIcon];\n        } else if ([mimeType isEqual:@\"application/octet-stream\"] || [mimeType isEqual:@\"application/binary\"]) {\n            transaction.responseThumbnail = [FLEXResources binaryIcon];\n        } else if ([mimeType rangeOfString:@\"javascript\"].length > 0) {\n            transaction.responseThumbnail = [FLEXResources jsIcon];\n        } else if ([mimeType rangeOfString:@\"xml\"].length > 0) {\n            transaction.responseThumbnail = [FLEXResources xmlIcon];\n        } else if ([mimeType hasPrefix:@\"audio\"]) {\n            transaction.responseThumbnail = [FLEXResources audioIcon];\n        } else if ([mimeType hasPrefix:@\"video\"]) {\n            transaction.responseThumbnail = [FLEXResources videoIcon];\n        } else if ([mimeType hasPrefix:@\"text\"]) {\n            transaction.responseThumbnail = [FLEXResources textIcon];\n        }\n        \n        [self postUpdateNotificationForTransaction:transaction];\n    });\n}\n\n- (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error\n{\n    dispatch_async(self.queue, ^{\n        FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];\n        if (!transaction) {\n            return;\n        }\n        transaction.transactionState = FLEXNetworkTransactionStateFailed;\n        transaction.duration = -[transaction.startTime timeIntervalSinceNow];\n        transaction.error = error;\n\n        [self postUpdateNotificationForTransaction:transaction];\n    });\n}\n\n- (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID\n{\n    dispatch_async(self.queue, ^{\n        FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];\n        if (!transaction) {\n            return;\n        }\n        transaction.requestMechanism = mechanism;\n\n        [self postUpdateNotificationForTransaction:transaction];\n    });\n}\n\n#pragma mark Notification Posting\n\n- (void)postNewTransactionNotificationWithTransaction:(FLEXNetworkTransaction *)transaction\n{\n    dispatch_async(dispatch_get_main_queue(), ^{\n        NSDictionary<NSString *, id> *userInfo = @{ kFLEXNetworkRecorderUserInfoTransactionKey : transaction };\n        [[NSNotificationCenter defaultCenter] postNotificationName:kFLEXNetworkRecorderNewTransactionNotification object:self userInfo:userInfo];\n    });\n}\n\n- (void)postUpdateNotificationForTransaction:(FLEXNetworkTransaction *)transaction\n{\n    dispatch_async(dispatch_get_main_queue(), ^{\n        NSDictionary<NSString *, id> *userInfo = @{ kFLEXNetworkRecorderUserInfoTransactionKey : transaction };\n        [[NSNotificationCenter defaultCenter] postNotificationName:kFLEXNetworkRecorderTransactionUpdatedNotification object:self userInfo:userInfo];\n    });\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkSettingsTableViewController.h",
    "content": "//\n//  FLEXNetworkSettingsTableViewController.h\n//  FLEXInjected\n//\n//  Created by Ryan Olson on 2/20/15.\n//\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXNetworkSettingsTableViewController : UITableViewController\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkSettingsTableViewController.m",
    "content": "//\n//  FLEXNetworkSettingsTableViewController.m\n//  FLEXInjected\n//\n//  Created by Ryan Olson on 2/20/15.\n//\n//\n\n#import \"FLEXNetworkSettingsTableViewController.h\"\n#import \"FLEXNetworkObserver.h\"\n#import \"FLEXNetworkRecorder.h\"\n#import \"FLEXUtility.h\"\n\n@interface FLEXNetworkSettingsTableViewController () <UIActionSheetDelegate>\n\n@property (nonatomic, copy) NSArray<UITableViewCell *> *cells;\n\n@property (nonatomic, strong) UITableViewCell *cacheLimitCell;\n\n@end\n\n@implementation FLEXNetworkSettingsTableViewController\n\n- (instancetype)initWithStyle:(UITableViewStyle)style\n{\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n\n    }\n    return self;\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n\n    NSMutableArray<UITableViewCell *> *mutableCells = [NSMutableArray array];\n\n    UITableViewCell *networkDebuggingCell = [self switchCellWithTitle:@\"Network Debugging\" toggleAction:@selector(networkDebuggingToggled:) isOn:[FLEXNetworkObserver isEnabled]];\n    [mutableCells addObject:networkDebuggingCell];\n\n    UITableViewCell *cacheMediaResponsesCell = [self switchCellWithTitle:@\"Cache Media Responses\" toggleAction:@selector(cacheMediaResponsesToggled:) isOn:NO];\n    [mutableCells addObject:cacheMediaResponsesCell];\n\n    NSUInteger currentCacheLimit = [[FLEXNetworkRecorder defaultRecorder] responseCacheByteLimit];\n    const NSUInteger fiftyMega = 50 * 1024 * 1024;\n    NSString *cacheLimitTitle = [self titleForCacheLimitCellWithValue:currentCacheLimit];\n    self.cacheLimitCell = [self sliderCellWithTitle:cacheLimitTitle changedAction:@selector(cacheLimitAdjusted:) minimum:0.0 maximum:fiftyMega initialValue:currentCacheLimit];\n    [mutableCells addObject:self.cacheLimitCell];\n\n    UITableViewCell *clearRecordedRequestsCell = [self buttonCellWithTitle:@\"❌  Clear Recorded Requests\" touchUpAction:@selector(clearRequestsTapped:) isDestructive:YES];\n    [mutableCells addObject:clearRecordedRequestsCell];\n\n    self.cells = mutableCells;\n}\n\n#pragma mark - Settings Actions\n\n- (void)networkDebuggingToggled:(UISwitch *)sender\n{\n    [FLEXNetworkObserver setEnabled:sender.isOn];\n}\n\n- (void)cacheMediaResponsesToggled:(UISwitch *)sender\n{\n    [[FLEXNetworkRecorder defaultRecorder] setShouldCacheMediaResponses:sender.isOn];\n}\n\n- (void)cacheLimitAdjusted:(UISlider *)sender\n{\n    [[FLEXNetworkRecorder defaultRecorder] setResponseCacheByteLimit:sender.value];\n    self.cacheLimitCell.textLabel.text = [self titleForCacheLimitCellWithValue:sender.value];\n}\n\n- (void)clearRequestsTapped:(UIButton *)sender\n{\n    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@\"Cancel\" destructiveButtonTitle:@\"Clear Recorded Requests\" otherButtonTitles:nil];\n    [actionSheet showInView:self.view];\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return [self.cells count];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath \n{\n    return self.cells[indexPath.row];\n}\n\n#pragma mark - UIActionSheetDelegate\n\n- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex\n{\n    if (buttonIndex != actionSheet.cancelButtonIndex) {\n        [[FLEXNetworkRecorder defaultRecorder] clearRecordedActivity];\n    }\n}\n\n#pragma mark - Helpers\n\n- (UITableViewCell *)switchCellWithTitle:(NSString *)title toggleAction:(SEL)toggleAction isOn:(BOOL)isOn\n{\n    UITableViewCell *cell = [[UITableViewCell alloc] init];\n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    cell.textLabel.text = title;\n    cell.textLabel.font = [[self class] cellTitleFont];\n\n    UISwitch *theSwitch = [[UISwitch alloc] init];\n    theSwitch.on = isOn;\n    [theSwitch addTarget:self action:toggleAction forControlEvents:UIControlEventValueChanged];\n\n    CGFloat switchOriginY = round((cell.contentView.frame.size.height - theSwitch.frame.size.height) / 2.0);\n    CGFloat switchOriginX = CGRectGetMaxX(cell.contentView.frame) - theSwitch.frame.size.width - self.tableView.separatorInset.left;\n    theSwitch.frame = CGRectMake(switchOriginX, switchOriginY, theSwitch.frame.size.width, theSwitch.frame.size.height);\n    theSwitch.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;\n    [cell.contentView addSubview:theSwitch];\n\n    return cell;\n}\n\n- (UITableViewCell *)buttonCellWithTitle:(NSString *)title touchUpAction:(SEL)action isDestructive:(BOOL)isDestructive\n{\n    UITableViewCell *buttonCell = [[UITableViewCell alloc] init];\n    buttonCell.selectionStyle = UITableViewCellSelectionStyleNone;\n\n    UIButton *actionButton = [UIButton buttonWithType:UIButtonTypeSystem];\n    [actionButton setTitle:title forState:UIControlStateNormal];\n    if (isDestructive) {\n        actionButton.tintColor = [UIColor redColor];\n    }\n    actionButton.titleLabel.font = [[self class] cellTitleFont];\n    [actionButton addTarget:self action:@selector(clearRequestsTapped:) forControlEvents:UIControlEventTouchUpInside];\n\n    [buttonCell.contentView addSubview:actionButton];\n    actionButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    actionButton.frame = buttonCell.contentView.frame;\n    actionButton.contentEdgeInsets = UIEdgeInsetsMake(0.0, self.tableView.separatorInset.left, 0.0, self.tableView.separatorInset.left);\n    actionButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;\n\n    return buttonCell;\n}\n\n- (NSString *)titleForCacheLimitCellWithValue:(long long)cacheLimit\n{\n    NSInteger limitInMB = round(cacheLimit / (1024 * 1024));\n    return [NSString stringWithFormat:@\"Cache Limit (%ld MB)\", (long)limitInMB];\n}\n\n- (UITableViewCell *)sliderCellWithTitle:(NSString *)title changedAction:(SEL)changedAction minimum:(CGFloat)minimum maximum:(CGFloat)maximum initialValue:(CGFloat)initialValue\n{\n    UITableViewCell *sliderCell = [[UITableViewCell alloc] init];\n    sliderCell.selectionStyle = UITableViewCellSelectionStyleNone;\n    sliderCell.textLabel.text = title;\n    sliderCell.textLabel.font = [[self class] cellTitleFont];\n\n    UISlider *slider = [[UISlider alloc] init];\n    slider.minimumValue = minimum;\n    slider.maximumValue = maximum;\n    slider.value = initialValue;\n    [slider addTarget:self action:changedAction forControlEvents:UIControlEventValueChanged];\n    [slider sizeToFit];\n\n    CGFloat sliderWidth = round(sliderCell.contentView.frame.size.width * 2.0 / 5.0);\n    CGFloat sliderOriginY = round((sliderCell.contentView.frame.size.height - slider.frame.size.height) / 2.0);\n    CGFloat sliderOriginX = CGRectGetMaxX(sliderCell.contentView.frame) - sliderWidth - self.tableView.separatorInset.left;\n    slider.frame = CGRectMake(sliderOriginX, sliderOriginY, sliderWidth, slider.frame.size.height);\n    slider.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;\n    [sliderCell.contentView addSubview:slider];\n\n    return sliderCell;\n}\n\n+ (UIFont *)cellTitleFont\n{\n    return [FLEXUtility defaultFontOfSize:14.0];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkTransaction.h",
    "content": "//\n//  FLEXNetworkTransaction.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2/8/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"UIKit/UIKit.h\"\n\ntypedef NS_ENUM(NSInteger, FLEXNetworkTransactionState) {\n    FLEXNetworkTransactionStateUnstarted,\n    FLEXNetworkTransactionStateAwaitingResponse,\n    FLEXNetworkTransactionStateReceivingData,\n    FLEXNetworkTransactionStateFinished,\n    FLEXNetworkTransactionStateFailed\n};\n\n@interface FLEXNetworkTransaction : NSObject\n\n@property (nonatomic, copy) NSString *requestID;\n\n@property (nonatomic, strong) NSURLRequest *request;\n@property (nonatomic, strong) NSURLResponse *response;\n@property (nonatomic, copy) NSString *requestMechanism;\n@property (nonatomic, assign) FLEXNetworkTransactionState transactionState;\n@property (nonatomic, strong) NSError *error;\n\n@property (nonatomic, strong) NSDate *startTime;\n@property (nonatomic, assign) NSTimeInterval latency;\n@property (nonatomic, assign) NSTimeInterval duration;\n\n@property (nonatomic, assign) int64_t receivedDataLength;\n\n/// Only applicable for image downloads. A small thumbnail to preview the full response.\n@property (nonatomic, strong) UIImage *responseThumbnail;\n\n/// Populated lazily. Handles both normal HTTPBody data and HTTPBodyStreams.\n@property (nonatomic, strong, readonly) NSData *cachedRequestBody;\n\n+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state;\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkTransaction.m",
    "content": "//\n//  FLEXNetworkTransaction.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2/8/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import \"FLEXNetworkTransaction.h\"\n\n@interface FLEXNetworkTransaction ()\n\n@property (nonatomic, strong, readwrite) NSData *cachedRequestBody;\n\n@end\n\n@implementation FLEXNetworkTransaction\n\n- (NSString *)description\n{\n    NSString *description = [super description];\n\n    description = [description stringByAppendingFormat:@\" id = %@;\", self.requestID];\n    description = [description stringByAppendingFormat:@\" url = %@;\", self.request.URL];\n    description = [description stringByAppendingFormat:@\" duration = %f;\", self.duration];\n    description = [description stringByAppendingFormat:@\" receivedDataLength = %lld\", self.receivedDataLength];\n\n    return description;\n}\n\n- (NSData *)cachedRequestBody {\n    if (!_cachedRequestBody) {\n        if (self.request.HTTPBody != nil) {\n            _cachedRequestBody = self.request.HTTPBody;\n        } else if ([self.request.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) {\n            NSInputStream *bodyStream = [self.request.HTTPBodyStream copy];\n            const NSUInteger bufferSize = 1024;\n            uint8_t buffer[bufferSize];\n            NSMutableData *data = [NSMutableData data];\n            [bodyStream open];\n            NSInteger readBytes = 0;\n            do {\n                readBytes = [bodyStream read:buffer maxLength:bufferSize];\n                [data appendBytes:buffer length:readBytes];\n            } while (readBytes > 0);\n            [bodyStream close];\n            _cachedRequestBody = data;\n        }\n    }\n    return _cachedRequestBody;\n}\n\n+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state\n{\n    NSString *readableString = nil;\n    switch (state) {\n        case FLEXNetworkTransactionStateUnstarted:\n            readableString = @\"Unstarted\";\n            break;\n\n        case FLEXNetworkTransactionStateAwaitingResponse:\n            readableString = @\"Awaiting Response\";\n            break;\n\n        case FLEXNetworkTransactionStateReceivingData:\n            readableString = @\"Receiving Data\";\n            break;\n\n        case FLEXNetworkTransactionStateFinished:\n            readableString = @\"Finished\";\n            break;\n\n        case FLEXNetworkTransactionStateFailed:\n            readableString = @\"Failed\";\n            break;\n    }\n    return readableString;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkTransactionDetailTableViewController.h",
    "content": "//\n//  FLEXNetworkTransactionDetailTableViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2/10/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@class FLEXNetworkTransaction;\n\n@interface FLEXNetworkTransactionDetailTableViewController : UITableViewController\n\n@property (nonatomic, strong) FLEXNetworkTransaction *transaction;\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkTransactionDetailTableViewController.m",
    "content": "//\n//  FLEXNetworkTransactionDetailTableViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2/10/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import \"FLEXNetworkTransactionDetailTableViewController.h\"\n#import \"FLEXNetworkCurlLogger.h\"\n#import \"FLEXNetworkRecorder.h\"\n#import \"FLEXNetworkTransaction.h\"\n#import \"FLEXWebViewController.h\"\n#import \"FLEXImagePreviewViewController.h\"\n#import \"FLEXMultilineTableViewCell.h\"\n#import \"FLEXUtility.h\"\n\ntypedef UIViewController *(^FLEXNetworkDetailRowSelectionFuture)(void);\n\n@interface FLEXNetworkDetailRow : NSObject\n\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *detailText;\n@property (nonatomic, copy) FLEXNetworkDetailRowSelectionFuture selectionFuture;\n\n@end\n\n@implementation FLEXNetworkDetailRow\n\n@end\n\n@interface FLEXNetworkDetailSection : NSObject\n\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSArray<FLEXNetworkDetailRow *> *rows;\n\n@end\n\n@implementation FLEXNetworkDetailSection\n\n@end\n\n@interface FLEXNetworkTransactionDetailTableViewController ()\n\n@property (nonatomic, copy) NSArray<FLEXNetworkDetailSection *> *sections;\n\n@end\n\n@implementation FLEXNetworkTransactionDetailTableViewController\n\n- (instancetype)initWithStyle:(UITableViewStyle)style\n{\n    // Force grouped style\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTransactionUpdatedNotification:) name:kFLEXNetworkRecorderTransactionUpdatedNotification object:nil];\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@\"Copy curl\" style:UIBarButtonItemStylePlain target:self action:@selector(copyButtonPressed:)];\n    }\n    return self;\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n\n    [self.tableView registerClass:[FLEXMultilineTableViewCell class] forCellReuseIdentifier:kFLEXMultilineTableViewCellIdentifier];\n}\n\n- (void)setTransaction:(FLEXNetworkTransaction *)transaction\n{\n    if (![_transaction isEqual:transaction]) {\n        _transaction = transaction;\n        self.title = [transaction.request.URL lastPathComponent];\n        [self rebuildTableSections];\n    }\n}\n\n- (void)setSections:(NSArray<FLEXNetworkDetailSection *> *)sections\n{\n    if (![_sections isEqual:sections]) {\n        _sections = [sections copy];\n        [self.tableView reloadData];\n    }\n}\n\n- (void)rebuildTableSections\n{\n    NSMutableArray<FLEXNetworkDetailSection *> *sections = [NSMutableArray array];\n\n    FLEXNetworkDetailSection *generalSection = [[self class] generalSectionForTransaction:self.transaction];\n    if ([generalSection.rows count] > 0) {\n        [sections addObject:generalSection];\n    }\n    FLEXNetworkDetailSection *requestHeadersSection = [[self class] requestHeadersSectionForTransaction:self.transaction];\n    if ([requestHeadersSection.rows count] > 0) {\n        [sections addObject:requestHeadersSection];\n    }\n    FLEXNetworkDetailSection *queryParametersSection = [[self class] queryParametersSectionForTransaction:self.transaction];\n    if ([queryParametersSection.rows count] > 0) {\n        [sections addObject:queryParametersSection];\n    }\n    FLEXNetworkDetailSection *postBodySection = [[self class] postBodySectionForTransaction:self.transaction];\n    if ([postBodySection.rows count] > 0) {\n        [sections addObject:postBodySection];\n    }\n    FLEXNetworkDetailSection *responseHeadersSection = [[self class] responseHeadersSectionForTransaction:self.transaction];\n    if ([responseHeadersSection.rows count] > 0) {\n        [sections addObject:responseHeadersSection];\n    }\n\n    self.sections = sections;\n}\n\n- (void)handleTransactionUpdatedNotification:(NSNotification *)notification\n{\n    FLEXNetworkTransaction *transaction = [[notification userInfo] objectForKey:kFLEXNetworkRecorderUserInfoTransactionKey];\n    if (transaction == self.transaction) {\n        [self rebuildTableSections];\n    }\n}\n\n- (void)copyButtonPressed:(id)sender\n{\n    [[UIPasteboard generalPasteboard] setString:[FLEXNetworkCurlLogger curlCommandString:_transaction.request]];\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return [self.sections count];\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    FLEXNetworkDetailSection *sectionModel = self.sections[section];\n    return [sectionModel.rows count];\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section\n{\n    FLEXNetworkDetailSection *sectionModel = self.sections[section];\n    return sectionModel.title;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXMultilineTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kFLEXMultilineTableViewCellIdentifier forIndexPath:indexPath];\n\n    FLEXNetworkDetailRow *rowModel = [self rowModelAtIndexPath:indexPath];\n\n    cell.textLabel.attributedText = [[self class] attributedTextForRow:rowModel];\n    cell.accessoryType = rowModel.selectionFuture ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;\n    cell.selectionStyle = rowModel.selectionFuture ? UITableViewCellSelectionStyleDefault : UITableViewCellSelectionStyleNone;\n\n    return cell;\n}\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXNetworkDetailRow *rowModel = [self rowModelAtIndexPath:indexPath];\n\n    UIViewController *viewControllerToPush = nil;\n    if (rowModel.selectionFuture) {\n        viewControllerToPush = rowModel.selectionFuture();\n    }\n\n    if (viewControllerToPush) {\n        [self.navigationController pushViewController:viewControllerToPush animated:YES];\n    }\n\n    [tableView deselectRowAtIndexPath:indexPath animated:YES];\n}\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXNetworkDetailRow *row = [self rowModelAtIndexPath:indexPath];\n    NSAttributedString *attributedText = [[self class] attributedTextForRow:row];\n    BOOL showsAccessory = row.selectionFuture != nil;\n    return [FLEXMultilineTableViewCell preferredHeightWithAttributedText:attributedText inTableViewWidth:self.tableView.bounds.size.width style:UITableViewStyleGrouped showsAccessory:showsAccessory];\n}\n\n- (FLEXNetworkDetailRow *)rowModelAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXNetworkDetailSection *sectionModel = self.sections[indexPath.section];\n    return sectionModel.rows[indexPath.row];\n}\n\n#pragma mark - Cell Copying\n\n- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    return YES;\n}\n\n- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender\n{\n    return action == @selector(copy:);\n}\n\n- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender\n{\n    if (action == @selector(copy:)) {\n        FLEXNetworkDetailRow *row = [self rowModelAtIndexPath:indexPath];\n        [[UIPasteboard generalPasteboard] setString:row.detailText];\n    }\n}\n\n#pragma mark - View Configuration\n\n+ (NSAttributedString *)attributedTextForRow:(FLEXNetworkDetailRow *)row\n{\n    NSDictionary<NSString *, id> *titleAttributes = @{ NSFontAttributeName : [UIFont fontWithName:@\"HelveticaNeue-Medium\" size:12.0],\n                                                       NSForegroundColorAttributeName : [UIColor colorWithWhite:0.5 alpha:1.0] };\n    NSDictionary<NSString *, id> *detailAttributes = @{ NSFontAttributeName : [FLEXUtility defaultTableViewCellLabelFont],\n                                                        NSForegroundColorAttributeName : [UIColor blackColor] };\n\n    NSString *title = [NSString stringWithFormat:@\"%@: \", row.title];\n    NSString *detailText = row.detailText ?: @\"\";\n    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] init];\n    [attributedText appendAttributedString:[[NSAttributedString alloc] initWithString:title attributes:titleAttributes]];\n    [attributedText appendAttributedString:[[NSAttributedString alloc] initWithString:detailText attributes:detailAttributes]];\n\n    return attributedText;\n}\n\n#pragma mark - Table Data Generation\n\n+ (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransaction *)transaction\n{\n    NSMutableArray<FLEXNetworkDetailRow *> *rows = [NSMutableArray array];\n\n    FLEXNetworkDetailRow *requestURLRow = [[FLEXNetworkDetailRow alloc] init];\n    requestURLRow.title = @\"Request URL\";\n    NSURL *url = transaction.request.URL;\n    requestURLRow.detailText = url.absoluteString;\n    requestURLRow.selectionFuture = ^{\n        UIViewController *urlWebViewController = [[FLEXWebViewController alloc] initWithURL:url];\n        urlWebViewController.title = url.absoluteString;\n        return urlWebViewController;\n    };\n    [rows addObject:requestURLRow];\n\n    FLEXNetworkDetailRow *requestMethodRow = [[FLEXNetworkDetailRow alloc] init];\n    requestMethodRow.title = @\"Request Method\";\n    requestMethodRow.detailText = transaction.request.HTTPMethod;\n    [rows addObject:requestMethodRow];\n\n    if ([transaction.cachedRequestBody length] > 0) {\n        FLEXNetworkDetailRow *postBodySizeRow = [[FLEXNetworkDetailRow alloc] init];\n        postBodySizeRow.title = @\"Request Body Size\";\n        postBodySizeRow.detailText = [NSByteCountFormatter stringFromByteCount:[transaction.cachedRequestBody length] countStyle:NSByteCountFormatterCountStyleBinary];\n        [rows addObject:postBodySizeRow];\n\n        FLEXNetworkDetailRow *postBodyRow = [[FLEXNetworkDetailRow alloc] init];\n        postBodyRow.title = @\"Request Body\";\n        postBodyRow.detailText = @\"tap to view\";\n        postBodyRow.selectionFuture = ^{\n            NSString *contentType = [transaction.request valueForHTTPHeaderField:@\"Content-Type\"];\n            UIViewController *detailViewController = [self detailViewControllerForMIMEType:contentType data:[self postBodyDataForTransaction:transaction]];\n            if (detailViewController) {\n                detailViewController.title = @\"Request Body\";\n            } else {\n                NSString *alertMessage = [NSString stringWithFormat:@\"FLEX does not have a viewer for request body data with MIME type: %@\", [transaction.request valueForHTTPHeaderField:@\"Content-Type\"]];\n                [[[UIAlertView alloc] initWithTitle:@\"Can't View Body Data\" message:alertMessage delegate:nil cancelButtonTitle:@\"OK\" otherButtonTitles:nil] show];\n            }\n            return detailViewController;\n        };\n        [rows addObject:postBodyRow];\n    }\n\n    NSString *statusCodeString = [FLEXUtility statusCodeStringFromURLResponse:transaction.response];\n    if ([statusCodeString length] > 0) {\n        FLEXNetworkDetailRow *statusCodeRow = [[FLEXNetworkDetailRow alloc] init];\n        statusCodeRow.title = @\"Status Code\";\n        statusCodeRow.detailText = statusCodeString;\n        [rows addObject:statusCodeRow];\n    }\n\n    if (transaction.error) {\n        FLEXNetworkDetailRow *errorRow = [[FLEXNetworkDetailRow alloc] init];\n        errorRow.title = @\"Error\";\n        errorRow.detailText = transaction.error.localizedDescription;\n        [rows addObject:errorRow];\n    }\n\n    FLEXNetworkDetailRow *responseBodyRow = [[FLEXNetworkDetailRow alloc] init];\n    responseBodyRow.title = @\"Response Body\";\n    NSData *responseData = [[FLEXNetworkRecorder defaultRecorder] cachedResponseBodyForTransaction:transaction];\n    if ([responseData length] > 0) {\n        responseBodyRow.detailText = @\"tap to view\";\n        // Avoid a long lived strong reference to the response data in case we need to purge it from the cache.\n        __weak NSData *weakResponseData = responseData;\n        responseBodyRow.selectionFuture = ^{\n            UIViewController *responseBodyDetailViewController = nil;\n            NSData *strongResponseData = weakResponseData;\n            if (strongResponseData) {\n                responseBodyDetailViewController = [self detailViewControllerForMIMEType:transaction.response.MIMEType data:strongResponseData];\n                if (!responseBodyDetailViewController) {\n                    NSString *alertMessage = [NSString stringWithFormat:@\"FLEX does not have a viewer for responses with MIME type: %@\", transaction.response.MIMEType];\n                    [[[UIAlertView alloc] initWithTitle:@\"Can't View Response\" message:alertMessage delegate:nil cancelButtonTitle:@\"OK\" otherButtonTitles:nil] show];\n                }\n                responseBodyDetailViewController.title = @\"Response\";\n            } else {\n                NSString *alertMessage = @\"The response has been purged from the cache\";\n                [[[UIAlertView alloc] initWithTitle:@\"Can't View Response\" message:alertMessage delegate:nil cancelButtonTitle:@\"OK\" otherButtonTitles:nil] show];\n            }\n            return responseBodyDetailViewController;\n        };\n    } else {\n        BOOL emptyResponse = transaction.receivedDataLength == 0;\n        responseBodyRow.detailText = emptyResponse ? @\"empty\" : @\"not in cache\";\n    }\n    [rows addObject:responseBodyRow];\n\n    FLEXNetworkDetailRow *responseSizeRow = [[FLEXNetworkDetailRow alloc] init];\n    responseSizeRow.title = @\"Response Size\";\n    responseSizeRow.detailText = [NSByteCountFormatter stringFromByteCount:transaction.receivedDataLength countStyle:NSByteCountFormatterCountStyleBinary];\n    [rows addObject:responseSizeRow];\n\n    FLEXNetworkDetailRow *mimeTypeRow = [[FLEXNetworkDetailRow alloc] init];\n    mimeTypeRow.title = @\"MIME Type\";\n    mimeTypeRow.detailText = transaction.response.MIMEType;\n    [rows addObject:mimeTypeRow];\n\n    FLEXNetworkDetailRow *mechanismRow = [[FLEXNetworkDetailRow alloc] init];\n    mechanismRow.title = @\"Mechanism\";\n    mechanismRow.detailText = transaction.requestMechanism;\n    [rows addObject:mechanismRow];\n\n    NSDateFormatter *startTimeFormatter = [[NSDateFormatter alloc] init];\n    startTimeFormatter.dateFormat = @\"yyyy-MM-dd HH:mm:ss.SSS\";\n\n    FLEXNetworkDetailRow *localStartTimeRow = [[FLEXNetworkDetailRow alloc] init];\n    localStartTimeRow.title = [NSString stringWithFormat:@\"Start Time (%@)\", [[NSTimeZone localTimeZone] abbreviationForDate:transaction.startTime]];\n    localStartTimeRow.detailText = [startTimeFormatter stringFromDate:transaction.startTime];\n    [rows addObject:localStartTimeRow];\n\n    startTimeFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@\"UTC\"];\n\n    FLEXNetworkDetailRow *utcStartTimeRow = [[FLEXNetworkDetailRow alloc] init];\n    utcStartTimeRow.title = @\"Start Time (UTC)\";\n    utcStartTimeRow.detailText = [startTimeFormatter stringFromDate:transaction.startTime];\n    [rows addObject:utcStartTimeRow];\n\n    FLEXNetworkDetailRow *unixStartTime = [[FLEXNetworkDetailRow alloc] init];\n    unixStartTime.title = @\"Unix Start Time\";\n    unixStartTime.detailText = [NSString stringWithFormat:@\"%f\", [transaction.startTime timeIntervalSince1970]];\n    [rows addObject:unixStartTime];\n\n    FLEXNetworkDetailRow *durationRow = [[FLEXNetworkDetailRow alloc] init];\n    durationRow.title = @\"Total Duration\";\n    durationRow.detailText = [FLEXUtility stringFromRequestDuration:transaction.duration];\n    [rows addObject:durationRow];\n\n    FLEXNetworkDetailRow *latencyRow = [[FLEXNetworkDetailRow alloc] init];\n    latencyRow.title = @\"Latency\";\n    latencyRow.detailText = [FLEXUtility stringFromRequestDuration:transaction.latency];\n    [rows addObject:latencyRow];\n\n    FLEXNetworkDetailSection *generalSection = [[FLEXNetworkDetailSection alloc] init];\n    generalSection.title = @\"General\";\n    generalSection.rows = rows;\n\n    return generalSection;\n}\n\n+ (FLEXNetworkDetailSection *)requestHeadersSectionForTransaction:(FLEXNetworkTransaction *)transaction\n{\n    FLEXNetworkDetailSection *requestHeadersSection = [[FLEXNetworkDetailSection alloc] init];\n    requestHeadersSection.title = @\"Request Headers\";\n    requestHeadersSection.rows = [self networkDetailRowsFromDictionary:transaction.request.allHTTPHeaderFields];\n\n    return requestHeadersSection;\n}\n\n+ (FLEXNetworkDetailSection *)postBodySectionForTransaction:(FLEXNetworkTransaction *)transaction\n{\n    FLEXNetworkDetailSection *postBodySection = [[FLEXNetworkDetailSection alloc] init];\n    postBodySection.title = @\"Request Body Parameters\";\n    if ([transaction.cachedRequestBody length] > 0) {\n        NSString *contentType = [transaction.request valueForHTTPHeaderField:@\"Content-Type\"];\n        if ([contentType hasPrefix:@\"application/x-www-form-urlencoded\"]) {\n            NSString *bodyString = [[NSString alloc] initWithData:[self postBodyDataForTransaction:transaction] encoding:NSUTF8StringEncoding];\n            postBodySection.rows = [self networkDetailRowsFromDictionary:[FLEXUtility dictionaryFromQuery:bodyString]];\n        }\n    }\n    return postBodySection;\n}\n\n+ (FLEXNetworkDetailSection *)queryParametersSectionForTransaction:(FLEXNetworkTransaction *)transaction\n{\n    NSDictionary<NSString *, id> *queryDictionary = [FLEXUtility dictionaryFromQuery:transaction.request.URL.query];\n    FLEXNetworkDetailSection *querySection = [[FLEXNetworkDetailSection alloc] init];\n    querySection.title = @\"Query Parameters\";\n    querySection.rows = [self networkDetailRowsFromDictionary:queryDictionary];\n\n    return querySection;\n}\n\n+ (FLEXNetworkDetailSection *)responseHeadersSectionForTransaction:(FLEXNetworkTransaction *)transaction\n{\n    FLEXNetworkDetailSection *responseHeadersSection = [[FLEXNetworkDetailSection alloc] init];\n    responseHeadersSection.title = @\"Response Headers\";\n    if ([transaction.response isKindOfClass:[NSHTTPURLResponse class]]) {\n        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)transaction.response;\n        responseHeadersSection.rows = [self networkDetailRowsFromDictionary:httpResponse.allHeaderFields];\n    }\n    return responseHeadersSection;\n}\n\n+ (NSArray<FLEXNetworkDetailRow *> *)networkDetailRowsFromDictionary:(NSDictionary<NSString *, id> *)dictionary\n{\n    NSMutableArray<FLEXNetworkDetailRow *> *rows = [NSMutableArray arrayWithCapacity:[dictionary count]];\n    NSArray<NSString *> *sortedKeys = [[dictionary allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];\n    for (NSString *key in sortedKeys) {\n        id value = dictionary[key];\n        FLEXNetworkDetailRow *row = [[FLEXNetworkDetailRow alloc] init];\n        row.title = key;\n        row.detailText = [value description];\n        [rows addObject:row];\n    }\n    return [rows copy];\n}\n\n+ (UIViewController *)detailViewControllerForMIMEType:(NSString *)mimeType data:(NSData *)data\n{\n    // FIXME (RKO): Don't rely on UTF8 string encoding\n    UIViewController *detailViewController = nil;\n    if ([FLEXUtility isValidJSONData:data]) {\n        NSString *prettyJSON = [FLEXUtility prettyJSONStringFromData:data];\n        if ([prettyJSON length] > 0) {\n            detailViewController = [[FLEXWebViewController alloc] initWithText:prettyJSON];\n        }\n    } else if ([mimeType hasPrefix:@\"image/\"]) {\n        UIImage *image = [UIImage imageWithData:data];\n        detailViewController = [[FLEXImagePreviewViewController alloc] initWithImage:image];\n    } else if ([mimeType isEqual:@\"application/x-plist\"]) {\n        id propertyList = [NSPropertyListSerialization propertyListWithData:data options:0 format:NULL error:NULL];\n        detailViewController = [[FLEXWebViewController alloc] initWithText:[propertyList description]];\n    }\n\n    // Fall back to trying to show the response as text\n    if (!detailViewController) {\n        NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];\n        if ([text length] > 0) {\n            detailViewController = [[FLEXWebViewController alloc] initWithText:text];\n        }\n    }\n    return detailViewController;\n}\n\n+ (NSData *)postBodyDataForTransaction:(FLEXNetworkTransaction *)transaction\n{\n    NSData *bodyData = transaction.cachedRequestBody;\n    if ([bodyData length] > 0) {\n        NSString *contentEncoding = [transaction.request valueForHTTPHeaderField:@\"Content-Encoding\"];\n        if ([contentEncoding rangeOfString:@\"deflate\" options:NSCaseInsensitiveSearch].length > 0 || [contentEncoding rangeOfString:@\"gzip\" options:NSCaseInsensitiveSearch].length > 0) {\n            bodyData = [FLEXUtility inflatedDataFromCompressedData:bodyData];\n        }\n    }\n    return bodyData;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkTransactionTableViewCell.h",
    "content": "//\n//  FLEXNetworkTransactionTableViewCell.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2/8/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\nextern NSString *const kFLEXNetworkTransactionCellIdentifier;\n\n@class FLEXNetworkTransaction;\n\n@interface FLEXNetworkTransactionTableViewCell : UITableViewCell\n\n@property (nonatomic, strong) FLEXNetworkTransaction *transaction;\n\n+ (CGFloat)preferredCellHeight;\n\n@end\n"
  },
  {
    "path": "FLEX/Network/FLEXNetworkTransactionTableViewCell.m",
    "content": "//\n//  FLEXNetworkTransactionTableViewCell.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2/8/15.\n//  Copyright (c) 2015 Flipboard. All rights reserved.\n//\n\n#import \"FLEXNetworkTransactionTableViewCell.h\"\n#import \"FLEXNetworkTransaction.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXResources.h\"\n\nNSString *const kFLEXNetworkTransactionCellIdentifier = @\"kFLEXNetworkTransactionCellIdentifier\";\n\n@interface FLEXNetworkTransactionTableViewCell ()\n\n@property (nonatomic, strong) UIImageView *thumbnailImageView;\n@property (nonatomic, strong) UILabel *nameLabel;\n@property (nonatomic, strong) UILabel *pathLabel;\n@property (nonatomic, strong) UILabel *transactionDetailsLabel;\n\n@end\n\n@implementation FLEXNetworkTransactionTableViewCell\n\n- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier\n{\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;\n\n        self.nameLabel = [[UILabel alloc] init];\n        self.nameLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n        [self.contentView addSubview:self.nameLabel];\n\n        self.pathLabel = [[UILabel alloc] init];\n        self.pathLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n        self.pathLabel.textColor = [UIColor colorWithWhite:0.4 alpha:1.0];\n        [self.contentView addSubview:self.pathLabel];\n\n        self.thumbnailImageView = [[UIImageView alloc] init];\n        self.thumbnailImageView.layer.borderColor = [[UIColor blackColor] CGColor];\n        self.thumbnailImageView.layer.borderWidth = 1.0;\n        self.thumbnailImageView.contentMode = UIViewContentModeScaleAspectFit;\n        [self.contentView addSubview:self.thumbnailImageView];\n\n        self.transactionDetailsLabel = [[UILabel alloc] init];\n        self.transactionDetailsLabel.font = [FLEXUtility defaultFontOfSize:10.0];\n        self.transactionDetailsLabel.textColor = [UIColor colorWithWhite:0.65 alpha:1.0];\n        [self.contentView addSubview:self.transactionDetailsLabel];\n    }\n    return self;\n}\n\n- (void)setTransaction:(FLEXNetworkTransaction *)transaction\n{\n    if (_transaction != transaction) {\n        _transaction = transaction;\n        [self setNeedsLayout];\n    }\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n\n    const CGFloat kVerticalPadding = 8.0;\n    const CGFloat kLeftPadding = 10.0;\n    const CGFloat kImageDimension = 32.0;\n\n    CGFloat thumbnailOriginY = round((self.contentView.bounds.size.height - kImageDimension) / 2.0);\n    self.thumbnailImageView.frame = CGRectMake(kLeftPadding, thumbnailOriginY, kImageDimension, kImageDimension);\n    self.thumbnailImageView.image = self.transaction.responseThumbnail;\n\n    CGFloat textOriginX = CGRectGetMaxX(self.thumbnailImageView.frame) + kLeftPadding;\n    CGFloat availableTextWidth = self.contentView.bounds.size.width - textOriginX;\n\n    self.nameLabel.text = [self nameLabelText];\n    CGSize nameLabelPreferredSize = [self.nameLabel sizeThatFits:CGSizeMake(availableTextWidth, CGFLOAT_MAX)];\n    self.nameLabel.frame = CGRectMake(textOriginX, kVerticalPadding, availableTextWidth, nameLabelPreferredSize.height);\n    self.nameLabel.textColor = (self.transaction.error || [FLEXUtility isErrorStatusCodeFromURLResponse:self.transaction.response]) ? [UIColor redColor] : [UIColor blackColor];\n\n    self.pathLabel.text = [self pathLabelText];\n    CGSize pathLabelPreferredSize = [self.pathLabel sizeThatFits:CGSizeMake(availableTextWidth, CGFLOAT_MAX)];\n    CGFloat pathLabelOriginY = ceil((self.contentView.bounds.size.height - pathLabelPreferredSize.height) / 2.0);\n    self.pathLabel.frame = CGRectMake(textOriginX, pathLabelOriginY, availableTextWidth, pathLabelPreferredSize.height);\n\n    self.transactionDetailsLabel.text = [self transactionDetailsLabelText];\n    CGSize transactionLabelPreferredSize = [self.transactionDetailsLabel sizeThatFits:CGSizeMake(availableTextWidth, CGFLOAT_MAX)];\n    CGFloat transactionDetailsOriginX = textOriginX;\n    CGFloat transactionDetailsLabelOriginY = CGRectGetMaxY(self.contentView.bounds) - kVerticalPadding - transactionLabelPreferredSize.height;\n    CGFloat transactionDetailsLabelWidth = self.contentView.bounds.size.width - transactionDetailsOriginX;\n    self.transactionDetailsLabel.frame = CGRectMake(transactionDetailsOriginX, transactionDetailsLabelOriginY, transactionDetailsLabelWidth, transactionLabelPreferredSize.height);\n}\n\n- (NSString *)nameLabelText\n{\n    NSURL *url = self.transaction.request.URL;\n    NSString *name = [url lastPathComponent];\n    if ([name length] == 0) {\n        name = @\"/\";\n    }\n    NSString *query = [url query];\n    if (query) {\n        name = [name stringByAppendingFormat:@\"?%@\", query];\n    }\n    return name;\n}\n\n- (NSString *)pathLabelText\n{\n    NSURL *url = self.transaction.request.URL;\n    NSMutableArray<NSString *> *mutablePathComponents = [[url pathComponents] mutableCopy];\n    if ([mutablePathComponents count] > 0) {\n        [mutablePathComponents removeLastObject];\n    }\n    NSString *path = [url host];\n    for (NSString *pathComponent in mutablePathComponents) {\n        path = [path stringByAppendingPathComponent:pathComponent];\n    }\n    return path;\n}\n\n- (NSString *)transactionDetailsLabelText\n{\n    NSMutableArray<NSString *> *detailComponents = [NSMutableArray array];\n\n    NSString *timestamp = [[self class] timestampStringFromRequestDate:self.transaction.startTime];\n    if ([timestamp length] > 0) {\n        [detailComponents addObject:timestamp];\n    }\n\n    // Omit method for GET (assumed as default)\n    NSString *httpMethod = self.transaction.request.HTTPMethod;\n    if ([httpMethod length] > 0) {\n        [detailComponents addObject:httpMethod];\n    }\n\n    if (self.transaction.transactionState == FLEXNetworkTransactionStateFinished || self.transaction.transactionState == FLEXNetworkTransactionStateFailed) {\n        NSString *statusCodeString = [FLEXUtility statusCodeStringFromURLResponse:self.transaction.response];\n        if ([statusCodeString length] > 0) {\n            [detailComponents addObject:statusCodeString];\n        }\n\n        if (self.transaction.receivedDataLength > 0) {\n            NSString *responseSize = [NSByteCountFormatter stringFromByteCount:self.transaction.receivedDataLength countStyle:NSByteCountFormatterCountStyleBinary];\n            [detailComponents addObject:responseSize];\n        }\n\n        NSString *totalDuration = [FLEXUtility stringFromRequestDuration:self.transaction.duration];\n        NSString *latency = [FLEXUtility stringFromRequestDuration:self.transaction.latency];\n        NSString *duration = [NSString stringWithFormat:@\"%@ (%@)\", totalDuration, latency];\n        [detailComponents addObject:duration];\n    } else {\n        // Unstarted, Awaiting Response, Receiving Data, etc.\n        NSString *state = [FLEXNetworkTransaction readableStringFromTransactionState:self.transaction.transactionState];\n        [detailComponents addObject:state];\n    }\n\n    return [detailComponents componentsJoinedByString:@\" ・ \"];\n}\n\n+ (NSString *)timestampStringFromRequestDate:(NSDate *)date\n{\n    static NSDateFormatter *dateFormatter = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        dateFormatter = [[NSDateFormatter alloc] init];\n        dateFormatter.dateFormat = @\"HH:mm:ss\";\n    });\n    return [dateFormatter stringFromDate:date];\n}\n\n+ (CGFloat)preferredCellHeight\n{\n    return 65.0;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Network/PonyDebugger/FLEXNetworkObserver.h",
    "content": "//\n//  FLEXNetworkObserver.h\n//  Derived from:\n//\n//  PDAFNetworkDomainController.h\n//  PonyDebugger\n//\n//  Created by Mike Lewis on 2/27/12.\n//\n//  Licensed to Square, Inc. under one or more contributor license agreements.\n//  See the LICENSE file distributed with this work for the terms under\n//  which Square, Inc. licenses this file to you.\n//\n\n#import <Foundation/Foundation.h>\n\nFOUNDATION_EXTERN NSString *const kFLEXNetworkObserverEnabledStateChangedNotification;\n\n/// This class swizzles NSURLConnection and NSURLSession delegate methods to observe events in the URL loading system.\n/// High level network events are sent to the default FLEXNetworkRecorder instance which maintains the request history and caches response bodies.\n@interface FLEXNetworkObserver : NSObject\n\n/// Swizzling occurs when the observer is enabled for the first time.\n/// This reduces the impact of FLEX if network debugging is not desired.\n/// NOTE: this setting persists between launches of the app.\n+ (void)setEnabled:(BOOL)enabled;\n+ (BOOL)isEnabled;\n\n@end\n"
  },
  {
    "path": "FLEX/Network/PonyDebugger/FLEXNetworkObserver.m",
    "content": "//\n//  FLEXNetworkObserver.m\n//  Derived from:\n//\n//  PDAFNetworkDomainController.m\n//  PonyDebugger\n//\n//  Created by Mike Lewis on 2/27/12.\n//\n//  Licensed to Square, Inc. under one or more contributor license agreements.\n//  See the LICENSE file distributed with this work for the terms under\n//  which Square, Inc. licenses this file to you.\n//\n\n#import \"FLEXNetworkObserver.h\"\n#import \"FLEXNetworkRecorder.h\"\n#import \"FLEXUtility.h\"\n\n#import <objc/runtime.h>\n#import <objc/message.h>\n#import <dispatch/queue.h>\n\nNSString *const kFLEXNetworkObserverEnabledStateChangedNotification = @\"kFLEXNetworkObserverEnabledStateChangedNotification\";\nstatic NSString *const kFLEXNetworkObserverEnabledDefaultsKey = @\"com.flex.FLEXNetworkObserver.enableOnLaunch\";\n\ntypedef void (^NSURLSessionAsyncCompletion)(id fileURLOrData, NSURLResponse *response, NSError *error);\n\n@interface FLEXInternalRequestState : NSObject\n\n@property (nonatomic, copy) NSURLRequest *request;\n@property (nonatomic, strong) NSMutableData *dataAccumulator;\n\n@end\n\n@implementation FLEXInternalRequestState\n\n@end\n\n@interface FLEXNetworkObserver (NSURLConnectionHelpers)\n\n- (void)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response delegate:(id <NSURLConnectionDelegate>)delegate;\n- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response delegate:(id <NSURLConnectionDelegate>)delegate;\n\n- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data delegate:(id <NSURLConnectionDelegate>)delegate;\n\n- (void)connectionDidFinishLoading:(NSURLConnection *)connection delegate:(id <NSURLConnectionDelegate>)delegate;\n- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error delegate:(id <NSURLConnectionDelegate>)delegate;\n\n- (void)connectionWillCancel:(NSURLConnection *)connection;\n\n@end\n\n\n@interface FLEXNetworkObserver (NSURLSessionTaskHelpers)\n\n- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler delegate:(id <NSURLSessionDelegate>)delegate;\n- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler delegate:(id <NSURLSessionDelegate>)delegate;\n- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data delegate:(id <NSURLSessionDelegate>)delegate;\n- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask\ndidBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSURLSessionDelegate>)delegate;\n- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error delegate:(id <NSURLSessionDelegate>)delegate;\n- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite delegate:(id <NSURLSessionDelegate>)delegate;\n- (void)URLSession:(NSURLSession *)session task:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location data:(NSData *)data delegate:(id <NSURLSessionDelegate>)delegate;\n\n- (void)URLSessionTaskWillResume:(NSURLSessionTask *)task;\n\n@end\n\n@interface FLEXNetworkObserver ()\n\n@property (nonatomic, strong) NSMutableDictionary<NSString *, FLEXInternalRequestState *> *requestStatesForRequestIDs;\n@property (nonatomic, strong) dispatch_queue_t queue;\n\n@end\n\n@implementation FLEXNetworkObserver\n\n#pragma mark - Public Methods\n\n+ (void)setEnabled:(BOOL)enabled\n{\n    BOOL previouslyEnabled = [self isEnabled];\n    \n    [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:kFLEXNetworkObserverEnabledDefaultsKey];\n    \n    if (enabled) {\n        // Inject if needed. This injection is protected with a dispatch_once, so we're ok calling it multiple times.\n        // By doing the injection lazily, we keep the impact of the tool lower when this feature isn't enabled.\n        [self injectIntoAllNSURLConnectionDelegateClasses];\n    }\n    \n    if (previouslyEnabled != enabled) {\n        [[NSNotificationCenter defaultCenter] postNotificationName:kFLEXNetworkObserverEnabledStateChangedNotification object:self];\n    }\n}\n\n+ (BOOL)isEnabled\n{\n    return [[[NSUserDefaults standardUserDefaults] objectForKey:kFLEXNetworkObserverEnabledDefaultsKey] boolValue];\n}\n\n+ (void)load\n{\n    // We don't want to do the swizzling from +load because not all the classes may be loaded at this point.\n    dispatch_async(dispatch_get_main_queue(), ^{\n        if ([self isEnabled]) {\n            [self injectIntoAllNSURLConnectionDelegateClasses];\n        }\n    });\n}\n\n#pragma mark - Statics\n\n+ (instancetype)sharedObserver\n{\n    static FLEXNetworkObserver *sharedObserver = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        sharedObserver = [[[self class] alloc] init];\n    });\n    return sharedObserver;\n}\n\n+ (NSString *)nextRequestID\n{\n    return [[NSUUID UUID] UUIDString];\n}\n\n#pragma mark Delegate Injection Convenience Methods\n\n/// All swizzled delegate methods should make use of this guard.\n/// This will prevent duplicated sniffing when the original implementation calls up to a superclass implementation which we've also swizzled.\n/// The superclass implementation (and implementations in classes above that) will be executed without inteference if called from the original implementation.\n+ (void)sniffWithoutDuplicationForObject:(NSObject *)object selector:(SEL)selector sniffingBlock:(void (^)(void))sniffingBlock originalImplementationBlock:(void (^)(void))originalImplementationBlock\n{\n    // If we don't have an object to detect nested calls on, just run the original implmentation and bail.\n    // This case can happen if someone besides the URL loading system calls the delegate methods directly.\n    // See https://github.com/Flipboard/FLEX/issues/61 for an example.\n    if (!object) {\n        originalImplementationBlock();\n        return;\n    }\n\n    const void *key = selector;\n\n    // Don't run the sniffing block if we're inside a nested call\n    if (!objc_getAssociatedObject(object, key)) {\n        sniffingBlock();\n    }\n\n    // Mark that we're calling through to the original so we can detect nested calls\n    objc_setAssociatedObject(object, key, @YES, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n    originalImplementationBlock();\n    objc_setAssociatedObject(object, key, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n}\n\n#pragma mark - Delegate Injection\n\n+ (void)injectIntoAllNSURLConnectionDelegateClasses\n{\n    // Only allow swizzling once.\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        // Swizzle any classes that implement one of these selectors.\n        const SEL selectors[] = {\n            @selector(connectionDidFinishLoading:),\n            @selector(connection:willSendRequest:redirectResponse:),\n            @selector(connection:didReceiveResponse:),\n            @selector(connection:didReceiveData:),\n            @selector(connection:didFailWithError:),\n            @selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:),\n            @selector(URLSession:dataTask:didReceiveData:),\n            @selector(URLSession:dataTask:didReceiveResponse:completionHandler:),\n            @selector(URLSession:task:didCompleteWithError:),\n            @selector(URLSession:dataTask:didBecomeDownloadTask:),\n            @selector(URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:),\n            @selector(URLSession:downloadTask:didFinishDownloadingToURL:)\n        };\n\n        const int numSelectors = sizeof(selectors) / sizeof(SEL);\n\n        Class *classes = NULL;\n        int numClasses = objc_getClassList(NULL, 0);\n\n        if (numClasses > 0) {\n            classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses);\n            numClasses = objc_getClassList(classes, numClasses);\n            for (NSInteger classIndex = 0; classIndex < numClasses; ++classIndex) {\n                Class class = classes[classIndex];\n\n                if (class == [FLEXNetworkObserver class]) {\n                    continue;\n                }\n\n                // Use the runtime API rather than the methods on NSObject to avoid sending messages to\n                // classes we're not interested in swizzling. Otherwise we hit +initialize on all classes.\n                // NOTE: calling class_getInstanceMethod() DOES send +initialize to the class. That's why we iterate through the method list.\n                unsigned int methodCount = 0;\n                Method *methods = class_copyMethodList(class, &methodCount);\n                BOOL matchingSelectorFound = NO;\n                for (unsigned int methodIndex = 0; methodIndex < methodCount; methodIndex++) {\n                    for (int selectorIndex = 0; selectorIndex < numSelectors; ++selectorIndex) {\n                        if (method_getName(methods[methodIndex]) == selectors[selectorIndex]) {\n                            [self injectIntoDelegateClass:class];\n                            matchingSelectorFound = YES;\n                            break;\n                        }\n                    }\n                    if (matchingSelectorFound) {\n                        break;\n                    }\n                }\n                free(methods);\n            }\n            \n            free(classes);\n        }\n\n        [self injectIntoNSURLConnectionCancel];\n        [self injectIntoNSURLSessionTaskResume];\n\n        [self injectIntoNSURLConnectionAsynchronousClassMethod];\n        [self injectIntoNSURLConnectionSynchronousClassMethod];\n\n        [self injectIntoNSURLSessionAsyncDataAndDownloadTaskMethods];\n        [self injectIntoNSURLSessionAsyncUploadTaskMethods];\n    });\n}\n\n+ (void)injectIntoDelegateClass:(Class)cls\n{\n    // Connections\n    [self injectWillSendRequestIntoDelegateClass:cls];\n    [self injectDidReceiveDataIntoDelegateClass:cls];\n    [self injectDidReceiveResponseIntoDelegateClass:cls];\n    [self injectDidFinishLoadingIntoDelegateClass:cls];\n    [self injectDidFailWithErrorIntoDelegateClass:cls];\n    \n    // Sessions\n    [self injectTaskWillPerformHTTPRedirectionIntoDelegateClass:cls];\n    [self injectTaskDidReceiveDataIntoDelegateClass:cls];\n    [self injectTaskDidReceiveResponseIntoDelegateClass:cls];\n    [self injectTaskDidCompleteWithErrorIntoDelegateClass:cls];\n    [self injectRespondsToSelectorIntoDelegateClass:cls];\n\n    // Data tasks\n    [self injectDataTaskDidBecomeDownloadTaskIntoDelegateClass:cls];\n\n    // Download tasks\n    [self injectDownloadTaskDidWriteDataIntoDelegateClass:cls];\n    [self injectDownloadTaskDidFinishDownloadingIntoDelegateClass:cls];\n}\n\n+ (void)injectIntoNSURLConnectionCancel\n{\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        Class class = [NSURLConnection class];\n        SEL selector = @selector(cancel);\n        SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n        Method originalCancel = class_getInstanceMethod(class, selector);\n\n        void (^swizzleBlock)(NSURLConnection *) = ^(NSURLConnection *slf) {\n            [[FLEXNetworkObserver sharedObserver] connectionWillCancel:slf];\n            ((void(*)(id, SEL))objc_msgSend)(slf, swizzledSelector);\n        };\n\n        IMP implementation = imp_implementationWithBlock(swizzleBlock);\n        class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalCancel));\n        Method newCancel = class_getInstanceMethod(class, swizzledSelector);\n        method_exchangeImplementations(originalCancel, newCancel);\n    });\n}\n\n+ (void)injectIntoNSURLSessionTaskResume\n{\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        // In iOS 7 resume lives in __NSCFLocalSessionTask\n        // In iOS 8 resume lives in NSURLSessionTask\n        // In iOS 9 resume lives in __NSCFURLSessionTask\n        Class class = Nil;\n        if (![[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) {\n            class = NSClassFromString([@[@\"__\", @\"NSC\", @\"FLocalS\", @\"ession\", @\"Task\"] componentsJoinedByString:@\"\"]);\n        } else if ([[NSProcessInfo processInfo] operatingSystemVersion].majorVersion < 9) {\n            class = [NSURLSessionTask class];\n        } else {\n            class = NSClassFromString([@[@\"__\", @\"NSC\", @\"FURLS\", @\"ession\", @\"Task\"] componentsJoinedByString:@\"\"]);\n        }\n        SEL selector = @selector(resume);\n        SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n\n        Method originalResume = class_getInstanceMethod(class, selector);\n\n        void (^swizzleBlock)(NSURLSessionTask *) = ^(NSURLSessionTask *slf) {\n            [[FLEXNetworkObserver sharedObserver] URLSessionTaskWillResume:slf];\n            ((void(*)(id, SEL))objc_msgSend)(slf, swizzledSelector);\n        };\n\n        IMP implementation = imp_implementationWithBlock(swizzleBlock);\n        class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalResume));\n        Method newResume = class_getInstanceMethod(class, swizzledSelector);\n        method_exchangeImplementations(originalResume, newResume);\n    });\n}\n\n+ (void)injectIntoNSURLConnectionAsynchronousClassMethod\n{\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        Class class = objc_getMetaClass(class_getName([NSURLConnection class]));\n        SEL selector = @selector(sendAsynchronousRequest:queue:completionHandler:);\n        SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n\n        typedef void (^NSURLConnectionAsyncCompletion)(NSURLResponse* response, NSData* data, NSError* connectionError);\n\n        void (^asyncSwizzleBlock)(Class, NSURLRequest *, NSOperationQueue *, NSURLConnectionAsyncCompletion) = ^(Class slf, NSURLRequest *request, NSOperationQueue *queue, NSURLConnectionAsyncCompletion completion) {\n            if ([FLEXNetworkObserver isEnabled]) {\n                NSString *requestID = [self nextRequestID];\n                [[FLEXNetworkRecorder defaultRecorder] recordRequestWillBeSentWithRequestID:requestID request:request redirectResponse:nil];\n                NSString *mechanism = [self mechanismFromClassMethod:selector onClass:class];\n                [[FLEXNetworkRecorder defaultRecorder] recordMechanism:mechanism forRequestID:requestID];\n                NSURLConnectionAsyncCompletion completionWrapper = ^(NSURLResponse *response, NSData *data, NSError *connectionError) {\n                    [[FLEXNetworkRecorder defaultRecorder] recordResponseReceivedWithRequestID:requestID response:response];\n                    [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:[data length]];\n                    if (connectionError) {\n                        [[FLEXNetworkRecorder defaultRecorder] recordLoadingFailedWithRequestID:requestID error:connectionError];\n                    } else {\n                        [[FLEXNetworkRecorder defaultRecorder] recordLoadingFinishedWithRequestID:requestID responseBody:data];\n                    }\n\n                    // Call through to the original completion handler\n                    if (completion) {\n                        completion(response, data, connectionError);\n                    }\n                };\n                ((void(*)(id, SEL, id, id, id))objc_msgSend)(slf, swizzledSelector, request, queue, completionWrapper);\n            } else {\n                ((void(*)(id, SEL, id, id, id))objc_msgSend)(slf, swizzledSelector, request, queue, completion);\n            }\n        };\n        \n        [FLEXUtility replaceImplementationOfKnownSelector:selector onClass:class withBlock:asyncSwizzleBlock swizzledSelector:swizzledSelector];\n    });\n}\n\n+ (void)injectIntoNSURLConnectionSynchronousClassMethod\n{\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        Class class = objc_getMetaClass(class_getName([NSURLConnection class]));\n        SEL selector = @selector(sendSynchronousRequest:returningResponse:error:);\n        SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n\n        NSData *(^syncSwizzleBlock)(Class, NSURLRequest *, NSURLResponse **, NSError **) = ^NSData *(Class slf, NSURLRequest *request, NSURLResponse **response, NSError **error) {\n            NSData *data = nil;\n            if ([FLEXNetworkObserver isEnabled]) {\n                NSString *requestID = [self nextRequestID];\n                [[FLEXNetworkRecorder defaultRecorder] recordRequestWillBeSentWithRequestID:requestID request:request redirectResponse:nil];\n                NSString *mechanism = [self mechanismFromClassMethod:selector onClass:class];\n                [[FLEXNetworkRecorder defaultRecorder] recordMechanism:mechanism forRequestID:requestID];\n                NSError *temporaryError = nil;\n                NSURLResponse *temporaryResponse = nil;\n                data = ((id(*)(id, SEL, id, NSURLResponse **, NSError **))objc_msgSend)(slf, swizzledSelector, request, &temporaryResponse, &temporaryError);\n                [[FLEXNetworkRecorder defaultRecorder] recordResponseReceivedWithRequestID:requestID response:temporaryResponse];\n                [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:[data length]];\n                if (temporaryError) {\n                    [[FLEXNetworkRecorder defaultRecorder] recordLoadingFailedWithRequestID:requestID error:temporaryError];\n                } else {\n                    [[FLEXNetworkRecorder defaultRecorder] recordLoadingFinishedWithRequestID:requestID responseBody:data];\n                }\n                if (error) {\n                    *error = temporaryError;\n                }\n                if (response) {\n                    *response = temporaryResponse;\n                }\n            } else {\n                data = ((id(*)(id, SEL, id, NSURLResponse **, NSError **))objc_msgSend)(slf, swizzledSelector, request, response, error);\n            }\n\n            return data;\n        };\n        \n        [FLEXUtility replaceImplementationOfKnownSelector:selector onClass:class withBlock:syncSwizzleBlock swizzledSelector:swizzledSelector];\n    });\n}\n\n+ (void)injectIntoNSURLSessionAsyncDataAndDownloadTaskMethods\n{\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        Class class = [NSURLSession class];\n\n        // The method signatures here are close enough that we can use the same logic to inject into all of them.\n        const SEL selectors[] = {\n            @selector(dataTaskWithRequest:completionHandler:),\n            @selector(dataTaskWithURL:completionHandler:),\n            @selector(downloadTaskWithRequest:completionHandler:),\n            @selector(downloadTaskWithResumeData:completionHandler:),\n            @selector(downloadTaskWithURL:completionHandler:)\n        };\n\n        const int numSelectors = sizeof(selectors) / sizeof(SEL);\n\n        for (int selectorIndex = 0; selectorIndex < numSelectors; selectorIndex++) {\n            SEL selector = selectors[selectorIndex];\n            SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n\n            if ([FLEXUtility instanceRespondsButDoesNotImplementSelector:selector class:class]) {\n                // iOS 7 does not implement these methods on NSURLSession. We actually want to\n                // swizzle __NSCFURLSession, which we can get from the class of the shared session\n                class = [[NSURLSession sharedSession] class];\n            }\n\n            NSURLSessionTask *(^asyncDataOrDownloadSwizzleBlock)(Class, id, NSURLSessionAsyncCompletion) = ^NSURLSessionTask *(Class slf, id argument, NSURLSessionAsyncCompletion completion) {\n                NSURLSessionTask *task = nil;\n                // If completion block was not provided sender expect to receive delegated methods or does not\n                // interested in callback at all. In this case we should just call original method implementation\n                // with nil completion block.\n                if ([FLEXNetworkObserver isEnabled] && completion) {\n                    NSString *requestID = [self nextRequestID];\n                    NSString *mechanism = [self mechanismFromClassMethod:selector onClass:class];\n                    NSURLSessionAsyncCompletion completionWrapper = [self asyncCompletionWrapperForRequestID:requestID mechanism:mechanism completion:completion];\n                    task = ((id(*)(id, SEL, id, id))objc_msgSend)(slf, swizzledSelector, argument, completionWrapper);\n                    [self setRequestID:requestID forConnectionOrTask:task];\n                } else {\n                    task = ((id(*)(id, SEL, id, id))objc_msgSend)(slf, swizzledSelector, argument, completion);\n                }\n                return task;\n            };\n            \n            [FLEXUtility replaceImplementationOfKnownSelector:selector onClass:class withBlock:asyncDataOrDownloadSwizzleBlock swizzledSelector:swizzledSelector];\n        }\n    });\n}\n\n+ (void)injectIntoNSURLSessionAsyncUploadTaskMethods\n{\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        Class class = [NSURLSession class];\n\n        // The method signatures here are close enough that we can use the same logic to inject into both of them.\n        // Note that they have 3 arguments, so we can't easily combine with the data and download method above.\n        const SEL selectors[] = {\n            @selector(uploadTaskWithRequest:fromData:completionHandler:),\n            @selector(uploadTaskWithRequest:fromFile:completionHandler:)\n        };\n\n        const int numSelectors = sizeof(selectors) / sizeof(SEL);\n\n        for (int selectorIndex = 0; selectorIndex < numSelectors; selectorIndex++) {\n            SEL selector = selectors[selectorIndex];\n            SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n\n            if ([FLEXUtility instanceRespondsButDoesNotImplementSelector:selector class:class]) {\n                // iOS 7 does not implement these methods on NSURLSession. We actually want to\n                // swizzle __NSCFURLSession, which we can get from the class of the shared session\n                class = [[NSURLSession sharedSession] class];\n            }\n\n            NSURLSessionUploadTask *(^asyncUploadTaskSwizzleBlock)(Class, NSURLRequest *, id, NSURLSessionAsyncCompletion) = ^NSURLSessionUploadTask *(Class slf, NSURLRequest *request, id argument, NSURLSessionAsyncCompletion completion) {\n                NSURLSessionUploadTask *task = nil;\n                if ([FLEXNetworkObserver isEnabled] && completion) {\n                    NSString *requestID = [self nextRequestID];\n                    NSString *mechanism = [self mechanismFromClassMethod:selector onClass:class];\n                    NSURLSessionAsyncCompletion completionWrapper = [self asyncCompletionWrapperForRequestID:requestID mechanism:mechanism completion:completion];\n                    task = ((id(*)(id, SEL, id, id, id))objc_msgSend)(slf, swizzledSelector, request, argument, completionWrapper);\n                    [self setRequestID:requestID forConnectionOrTask:task];\n                } else {\n                    task = ((id(*)(id, SEL, id, id, id))objc_msgSend)(slf, swizzledSelector, request, argument, completion);\n                }\n                return task;\n            };\n            \n            [FLEXUtility replaceImplementationOfKnownSelector:selector onClass:class withBlock:asyncUploadTaskSwizzleBlock swizzledSelector:swizzledSelector];\n        }\n    });\n}\n\n+ (NSString *)mechanismFromClassMethod:(SEL)selector onClass:(Class)class\n{\n    return [NSString stringWithFormat:@\"+[%@ %@]\", NSStringFromClass(class), NSStringFromSelector(selector)];\n}\n\n+ (NSURLSessionAsyncCompletion)asyncCompletionWrapperForRequestID:(NSString *)requestID mechanism:(NSString *)mechanism completion:(NSURLSessionAsyncCompletion)completion\n{\n    NSURLSessionAsyncCompletion completionWrapper = ^(id fileURLOrData, NSURLResponse *response, NSError *error) {\n        [[FLEXNetworkRecorder defaultRecorder] recordMechanism:mechanism forRequestID:requestID];\n        [[FLEXNetworkRecorder defaultRecorder] recordResponseReceivedWithRequestID:requestID response:response];\n        NSData *data = nil;\n        if ([fileURLOrData isKindOfClass:[NSURL class]]) {\n            data = [NSData dataWithContentsOfURL:fileURLOrData];\n        } else if ([fileURLOrData isKindOfClass:[NSData class]]) {\n            data = fileURLOrData;\n        }\n        [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:[data length]];\n        if (error) {\n            [[FLEXNetworkRecorder defaultRecorder] recordLoadingFailedWithRequestID:requestID error:error];\n        } else {\n            [[FLEXNetworkRecorder defaultRecorder] recordLoadingFinishedWithRequestID:requestID responseBody:data];\n        }\n\n        // Call through to the original completion handler\n        if (completion) {\n            completion(fileURLOrData, response, error);\n        }\n    };\n    return completionWrapper;\n}\n\n+ (void)injectWillSendRequestIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(connection:willSendRequest:redirectResponse:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n    \n    Protocol *protocol = @protocol(NSURLConnectionDataDelegate);\n    if (!protocol) {\n        protocol = @protocol(NSURLConnectionDelegate);\n    }\n    \n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n    \n    typedef NSURLRequest *(^NSURLConnectionWillSendRequestBlock)(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSURLRequest *request, NSURLResponse *response);\n    \n    NSURLConnectionWillSendRequestBlock undefinedBlock = ^NSURLRequest *(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSURLRequest *request, NSURLResponse *response) {\n        [[FLEXNetworkObserver sharedObserver] connection:connection willSendRequest:request redirectResponse:response delegate:slf];\n        return request;\n    };\n    \n    NSURLConnectionWillSendRequestBlock implementationBlock = ^NSURLRequest *(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSURLRequest *request, NSURLResponse *response) {\n        __block NSURLRequest *returnValue = nil;\n        [self sniffWithoutDuplicationForObject:connection selector:selector sniffingBlock:^{\n            undefinedBlock(slf, connection, request, response);\n        } originalImplementationBlock:^{\n            returnValue = ((id(*)(id, SEL, id, id, id))objc_msgSend)(slf, swizzledSelector, connection, request, response);\n        }];\n        return returnValue;\n    };\n    \n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n}\n\n+ (void)injectDidReceiveResponseIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(connection:didReceiveResponse:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n    \n    Protocol *protocol = @protocol(NSURLConnectionDataDelegate);\n    if (!protocol) {\n        protocol = @protocol(NSURLConnectionDelegate);\n    }\n    \n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n    \n    typedef void (^NSURLConnectionDidReceiveResponseBlock)(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSURLResponse *response);\n    \n    NSURLConnectionDidReceiveResponseBlock undefinedBlock = ^(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSURLResponse *response) {\n        [[FLEXNetworkObserver sharedObserver] connection:connection didReceiveResponse:response delegate:slf];\n    };\n    \n    NSURLConnectionDidReceiveResponseBlock implementationBlock = ^(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSURLResponse *response) {\n        [self sniffWithoutDuplicationForObject:connection selector:selector sniffingBlock:^{\n            undefinedBlock(slf, connection, response);\n        } originalImplementationBlock:^{\n            ((void(*)(id, SEL, id, id))objc_msgSend)(slf, swizzledSelector, connection, response);\n        }];\n    };\n    \n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n}\n\n+ (void)injectDidReceiveDataIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(connection:didReceiveData:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n    \n    Protocol *protocol = @protocol(NSURLConnectionDataDelegate);\n    if (!protocol) {\n        protocol = @protocol(NSURLConnectionDelegate);\n    }\n    \n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n    \n    typedef void (^NSURLConnectionDidReceiveDataBlock)(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSData *data);\n    \n    NSURLConnectionDidReceiveDataBlock undefinedBlock = ^(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSData *data) {\n        [[FLEXNetworkObserver sharedObserver] connection:connection didReceiveData:data delegate:slf];\n    };\n    \n    NSURLConnectionDidReceiveDataBlock implementationBlock = ^(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSData *data) {\n        [self sniffWithoutDuplicationForObject:connection selector:selector sniffingBlock:^{\n            undefinedBlock(slf, connection, data);\n        } originalImplementationBlock:^{\n            ((void(*)(id, SEL, id, id))objc_msgSend)(slf, swizzledSelector, connection, data);\n        }];\n    };\n    \n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n}\n\n+ (void)injectDidFinishLoadingIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(connectionDidFinishLoading:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n    \n    Protocol *protocol = @protocol(NSURLConnectionDataDelegate);\n    if (!protocol) {\n        protocol = @protocol(NSURLConnectionDelegate);\n    }\n    \n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n    \n    typedef void (^NSURLConnectionDidFinishLoadingBlock)(id <NSURLConnectionDelegate> slf, NSURLConnection *connection);\n    \n    NSURLConnectionDidFinishLoadingBlock undefinedBlock = ^(id <NSURLConnectionDelegate> slf, NSURLConnection *connection) {\n        [[FLEXNetworkObserver sharedObserver] connectionDidFinishLoading:connection delegate:slf];\n    };\n    \n    NSURLConnectionDidFinishLoadingBlock implementationBlock = ^(id <NSURLConnectionDelegate> slf, NSURLConnection *connection) {\n        [self sniffWithoutDuplicationForObject:connection selector:selector sniffingBlock:^{\n            undefinedBlock(slf, connection);\n        } originalImplementationBlock:^{\n            ((void(*)(id, SEL, id))objc_msgSend)(slf, swizzledSelector, connection);\n        }];\n    };\n    \n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n}\n\n+ (void)injectDidFailWithErrorIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(connection:didFailWithError:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n    \n    Protocol *protocol = @protocol(NSURLConnectionDelegate);\n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n    \n    typedef void (^NSURLConnectionDidFailWithErrorBlock)(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSError *error);\n    \n    NSURLConnectionDidFailWithErrorBlock undefinedBlock = ^(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSError *error) {\n        [[FLEXNetworkObserver sharedObserver] connection:connection didFailWithError:error delegate:slf];\n    };\n    \n    NSURLConnectionDidFailWithErrorBlock implementationBlock = ^(id <NSURLConnectionDelegate> slf, NSURLConnection *connection, NSError *error) {\n        [self sniffWithoutDuplicationForObject:connection selector:selector sniffingBlock:^{\n            undefinedBlock(slf, connection, error);\n        } originalImplementationBlock:^{\n            ((void(*)(id, SEL, id, id))objc_msgSend)(slf, swizzledSelector, connection, error);\n        }];\n    };\n    \n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n}\n\n+ (void)injectTaskWillPerformHTTPRedirectionIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n\n    Protocol *protocol = @protocol(NSURLSessionTaskDelegate);\n\n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n    \n    typedef void (^NSURLSessionWillPerformHTTPRedirectionBlock)(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionTask *task, NSHTTPURLResponse *response, NSURLRequest *newRequest, void(^completionHandler)(NSURLRequest *));\n    \n    NSURLSessionWillPerformHTTPRedirectionBlock undefinedBlock = ^(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionTask *task, NSHTTPURLResponse *response, NSURLRequest *newRequest, void(^completionHandler)(NSURLRequest *)) {\n        [[FLEXNetworkObserver sharedObserver] URLSession:session task:task willPerformHTTPRedirection:response newRequest:newRequest completionHandler:completionHandler delegate:slf];\n        completionHandler(newRequest);\n    };\n\n    NSURLSessionWillPerformHTTPRedirectionBlock implementationBlock = ^(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionTask *task, NSHTTPURLResponse *response, NSURLRequest *newRequest, void(^completionHandler)(NSURLRequest *)) {\n        [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{\n            [[FLEXNetworkObserver sharedObserver] URLSession:session task:task willPerformHTTPRedirection:response newRequest:newRequest completionHandler:completionHandler delegate:slf];\n        } originalImplementationBlock:^{\n            ((id(*)(id, SEL, id, id, id, id, void(^)(NSURLRequest *)))objc_msgSend)(slf, swizzledSelector, session, task, response, newRequest, completionHandler);\n        }];\n    };\n\n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n\n}\n\n+ (void)injectTaskDidReceiveDataIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(URLSession:dataTask:didReceiveData:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n    \n    Protocol *protocol = @protocol(NSURLSessionDataDelegate);\n    \n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n    \n    typedef void (^NSURLSessionDidReceiveDataBlock)(id <NSURLSessionDataDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data);\n    \n    NSURLSessionDidReceiveDataBlock undefinedBlock = ^(id <NSURLSessionDataDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data) {\n        [[FLEXNetworkObserver sharedObserver] URLSession:session dataTask:dataTask didReceiveData:data delegate:slf];\n    };\n    \n    NSURLSessionDidReceiveDataBlock implementationBlock = ^(id <NSURLSessionDataDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data) {\n        [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{\n            undefinedBlock(slf, session, dataTask, data);\n        } originalImplementationBlock:^{\n            ((void(*)(id, SEL, id, id, id))objc_msgSend)(slf, swizzledSelector, session, dataTask, data);\n        }];\n    };\n    \n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n\n}\n\n+ (void)injectDataTaskDidBecomeDownloadTaskIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(URLSession:dataTask:didBecomeDownloadTask:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n\n    Protocol *protocol = @protocol(NSURLSessionDataDelegate);\n\n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n\n    typedef void (^NSURLSessionDidBecomeDownloadTaskBlock)(id <NSURLSessionDataDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask);\n\n    NSURLSessionDidBecomeDownloadTaskBlock undefinedBlock = ^(id <NSURLSessionDataDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask) {\n        [[FLEXNetworkObserver sharedObserver] URLSession:session dataTask:dataTask didBecomeDownloadTask:downloadTask delegate:slf];\n    };\n\n    NSURLSessionDidBecomeDownloadTaskBlock implementationBlock = ^(id <NSURLSessionDataDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask) {\n        [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{\n            undefinedBlock(slf, session, dataTask, downloadTask);\n        } originalImplementationBlock:^{\n            ((void(*)(id, SEL, id, id, id))objc_msgSend)(slf, swizzledSelector, session, dataTask, downloadTask);\n        }];\n    };\n\n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n}\n\n+ (void)injectTaskDidReceiveResponseIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(URLSession:dataTask:didReceiveResponse:completionHandler:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n    \n    Protocol *protocol = @protocol(NSURLSessionDataDelegate);\n    \n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n    \n    typedef void (^NSURLSessionDidReceiveResponseBlock)(id <NSURLSessionDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response, void(^completionHandler)(NSURLSessionResponseDisposition disposition));\n    \n    NSURLSessionDidReceiveResponseBlock undefinedBlock = ^(id <NSURLSessionDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response, void(^completionHandler)(NSURLSessionResponseDisposition disposition)) {\n        [[FLEXNetworkObserver sharedObserver] URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler delegate:slf];\n        completionHandler(NSURLSessionResponseAllow);\n    };\n    \n    NSURLSessionDidReceiveResponseBlock implementationBlock = ^(id <NSURLSessionDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response, void(^completionHandler)(NSURLSessionResponseDisposition disposition)) {\n        [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{\n            [[FLEXNetworkObserver sharedObserver] URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler delegate:slf];\n        } originalImplementationBlock:^{\n            ((void(*)(id, SEL, id, id, id, void(^)(NSURLSessionResponseDisposition)))objc_msgSend)(slf, swizzledSelector, session, dataTask, response, completionHandler);\n        }];\n    };\n    \n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n\n}\n\n+ (void)injectTaskDidCompleteWithErrorIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(URLSession:task:didCompleteWithError:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n    \n    Protocol *protocol = @protocol(NSURLSessionTaskDelegate);\n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n    \n    typedef void (^NSURLSessionTaskDidCompleteWithErrorBlock)(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionTask *task, NSError *error);\n\n    NSURLSessionTaskDidCompleteWithErrorBlock undefinedBlock = ^(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionTask *task, NSError *error) {\n        [[FLEXNetworkObserver sharedObserver] URLSession:session task:task didCompleteWithError:error delegate:slf];\n    };\n\n    NSURLSessionTaskDidCompleteWithErrorBlock implementationBlock = ^(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionTask *task, NSError *error) {\n        [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{\n            undefinedBlock(slf, session, task, error);\n        } originalImplementationBlock:^{\n            ((void(*)(id, SEL, id, id, id))objc_msgSend)(slf, swizzledSelector, session, task, error);\n        }];\n    };\n\n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n}\n\n// Used for overriding AFNetworking behavior\n+ (void)injectRespondsToSelectorIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(respondsToSelector:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n\n    //Protocol *protocol = @protocol(NSURLSessionTaskDelegate);\n    Method method = class_getInstanceMethod(cls, selector);\n    struct objc_method_description methodDescription = *method_getDescription(method);\n\n    BOOL (^undefinedBlock)(id <NSURLSessionTaskDelegate>, SEL) = ^(id slf, SEL sel) {\n        return YES;\n    };\n\n    BOOL (^implementationBlock)(id <NSURLSessionTaskDelegate>, SEL) = ^(id <NSURLSessionTaskDelegate> slf, SEL sel) {\n        if (sel == @selector(URLSession:dataTask:didReceiveResponse:completionHandler:)) {\n            return undefinedBlock(slf, sel);\n        }\n        return ((BOOL(*)(id, SEL, SEL))objc_msgSend)(slf, swizzledSelector, sel);\n    };\n\n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n}\n\n\n+ (void)injectDownloadTaskDidFinishDownloadingIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(URLSession:downloadTask:didFinishDownloadingToURL:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n\n    Protocol *protocol = @protocol(NSURLSessionDownloadDelegate);\n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n\n    typedef void (^NSURLSessionDownloadTaskDidFinishDownloadingBlock)(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionDownloadTask *task, NSURL *location);\n\n    NSURLSessionDownloadTaskDidFinishDownloadingBlock undefinedBlock = ^(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionDownloadTask *task, NSURL *location) {\n        NSData *data = [NSData dataWithContentsOfFile:location.relativePath];\n        [[FLEXNetworkObserver sharedObserver] URLSession:session task:task didFinishDownloadingToURL:location data:data delegate:slf];\n    };\n\n    NSURLSessionDownloadTaskDidFinishDownloadingBlock implementationBlock = ^(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionDownloadTask *task, NSURL *location) {\n        [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{\n            undefinedBlock(slf, session, task, location);\n        } originalImplementationBlock:^{\n            ((void(*)(id, SEL, id, id, id))objc_msgSend)(slf, swizzledSelector, session, task, location);\n        }];\n    };\n\n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n}\n\n+ (void)injectDownloadTaskDidWriteDataIntoDelegateClass:(Class)cls\n{\n    SEL selector = @selector(URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:);\n    SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];\n\n    Protocol *protocol = @protocol(NSURLSessionDownloadDelegate);\n    struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);\n\n    typedef void (^NSURLSessionDownloadTaskDidWriteDataBlock)(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionDownloadTask *task, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite);\n\n    NSURLSessionDownloadTaskDidWriteDataBlock undefinedBlock = ^(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionDownloadTask *task, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {\n        [[FLEXNetworkObserver sharedObserver] URLSession:session downloadTask:task didWriteData:bytesWritten totalBytesWritten:totalBytesWritten totalBytesExpectedToWrite:totalBytesExpectedToWrite delegate:slf];\n    };\n\n    NSURLSessionDownloadTaskDidWriteDataBlock implementationBlock = ^(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionDownloadTask *task, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {\n        [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{\n            undefinedBlock(slf, session, task, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);\n        } originalImplementationBlock:^{\n            ((void(*)(id, SEL, id, id, int64_t, int64_t, int64_t))objc_msgSend)(slf, swizzledSelector, session, task, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);\n        }];\n    };\n\n    [FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];\n\n}\n\nstatic char const * const kFLEXRequestIDKey = \"kFLEXRequestIDKey\";\n\n+ (NSString *)requestIDForConnectionOrTask:(id)connectionOrTask\n{\n    NSString *requestID = objc_getAssociatedObject(connectionOrTask, kFLEXRequestIDKey);\n    if (!requestID) {\n        requestID = [self nextRequestID];\n        [self setRequestID:requestID forConnectionOrTask:connectionOrTask];\n    }\n    return requestID;\n}\n\n+ (void)setRequestID:(NSString *)requestID forConnectionOrTask:(id)connectionOrTask\n{\n    objc_setAssociatedObject(connectionOrTask, kFLEXRequestIDKey, requestID, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n}\n\n#pragma mark - Initialization\n\n- (id)init\n{\n    self = [super init];\n    if (self) {\n        self.requestStatesForRequestIDs = [[NSMutableDictionary alloc] init];\n        self.queue = dispatch_queue_create(\"com.flex.FLEXNetworkObserver\", DISPATCH_QUEUE_SERIAL);\n    }\n    return self;\n}\n\n#pragma mark - Private Methods\n\n- (void)performBlock:(dispatch_block_t)block\n{\n    if ([[self class] isEnabled]) {\n        dispatch_async(_queue, block);\n    }\n}\n\n- (FLEXInternalRequestState *)requestStateForRequestID:(NSString *)requestID\n{\n    FLEXInternalRequestState *requestState = self.requestStatesForRequestIDs[requestID];\n    if (!requestState) {\n        requestState = [[FLEXInternalRequestState alloc] init];\n        [self.requestStatesForRequestIDs setObject:requestState forKey:requestID];\n    }\n    return requestState;\n}\n\n- (void)removeRequestStateForRequestID:(NSString *)requestID\n{\n    [self.requestStatesForRequestIDs removeObjectForKey:requestID];\n}\n\n@end\n\n\n@implementation FLEXNetworkObserver (NSURLConnectionHelpers)\n\n- (void)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response delegate:(id<NSURLConnectionDelegate>)delegate\n{\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:connection];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n        requestState.request = request;\n        [[FLEXNetworkRecorder defaultRecorder] recordRequestWillBeSentWithRequestID:requestID request:request redirectResponse:response];\n        NSString *mechanism = [NSString stringWithFormat:@\"NSURLConnection (delegate: %@)\", [delegate class]];\n        [[FLEXNetworkRecorder defaultRecorder] recordMechanism:mechanism forRequestID:requestID];\n    }];\n}\n\n- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response delegate:(id<NSURLConnectionDelegate>)delegate\n{\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:connection];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n\n        NSMutableData *dataAccumulator = nil;\n        if (response.expectedContentLength < 0) {\n            dataAccumulator = [[NSMutableData alloc] init];\n        } else if (response.expectedContentLength < 52428800) {\n            dataAccumulator = [[NSMutableData alloc] initWithCapacity:(NSUInteger)response.expectedContentLength];\n        }\n        requestState.dataAccumulator = dataAccumulator;\n\n        [[FLEXNetworkRecorder defaultRecorder] recordResponseReceivedWithRequestID:requestID response:response];\n    }];\n}\n\n- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data delegate:(id<NSURLConnectionDelegate>)delegate\n{\n    // Just to be safe since we're doing this async\n    data = [data copy];\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:connection];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n        [requestState.dataAccumulator appendData:data];\n        [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:data.length];\n    }];\n}\n\n- (void)connectionDidFinishLoading:(NSURLConnection *)connection delegate:(id<NSURLConnectionDelegate>)delegate\n{\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:connection];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n        [[FLEXNetworkRecorder defaultRecorder] recordLoadingFinishedWithRequestID:requestID responseBody:requestState.dataAccumulator];\n        [self removeRequestStateForRequestID:requestID];\n    }];\n}\n\n- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error delegate:(id<NSURLConnectionDelegate>)delegate\n{\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:connection];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n\n        // Cancellations can occur prior to the willSendRequest:... NSURLConnection delegate call.\n        // These are pretty common and clutter up the logs. Only record the failure if the recorder already knows about the request through willSendRequest:...\n        if (requestState.request) {\n            [[FLEXNetworkRecorder defaultRecorder] recordLoadingFailedWithRequestID:requestID error:error];\n        }\n        \n        [self removeRequestStateForRequestID:requestID];\n    }];\n}\n\n- (void)connectionWillCancel:(NSURLConnection *)connection\n{\n    [self performBlock:^{\n        // Mimic the behavior of NSURLSession which is to create an error on cancellation.\n        NSDictionary<NSString *, id> *userInfo = @{ NSLocalizedDescriptionKey : @\"cancelled\" };\n        NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:userInfo];\n        [self connection:connection didFailWithError:error delegate:nil];\n    }];\n}\n\n@end\n\n\n@implementation FLEXNetworkObserver (NSURLSessionTaskHelpers)\n\n- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler delegate:(id<NSURLSessionDelegate>)delegate\n{\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:task];\n        [[FLEXNetworkRecorder defaultRecorder] recordRequestWillBeSentWithRequestID:requestID request:request redirectResponse:response];\n    }];\n}\n\n- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler delegate:(id<NSURLSessionDelegate>)delegate\n{\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:dataTask];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n\n        NSMutableData *dataAccumulator = nil;\n        if (response.expectedContentLength < 0) {\n            dataAccumulator = [[NSMutableData alloc] init];\n        } else {\n            dataAccumulator = [[NSMutableData alloc] initWithCapacity:(NSUInteger)response.expectedContentLength];\n        }\n        requestState.dataAccumulator = dataAccumulator;\n\n        NSString *requestMechanism = [NSString stringWithFormat:@\"NSURLSessionDataTask (delegate: %@)\", [delegate class]];\n        [[FLEXNetworkRecorder defaultRecorder] recordMechanism:requestMechanism forRequestID:requestID];\n\n        [[FLEXNetworkRecorder defaultRecorder] recordResponseReceivedWithRequestID:requestID response:response];\n    }];\n}\n\n- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id<NSURLSessionDelegate>)delegate\n{\n    [self performBlock:^{\n        // By setting the request ID of the download task to match the data task,\n        // it can pick up where the data task left off.\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:dataTask];\n        [[self class] setRequestID:requestID forConnectionOrTask:downloadTask];\n    }];\n}\n\n- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data delegate:(id<NSURLSessionDelegate>)delegate\n{\n    // Just to be safe since we're doing this async\n    data = [data copy];\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:dataTask];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n\n        [requestState.dataAccumulator appendData:data];\n\n        [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:data.length];\n    }];\n}\n\n- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error delegate:(id<NSURLSessionDelegate>)delegate\n{\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:task];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n\n        if (error) {\n            [[FLEXNetworkRecorder defaultRecorder] recordLoadingFailedWithRequestID:requestID error:error];\n        } else {\n            [[FLEXNetworkRecorder defaultRecorder] recordLoadingFinishedWithRequestID:requestID responseBody:requestState.dataAccumulator];\n        }\n\n        [self removeRequestStateForRequestID:requestID];\n    }];\n}\n\n- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite delegate:(id<NSURLSessionDelegate>)delegate\n{\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:downloadTask];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n\n        if (!requestState.dataAccumulator) {\n            NSUInteger unsignedBytesExpectedToWrite = totalBytesExpectedToWrite > 0 ? (NSUInteger)totalBytesExpectedToWrite : 0;\n            requestState.dataAccumulator = [[NSMutableData alloc] initWithCapacity:unsignedBytesExpectedToWrite];\n            [[FLEXNetworkRecorder defaultRecorder] recordResponseReceivedWithRequestID:requestID response:downloadTask.response];\n\n            NSString *requestMechanism = [NSString stringWithFormat:@\"NSURLSessionDownloadTask (delegate: %@)\", [delegate class]];\n            [[FLEXNetworkRecorder defaultRecorder] recordMechanism:requestMechanism forRequestID:requestID];\n        }\n\n        [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:bytesWritten];\n    }];\n}\n\n- (void)URLSession:(NSURLSession *)session task:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location data:(NSData *)data delegate:(id<NSURLSessionDelegate>)delegate\n{\n    data = [data copy];\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:downloadTask];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n        [requestState.dataAccumulator appendData:data];\n    }];\n}\n\n- (void)URLSessionTaskWillResume:(NSURLSessionTask *)task\n{\n    // Since resume can be called multiple times on the same task, only treat the first resume as\n    // the equivalent to connection:willSendRequest:...\n    [self performBlock:^{\n        NSString *requestID = [[self class] requestIDForConnectionOrTask:task];\n        FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];\n        if (!requestState.request) {\n            requestState.request = task.currentRequest;\n\n            [[FLEXNetworkRecorder defaultRecorder] recordRequestWillBeSentWithRequestID:requestID request:task.currentRequest redirectResponse:nil];\n        }\n    }];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Network/PonyDebugger/LICENSE",
    "content": "\nPonyDebugger\nCopyright 2012 Square Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXArrayExplorerViewController.h",
    "content": "//\n//  FLEXArrayExplorerViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/15/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerViewController.h\"\n\n@interface FLEXArrayExplorerViewController : FLEXObjectExplorerViewController\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXArrayExplorerViewController.m",
    "content": "//\n//  FLEXArrayExplorerViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/15/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXArrayExplorerViewController.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n\n@interface FLEXArrayExplorerViewController ()\n\n@property (nonatomic, readonly) NSArray *array;\n\n@end\n\n@implementation FLEXArrayExplorerViewController\n\n- (NSArray *)array\n{\n    return [self.object isKindOfClass:[NSArray class]] ? self.object : nil;\n}\n\n\n#pragma mark - Superclass Overrides\n\n- (NSString *)customSectionTitle\n{\n    return @\"Array Indices\";\n}\n\n- (NSArray *)customSectionRowCookies\n{\n    // Use index numbers as the row cookies\n    NSMutableArray *cookies = [NSMutableArray arrayWithCapacity:[self.array count]];\n    for (NSUInteger i = 0; i < [self.array count]; i++) {\n        [cookies addObject:@(i)];\n    }\n    return cookies;\n}\n\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie\n{\n    return [rowCookie description];\n}\n\n- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie\n{\n    return [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:[self detailObjectForRowCookie:rowCookie]];\n}\n\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie\n{\n    return YES;\n}\n\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie\n{\n    return [FLEXObjectExplorerFactory explorerViewControllerForObject:[self detailObjectForRowCookie:rowCookie]];\n}\n\n- (BOOL)shouldShowDescription\n{\n    return NO;\n}\n\n\n#pragma mark - Helpers\n\n- (id)detailObjectForRowCookie:(id)rowCookie\n{\n    NSUInteger index = [rowCookie unsignedIntegerValue];\n    return self.array[index];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXClassExplorerViewController.h",
    "content": "//\n//  FLEXClassExplorerViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/18/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerViewController.h\"\n\n@interface FLEXClassExplorerViewController : FLEXObjectExplorerViewController\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXClassExplorerViewController.m",
    "content": "//\n//  FLEXClassExplorerViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/18/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXClassExplorerViewController.h\"\n#import \"FLEXMethodCallingViewController.h\"\n#import \"FLEXInstancesTableViewController.h\"\n\ntypedef NS_ENUM(NSUInteger, FLEXClassExplorerRow) {\n    FLEXClassExplorerRowNew,\n    FLEXClassExplorerRowAlloc,\n    FLEXClassExplorerRowLiveInstances\n};\n\n@interface FLEXClassExplorerViewController ()\n\n@property (nonatomic, readonly) Class theClass;\n\n@end\n\n@implementation FLEXClassExplorerViewController\n\n- (Class)theClass\n{\n    Class theClass = Nil;\n    if (class_isMetaClass(object_getClass(self.object))) {\n        theClass = self.object;\n    }\n    return theClass;\n}\n\n#pragma mark - Superclass Overrides\n\n- (NSArray<NSNumber *> *)possibleExplorerSections\n{\n    // Move class methods to between our custom section and the properties section since\n    // we are more interested in the class sections than in the instance level sections.\n    NSMutableArray<NSNumber *> *mutableSections = [[super possibleExplorerSections] mutableCopy];\n    [mutableSections removeObject:@(FLEXObjectExplorerSectionClassMethods)];\n    [mutableSections insertObject:@(FLEXObjectExplorerSectionClassMethods) atIndex:[mutableSections indexOfObject:@(FLEXObjectExplorerSectionProperties)]];\n    return mutableSections;\n}\n\n- (NSString *)customSectionTitle\n{\n    return @\"Shortcuts\";\n}\n\n- (NSArray *)customSectionRowCookies\n{\n    NSMutableArray *cookies = [NSMutableArray array];\n    if ([self.theClass respondsToSelector:@selector(new)]) {\n        [cookies addObject:@(FLEXClassExplorerRowNew)];\n    }\n    if ([self.theClass respondsToSelector:@selector(alloc)]) {\n        [cookies addObject:@(FLEXClassExplorerRowAlloc)];\n    }\n    [cookies addObject:@(FLEXClassExplorerRowLiveInstances)];\n    return cookies;\n}\n\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie\n{\n    NSString *title = nil;\n    FLEXClassExplorerRow row = [rowCookie unsignedIntegerValue];\n    switch (row) {\n        case FLEXClassExplorerRowNew:\n            title = @\"+ (id)new\";\n            break;\n            \n        case FLEXClassExplorerRowAlloc:\n            title = @\"+ (id)alloc\";\n            break;\n            \n        case FLEXClassExplorerRowLiveInstances:\n            title = @\"Live Instances\";\n            break;\n    }\n    return title;\n}\n\n- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie\n{\n    return nil;\n}\n\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie\n{\n    return YES;\n}\n\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie\n{\n    UIViewController *drillInViewController = nil;\n    FLEXClassExplorerRow row = [rowCookie unsignedIntegerValue];\n    switch (row) {\n        case FLEXClassExplorerRowNew:\n            drillInViewController = [[FLEXMethodCallingViewController alloc] initWithTarget:self.theClass method:class_getClassMethod(self.theClass, @selector(new))];\n            break;\n            \n        case FLEXClassExplorerRowAlloc:\n            drillInViewController = [[FLEXMethodCallingViewController alloc] initWithTarget:self.theClass method:class_getClassMethod(self.theClass, @selector(alloc))];\n            break;\n            \n        case FLEXClassExplorerRowLiveInstances:\n            drillInViewController = [FLEXInstancesTableViewController instancesTableViewControllerForClassName:NSStringFromClass(self.theClass)];\n            break;\n    }\n    return drillInViewController;\n}\n\n- (BOOL)shouldShowDescription\n{\n    // Redundant with our title.\n    return NO;\n}\n\n- (BOOL)canCallInstanceMethods\n{\n    return NO;\n}\n\n- (BOOL)canHaveInstanceState\n{\n    return NO;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXDefaultsExplorerViewController.h",
    "content": "//\n//  FLEXDefaultsExplorerViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/23/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerViewController.h\"\n\n@interface FLEXDefaultsExplorerViewController : FLEXObjectExplorerViewController\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXDefaultsExplorerViewController.m",
    "content": "//\n//  FLEXDefaultsExplorerViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/23/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXDefaultsExplorerViewController.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXDefaultEditorViewController.h\"\n\n@interface FLEXDefaultsExplorerViewController ()\n\n@property (nonatomic, readonly) NSUserDefaults *defaults;\n\n@end\n\n@implementation FLEXDefaultsExplorerViewController\n\n- (NSUserDefaults *)defaults\n{\n    return [self.object isKindOfClass:[NSUserDefaults class]] ? self.object : nil;\n}\n\n\n#pragma mark - Superclass Overrides\n\n- (NSString *)customSectionTitle\n{\n    return @\"Defaults\";\n}\n\n- (NSArray *)customSectionRowCookies\n{\n    return [[[self.defaults dictionaryRepresentation] allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];\n}\n\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie\n{\n    return rowCookie;\n}\n\n- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie\n{\n    return [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:[self.defaults objectForKey:rowCookie]];\n}\n\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie\n{\n    return YES;\n}\n\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie\n{\n    UIViewController *drillInViewController = nil;\n    NSString *key = rowCookie;\n    id drillInObject = [self.defaults objectForKey:key];\n    if ([FLEXDefaultEditorViewController canEditDefaultWithValue:drillInObject]) {\n        drillInViewController = [[FLEXDefaultEditorViewController alloc] initWithDefaults:self.defaults key:key];\n    } else {\n        drillInViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:drillInObject];\n    }\n    return drillInViewController;\n}\n\n- (BOOL)shouldShowDescription\n{\n    return NO;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXDictionaryExplorerViewController.h",
    "content": "//\n//  FLEXDictionaryExplorerViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerViewController.h\"\n\n@interface FLEXDictionaryExplorerViewController : FLEXObjectExplorerViewController\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXDictionaryExplorerViewController.m",
    "content": "//\n//  FLEXDictionaryExplorerViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXDictionaryExplorerViewController.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n\n@interface FLEXDictionaryExplorerViewController ()\n\n@property (nonatomic, readonly) NSDictionary *dictionary;\n\n@end\n\n@implementation FLEXDictionaryExplorerViewController\n\n- (NSDictionary *)dictionary\n{\n    return [self.object isKindOfClass:[NSDictionary class]] ? self.object : nil;\n}\n\n\n#pragma mark - Superclass Overrides\n\n- (NSString *)customSectionTitle\n{\n    return @\"Dictionary Objects\";\n}\n\n- (NSArray *)customSectionRowCookies\n{\n    return [self.dictionary allKeys];\n}\n\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie\n{\n    return [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:rowCookie];\n}\n\n- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie\n{\n    return [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:self.dictionary[rowCookie]];\n}\n\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie\n{\n    return YES;\n}\n\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie\n{\n    return [FLEXObjectExplorerFactory explorerViewControllerForObject:self.dictionary[rowCookie]];\n}\n\n- (BOOL)shouldShowDescription\n{\n    return NO;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXGlobalsTableViewControllerEntry.h",
    "content": "//\n//  FLEXGlobalsTableViewControllerEntry.h\n//  UICatalog\n//\n//  Created by Javier Soto on 7/26/14.\n//  Copyright (c) 2014 f. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n\ntypedef NSString *(^FLEXGlobalsTableViewControllerEntryNameFuture)(void);\ntypedef UIViewController *(^FLEXGlobalsTableViewControllerViewControllerFuture)(void);\n\n@interface FLEXGlobalsTableViewControllerEntry : NSObject\n\n@property (nonatomic, readonly, copy) FLEXGlobalsTableViewControllerEntryNameFuture entryNameFuture;\n@property (nonatomic, readonly, copy) FLEXGlobalsTableViewControllerViewControllerFuture viewControllerFuture;\n\n+ (instancetype)entryWithNameFuture:(FLEXGlobalsTableViewControllerEntryNameFuture)nameFuture viewControllerFuture:(FLEXGlobalsTableViewControllerViewControllerFuture)viewControllerFuture;\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXGlobalsTableViewControllerEntry.m",
    "content": "//\n//  FLEXGlobalsTableViewControllerEntry.m\n//  UICatalog\n//\n//  Created by Javier Soto on 7/26/14.\n//  Copyright (c) 2014 f. All rights reserved.\n//\n\n#import \"FLEXGlobalsTableViewControllerEntry.h\"\n\n@implementation FLEXGlobalsTableViewControllerEntry\n\n+ (instancetype)entryWithNameFuture:(FLEXGlobalsTableViewControllerEntryNameFuture)nameFuture viewControllerFuture:(FLEXGlobalsTableViewControllerViewControllerFuture)viewControllerFuture\n{\n    NSParameterAssert(nameFuture);\n    NSParameterAssert(viewControllerFuture);\n\n    FLEXGlobalsTableViewControllerEntry *entry = [[self alloc] init];\n    entry->_entryNameFuture = [nameFuture copy];\n    entry->_viewControllerFuture = [viewControllerFuture copy];\n\n    return entry;\n}\n\n@end"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXImageExplorerViewController.h",
    "content": "//\n//  FLEXImageExplorerViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/12/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerViewController.h\"\n\n@interface FLEXImageExplorerViewController : FLEXObjectExplorerViewController\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXImageExplorerViewController.m",
    "content": "//\n//  FLEXImageExplorerViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/12/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXImageExplorerViewController.h\"\n#import \"FLEXImagePreviewViewController.h\"\n\ntypedef NS_ENUM(NSUInteger, FLEXImageExplorerRow) {\n    FLEXImageExplorerRowImage\n};\n\n@interface FLEXImageExplorerViewController ()\n\n@property (nonatomic, readonly) UIImage *image;\n\n@end\n\n@implementation FLEXImageExplorerViewController\n\n- (UIImage *)image\n{\n    return [self.object isKindOfClass:[UIImage class]] ? self.object : nil;\n}\n\n#pragma mark - Superclass Overrides\n\n- (NSString *)customSectionTitle\n{\n    return @\"Shortcuts\";\n}\n\n- (NSArray *)customSectionRowCookies\n{\n    return @[@(FLEXImageExplorerRowImage)];\n}\n\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie\n{\n    NSString *title = nil;\n    if ([rowCookie isEqual:@(FLEXImageExplorerRowImage)]) {\n        title = @\"Show Image\";\n    }\n    return title;\n}\n\n- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie\n{\n    return nil;\n}\n\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie\n{\n    return YES;\n}\n\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie\n{\n    UIViewController *drillInViewController = nil;\n    if ([rowCookie isEqual:@(FLEXImageExplorerRowImage)]) {\n        drillInViewController = [[FLEXImagePreviewViewController alloc] initWithImage:self.image];\n    }\n    return drillInViewController;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXLayerExplorerViewController.h",
    "content": "//\n//  FLEXLayerExplorerViewController.h\n//  UICatalog\n//\n//  Created by Ryan Olson on 12/14/14.\n//  Copyright (c) 2014 f. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerViewController.h\"\n\n@interface FLEXLayerExplorerViewController : FLEXObjectExplorerViewController\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXLayerExplorerViewController.m",
    "content": "//\n//  FLEXLayerExplorerViewController.m\n//  UICatalog\n//\n//  Created by Ryan Olson on 12/14/14.\n//  Copyright (c) 2014 f. All rights reserved.\n//\n\n#import \"FLEXLayerExplorerViewController.h\"\n#import \"FLEXImagePreviewViewController.h\"\n\ntypedef NS_ENUM(NSUInteger, FLEXLayerExplorerRow) {\n    FLEXLayerExplorerRowPreview\n};\n\n@interface FLEXLayerExplorerViewController ()\n\n@property (nonatomic, readonly) CALayer *layerToExplore;\n\n@end\n\n@implementation FLEXLayerExplorerViewController\n\n- (CALayer *)layerToExplore\n{\n    return [self.object isKindOfClass:[CALayer class]] ? self.object : nil;\n}\n\n#pragma mark - Superclass Overrides\n\n- (NSString *)customSectionTitle\n{\n    return @\"Shortcuts\";\n}\n\n- (NSArray *)customSectionRowCookies\n{\n    return @[@(FLEXLayerExplorerRowPreview)];\n}\n\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie\n{\n    NSString *title = nil;\n\n    if ([rowCookie isKindOfClass:[NSNumber class]]) {\n        FLEXLayerExplorerRow row = [rowCookie unsignedIntegerValue];\n        switch (row) {\n            case FLEXLayerExplorerRowPreview:\n                title = @\"Preview Image\";\n                break;\n        }\n    }\n\n    return title;\n}\n\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie\n{\n    return YES;\n}\n\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie\n{\n    UIViewController *drillInViewController = nil;\n\n    if ([rowCookie isKindOfClass:[NSNumber class]]) {\n        FLEXLayerExplorerRow row = [rowCookie unsignedIntegerValue];\n        switch (row) {\n            case FLEXLayerExplorerRowPreview:\n                drillInViewController = [[self class] imagePreviewViewControllerForLayer:self.layerToExplore];\n                break;\n        }\n    }\n\n    return drillInViewController;\n}\n\n+ (UIViewController *)imagePreviewViewControllerForLayer:(CALayer *)layer\n{\n    UIViewController *imagePreviewViewController = nil;\n    if (!CGRectIsEmpty(layer.bounds)) {\n        UIGraphicsBeginImageContextWithOptions(layer.bounds.size, NO, 0.0);\n        CGContextRef imageContext = UIGraphicsGetCurrentContext();\n        [layer renderInContext:imageContext];\n        UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext();\n        UIGraphicsEndImageContext();\n        imagePreviewViewController = [[FLEXImagePreviewViewController alloc] initWithImage:previewImage];\n    }\n    return imagePreviewViewController;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXObjectExplorerFactory.h",
    "content": "//\n//  FLEXObjectExplorerFactory.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/15/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@class FLEXObjectExplorerViewController;\n\n@interface FLEXObjectExplorerFactory : NSObject\n\n+ (FLEXObjectExplorerViewController *)explorerViewControllerForObject:(id)object;\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXObjectExplorerFactory.m",
    "content": "//\n//  FLEXObjectExplorerFactory.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/15/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXObjectExplorerViewController.h\"\n#import \"FLEXArrayExplorerViewController.h\"\n#import \"FLEXSetExplorerViewController.h\"\n#import \"FLEXDictionaryExplorerViewController.h\"\n#import \"FLEXDefaultsExplorerViewController.h\"\n#import \"FLEXViewControllerExplorerViewController.h\"\n#import \"FLEXViewExplorerViewController.h\"\n#import \"FLEXImageExplorerViewController.h\"\n#import \"FLEXClassExplorerViewController.h\"\n#import \"FLEXLayerExplorerViewController.h\"\n#import <objc/runtime.h>\n\n@implementation FLEXObjectExplorerFactory\n\n+ (FLEXObjectExplorerViewController *)explorerViewControllerForObject:(id)object\n{\n    // Bail for nil object. We can't explore nil.\n    if (!object) {\n        return nil;\n    }\n    \n    static NSDictionary<NSString *, Class> *explorerSubclassesForObjectTypeStrings = nil;\n    static dispatch_once_t once;\n    dispatch_once(&once, ^{\n        explorerSubclassesForObjectTypeStrings = @{NSStringFromClass([NSArray class])          : [FLEXArrayExplorerViewController class],\n                                                   NSStringFromClass([NSSet class])            : [FLEXSetExplorerViewController class],\n                                                   NSStringFromClass([NSDictionary class])     : [FLEXDictionaryExplorerViewController class],\n                                                   NSStringFromClass([NSUserDefaults class])   : [FLEXDefaultsExplorerViewController class],\n                                                   NSStringFromClass([UIViewController class]) : [FLEXViewControllerExplorerViewController class],\n                                                   NSStringFromClass([UIView class])           : [FLEXViewExplorerViewController class],\n                                                   NSStringFromClass([UIImage class])          : [FLEXImageExplorerViewController class],\n                                                   NSStringFromClass([CALayer class])          : [FLEXLayerExplorerViewController class]};\n    });\n    \n    Class explorerClass = nil;\n    BOOL objectIsClass = class_isMetaClass(object_getClass(object));\n    if (objectIsClass) {\n        explorerClass = [FLEXClassExplorerViewController class];\n    } else {\n        explorerClass = [FLEXObjectExplorerViewController class];\n        for (NSString *objectTypeString in explorerSubclassesForObjectTypeStrings) {\n            Class objectClass = NSClassFromString(objectTypeString);\n            if ([object isKindOfClass:objectClass]) {\n                explorerClass = explorerSubclassesForObjectTypeStrings[objectTypeString];\n                break;\n            }\n        }\n    }\n    \n    FLEXObjectExplorerViewController *explorerViewController = [[explorerClass alloc] init];\n    explorerViewController.object = object;\n    \n    return explorerViewController;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXObjectExplorerViewController.h",
    "content": "//\n//  FLEXObjectExplorerViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-03.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\ntypedef NS_ENUM(NSUInteger, FLEXObjectExplorerSection) {\n    FLEXObjectExplorerSectionDescription,\n    FLEXObjectExplorerSectionCustom,\n    FLEXObjectExplorerSectionProperties,\n    FLEXObjectExplorerSectionIvars,\n    FLEXObjectExplorerSectionMethods,\n    FLEXObjectExplorerSectionClassMethods,\n    FLEXObjectExplorerSectionSuperclasses,\n    FLEXObjectExplorerSectionReferencingInstances\n};\n\n@interface FLEXObjectExplorerViewController : UITableViewController\n\n@property (nonatomic, strong) id object;\n\n// Sublasses can override the methods below to provide data in a custom section.\n// The subclass should provide an array of \"row cookies\" to allow retreival of individual row data later on.\n// The objects in the rowCookies array will be used to call the row title, subtitle, etc methods to consturct the rows.\n// The cookies approach is used here because we may filter the visible rows based on the search text entered by the user.\n- (NSString *)customSectionTitle;\n- (NSArray *)customSectionRowCookies;\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie;\n- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie;\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie;\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie;\n\n// More subclass configuration hooks.\n\n/// Whether to allow showing/drilling in to current values for ivars and properties. Defalut is YES.\n- (BOOL)canHaveInstanceState;\n\n/// Whether to allow drilling in to method calling interfaces for instance methods. Default is YES.\n- (BOOL)canCallInstanceMethods;\n\n/// If the custom section data makes the description redundant, subclasses can choose to hide it. Default is YES.\n- (BOOL)shouldShowDescription;\n\n/// Subclasses can reorder/change which sections can display directly by overriding this method.\n- (NSArray *)possibleExplorerSections;\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXObjectExplorerViewController.m",
    "content": "//\n//  FLEXObjectExplorerViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-03.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerViewController.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXMultilineTableViewCell.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXPropertyEditorViewController.h\"\n#import \"FLEXIvarEditorViewController.h\"\n#import \"FLEXMethodCallingViewController.h\"\n#import \"FLEXInstancesTableViewController.h\"\n#import <objc/runtime.h>\n\ntypedef NS_ENUM(NSUInteger, FLEXObjectExplorerScope) {\n    FLEXObjectExplorerScopeNoInheritance,\n    FLEXObjectExplorerScopeWithParent,\n    FLEXObjectExplorerScopeAllButNSObject,\n    FLEXObjectExplorerScopeNSObjectOnly\n};\n\ntypedef NS_ENUM(NSUInteger, FLEXMetadataKind) {\n    FLEXMetadataKindProperties,\n    FLEXMetadataKindIvars,\n    FLEXMetadataKindMethods,\n    FLEXMetadataKindClassMethods\n};\n\n// Convenience boxes to keep runtime properties, ivars, and methods in foundation collections.\n@interface FLEXPropertyBox : NSObject\n@property (nonatomic, assign) objc_property_t property;\n@end\n@implementation FLEXPropertyBox\n@end\n\n@interface FLEXIvarBox : NSObject\n@property (nonatomic, assign) Ivar ivar;\n@end\n@implementation FLEXIvarBox\n@end\n\n@interface FLEXMethodBox : NSObject\n@property (nonatomic, assign) Method method;\n@end\n@implementation FLEXMethodBox\n@end\n\n@interface FLEXObjectExplorerViewController () <UISearchBarDelegate>\n\n@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *properties;\n@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *propertiesWithParent;\n@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *inheritedProperties;\n@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *NSObjectProperties;\n@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *filteredProperties;\n\n@property (nonatomic, strong) NSArray<FLEXIvarBox *> *ivars;\n@property (nonatomic, strong) NSArray<FLEXIvarBox *> *ivarsWithParent;\n@property (nonatomic, strong) NSArray<FLEXIvarBox *> *inheritedIvars;\n@property (nonatomic, strong) NSArray<FLEXIvarBox *> *NSObjectIvars;\n@property (nonatomic, strong) NSArray<FLEXIvarBox *> *filteredIvars;\n\n@property (nonatomic, strong) NSArray<FLEXMethodBox *> *methods;\n@property (nonatomic, strong) NSArray<FLEXMethodBox *> *methodsWithParent;\n@property (nonatomic, strong) NSArray<FLEXMethodBox *> *inheritedMethods;\n@property (nonatomic, strong) NSArray<FLEXMethodBox *> *NSObjectMethods;\n@property (nonatomic, strong) NSArray<FLEXMethodBox *> *filteredMethods;\n\n@property (nonatomic, strong) NSArray<FLEXMethodBox *> *classMethods;\n@property (nonatomic, strong) NSArray<FLEXMethodBox *> *classMethodsWithParent;\n@property (nonatomic, strong) NSArray<FLEXMethodBox *> *inheritedClassMethods;\n@property (nonatomic, strong) NSArray<FLEXMethodBox *> *NSObjectClassMethods;\n@property (nonatomic, strong) NSArray<FLEXMethodBox *> *filteredClassMethods;\n\n@property (nonatomic, strong) NSArray<Class> *superclasses;\n@property (nonatomic, strong) NSArray<Class> *filteredSuperclasses;\n\n@property (nonatomic, strong) NSArray *cachedCustomSectionRowCookies;\n@property (nonatomic, strong) NSIndexSet *customSectionVisibleIndexes;\n\n@property (nonatomic, strong) UISearchBar *searchBar;\n@property (nonatomic, strong) NSString *filterText;\n@property (nonatomic, assign) FLEXObjectExplorerScope scope;\n\n@end\n\n@implementation FLEXObjectExplorerViewController\n\n- (id)initWithStyle:(UITableViewStyle)style\n{\n    // Force grouped style\n    return [super initWithStyle:UITableViewStyleGrouped];\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.searchBar = [[UISearchBar alloc] init];\n    self.searchBar.placeholder = [FLEXUtility searchBarPlaceholderText];\n    self.searchBar.delegate = self;\n    self.searchBar.showsScopeBar = YES;\n    [self refreshScopeTitles];\n    self.tableView.tableHeaderView = self.searchBar;\n    \n    self.refreshControl = [[UIRefreshControl alloc] init];\n    [self.refreshControl addTarget:self action:@selector(refreshControlDidRefresh:) forControlEvents:UIControlEventValueChanged];\n}\n\n- (void)viewWillAppear:(BOOL)animated\n{\n    [super viewWillAppear:animated];\n    \n    // Reload the entire table view rather than just the visible cells because the filtered rows\n    // may have changed (i.e. a change in the description row that causes it to get filtered out).\n    [self updateTableData];\n}\n\n- (void)scrollViewDidScroll:(UIScrollView *)scrollView\n{\n    [self.searchBar endEditing:YES];\n}\n\n- (void)refreshControlDidRefresh:(id)sender\n{\n    [self updateTableData];\n    [self.refreshControl endRefreshing];\n}\n\n\n#pragma mark - Search\n\n- (void)refreshScopeTitles {\n    if (!self.searchBar) return;\n\n    Class parent = [self.object superclass];\n    Class parentSuper = [parent superclass];\n\n    NSMutableArray *scopes = [NSMutableArray arrayWithObject:@\"Base\"];\n    if (parent) {\n        [scopes addObject:@\"+ Parent\"];\n    }\n    if (parentSuper && parentSuper != [NSObject class]) {\n        [scopes addObject:@\"+ Inherited\"];\n    }\n    if ([self.object isKindOfClass:[NSObject class]]) {\n        [scopes addObject:@\"NSObject\"];\n    }\n\n    self.searchBar.scopeButtonTitles = scopes;\n    [self.searchBar sizeToFit];\n    [self updateTableData];\n}\n\n- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText\n{\n    self.filterText = searchText;\n}\n\n- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar\n{\n    [searchBar resignFirstResponder];\n}\n\n- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope\n{\n    self.scope = selectedScope;\n    [self updateDisplayedData];\n}\n\n- (NSArray *)metadata:(FLEXMetadataKind)metadataKind forScope:(FLEXObjectExplorerScope)scope {\n    switch (metadataKind) {\n        case FLEXMetadataKindProperties:\n            switch (self.scope) {\n                case FLEXObjectExplorerScopeNoInheritance:\n                    return self.properties;\n                case FLEXObjectExplorerScopeWithParent:\n                    return self.propertiesWithParent;\n                case FLEXObjectExplorerScopeAllButNSObject:\n                    return self.inheritedProperties;\n                case FLEXObjectExplorerScopeNSObjectOnly:\n                    return self.NSObjectProperties;\n            }\n        case FLEXMetadataKindIvars:\n            switch (self.scope) {\n                case FLEXObjectExplorerScopeNoInheritance:\n                    return self.ivars;\n                case FLEXObjectExplorerScopeWithParent:\n                    return self.ivarsWithParent;\n                case FLEXObjectExplorerScopeAllButNSObject:\n                    return self.inheritedIvars;\n                case FLEXObjectExplorerScopeNSObjectOnly:\n                    return self.NSObjectIvars;\n            }\n        case FLEXMetadataKindMethods:\n            switch (self.scope) {\n                case FLEXObjectExplorerScopeNoInheritance:\n                    return self.methods;\n                case FLEXObjectExplorerScopeWithParent:\n                    return self.methodsWithParent;\n                case FLEXObjectExplorerScopeAllButNSObject:\n                    return self.inheritedMethods;\n                case FLEXObjectExplorerScopeNSObjectOnly:\n                    return self.NSObjectMethods;\n            }\n        case FLEXMetadataKindClassMethods:\n            switch (self.scope) {\n                case FLEXObjectExplorerScopeNoInheritance:\n                    return self.classMethods;\n                case FLEXObjectExplorerScopeWithParent:\n                    return self.classMethodsWithParent;\n                case FLEXObjectExplorerScopeAllButNSObject:\n                    return self.inheritedClassMethods;\n                case FLEXObjectExplorerScopeNSObjectOnly:\n                    return self.NSObjectClassMethods;\n            }\n    }\n}\n\n- (NSInteger)totalCountOfMetadata:(FLEXMetadataKind)metadataKind forScope:(FLEXObjectExplorerScope)scope {\n    return [self metadata:metadataKind forScope:scope].count;\n}\n\n#pragma mark - Setter overrides\n\n- (void)setObject:(id)object\n{\n    _object = object;\n    // Use [object class] here rather than object_getClass because we don't want to show the KVO prefix for observed objects.\n    self.title = [[object class] description];\n    [self refreshScopeTitles];\n}\n\n- (void)setFilterText:(NSString *)filterText\n{\n    if (_filterText != filterText || ![_filterText isEqual:filterText]) {\n        _filterText = filterText;\n        [self updateDisplayedData];\n    }\n}\n\n\n#pragma mark - Reloading\n\n- (void)updateTableData\n{\n    [self updateCustomData];\n    [self updateProperties];\n    [self updateIvars];\n    [self updateMethods];\n    [self updateClassMethods];\n    [self updateSuperclasses];\n    [self updateDisplayedData];\n}\n\n- (void)updateDisplayedData\n{\n    [self updateFilteredCustomData];\n    [self updateFilteredProperties];\n    [self updateFilteredIvars];\n    [self updateFilteredMethods];\n    [self updateFilteredClassMethods];\n    [self updateFilteredSuperclasses];\n    \n    if (self.isViewLoaded) {\n        [self.tableView reloadData];\n    }\n}\n\n- (BOOL)shouldShowDescription\n{\n    BOOL showDescription = YES;\n    \n    // Not if it's empty or nil.\n    NSString *descripition = [FLEXUtility safeDescriptionForObject:self.object];\n    if (showDescription) {\n        showDescription = [descripition length] > 0;\n    }\n    \n    // Not if we have filter text that doesn't match the desctiption.\n    if (showDescription && [self.filterText length] > 0) {\n        showDescription = [descripition rangeOfString:self.filterText options:NSCaseInsensitiveSearch].length > 0;\n    }\n    \n    return showDescription;\n}\n\n\n#pragma mark - Properties\n\n- (void)updateProperties\n{\n    Class class = [self.object class];\n    self.properties = [[self class] propertiesForClass:class];\n    self.propertiesWithParent = [self.properties arrayByAddingObjectsFromArray:[[self class] propertiesForClass:[class superclass]]];\n    self.inheritedProperties = [self.properties arrayByAddingObjectsFromArray:[[self class] inheritedPropertiesForClass:class]];\n    self.NSObjectProperties = [[self class] propertiesForClass:[NSObject class]];\n}\n\n+ (NSArray<FLEXPropertyBox *> *)propertiesForClass:(Class)class\n{\n    if (!class) {\n        return @[];\n    }\n    \n    NSMutableArray<FLEXPropertyBox *> *boxedProperties = [NSMutableArray array];\n    unsigned int propertyCount = 0;\n    objc_property_t *propertyList = class_copyPropertyList(class, &propertyCount);\n    if (propertyList) {\n        for (unsigned int i = 0; i < propertyCount; i++) {\n            FLEXPropertyBox *propertyBox = [[FLEXPropertyBox alloc] init];\n            propertyBox.property = propertyList[i];\n            [boxedProperties addObject:propertyBox];\n        }\n        free(propertyList);\n    }\n    return boxedProperties;\n}\n\n/// Skips NSObject\n+ (NSArray<FLEXPropertyBox *> *)inheritedPropertiesForClass:(Class)class\n{\n    NSMutableArray<FLEXPropertyBox *> *inheritedProperties = [NSMutableArray array];\n    while ((class = [class superclass]) && class != [NSObject class]) {\n        [inheritedProperties addObjectsFromArray:[self propertiesForClass:class]];\n    }\n    return inheritedProperties;\n}\n\n- (void)updateFilteredProperties\n{\n    NSArray<FLEXPropertyBox *> *candidateProperties = [self metadata:FLEXMetadataKindProperties forScope:self.scope];\n    \n    NSArray<FLEXPropertyBox *> *unsortedFilteredProperties = nil;\n    if ([self.filterText length] > 0) {\n        NSMutableArray<FLEXPropertyBox *> *mutableUnsortedFilteredProperties = [NSMutableArray array];\n        for (FLEXPropertyBox *propertyBox in candidateProperties) {\n            NSString *prettyName = [FLEXRuntimeUtility prettyNameForProperty:propertyBox.property];\n            if ([prettyName rangeOfString:self.filterText options:NSCaseInsensitiveSearch].location != NSNotFound) {\n                [mutableUnsortedFilteredProperties addObject:propertyBox];\n            }\n        }\n        unsortedFilteredProperties = mutableUnsortedFilteredProperties;\n    } else {\n        unsortedFilteredProperties = candidateProperties;\n    }\n    \n    self.filteredProperties = [unsortedFilteredProperties sortedArrayUsingComparator:^NSComparisonResult(FLEXPropertyBox *propertyBox1, FLEXPropertyBox *propertyBox2) {\n        NSString *name1 = [NSString stringWithUTF8String:property_getName(propertyBox1.property)];\n        NSString *name2 = [NSString stringWithUTF8String:property_getName(propertyBox2.property)];\n        return [name1 caseInsensitiveCompare:name2];\n    }];\n}\n\n- (NSString *)titleForPropertyAtIndex:(NSInteger)index\n{\n    FLEXPropertyBox *propertyBox = self.filteredProperties[index];\n    return [FLEXRuntimeUtility prettyNameForProperty:propertyBox.property];\n}\n\n- (id)valueForPropertyAtIndex:(NSInteger)index\n{\n    id value = nil;\n    if ([self canHaveInstanceState]) {\n        FLEXPropertyBox *propertyBox = self.filteredProperties[index];\n        value = [FLEXRuntimeUtility valueForProperty:propertyBox.property onObject:self.object];\n    }\n    return value;\n}\n\n\n#pragma mark - Ivars\n\n- (void)updateIvars\n{\n    Class class = [self.object class];\n    self.ivars = [[self class] ivarsForClass:class];\n    self.ivarsWithParent = [self.ivars arrayByAddingObjectsFromArray:[[self class] ivarsForClass:[class superclass]]];\n    self.inheritedIvars = [self.ivars arrayByAddingObjectsFromArray:[[self class] inheritedIvarsForClass:class]];\n    self.NSObjectIvars = [[self class] ivarsForClass:[NSObject class]];\n}\n\n+ (NSArray<FLEXIvarBox *> *)ivarsForClass:(Class)class\n{\n    if (!class) {\n        return @[];\n    }\n    NSMutableArray<FLEXIvarBox *> *boxedIvars = [NSMutableArray array];\n    unsigned int ivarCount = 0;\n    Ivar *ivarList = class_copyIvarList(class, &ivarCount);\n    if (ivarList) {\n        for (unsigned int i = 0; i < ivarCount; i++) {\n            FLEXIvarBox *ivarBox = [[FLEXIvarBox alloc] init];\n            ivarBox.ivar = ivarList[i];\n            [boxedIvars addObject:ivarBox];\n        }\n        free(ivarList);\n    }\n    return boxedIvars;\n}\n\n/// Skips NSObject\n+ (NSArray<FLEXIvarBox *> *)inheritedIvarsForClass:(Class)class\n{\n    NSMutableArray<FLEXIvarBox *> *inheritedIvars = [NSMutableArray array];\n    while ((class = [class superclass]) && class != [NSObject class]) {\n        [inheritedIvars addObjectsFromArray:[self ivarsForClass:class]];\n    }\n    return inheritedIvars;\n}\n\n- (void)updateFilteredIvars\n{\n    NSArray<FLEXIvarBox *> *candidateIvars = [self metadata:FLEXMetadataKindIvars forScope:self.scope];\n    \n    NSArray<FLEXIvarBox *> *unsortedFilteredIvars = nil;\n    if ([self.filterText length] > 0) {\n        NSMutableArray<FLEXIvarBox *> *mutableUnsortedFilteredIvars = [NSMutableArray array];\n        for (FLEXIvarBox *ivarBox in candidateIvars) {\n            NSString *prettyName = [FLEXRuntimeUtility prettyNameForIvar:ivarBox.ivar];\n            if ([prettyName rangeOfString:self.filterText options:NSCaseInsensitiveSearch].location != NSNotFound) {\n                [mutableUnsortedFilteredIvars addObject:ivarBox];\n            }\n        }\n        unsortedFilteredIvars = mutableUnsortedFilteredIvars;\n    } else {\n        unsortedFilteredIvars = candidateIvars;\n    }\n    \n    self.filteredIvars = [unsortedFilteredIvars sortedArrayUsingComparator:^NSComparisonResult(FLEXIvarBox *ivarBox1, FLEXIvarBox *ivarBox2) {\n        NSString *name1 = [NSString stringWithUTF8String:ivar_getName(ivarBox1.ivar)];\n        NSString *name2 = [NSString stringWithUTF8String:ivar_getName(ivarBox2.ivar)];\n        return [name1 caseInsensitiveCompare:name2];\n    }];\n}\n\n- (NSString *)titleForIvarAtIndex:(NSInteger)index\n{\n    FLEXIvarBox *ivarBox = self.filteredIvars[index];\n    return [FLEXRuntimeUtility prettyNameForIvar:ivarBox.ivar];\n}\n\n- (id)valueForIvarAtIndex:(NSInteger)index\n{\n    id value = nil;\n    if ([self canHaveInstanceState]) {\n        FLEXIvarBox *ivarBox = self.filteredIvars[index];\n        value = [FLEXRuntimeUtility valueForIvar:ivarBox.ivar onObject:self.object];\n    }\n    return value;\n}\n\n\n#pragma mark - Methods\n\n- (void)updateMethods\n{\n    Class class = [self.object class];\n    self.methods = [[self class] methodsForClass:class];\n    self.methodsWithParent = [self.methods arrayByAddingObjectsFromArray:[[self class] methodsForClass:[class superclass]]];\n    self.inheritedMethods = [self.methods arrayByAddingObjectsFromArray:[[self class] inheritedMethodsForClass:class]];\n    self.NSObjectMethods = [[self class] methodsForClass:[NSObject class]];\n}\n\n- (void)updateFilteredMethods\n{\n    NSArray<FLEXMethodBox *> *candidateMethods = [self metadata:FLEXMetadataKindMethods forScope:self.scope];\n    self.filteredMethods = [self filteredMethodsFromMethods:candidateMethods areClassMethods:NO];\n}\n\n- (void)updateClassMethods\n{\n    const char *className = [NSStringFromClass([self.object class]) UTF8String];\n    Class metaClass = objc_getMetaClass(className);\n    self.classMethods = [[self class] methodsForClass:metaClass];\n    self.classMethodsWithParent = [self.classMethods arrayByAddingObjectsFromArray:[[self class] methodsForClass:[metaClass superclass]]];\n    self.inheritedClassMethods = [self.classMethods arrayByAddingObjectsFromArray:[[self class] inheritedMethodsForClass:metaClass]];\n    self.NSObjectClassMethods = [[self class] methodsForClass:[NSObject class]];\n}\n\n- (void)updateFilteredClassMethods\n{\n    NSArray<FLEXMethodBox *> *candidateMethods = [self metadata:FLEXMetadataKindClassMethods forScope:self.scope];\n    self.filteredClassMethods = [self filteredMethodsFromMethods:candidateMethods areClassMethods:YES];\n}\n\n+ (NSArray<FLEXMethodBox *> *)methodsForClass:(Class)class\n{\n    if (!class) {\n        return @[];\n    }\n    \n    NSMutableArray<FLEXMethodBox *> *boxedMethods = [NSMutableArray array];\n    unsigned int methodCount = 0;\n    Method *methodList = class_copyMethodList(class, &methodCount);\n    if (methodList) {\n        for (unsigned int i = 0; i < methodCount; i++) {\n            FLEXMethodBox *methodBox = [[FLEXMethodBox alloc] init];\n            methodBox.method = methodList[i];\n            [boxedMethods addObject:methodBox];\n        }\n        free(methodList);\n    }\n    return boxedMethods;\n}\n\n/// Skips NSObject\n+ (NSArray<FLEXMethodBox *> *)inheritedMethodsForClass:(Class)class\n{\n    NSMutableArray<FLEXMethodBox *> *inheritedMethods = [NSMutableArray array];\n    while ((class = [class superclass]) && class != [NSObject class]) {\n        [inheritedMethods addObjectsFromArray:[self methodsForClass:class]];\n    }\n    return inheritedMethods;\n}\n\n- (NSArray<FLEXMethodBox *> *)filteredMethodsFromMethods:(NSArray<FLEXMethodBox *> *)methods areClassMethods:(BOOL)areClassMethods\n{\n    NSArray<FLEXMethodBox *> *candidateMethods = methods;\n    NSArray<FLEXMethodBox *> *unsortedFilteredMethods = nil;\n    if ([self.filterText length] > 0) {\n        NSMutableArray<FLEXMethodBox *> *mutableUnsortedFilteredMethods = [NSMutableArray array];\n        for (FLEXMethodBox *methodBox in candidateMethods) {\n            NSString *prettyName = [FLEXRuntimeUtility prettyNameForMethod:methodBox.method isClassMethod:areClassMethods];\n            if ([prettyName rangeOfString:self.filterText options:NSCaseInsensitiveSearch].location != NSNotFound) {\n                [mutableUnsortedFilteredMethods addObject:methodBox];\n            }\n        }\n        unsortedFilteredMethods = mutableUnsortedFilteredMethods;\n    } else {\n        unsortedFilteredMethods = candidateMethods;\n    }\n    \n    NSArray<FLEXMethodBox *> *sortedFilteredMethods = [unsortedFilteredMethods sortedArrayUsingComparator:^NSComparisonResult(FLEXMethodBox *methodBox1, FLEXMethodBox *methodBox2) {\n        NSString *name1 = NSStringFromSelector(method_getName(methodBox1.method));\n        NSString *name2 = NSStringFromSelector(method_getName(methodBox2.method));\n        return [name1 caseInsensitiveCompare:name2];\n    }];\n    \n    return sortedFilteredMethods;\n}\n\n- (NSString *)titleForMethodAtIndex:(NSInteger)index\n{\n    FLEXMethodBox *methodBox = self.filteredMethods[index];\n    return [FLEXRuntimeUtility prettyNameForMethod:methodBox.method isClassMethod:NO];\n}\n\n- (NSString *)titleForClassMethodAtIndex:(NSInteger)index\n{\n    FLEXMethodBox *classMethodBox = self.filteredClassMethods[index];\n    return [FLEXRuntimeUtility prettyNameForMethod:classMethodBox.method isClassMethod:YES];\n}\n\n\n#pragma mark - Superclasses\n\n+ (NSArray<Class> *)superclassesForClass:(Class)class\n{\n    NSMutableArray<Class> *superClasses = [NSMutableArray array];\n    while ((class = [class superclass])) {\n        [superClasses addObject:class];\n    }\n    return superClasses;\n}\n\n- (void)updateSuperclasses\n{\n    self.superclasses = [[self class] superclassesForClass:[self.object class]];\n}\n\n- (void)updateFilteredSuperclasses\n{\n    if ([self.filterText length] > 0) {\n        NSMutableArray<Class> *filteredSuperclasses = [NSMutableArray array];\n        for (Class superclass in self.superclasses) {\n            if ([NSStringFromClass(superclass) rangeOfString:self.filterText options:NSCaseInsensitiveSearch].length > 0) {\n                [filteredSuperclasses addObject:superclass];\n            }\n        }\n        self.filteredSuperclasses = filteredSuperclasses;\n    } else {\n        self.filteredSuperclasses = self.superclasses;\n    }\n}\n\n\n#pragma mark - Table View Data Helpers\n\n- (NSArray<NSNumber *> *)possibleExplorerSections\n{\n    static NSArray<NSNumber *> *possibleSections = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        possibleSections = @[@(FLEXObjectExplorerSectionDescription),\n                             @(FLEXObjectExplorerSectionCustom),\n                             @(FLEXObjectExplorerSectionProperties),\n                             @(FLEXObjectExplorerSectionIvars),\n                             @(FLEXObjectExplorerSectionMethods),\n                             @(FLEXObjectExplorerSectionClassMethods),\n                             @(FLEXObjectExplorerSectionSuperclasses),\n                             @(FLEXObjectExplorerSectionReferencingInstances)];\n    });\n    return possibleSections;\n}\n\n- (NSArray<NSNumber *> *)visibleExplorerSections\n{\n    NSMutableArray<NSNumber *> *visibleSections = [NSMutableArray array];\n    \n    for (NSNumber *possibleSection in [self possibleExplorerSections]) {\n        FLEXObjectExplorerSection explorerSection = [possibleSection unsignedIntegerValue];\n        if ([self numberOfRowsForExplorerSection:explorerSection] > 0) {\n            [visibleSections addObject:possibleSection];\n        }\n    }\n    \n    return visibleSections;\n}\n\n- (NSString *)sectionTitleWithBaseName:(NSString *)baseName totalCount:(NSUInteger)totalCount filteredCount:(NSUInteger)filteredCount\n{\n    NSString *sectionTitle = nil;\n    if (totalCount == filteredCount) {\n        sectionTitle = [baseName stringByAppendingFormat:@\" (%lu)\", (unsigned long)totalCount];\n    } else {\n        sectionTitle = [baseName stringByAppendingFormat:@\" (%lu of %lu)\", (unsigned long)filteredCount, (unsigned long)totalCount];\n    }\n    return sectionTitle;\n}\n\n- (FLEXObjectExplorerSection)explorerSectionAtIndex:(NSInteger)sectionIndex\n{\n    return [[[self visibleExplorerSections] objectAtIndex:sectionIndex] unsignedIntegerValue];\n}\n\n- (NSInteger)numberOfRowsForExplorerSection:(FLEXObjectExplorerSection)section\n{\n    NSInteger numberOfRows = 0;\n    switch (section) {\n        case FLEXObjectExplorerSectionDescription:\n            numberOfRows = [self shouldShowDescription] ? 1 : 0;\n            break;\n            \n        case FLEXObjectExplorerSectionCustom:\n            numberOfRows = [self.customSectionVisibleIndexes count];\n            break;\n            \n        case FLEXObjectExplorerSectionProperties:\n            numberOfRows = [self.filteredProperties count];\n            break;\n            \n        case FLEXObjectExplorerSectionIvars:\n            numberOfRows = [self.filteredIvars count];\n            break;\n            \n        case FLEXObjectExplorerSectionMethods:\n            numberOfRows = [self.filteredMethods count];\n            break;\n            \n        case FLEXObjectExplorerSectionClassMethods:\n            numberOfRows = [self.filteredClassMethods count];\n            break;\n            \n        case FLEXObjectExplorerSectionSuperclasses:\n            numberOfRows = [self.filteredSuperclasses count];\n            break;\n            \n        case FLEXObjectExplorerSectionReferencingInstances:\n            // Hide this section if there is fliter text since there's nothing searchable (only 1 row, always the same).\n            numberOfRows = [self.filterText length] == 0 ? 1 : 0;\n            break;\n    }\n    return numberOfRows;\n}\n\n- (NSString *)titleForRow:(NSInteger)row inExplorerSection:(FLEXObjectExplorerSection)section\n{\n    NSString *title = nil;\n    switch (section) {\n        case FLEXObjectExplorerSectionDescription:\n            title = [FLEXUtility safeDescriptionForObject:self.object];\n            break;\n            \n        case FLEXObjectExplorerSectionCustom:\n            title = [self customSectionTitleForRowCookie:[self customSectionRowCookieForVisibleRow:row]];\n            break;\n            \n        case FLEXObjectExplorerSectionProperties:\n            title = [self titleForPropertyAtIndex:row];\n            break;\n            \n        case FLEXObjectExplorerSectionIvars:\n            title = [self titleForIvarAtIndex:row];\n            break;\n            \n        case FLEXObjectExplorerSectionMethods:\n            title = [self titleForMethodAtIndex:row];\n            break;\n            \n        case FLEXObjectExplorerSectionClassMethods:\n            title = [self titleForClassMethodAtIndex:row];\n            break;\n            \n        case FLEXObjectExplorerSectionSuperclasses:\n            title = NSStringFromClass(self.filteredSuperclasses[row]);\n            break;\n            \n        case FLEXObjectExplorerSectionReferencingInstances:\n            title = @\"Other objects with ivars referencing this object\";\n            break;\n    }\n    return title;\n}\n\n- (NSString *)subtitleForRow:(NSInteger)row inExplorerSection:(FLEXObjectExplorerSection)section\n{\n    NSString *subtitle = nil;\n    switch (section) {\n        case FLEXObjectExplorerSectionDescription:\n            break;\n            \n        case FLEXObjectExplorerSectionCustom:\n            subtitle = [self customSectionSubtitleForRowCookie:[self customSectionRowCookieForVisibleRow:row]];\n            break;\n            \n        case FLEXObjectExplorerSectionProperties:\n            subtitle = [self canHaveInstanceState] ? [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:[self valueForPropertyAtIndex:row]] : nil;\n            break;\n            \n        case FLEXObjectExplorerSectionIvars:\n            subtitle = [self canHaveInstanceState] ? [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:[self valueForIvarAtIndex:row]] : nil;\n            break;\n            \n        case FLEXObjectExplorerSectionMethods:\n            break;\n            \n        case FLEXObjectExplorerSectionClassMethods:\n            break;\n            \n        case FLEXObjectExplorerSectionSuperclasses:\n            break;\n            \n        case FLEXObjectExplorerSectionReferencingInstances:\n            break;\n    }\n    return subtitle;\n}\n\n- (BOOL)canDrillInToRow:(NSInteger)row inExplorerSection:(FLEXObjectExplorerSection)section\n{\n    BOOL canDrillIn = NO;\n    switch (section) {\n        case FLEXObjectExplorerSectionDescription:\n            break;\n            \n        case FLEXObjectExplorerSectionCustom:\n            canDrillIn = [self customSectionCanDrillIntoRowWithCookie:[self customSectionRowCookieForVisibleRow:row]];\n            break;\n            \n        case FLEXObjectExplorerSectionProperties: {\n            if ([self canHaveInstanceState]) {\n                FLEXPropertyBox *propertyBox = self.filteredProperties[row];\n                objc_property_t property = propertyBox.property;\n                id currentValue = [self valueForPropertyAtIndex:row];\n                BOOL canEdit = [FLEXPropertyEditorViewController canEditProperty:property currentValue:currentValue];\n                BOOL canExplore = currentValue != nil;\n                canDrillIn = canEdit || canExplore;\n            }\n        }   break;\n            \n        case FLEXObjectExplorerSectionIvars: {\n            if ([self canHaveInstanceState]) {\n                FLEXIvarBox *ivarBox = self.filteredIvars[row];\n                Ivar ivar = ivarBox.ivar;\n                id currentValue = [self valueForIvarAtIndex:row];\n                BOOL canEdit = [FLEXIvarEditorViewController canEditIvar:ivar currentValue:currentValue];\n                BOOL canExplore = currentValue != nil;\n                canDrillIn = canEdit || canExplore;\n            }\n        }   break;\n            \n        case FLEXObjectExplorerSectionMethods:\n            canDrillIn = [self canCallInstanceMethods];\n            break;\n            \n        case FLEXObjectExplorerSectionClassMethods:\n            canDrillIn = YES;\n            break;\n            \n        case FLEXObjectExplorerSectionSuperclasses:\n            canDrillIn = YES;\n            break;\n            \n        case FLEXObjectExplorerSectionReferencingInstances:\n            canDrillIn = YES;\n            break;\n    }\n    return canDrillIn;\n}\n\n- (BOOL)canCopyRow:(NSInteger)row inExplorerSection:(FLEXObjectExplorerSection)section\n{\n    BOOL canCopy = NO;\n    \n    switch (section) {\n        case FLEXObjectExplorerSectionDescription:\n            canCopy = YES;\n            break;\n            \n        default:\n            break;\n    }\n    return canCopy;\n}\n\n- (NSString *)titleForExplorerSection:(FLEXObjectExplorerSection)section\n{\n    NSString *title = nil;\n    switch (section) {\n        case FLEXObjectExplorerSectionDescription: {\n            title = @\"Description\";\n        } break;\n            \n        case FLEXObjectExplorerSectionCustom: {\n            title = [self customSectionTitle];\n        } break;\n            \n        case FLEXObjectExplorerSectionProperties: {\n            NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindProperties forScope:self.scope];\n            title = [self sectionTitleWithBaseName:@\"Properties\" totalCount:totalCount filteredCount:[self.filteredProperties count]];\n        } break;\n            \n        case FLEXObjectExplorerSectionIvars: {\n            NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindIvars forScope:self.scope];\n            title = [self sectionTitleWithBaseName:@\"Ivars\" totalCount:totalCount filteredCount:[self.filteredIvars count]];\n        } break;\n            \n        case FLEXObjectExplorerSectionMethods: {\n            NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindMethods forScope:self.scope];\n            title = [self sectionTitleWithBaseName:@\"Methods\" totalCount:totalCount filteredCount:[self.filteredMethods count]];\n        } break;\n            \n        case FLEXObjectExplorerSectionClassMethods: {\n            NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindClassMethods forScope:self.scope];\n            title = [self sectionTitleWithBaseName:@\"Class Methods\" totalCount:totalCount filteredCount:[self.filteredClassMethods count]];\n        } break;\n            \n        case FLEXObjectExplorerSectionSuperclasses: {\n            title = [self sectionTitleWithBaseName:@\"Superclasses\" totalCount:[self.superclasses count] filteredCount:[self.filteredSuperclasses count]];\n        } break;\n            \n        case FLEXObjectExplorerSectionReferencingInstances: {\n            title = @\"Object Graph\";\n        } break;\n    }\n    return title;\n}\n\n- (UIViewController *)drillInViewControllerForRow:(NSUInteger)row inExplorerSection:(FLEXObjectExplorerSection)section\n{\n    UIViewController *viewController = nil;\n    switch (section) {\n        case FLEXObjectExplorerSectionDescription:\n            break;\n            \n        case FLEXObjectExplorerSectionCustom:\n            viewController = [self customSectionDrillInViewControllerForRowCookie:[self customSectionRowCookieForVisibleRow:row]];\n            break;\n            \n        case FLEXObjectExplorerSectionProperties: {\n            FLEXPropertyBox *propertyBox = self.filteredProperties[row];\n            objc_property_t property = propertyBox.property;\n            id currentValue = [self valueForPropertyAtIndex:row];\n            if ([FLEXPropertyEditorViewController canEditProperty:property currentValue:currentValue]) {\n                viewController = [[FLEXPropertyEditorViewController alloc] initWithTarget:self.object property:property];\n            } else if (currentValue) {\n                viewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:currentValue];\n            }\n        } break;\n            \n        case FLEXObjectExplorerSectionIvars: {\n            FLEXIvarBox *ivarBox = self.filteredIvars[row];\n            Ivar ivar = ivarBox.ivar;\n            id currentValue = [self valueForIvarAtIndex:row];\n            if ([FLEXIvarEditorViewController canEditIvar:ivar currentValue:currentValue]) {\n                viewController = [[FLEXIvarEditorViewController alloc] initWithTarget:self.object ivar:ivar];\n            } else if (currentValue) {\n                viewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:currentValue];\n            }\n        } break;\n            \n        case FLEXObjectExplorerSectionMethods: {\n            FLEXMethodBox *methodBox = self.filteredMethods[row];\n            Method method = methodBox.method;\n            viewController = [[FLEXMethodCallingViewController alloc] initWithTarget:self.object method:method];\n        } break;\n            \n        case FLEXObjectExplorerSectionClassMethods: {\n            FLEXMethodBox *methodBox = self.filteredClassMethods[row];\n            Method method = methodBox.method;\n            viewController = [[FLEXMethodCallingViewController alloc] initWithTarget:[self.object class] method:method];\n        } break;\n            \n        case FLEXObjectExplorerSectionSuperclasses: {\n            Class superclass = self.filteredSuperclasses[row];\n            viewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:superclass];\n        } break;\n            \n        case FLEXObjectExplorerSectionReferencingInstances: {\n            viewController = [FLEXInstancesTableViewController instancesTableViewControllerForInstancesReferencingObject:self.object];\n        } break;\n    }\n    return viewController;\n}\n\n\n#pragma mark - Table View Data Source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return [[self visibleExplorerSections] count];\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    FLEXObjectExplorerSection explorerSection = [self explorerSectionAtIndex:section];\n    return [self numberOfRowsForExplorerSection:explorerSection];\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section\n{\n    FLEXObjectExplorerSection explorerSection = [self explorerSectionAtIndex:section];\n    return [self titleForExplorerSection:explorerSection];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXObjectExplorerSection explorerSection = [self explorerSectionAtIndex:indexPath.section];\n    \n    BOOL useDescriptionCell = explorerSection == FLEXObjectExplorerSectionDescription;\n    NSString *cellIdentifier = useDescriptionCell ? kFLEXMultilineTableViewCellIdentifier : @\"cell\";\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];\n    if (!cell) {\n        if (useDescriptionCell) {\n            cell = [[FLEXMultilineTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];\n            cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n        } else {\n            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];\n            UIFont *cellFont = [FLEXUtility defaultTableViewCellLabelFont];\n            cell.textLabel.font = cellFont;\n            cell.detailTextLabel.font = cellFont;\n            cell.detailTextLabel.textColor = [UIColor grayColor];\n        }\n    }\n    \n    cell.textLabel.text = [self titleForRow:indexPath.row inExplorerSection:explorerSection];\n    cell.detailTextLabel.text = [self subtitleForRow:indexPath.row inExplorerSection:explorerSection];\n    cell.accessoryType = [self canDrillInToRow:indexPath.row inExplorerSection:explorerSection] ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;\n    \n    return cell;\n}\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXObjectExplorerSection explorerSection = [self explorerSectionAtIndex:indexPath.section];\n    CGFloat height = self.tableView.rowHeight;\n    if (explorerSection == FLEXObjectExplorerSectionDescription) {\n        NSString *text = [self titleForRow:indexPath.row inExplorerSection:explorerSection];\n        NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@{ NSFontAttributeName : [FLEXUtility defaultTableViewCellLabelFont] }];\n        CGFloat preferredHeight = [FLEXMultilineTableViewCell preferredHeightWithAttributedText:attributedText inTableViewWidth:self.tableView.frame.size.width style:tableView.style showsAccessory:NO];\n        height = MAX(height, preferredHeight);\n    }\n    return height;\n}\n\n\n#pragma mark - Table View Delegate\n\n- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXObjectExplorerSection explorerSection = [self explorerSectionAtIndex:indexPath.section];\n    return [self canDrillInToRow:indexPath.row inExplorerSection:explorerSection];\n}\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXObjectExplorerSection explorerSection = [self explorerSectionAtIndex:indexPath.section];\n    UIViewController *detailViewController = [self drillInViewControllerForRow:indexPath.row inExplorerSection:explorerSection];\n    if (detailViewController) {\n        [self.navigationController pushViewController:detailViewController animated:YES];\n    } else {\n        [tableView deselectRowAtIndexPath:indexPath animated:YES];\n    }\n}\n\n- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    FLEXObjectExplorerSection explorerSection = [self explorerSectionAtIndex:indexPath.section];\n    BOOL canCopy = [self canCopyRow:indexPath.row inExplorerSection:explorerSection];\n    return canCopy;\n}\n\n- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender\n{\n    BOOL canPerformAction = NO;\n    \n    if (action == @selector(copy:)) {\n        FLEXObjectExplorerSection explorerSection = [self explorerSectionAtIndex:indexPath.section];\n        BOOL canCopy = [self canCopyRow:indexPath.row inExplorerSection:explorerSection];\n        canPerformAction = canCopy;\n    }\n    \n    return canPerformAction;\n}\n\n- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender\n{\n    if (action == @selector(copy:)) {\n        FLEXObjectExplorerSection explorerSection = [self explorerSectionAtIndex:indexPath.section];\n        NSString *stringToCopy = @\"\";\n        \n        NSString *title = [self titleForRow:indexPath.row inExplorerSection:explorerSection];\n        if ([title length] > 0) {\n            stringToCopy = [stringToCopy stringByAppendingString:title];\n        }\n        \n        NSString *subtitle = [self subtitleForRow:indexPath.row inExplorerSection:explorerSection];\n        if ([subtitle length] > 0) {\n            if ([stringToCopy length] > 0) {\n                stringToCopy = [stringToCopy stringByAppendingString:@\"\\n\\n\"];\n            }\n            stringToCopy = [stringToCopy stringByAppendingString:subtitle];\n        }\n        \n        [[UIPasteboard generalPasteboard] setString:stringToCopy];\n    }\n}\n\n\n#pragma mark - Custom Section\n\n- (void)updateCustomData\n{\n    self.cachedCustomSectionRowCookies = [self customSectionRowCookies];\n}\n\n- (void)updateFilteredCustomData\n{\n    NSIndexSet *filteredIndexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self.cachedCustomSectionRowCookies count])];\n    if ([self.filterText length] > 0) {\n        filteredIndexSet = [filteredIndexSet indexesPassingTest:^BOOL(NSUInteger index, BOOL *stop) {\n            BOOL matches = NO;\n            NSString *rowTitle = [self customSectionTitleForRowCookie:self.cachedCustomSectionRowCookies[index]];\n            if ([rowTitle rangeOfString:self.filterText options:NSCaseInsensitiveSearch].location != NSNotFound) {\n                matches = YES;\n            }\n            return matches;\n        }];\n    }\n    self.customSectionVisibleIndexes = filteredIndexSet;\n}\n\n- (id)customSectionRowCookieForVisibleRow:(NSUInteger)row\n{\n    return [[self.cachedCustomSectionRowCookies objectsAtIndexes:self.customSectionVisibleIndexes] objectAtIndex:row];\n}\n\n\n#pragma mark - Subclasses Can Override\n\n- (NSString *)customSectionTitle\n{\n    return nil;\n}\n\n- (NSArray *)customSectionRowCookies\n{\n    return nil;\n}\n\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie\n{\n    return nil;\n}\n\n- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie\n{\n    return nil;\n}\n\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie\n{\n    return NO;\n}\n\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie\n{\n    return nil;\n}\n\n- (BOOL)canHaveInstanceState\n{\n    return YES;\n}\n\n- (BOOL)canCallInstanceMethods\n{\n    return YES;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXSetExplorerViewController.h",
    "content": "//\n//  FLEXSetExplorerViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerViewController.h\"\n\n@interface FLEXSetExplorerViewController : FLEXObjectExplorerViewController\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXSetExplorerViewController.m",
    "content": "//\n//  FLEXSetExplorerViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/16/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXSetExplorerViewController.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n\n@interface FLEXSetExplorerViewController ()\n\n@property (nonatomic, readonly) NSSet *set;\n\n@end\n\n@implementation FLEXSetExplorerViewController\n\n- (NSSet *)set\n{\n    return [self.object isKindOfClass:[NSSet class]] ? self.object : nil;\n}\n\n\n#pragma mark - Superclass Overrides\n\n- (NSString *)customSectionTitle\n{\n    return @\"Set Objects\";\n}\n\n- (NSArray *)customSectionRowCookies\n{\n    return [self.set allObjects];\n}\n\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie\n{\n    return [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:rowCookie];\n}\n\n- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie\n{\n    return nil;\n}\n\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie\n{\n    return YES;\n}\n\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie\n{\n    return [FLEXObjectExplorerFactory explorerViewControllerForObject:rowCookie];\n}\n\n- (BOOL)shouldShowDescription\n{\n    return NO;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXViewControllerExplorerViewController.h",
    "content": "//\n//  FLEXViewControllerExplorerViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/11/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerViewController.h\"\n\n@interface FLEXViewControllerExplorerViewController : FLEXObjectExplorerViewController\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXViewControllerExplorerViewController.m",
    "content": "//\n//  FLEXViewControllerExplorerViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/11/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXViewControllerExplorerViewController.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n\ntypedef NS_ENUM(NSUInteger, FLEXViewControllerExplorerRow) {\n    FLEXViewControllerExplorerRowPush,\n    FLEXViewControllerExplorerRowView\n};\n\n@interface FLEXViewControllerExplorerViewController ()\n\n@property (nonatomic, readonly) UIViewController *viewController;\n\n@end\n\n@implementation FLEXViewControllerExplorerViewController\n\n- (UIViewController *)viewController\n{\n    return [self.object isKindOfClass:[UIViewController class]] ? self.object : nil;\n}\n\n- (BOOL)canPushViewController\n{\n    // Only show the \"Push View Controller\" option if it's not already part of the hierarchy to avoid really disrupting the app.\n    return self.viewController.view.window == nil;\n}\n\n\n#pragma mark - Superclass Overrides\n\n- (NSString *)customSectionTitle\n{\n    return @\"Shortcuts\";\n}\n\n- (NSArray *)customSectionRowCookies\n{\n    NSArray *rowCookies = @[@(FLEXViewControllerExplorerRowView)];\n    if ([self canPushViewController]) {\n        rowCookies = [@[@(FLEXViewControllerExplorerRowPush)] arrayByAddingObjectsFromArray:rowCookies];\n    }\n    return rowCookies;\n}\n\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie\n{\n    NSString *title = nil;\n    if ([rowCookie isEqual:@(FLEXViewControllerExplorerRowPush)]) {\n        title = @\"Push View Controller\";\n    } else if ([rowCookie isEqual:@(FLEXViewControllerExplorerRowView)]) {\n        title = @\"@property UIView *view\";\n    }\n    return title;\n}\n\n- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie\n{\n    NSString *subtitle = nil;\n    if ([rowCookie isEqual:@(FLEXViewControllerExplorerRowView)]) {\n        subtitle = [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:self.viewController.view];\n    }\n    return subtitle;\n}\n\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie\n{\n    BOOL canDrillIn = NO;\n    if ([rowCookie isEqual:@(FLEXViewControllerExplorerRowPush)]) {\n        canDrillIn = [self canPushViewController];\n    }else if ([rowCookie isEqual:@(FLEXViewControllerExplorerRowView)]) {\n        canDrillIn = self.viewController.view != nil;\n    }\n    return canDrillIn;\n}\n\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie\n{\n    UIViewController *drillInViewController = nil;\n    if ([rowCookie isEqual:@(FLEXViewControllerExplorerRowPush)]) {\n        drillInViewController = self.viewController;\n    } else if ([rowCookie isEqual:@(FLEXViewControllerExplorerRowView)]) {\n        drillInViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:self.viewController.view];\n    }\n    return drillInViewController;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXViewExplorerViewController.h",
    "content": "//\n//  FLEXViewExplorerViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/11/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXObjectExplorerViewController.h\"\n\n@interface FLEXViewExplorerViewController : FLEXObjectExplorerViewController\n\n@end\n"
  },
  {
    "path": "FLEX/ObjectExplorers/FLEXViewExplorerViewController.m",
    "content": "//\n//  FLEXViewExplorerViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/11/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXViewExplorerViewController.h\"\n#import \"FLEXRuntimeUtility.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n#import \"FLEXImagePreviewViewController.h\"\n#import \"FLEXPropertyEditorViewController.h\"\n\ntypedef NS_ENUM(NSUInteger, FLEXViewExplorerRow) {\n    FLEXViewExplorerRowViewController,\n    FLEXViewExplorerRowPreview,\n    FLEXViewExplorerRowViewControllerForAncestor\n};\n\n@interface FLEXViewExplorerViewController ()\n\n// Don't clash with UIViewController's view property\n@property (nonatomic, readonly) UIView *viewToExplore;\n\n@end\n\n@implementation FLEXViewExplorerViewController\n\n- (UIView *)viewToExplore\n{\n    return [self.object isKindOfClass:[UIView class]] ? self.object : nil;\n}\n\n\n#pragma mark - Superclass Overrides\n\n- (NSString *)customSectionTitle\n{\n    return @\"Shortcuts\";\n}\n\n- (NSArray *)customSectionRowCookies\n{\n    NSMutableArray *rowCookies = [NSMutableArray array];\n    \n    if ([FLEXUtility viewControllerForView:self.viewToExplore]) {\n        [rowCookies addObject:@(FLEXViewExplorerRowViewController)];\n    }else{\n        [rowCookies addObject:@(FLEXViewExplorerRowViewControllerForAncestor)];\n    }\n    \n    [rowCookies addObject:@(FLEXViewExplorerRowPreview)];\n    [rowCookies addObjectsFromArray:[self shortcutPropertyNames]];\n    \n    return rowCookies;\n}\n\n- (NSArray<NSString *> *)shortcutPropertyNames\n{\n    NSArray<NSString *> *propertyNames = @[@\"frame\", @\"bounds\", @\"center\", @\"transform\", @\"backgroundColor\", @\"alpha\", @\"opaque\", @\"hidden\", @\"clipsToBounds\", @\"userInteractionEnabled\", @\"layer\"];\n    \n    if ([self.viewToExplore isKindOfClass:[UILabel class]]) {\n        propertyNames = [@[@\"text\", @\"font\", @\"textColor\"] arrayByAddingObjectsFromArray:propertyNames];\n    }\n    \n    return propertyNames;\n}\n\n- (NSString *)customSectionTitleForRowCookie:(id)rowCookie\n{\n    NSString *title = nil;\n    \n    if ([rowCookie isKindOfClass:[NSNumber class]]) {\n        FLEXViewExplorerRow row = [rowCookie unsignedIntegerValue];\n        switch (row) {\n            case FLEXViewExplorerRowViewController:\n                title = @\"View Controller\";\n                break;\n                \n            case FLEXViewExplorerRowPreview:\n                title = @\"Preview Image\";\n                break;\n            \n            case FLEXViewExplorerRowViewControllerForAncestor:\n                title = @\"View Controller For Ancestor\";\n                break;\n        }\n    } else if ([rowCookie isKindOfClass:[NSString class]]) {\n        objc_property_t property = [self viewPropertyForName:rowCookie];\n        if (property) {\n            NSString *prettyPropertyName = [FLEXRuntimeUtility prettyNameForProperty:property];\n            // Since we're outside of the \"properties\" section, prepend @property for clarity.\n            title = [NSString stringWithFormat:@\"@property %@\", prettyPropertyName];\n        }\n    }\n    \n    return title;\n}\n\n- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie\n{\n    NSString *subtitle = nil;\n    \n    if ([rowCookie isKindOfClass:[NSNumber class]]) {\n        FLEXViewExplorerRow row = [rowCookie unsignedIntegerValue];\n        switch (row) {\n            case FLEXViewExplorerRowViewController:\n                subtitle = [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:[FLEXUtility viewControllerForView:self.viewToExplore]];\n                break;\n                \n            case FLEXViewExplorerRowPreview:\n                break;\n            \n            case FLEXViewExplorerRowViewControllerForAncestor:\n                subtitle = [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:[FLEXUtility viewControllerForAncestralView:self.viewToExplore]];\n                break;\n        }\n    } else if ([rowCookie isKindOfClass:[NSString class]]) {\n        objc_property_t property = [self viewPropertyForName:rowCookie];\n        if (property) {\n            id value = [FLEXRuntimeUtility valueForProperty:property onObject:self.viewToExplore];\n            subtitle = [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:value];\n        }\n    }\n    \n    return subtitle;\n}\n\n- (objc_property_t)viewPropertyForName:(NSString *)propertyName\n{\n    return class_getProperty([self.viewToExplore class], [propertyName UTF8String]);\n}\n\n- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie\n{\n    return YES;\n}\n\n- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie\n{\n    UIViewController *drillInViewController = nil;\n    \n    if ([rowCookie isKindOfClass:[NSNumber class]]) {\n        FLEXViewExplorerRow row = [rowCookie unsignedIntegerValue];\n        switch (row) {\n            case FLEXViewExplorerRowViewController:\n                drillInViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:[FLEXUtility viewControllerForView:self.viewToExplore]];\n                break;\n                \n            case FLEXViewExplorerRowPreview:\n                drillInViewController = [[self class] imagePreviewViewControllerForView:self.viewToExplore];\n                break;\n                \n            case FLEXViewExplorerRowViewControllerForAncestor:\n                drillInViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:[FLEXUtility viewControllerForAncestralView:self.viewToExplore]];\n                break;\n        }\n    } else if ([rowCookie isKindOfClass:[NSString class]]) {\n        objc_property_t property = [self viewPropertyForName:rowCookie];\n        if (property) {\n            id currentValue = [FLEXRuntimeUtility valueForProperty:property onObject:self.viewToExplore];\n            if ([FLEXPropertyEditorViewController canEditProperty:property currentValue:currentValue]) {\n                drillInViewController = [[FLEXPropertyEditorViewController alloc] initWithTarget:self.object property:property];\n            } else {\n                drillInViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:currentValue];\n            }\n        }\n    }\n\n    return drillInViewController;\n}\n\n+ (UIViewController *)imagePreviewViewControllerForView:(UIView *)view\n{\n    UIViewController *imagePreviewViewController = nil;\n    if (!CGRectIsEmpty(view.bounds)) {\n        CGSize viewSize = view.bounds.size;\n        UIGraphicsBeginImageContextWithOptions(viewSize, NO, 0.0);\n        [view drawViewHierarchyInRect:CGRectMake(0, 0, viewSize.width, viewSize.height) afterScreenUpdates:YES];\n        UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext();\n        UIGraphicsEndImageContext();\n        imagePreviewViewController = [[FLEXImagePreviewViewController alloc] initWithImage:previewImage];\n    }\n    return imagePreviewViewController;\n}\n\n\n#pragma mark - Runtime Adjustment\n\n+ (void)initialize\n{\n    // A quirk of UIView: a lot of the \"@property\"s are not actually properties from the perspective of the runtime.\n    // We add these properties to the class at runtime if they haven't been added yet.\n    // This way, we can use our property editor to access and change them.\n    // The property attributes match the declared attributes in UIView.h\n    NSDictionary<NSString *, NSString *> *frameAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(@encode(CGRect)), kFLEXUtilityAttributeNonAtomic : @\"\"};\n    [FLEXRuntimeUtility tryAddPropertyWithName:\"frame\" attributes:frameAttributes toClass:[UIView class]];\n    \n    NSDictionary<NSString *, NSString *> *alphaAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(@encode(CGFloat)), kFLEXUtilityAttributeNonAtomic : @\"\"};\n    [FLEXRuntimeUtility tryAddPropertyWithName:\"alpha\" attributes:alphaAttributes toClass:[UIView class]];\n    \n    NSDictionary<NSString *, NSString *> *clipsAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(@encode(BOOL)), kFLEXUtilityAttributeNonAtomic : @\"\"};\n    [FLEXRuntimeUtility tryAddPropertyWithName:\"clipsToBounds\" attributes:clipsAttributes toClass:[UIView class]];\n    \n    NSDictionary<NSString *, NSString *> *opaqueAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(@encode(BOOL)), kFLEXUtilityAttributeNonAtomic : @\"\", kFLEXUtilityAttributeCustomGetter : @\"isOpaque\"};\n    [FLEXRuntimeUtility tryAddPropertyWithName:\"opaque\" attributes:opaqueAttributes toClass:[UIView class]];\n    \n    NSDictionary<NSString *, NSString *> *hiddenAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(@encode(BOOL)), kFLEXUtilityAttributeNonAtomic : @\"\", kFLEXUtilityAttributeCustomGetter : @\"isHidden\"};\n    [FLEXRuntimeUtility tryAddPropertyWithName:\"hidden\" attributes:hiddenAttributes toClass:[UIView class]];\n    \n    NSDictionary<NSString *, NSString *> *backgroundColorAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(FLEXEncodeClass(UIColor)), kFLEXUtilityAttributeNonAtomic : @\"\", kFLEXUtilityAttributeCopy : @\"\"};\n    [FLEXRuntimeUtility tryAddPropertyWithName:\"backgroundColor\" attributes:backgroundColorAttributes toClass:[UIView class]];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Toolbar/FLEXExplorerToolbar.h",
    "content": "//\n//  FLEXExplorerToolbar.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/4/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@class FLEXToolbarItem;\n\n@interface FLEXExplorerToolbar : UIView\n\n/// The items to be displayed in the toolbar. Defaults to:\n/// globalsItem, hierarchyItem, selectItem, moveItem, closeItem\n@property (nonatomic, copy) NSArray<FLEXToolbarItem *> *toolbarItems;\n\n/// Toolbar item for selecting views.\n/// Users of the toolbar can configure the enabled/selected state and event targets/actions.\n@property (nonatomic, strong, readonly) FLEXToolbarItem *selectItem;\n\n/// Toolbar item for presenting a list with the view hierarchy.\n/// Users of the toolbar can configure the enabled state and event targets/actions.\n@property (nonatomic, strong, readonly) FLEXToolbarItem *hierarchyItem;\n\n/// Toolbar item for moving views.\n/// Users of the toolbar can configure the enabled/selected state and event targets/actions.\n@property (nonatomic, strong, readonly) FLEXToolbarItem *moveItem;\n\n/// Toolbar item for inspecting details of the selected view.\n/// Users of the toolbar can configure the enabled state and event targets/actions.\n@property (nonatomic, strong, readonly) FLEXToolbarItem *globalsItem;\n\n/// Toolbar item for hiding the explorer.\n/// Users of the toolbar can configure the event targets/actions.\n@property (nonatomic, strong, readonly) FLEXToolbarItem *closeItem;\n\n/// A view for moving the entire toolbar.\n/// Users of the toolbar can attach a pan gesture recognizer to decide how to reposition the toolbar.\n@property (nonatomic, strong, readonly) UIView *dragHandle;\n\n/// A color matching the overlay on color on the selected view.\n@property (nonatomic, strong) UIColor *selectedViewOverlayColor;\n\n/// Description text for the selected view displayed below the toolbar items.\n@property (nonatomic, copy) NSString *selectedViewDescription;\n\n/// Area where details of the selected view are shown\n/// Users of the toolbar can attach a tap gesture recognizer to show additional details.\n@property (nonatomic, strong, readonly) UIView *selectedViewDescriptionContainer;\n\n@end\n"
  },
  {
    "path": "FLEX/Toolbar/FLEXExplorerToolbar.m",
    "content": "//\n//  FLEXExplorerToolbar.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/4/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXExplorerToolbar.h\"\n#import \"FLEXToolbarItem.h\"\n#import \"FLEXResources.h\"\n#import \"FLEXUtility.h\"\n\n@interface FLEXExplorerToolbar ()\n\n@property (nonatomic, strong, readwrite) FLEXToolbarItem *selectItem;\n@property (nonatomic, strong, readwrite) FLEXToolbarItem *moveItem;\n@property (nonatomic, strong, readwrite) FLEXToolbarItem *globalsItem;\n@property (nonatomic, strong, readwrite) FLEXToolbarItem *closeItem;\n@property (nonatomic, strong, readwrite) FLEXToolbarItem *hierarchyItem;\n@property (nonatomic, strong, readwrite) UIView *dragHandle;\n\n@property (nonatomic, strong) UIImageView *dragHandleImageView;\n\n@property (nonatomic, strong) UIView *selectedViewDescriptionContainer;\n@property (nonatomic, strong) UIView *selectedViewDescriptionSafeAreaContainer;\n@property (nonatomic, strong) UIView *selectedViewColorIndicator;\n@property (nonatomic, strong) UILabel *selectedViewDescriptionLabel;\n\n@property (nonatomic, strong,readwrite) UIView *backgroundView;\n\n@end\n\n@implementation FLEXExplorerToolbar\n\n- (id)initWithFrame:(CGRect)frame\n{\n    self = [super initWithFrame:frame];\n    if (self) {\n        self.backgroundView = [[UIView alloc] init];\n        self.backgroundView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.95];\n        [self addSubview:self.backgroundView];\n\n        self.dragHandle = [[UIView alloc] init];\n        self.dragHandle.backgroundColor = [UIColor clearColor];\n        [self addSubview:self.dragHandle];\n        \n        UIImage *dragHandle = [FLEXResources dragHandle];\n        self.dragHandleImageView = [[UIImageView alloc] initWithImage:dragHandle];\n        [self.dragHandle addSubview:self.dragHandleImageView];\n        \n        UIImage *globalsIcon = [FLEXResources globeIcon];\n        self.globalsItem = [FLEXToolbarItem toolbarItemWithTitle:@\"menu\" image:globalsIcon];\n        \n        UIImage *listIcon = [FLEXResources listIcon];\n        self.hierarchyItem = [FLEXToolbarItem toolbarItemWithTitle:@\"views\" image:listIcon];\n        \n        UIImage *selectIcon = [FLEXResources selectIcon];\n        self.selectItem = [FLEXToolbarItem toolbarItemWithTitle:@\"select\" image:selectIcon];\n        \n        UIImage *moveIcon = [FLEXResources moveIcon];\n        self.moveItem = [FLEXToolbarItem toolbarItemWithTitle:@\"move\" image:moveIcon];\n        \n        UIImage *closeIcon = [FLEXResources closeIcon];\n        self.closeItem = [FLEXToolbarItem toolbarItemWithTitle:@\"close\" image:closeIcon];\n\n        self.selectedViewDescriptionContainer = [[UIView alloc] init];\n        self.selectedViewDescriptionContainer.backgroundColor = [UIColor colorWithWhite:0.9 alpha:0.95];\n        self.selectedViewDescriptionContainer.hidden = YES;\n        [self addSubview:self.selectedViewDescriptionContainer];\n\n        self.selectedViewDescriptionSafeAreaContainer = [[UIView alloc] init];\n        self.selectedViewDescriptionSafeAreaContainer.backgroundColor = [UIColor clearColor];\n        [self.selectedViewDescriptionContainer addSubview:self.selectedViewDescriptionSafeAreaContainer];\n        \n        self.selectedViewColorIndicator = [[UIView alloc] init];\n        self.selectedViewColorIndicator.backgroundColor = [UIColor redColor];\n        [self.selectedViewDescriptionSafeAreaContainer addSubview:self.selectedViewColorIndicator];\n        \n        self.selectedViewDescriptionLabel = [[UILabel alloc] init];\n        self.selectedViewDescriptionLabel.backgroundColor = [UIColor clearColor];\n        self.selectedViewDescriptionLabel.font = [[self class] descriptionLabelFont];\n        [self.selectedViewDescriptionSafeAreaContainer addSubview:self.selectedViewDescriptionLabel];\n        \n        self.toolbarItems = @[_globalsItem, _hierarchyItem, _selectItem, _moveItem, _closeItem];\n    }\n        \n    return self;\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n\n\n    CGRect safeArea = [self safeArea];\n    // Drag Handle\n    const CGFloat kToolbarItemHeight = [[self class] toolbarItemHeight];\n    self.dragHandle.frame = CGRectMake(CGRectGetMinX(safeArea), CGRectGetMinY(safeArea), [[self class] dragHandleWidth], kToolbarItemHeight);\n    CGRect dragHandleImageFrame = self.dragHandleImageView.frame;\n    dragHandleImageFrame.origin.x = FLEXFloor((self.dragHandle.frame.size.width - dragHandleImageFrame.size.width) / 2.0);\n    dragHandleImageFrame.origin.y = FLEXFloor((self.dragHandle.frame.size.height - dragHandleImageFrame.size.height) / 2.0);\n    self.dragHandleImageView.frame = dragHandleImageFrame;\n    \n    \n    // Toolbar Items\n    CGFloat originX = CGRectGetMaxX(self.dragHandle.frame);\n    CGFloat originY = CGRectGetMinY(safeArea);\n    CGFloat height = kToolbarItemHeight;\n    CGFloat width = FLEXFloor((CGRectGetWidth(safeArea) - CGRectGetWidth(self.dragHandle.frame)) / [self.toolbarItems count]);\n    for (UIView *toolbarItem in self.toolbarItems) {\n        toolbarItem.frame = CGRectMake(originX, originY, width, height);\n        originX = CGRectGetMaxX(toolbarItem.frame);\n    }\n    \n    // Make sure the last toolbar item goes to the edge to account for any accumulated rounding effects.\n    UIView *lastToolbarItem = [self.toolbarItems lastObject];\n    CGRect lastToolbarItemFrame = lastToolbarItem.frame;\n    lastToolbarItemFrame.size.width = CGRectGetMaxX(safeArea) - lastToolbarItemFrame.origin.x;\n    lastToolbarItem.frame = lastToolbarItemFrame;\n\n    self.backgroundView.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), kToolbarItemHeight);\n    \n    const CGFloat kSelectedViewColorDiameter = [[self class] selectedViewColorIndicatorDiameter];\n    const CGFloat kDescriptionLabelHeight = [[self class] descriptionLabelHeight];\n    const CGFloat kHorizontalPadding = [[self class] horizontalPadding];\n    const CGFloat kDescriptionVerticalPadding = [[self class] descriptionVerticalPadding];\n    const CGFloat kDescriptionContainerHeight = [[self class] descriptionContainerHeight];\n    \n    CGRect descriptionContainerFrame = CGRectZero;\n    descriptionContainerFrame.size.width = CGRectGetWidth(self.bounds);\n    descriptionContainerFrame.size.height = kDescriptionContainerHeight;\n    descriptionContainerFrame.origin.x = CGRectGetMinX(self.bounds);\n    descriptionContainerFrame.origin.y = CGRectGetMaxY(self.bounds) - kDescriptionContainerHeight;\n    self.selectedViewDescriptionContainer.frame = descriptionContainerFrame;\n\n    CGRect descriptionSafeAreaContainerFrame = CGRectZero;\n    descriptionSafeAreaContainerFrame.size.width = CGRectGetWidth(safeArea);\n    descriptionSafeAreaContainerFrame.size.height = kDescriptionContainerHeight;\n    descriptionSafeAreaContainerFrame.origin.x = CGRectGetMinX(safeArea);\n    descriptionSafeAreaContainerFrame.origin.y = CGRectGetMinY(safeArea);\n    self.selectedViewDescriptionSafeAreaContainer.frame = descriptionSafeAreaContainerFrame;\n\n    // Selected View Color\n    CGRect selectedViewColorFrame = CGRectZero;\n    selectedViewColorFrame.size.width = kSelectedViewColorDiameter;\n    selectedViewColorFrame.size.height = kSelectedViewColorDiameter;\n    selectedViewColorFrame.origin.x = kHorizontalPadding;\n    selectedViewColorFrame.origin.y = FLEXFloor((kDescriptionContainerHeight - kSelectedViewColorDiameter) / 2.0);\n    self.selectedViewColorIndicator.frame = selectedViewColorFrame;\n    self.selectedViewColorIndicator.layer.cornerRadius = ceil(selectedViewColorFrame.size.height / 2.0);\n    \n    // Selected View Description\n    CGRect descriptionLabelFrame = CGRectZero;\n    CGFloat descriptionOriginX = CGRectGetMaxX(selectedViewColorFrame) + kHorizontalPadding;\n    descriptionLabelFrame.size.height = kDescriptionLabelHeight;\n    descriptionLabelFrame.origin.x = descriptionOriginX;\n    descriptionLabelFrame.origin.y = kDescriptionVerticalPadding;\n    descriptionLabelFrame.size.width = CGRectGetMaxX(self.selectedViewDescriptionContainer.bounds) - kHorizontalPadding - descriptionOriginX;\n    self.selectedViewDescriptionLabel.frame = descriptionLabelFrame;\n}\n    \n    \n#pragma mark - Setter Overrides\n\n- (void)setToolbarItems:(NSArray<FLEXToolbarItem *> *)toolbarItems {\n    if (_toolbarItems == toolbarItems) {\n        return;\n    }\n    \n    // Remove old toolbar items, if any\n    for (FLEXToolbarItem *item in _toolbarItems) {\n        [item removeFromSuperview];\n    }\n    \n    // Trim to 5 items if necessary\n    if (toolbarItems.count > 5) {\n        toolbarItems = [toolbarItems subarrayWithRange:NSMakeRange(0, 5)];\n    }\n\n    for (FLEXToolbarItem *item in toolbarItems) {\n        [self addSubview:item];\n    }\n\n    _toolbarItems = toolbarItems.copy;\n\n    // Lay out new items\n    [self setNeedsLayout];\n    [self layoutIfNeeded];\n}\n\n- (void)setSelectedViewOverlayColor:(UIColor *)selectedViewOverlayColor\n{\n    if (![_selectedViewOverlayColor isEqual:selectedViewOverlayColor]) {\n        _selectedViewOverlayColor = selectedViewOverlayColor;\n        self.selectedViewColorIndicator.backgroundColor = selectedViewOverlayColor;\n    }\n}\n\n- (void)setSelectedViewDescription:(NSString *)selectedViewDescription\n{\n    if (![_selectedViewDescription isEqual:selectedViewDescription]) {\n        _selectedViewDescription = selectedViewDescription;\n        self.selectedViewDescriptionLabel.text = selectedViewDescription;\n        BOOL showDescription = [selectedViewDescription length] > 0;\n        self.selectedViewDescriptionContainer.hidden = !showDescription;\n    }\n}\n\n\n#pragma mark - Sizing Convenience Methods\n\n+ (UIFont *)descriptionLabelFont\n{\n    return [UIFont systemFontOfSize:12.0];\n}\n\n+ (CGFloat)toolbarItemHeight\n{\n    return 44.0;\n}\n\n+ (CGFloat)dragHandleWidth\n{\n    return 30.0;\n}\n\n+ (CGFloat)descriptionLabelHeight\n{\n    return ceil([[self descriptionLabelFont] lineHeight]);\n}\n\n+ (CGFloat)descriptionVerticalPadding\n{\n    return 2.0;\n}\n\n+ (CGFloat)descriptionContainerHeight\n{\n    return [self descriptionVerticalPadding] * 2.0 + [self descriptionLabelHeight];\n}\n\n+ (CGFloat)selectedViewColorIndicatorDiameter\n{\n    return ceil([self descriptionLabelHeight] / 2.0);\n}\n\n+ (CGFloat)horizontalPadding\n{\n    return 11.0;\n}\n\n- (CGSize)sizeThatFits:(CGSize)size\n{\n    CGFloat height = 0.0;\n    height += [[self class] toolbarItemHeight];\n    height += [[self class] descriptionContainerHeight];\n    return CGSizeMake(size.width, height);\n}\n\n- (CGRect)safeArea\n{\n  CGRect safeArea = self.bounds;\n#if FLEX_AT_LEAST_IOS11_SDK\n  if (@available(iOS 11, *)) {\n    safeArea = UIEdgeInsetsInsetRect(self.bounds, self.safeAreaInsets);\n  }\n#endif\n  return safeArea;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Toolbar/FLEXToolbarItem.h",
    "content": "//\n//  FLEXToolbarItem.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/4/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXToolbarItem : UIButton\n\n+ (instancetype)toolbarItemWithTitle:(NSString *)title image:(UIImage *)image;\n\n@end\n"
  },
  {
    "path": "FLEX/Toolbar/FLEXToolbarItem.m",
    "content": "//\n//  FLEXToolbarItem.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/4/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXToolbarItem.h\"\n#import \"FLEXUtility.h\"\n\n@interface FLEXToolbarItem ()\n\n@property (nonatomic, copy) NSAttributedString *attributedTitle;\n@property (nonatomic, strong) UIImage *image;\n\n@end\n\n@implementation FLEXToolbarItem\n\n- (id)initWithFrame:(CGRect)frame\n{\n    self = [super initWithFrame:frame];\n    if (self) {\n        self.backgroundColor = [[self class] defaultBackgroundColor];\n        [self setTitleColor:[[self class] defaultTitleColor] forState:UIControlStateNormal];\n        [self setTitleColor:[[self class] disabledTitleColor] forState:UIControlStateDisabled];\n    }\n    return self;\n}\n\n+ (instancetype)toolbarItemWithTitle:(NSString *)title image:(UIImage *)image\n{\n    FLEXToolbarItem *toolbarItem = [self buttonWithType:UIButtonTypeCustom];\n    NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title attributes:[self titleAttributes]];\n    toolbarItem.attributedTitle = attributedTitle;\n    toolbarItem.image = image;\n    [toolbarItem setAttributedTitle:attributedTitle forState:UIControlStateNormal];\n    [toolbarItem setImage:image forState:UIControlStateNormal];\n    return toolbarItem;\n}\n\n\n#pragma mark - Display Defaults\n\n+ (NSDictionary<NSString *, id> *)titleAttributes\n{\n    return @{NSFontAttributeName : [FLEXUtility defaultFontOfSize:12.0]};\n}\n\n+ (UIColor *)defaultTitleColor\n{\n    return [UIColor blackColor];\n}\n\n+ (UIColor *)disabledTitleColor\n{\n    return [UIColor colorWithWhite:121.0/255.0 alpha:1.0];\n}\n\n+ (UIColor *)highlightedBackgroundColor\n{\n    return [UIColor colorWithWhite:0.9 alpha:1.0];\n}\n\n+ (UIColor *)selectedBackgroundColor\n{\n    return [UIColor colorWithRed:199.0/255.0 green:199.0/255.0 blue:255.0/255.0 alpha:1.0];\n}\n\n+ (UIColor *)defaultBackgroundColor\n{\n    return [UIColor clearColor];\n}\n\n+ (CGFloat)topMargin\n{\n    return 2.0;\n}\n\n\n#pragma mark - State Changes\n\n- (void)setHighlighted:(BOOL)highlighted\n{\n    [super setHighlighted:highlighted];\n    [self updateBackgroundColor];\n}\n\n- (void)setSelected:(BOOL)selected\n{\n    [super setSelected:selected];\n    [self updateBackgroundColor];\n}\n\n- (void)updateBackgroundColor\n{\n    if (self.highlighted) {\n        self.backgroundColor = [[self class] highlightedBackgroundColor];\n    } else if (self.selected) {\n        self.backgroundColor = [[self class] selectedBackgroundColor];\n    } else {\n        self.backgroundColor = [[self class] defaultBackgroundColor];\n    }\n}\n\n\n#pragma mark - UIButton Layout Overrides\n\n- (CGRect)titleRectForContentRect:(CGRect)contentRect\n{\n    // Bottom aligned and centered.\n    CGRect titleRect = CGRectZero;\n    CGSize titleSize = [self.attributedTitle boundingRectWithSize:contentRect.size options:0 context:nil].size;\n    titleSize = CGSizeMake(ceil(titleSize.width), ceil(titleSize.height));\n    titleRect.size = titleSize;\n    titleRect.origin.y = contentRect.origin.y + CGRectGetMaxY(contentRect) - titleSize.height;\n    titleRect.origin.x = contentRect.origin.x + FLEXFloor((contentRect.size.width - titleSize.width) / 2.0);\n    return titleRect;\n}\n\n- (CGRect)imageRectForContentRect:(CGRect)contentRect\n{\n    CGSize imageSize = self.image.size;\n    CGRect titleRect = [self titleRectForContentRect:contentRect];\n    CGFloat availableHeight = contentRect.size.height - titleRect.size.height - [[self class] topMargin];\n    CGFloat originY = [[self class] topMargin] + FLEXFloor((availableHeight - imageSize.height) / 2.0);\n    CGFloat originX = FLEXFloor((contentRect.size.width - imageSize.width) / 2.0);\n    CGRect imageRect = CGRectMake(originX, originY, imageSize.width, imageSize.height);\n    return imageRect;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXHeapEnumerator.h",
    "content": "//\n//  FLEXHeapEnumerator.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/28/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\ntypedef void (^flex_object_enumeration_block_t)(__unsafe_unretained id object, __unsafe_unretained Class actualClass);\n\n@interface FLEXHeapEnumerator : NSObject\n\n+ (void)enumerateLiveObjectsUsingBlock:(flex_object_enumeration_block_t)block;\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXHeapEnumerator.m",
    "content": "//\n//  FLEXHeapEnumerator.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 5/28/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXHeapEnumerator.h\"\n#import <malloc/malloc.h>\n#import <mach/mach.h>\n#import <objc/runtime.h>\n\nstatic CFMutableSetRef registeredClasses;\n\n// Mimics the objective-c object stucture for checking if a range of memory is an object.\ntypedef struct {\n    Class isa;\n} flex_maybe_object_t;\n\n@implementation FLEXHeapEnumerator\n\nstatic void range_callback(task_t task, void *context, unsigned type, vm_range_t *ranges, unsigned rangeCount)\n{\n    if (!context) {\n        return;\n    }\n    \n    for (unsigned int i = 0; i < rangeCount; i++) {\n        vm_range_t range = ranges[i];\n        flex_maybe_object_t *tryObject = (flex_maybe_object_t *)range.address;\n        Class tryClass = NULL;\n#ifdef __arm64__\n        // See http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html\n        extern uint64_t objc_debug_isa_class_mask WEAK_IMPORT_ATTRIBUTE;\n        tryClass = (__bridge Class)((void *)((uint64_t)tryObject->isa & objc_debug_isa_class_mask));\n#else\n        tryClass = tryObject->isa;\n#endif\n        // If the class pointer matches one in our set of class pointers from the runtime, then we should have an object.\n        if (CFSetContainsValue(registeredClasses, (__bridge const void *)(tryClass))) {\n            (*(flex_object_enumeration_block_t __unsafe_unretained *)context)((__bridge id)tryObject, tryClass);\n        }\n    }\n}\n\nstatic kern_return_t reader(__unused task_t remote_task, vm_address_t remote_address, __unused vm_size_t size, void **local_memory)\n{\n    *local_memory = (void *)remote_address;\n    return KERN_SUCCESS;\n}\n\n+ (void)enumerateLiveObjectsUsingBlock:(flex_object_enumeration_block_t)block\n{\n    if (!block) {\n        return;\n    }\n    \n    // Refresh the class list on every call in case classes are added to the runtime.\n    [self updateRegisteredClasses];\n    \n    // Inspired by:\n    // http://llvm.org/svn/llvm-project/lldb/tags/RELEASE_34/final/examples/darwin/heap_find/heap/heap_find.cpp\n    // https://gist.github.com/samdmarshall/17f4e66b5e2e579fd396\n    \n    vm_address_t *zones = NULL;\n    unsigned int zoneCount = 0;\n    kern_return_t result = malloc_get_all_zones(TASK_NULL, reader, &zones, &zoneCount);\n    \n    if (result == KERN_SUCCESS) {\n        for (unsigned int i = 0; i < zoneCount; i++) {\n            malloc_zone_t *zone = (malloc_zone_t *)zones[i];\n            malloc_introspection_t *introspection = zone->introspect;\n            NSString *zoneName = @(zone->zone_name);\n\n            if (![zoneName isEqualToString:@\"DefaultMallocZone\"] || !introspection) {\n                continue;\n            }\n\n            void (*lock_zone)(malloc_zone_t *zone)   = introspection->force_lock;\n            void (*unlock_zone)(malloc_zone_t *zone) = introspection->force_unlock;\n\n            // Callback has to unlock the zone so we freely allocate memory inside the given block\n            flex_object_enumeration_block_t callback = ^(__unsafe_unretained id object, __unsafe_unretained Class actualClass) {\n                unlock_zone(zone);\n                block(object, actualClass);\n                lock_zone(zone);\n            };\n\n            // The largest realistic memory address varies by platform.\n            // Only 48 bits are used by 64 bit machines while\n            // 32 bit machines use all bits.\n#if __arm64__\n            static uintptr_t MAX_REALISTIC_ADDRESS = 0xFFFFFFFFFFFF;\n#else\n            static uintptr_t MAX_REALISTIC_ADDRESS = INT_MAX;\n#endif\n\n            // There is little documentation on when and why\n            // any of these function pointers might be NULL\n            // or garbage, so we resort to checking for NULL\n            // and impossible memory addresses at least\n            if (lock_zone && unlock_zone &&\n                introspection->enumerator &&\n                (uintptr_t)lock_zone < MAX_REALISTIC_ADDRESS &&\n                (uintptr_t)unlock_zone < MAX_REALISTIC_ADDRESS) {\n                lock_zone(zone);\n                introspection->enumerator(TASK_NULL, (void *)&callback, MALLOC_PTR_IN_USE_RANGE_TYPE, (vm_address_t)zone, reader, &range_callback);\n                unlock_zone(zone);\n            }\n\n            // Only one zone to enumerate\n            break;\n        }\n    }\n}\n\n+ (void)updateRegisteredClasses\n{\n    if (!registeredClasses) {\n        registeredClasses = CFSetCreateMutable(NULL, 0, NULL);\n    } else {\n        CFSetRemoveAllValues(registeredClasses);\n    }\n    unsigned int count = 0;\n    Class *classes = objc_copyClassList(&count);\n    for (unsigned int i = 0; i < count; i++) {\n        CFSetAddValue(registeredClasses, (__bridge const void *)(classes[i]));\n    }\n    free(classes);\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXKeyboardHelpViewController.h",
    "content": "//\n//  FLEXKeyboardHelpViewController.h\n//  UICatalog\n//\n//  Created by Ryan Olson on 9/19/15.\n//  Copyright © 2015 f. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXKeyboardHelpViewController : UIViewController\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXKeyboardHelpViewController.m",
    "content": "//\n//  FLEXKeyboardHelpViewController.m\n//  UICatalog\n//\n//  Created by Ryan Olson on 9/19/15.\n//  Copyright © 2015 f. All rights reserved.\n//\n\n#import \"FLEXKeyboardHelpViewController.h\"\n#import \"FLEXKeyboardShortcutManager.h\"\n\n@interface FLEXKeyboardHelpViewController ()\n\n@property (nonatomic, strong) UITextView *textView;\n\n@end\n\n@implementation FLEXKeyboardHelpViewController\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n\n    self.textView = [[UITextView alloc] initWithFrame:self.view.bounds];\n    self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;\n    [self.view addSubview:self.textView];\n#if TARGET_OS_SIMULATOR\n    self.textView.text = [[FLEXKeyboardShortcutManager sharedManager] keyboardShortcutsDescription];\n#endif\n    self.textView.backgroundColor = [UIColor blackColor];\n    self.textView.textColor = [UIColor whiteColor];\n    self.textView.font = [UIFont boldSystemFontOfSize:14.0];\n    self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;\n    \n    self.title = @\"Simulator Shortcuts\";\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(donePressed:)];\n}\n\n- (void)donePressed:(id)sender\n{\n    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXKeyboardShortcutManager.h",
    "content": "//\n//  FLEXKeyboardShortcutManager.h\n//  FLEX\n//\n//  Created by Ryan Olson on 9/19/15.\n//  Copyright © 2015 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n#if TARGET_OS_SIMULATOR\n\n@interface FLEXKeyboardShortcutManager : NSObject\n\n+ (instancetype)sharedManager;\n\n- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description;\n- (NSString *)keyboardShortcutsDescription;\n\n@property (nonatomic, assign, getter=isEnabled) BOOL enabled;\n\n@end\n\n#endif\n"
  },
  {
    "path": "FLEX/Utility/FLEXKeyboardShortcutManager.m",
    "content": "//\n//  FLEXKeyboardShortcutManager.m\n//  FLEX\n//\n//  Created by Ryan Olson on 9/19/15.\n//  Copyright © 2015 Flipboard. All rights reserved.\n//\n\n#import \"FLEXKeyboardShortcutManager.h\"\n#import \"FLEXUtility.h\"\n#import <objc/runtime.h>\n#import <objc/message.h>\n\n#if TARGET_OS_SIMULATOR\n\n@interface UIEvent (UIPhysicalKeyboardEvent)\n\n@property (nonatomic, strong) NSString *_modifiedInput;\n@property (nonatomic, strong) NSString *_unmodifiedInput;\n@property (nonatomic, assign) UIKeyModifierFlags _modifierFlags;\n@property (nonatomic, assign) BOOL _isKeyDown;\n@property (nonatomic, assign) long _keyCode;\n\n@end\n\n@interface FLEXKeyInput : NSObject <NSCopying>\n\n@property (nonatomic, copy, readonly) NSString *key;\n@property (nonatomic, assign, readonly) UIKeyModifierFlags flags;\n@property (nonatomic, copy, readonly) NSString *helpDescription;\n\n@end\n\n@implementation FLEXKeyInput\n\n- (BOOL)isEqual:(id)object\n{\n    BOOL isEqual = NO;\n    if ([object isKindOfClass:[FLEXKeyInput class]]) {\n        FLEXKeyInput *keyCommand = (FLEXKeyInput *)object;\n        BOOL equalKeys = self.key == keyCommand.key || [self.key isEqual:keyCommand.key];\n        BOOL equalFlags = self.flags == keyCommand.flags;\n        isEqual = equalKeys && equalFlags;\n    }\n    return isEqual;\n}\n\n- (NSUInteger)hash\n{\n    return [self.key hash] ^ self.flags;\n}\n\n- (id)copyWithZone:(NSZone *)zone\n{\n    return [[self class] keyInputForKey:self.key flags:self.flags helpDescription:self.helpDescription];\n}\n\n- (NSString *)description\n{\n    NSDictionary<NSString *, NSString *> *keyMappings = @{ UIKeyInputUpArrow : @\"↑\",\n                                                           UIKeyInputDownArrow : @\"↓\",\n                                                           UIKeyInputLeftArrow : @\"←\",\n                                                           UIKeyInputRightArrow : @\"→\",\n                                                           UIKeyInputEscape : @\"␛\",\n                                                           @\" \" : @\"␠\"};\n    \n    NSString *prettyKey = nil;\n    if (self.key && keyMappings[self.key]) {\n        prettyKey = keyMappings[self.key];\n    } else {\n        prettyKey = [self.key uppercaseString];\n    }\n    \n    NSString *prettyFlags = @\"\";\n    if (self.flags & UIKeyModifierControl) {\n        prettyFlags = [prettyFlags stringByAppendingString:@\"⌃\"];\n    }\n    if (self.flags & UIKeyModifierAlternate) {\n        prettyFlags = [prettyFlags stringByAppendingString:@\"⌥\"];\n    }\n    if (self.flags & UIKeyModifierShift) {\n        prettyFlags = [prettyFlags stringByAppendingString:@\"⇧\"];\n    }\n    if (self.flags & UIKeyModifierCommand) {\n        prettyFlags = [prettyFlags stringByAppendingString:@\"⌘\"];\n    }\n    \n    // Fudging to get easy columns with tabs\n    if ([prettyFlags length] < 2) {\n        prettyKey = [prettyKey stringByAppendingString:@\"\\t\"];\n    }\n    \n    return [NSString stringWithFormat:@\"%@%@\\t%@\", prettyFlags, prettyKey, self.helpDescription];\n}\n\n+ (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags\n{\n    return [self keyInputForKey:key flags:flags helpDescription:nil];\n}\n\n+ (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags helpDescription:(NSString *)helpDescription\n{\n    FLEXKeyInput *keyInput = [[self alloc] init];\n    if (keyInput) {\n        keyInput->_key = key;\n        keyInput->_flags = flags;\n        keyInput->_helpDescription = helpDescription;\n    }\n    return keyInput;\n}\n\n@end\n\n@interface FLEXKeyboardShortcutManager ()\n\n@property (nonatomic, strong) NSMutableDictionary<FLEXKeyInput *, dispatch_block_t> *actionsForKeyInputs;\n\n@property (nonatomic, assign, getter=isPressingShift) BOOL pressingShift;\n@property (nonatomic, assign, getter=isPressingCommand) BOOL pressingCommand;\n@property (nonatomic, assign, getter=isPressingControl) BOOL pressingControl;\n\n@end\n\n@implementation FLEXKeyboardShortcutManager\n\n+ (instancetype)sharedManager\n{\n    static FLEXKeyboardShortcutManager *sharedManager = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        sharedManager = [[[self class] alloc] init];\n    });\n    return sharedManager;\n}\n\n+ (void)load\n{\n    SEL originalKeyEventSelector = NSSelectorFromString(@\"handleKeyUIEvent:\");\n    SEL swizzledKeyEventSelector = [FLEXUtility swizzledSelectorForSelector:originalKeyEventSelector];\n    \n    void (^handleKeyUIEventSwizzleBlock)(UIApplication *, UIEvent *) = ^(UIApplication *slf, UIEvent *event) {\n        \n        [[[self class] sharedManager] handleKeyboardEvent:event];\n        \n        ((void(*)(id, SEL, id))objc_msgSend)(slf, swizzledKeyEventSelector, event);\n    };\n    \n    [FLEXUtility replaceImplementationOfKnownSelector:originalKeyEventSelector onClass:[UIApplication class] withBlock:handleKeyUIEventSwizzleBlock swizzledSelector:swizzledKeyEventSelector];\n    \n    if ([[UITouch class] instancesRespondToSelector:@selector(maximumPossibleForce)]) {\n        SEL originalSendEventSelector = NSSelectorFromString(@\"sendEvent:\");\n        SEL swizzledSendEventSelector = [FLEXUtility swizzledSelectorForSelector:originalSendEventSelector];\n        \n        void (^sendEventSwizzleBlock)(UIApplication *, UIEvent *) = ^(UIApplication *slf, UIEvent *event) {\n            if (event.type == UIEventTypeTouches) {\n                FLEXKeyboardShortcutManager *keyboardManager = [FLEXKeyboardShortcutManager sharedManager];\n                NSInteger pressureLevel = 0;\n                if (keyboardManager.isPressingShift) {\n                    pressureLevel++;\n                }\n                if (keyboardManager.isPressingCommand) {\n                    pressureLevel++;\n                }\n                if (keyboardManager.isPressingControl) {\n                    pressureLevel++;\n                }\n                if (pressureLevel > 0) {\n#if FLEX_AT_LEAST_IOS11_SDK\n                    if (@available(iOS 9.0, *)) {\n                        for (UITouch *touch in [event allTouches]) {\n                            double adjustedPressureLevel = pressureLevel * 20 * touch.maximumPossibleForce;\n                            [touch setValue:@(adjustedPressureLevel) forKey:@\"_pressure\"];\n                        }\n                    }\n#endif\n                }\n            }\n            \n            ((void(*)(id, SEL, id))objc_msgSend)(slf, swizzledSendEventSelector, event);\n        };\n        \n        [FLEXUtility replaceImplementationOfKnownSelector:originalSendEventSelector onClass:[UIApplication class] withBlock:sendEventSwizzleBlock swizzledSelector:swizzledSendEventSelector];\n        \n        SEL originalSupportsTouchPressureSelector = NSSelectorFromString(@\"_supportsForceTouch\");\n        SEL swizzledSupportsTouchPressureSelector = [FLEXUtility swizzledSelectorForSelector:originalSupportsTouchPressureSelector];\n        \n        BOOL (^supportsTouchPressureSwizzleBlock)(UIDevice *) = ^BOOL(UIDevice *slf) {\n            return YES;\n        };\n        \n        [FLEXUtility replaceImplementationOfKnownSelector:originalSupportsTouchPressureSelector onClass:[UIDevice class] withBlock:supportsTouchPressureSwizzleBlock swizzledSelector:swizzledSupportsTouchPressureSelector];\n    }\n}\n\n- (instancetype)init\n{\n    self = [super init];\n    \n    if (self) {\n        _actionsForKeyInputs = [NSMutableDictionary dictionary];\n        _enabled = YES;\n    }\n    \n    return self;\n}\n\n- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description\n{\n    FLEXKeyInput *keyInput = [FLEXKeyInput keyInputForKey:key flags:modifiers helpDescription:description];\n    [self.actionsForKeyInputs setObject:action forKey:keyInput];\n}\n\nstatic const long kFLEXControlKeyCode = 0xe0;\nstatic const long kFLEXShiftKeyCode = 0xe1;\nstatic const long kFLEXCommandKeyCode = 0xe3;\n\n- (void)handleKeyboardEvent:(UIEvent *)event\n{\n    if (!self.enabled) {\n        return;\n    }\n    \n    NSString *modifiedInput = nil;\n    NSString *unmodifiedInput = nil;\n    UIKeyModifierFlags flags = 0;\n    BOOL isKeyDown = NO;\n    \n    if ([event respondsToSelector:@selector(_modifiedInput)]) {\n        modifiedInput = [event _modifiedInput];\n    }\n    \n    if ([event respondsToSelector:@selector(_unmodifiedInput)]) {\n        unmodifiedInput = [event _unmodifiedInput];\n    }\n    \n    if ([event respondsToSelector:@selector(_modifierFlags)]) {\n        flags = [event _modifierFlags];\n    }\n    \n    if ([event respondsToSelector:@selector(_isKeyDown)]) {\n        isKeyDown = [event _isKeyDown];\n    }\n    \n    BOOL interactionEnabled = ![[UIApplication sharedApplication] isIgnoringInteractionEvents];\n    BOOL hasFirstResponder = NO;\n    if (isKeyDown && [modifiedInput length] > 0 && interactionEnabled) {\n        UIResponder *firstResponder = nil;\n        for (UIWindow *window in [FLEXUtility allWindows]) {\n            firstResponder = [window valueForKey:@\"firstResponder\"];\n            if (firstResponder) {\n                hasFirstResponder = YES;\n                break;\n            }\n        }\n        \n        // Ignore key commands (except escape) when there's an active responder\n        if (firstResponder) {\n            if ([unmodifiedInput isEqual:UIKeyInputEscape]) {\n                [firstResponder resignFirstResponder];\n            }\n        } else {\n            FLEXKeyInput *exactMatch = [FLEXKeyInput keyInputForKey:unmodifiedInput flags:flags];\n            \n            dispatch_block_t actionBlock = self.actionsForKeyInputs[exactMatch];\n            \n            if (!actionBlock) {\n                FLEXKeyInput *shiftMatch = [FLEXKeyInput keyInputForKey:modifiedInput flags:flags&(~UIKeyModifierShift)];\n                actionBlock = self.actionsForKeyInputs[shiftMatch];\n            }\n            \n            if (!actionBlock) {\n                FLEXKeyInput *capitalMatch = [FLEXKeyInput keyInputForKey:[unmodifiedInput uppercaseString] flags:flags];\n                actionBlock = self.actionsForKeyInputs[capitalMatch];\n            }\n            \n            if (actionBlock) {\n                actionBlock();\n            }\n        }\n    }\n    \n    // Calling _keyCode on events from the simulator keyboard will crash.\n    // It is only safe to call _keyCode when there's not an active responder.\n    if (!hasFirstResponder && [event respondsToSelector:@selector(_keyCode)]) {\n        long keyCode = [event _keyCode];\n        if (keyCode == kFLEXControlKeyCode) {\n            self.pressingControl = isKeyDown;\n        } else if (keyCode == kFLEXCommandKeyCode) {\n            self.pressingCommand = isKeyDown;\n        } else if (keyCode == kFLEXShiftKeyCode) {\n            self.pressingShift = isKeyDown;\n        }\n    }\n}\n\n- (NSString *)keyboardShortcutsDescription\n{\n    NSMutableString *description = [NSMutableString string];\n    NSArray<FLEXKeyInput *> *keyInputs = [[self.actionsForKeyInputs allKeys] sortedArrayUsingComparator:^NSComparisonResult(FLEXKeyInput *_Nonnull input1, FLEXKeyInput *_Nonnull input2) {\n        return [input1.key caseInsensitiveCompare:input2.key];\n    }];\n    for (FLEXKeyInput *keyInput in keyInputs) {\n        [description appendFormat:@\"%@\\n\", keyInput];\n    }\n    return [description copy];\n}\n\n@end\n\n#endif\n"
  },
  {
    "path": "FLEX/Utility/FLEXMultilineTableViewCell.h",
    "content": "//\n//  FLEXMultilineTableViewCell.h\n//  UICatalog\n//\n//  Created by Ryan Olson on 2/13/15.\n//  Copyright (c) 2015 f. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\nextern NSString *const kFLEXMultilineTableViewCellIdentifier;\n\n@interface FLEXMultilineTableViewCell : UITableViewCell\n\n+ (CGFloat)preferredHeightWithAttributedText:(NSAttributedString *)attributedText inTableViewWidth:(CGFloat)tableViewWidth style:(UITableViewStyle)style showsAccessory:(BOOL)showsAccessory;\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXMultilineTableViewCell.m",
    "content": "//\n//  FLEXMultilineTableViewCell.m\n//  UICatalog\n//\n//  Created by Ryan Olson on 2/13/15.\n//  Copyright (c) 2015 f. All rights reserved.\n//\n\n#import \"FLEXMultilineTableViewCell.h\"\n\nNSString *const kFLEXMultilineTableViewCellIdentifier = @\"kFLEXMultilineTableViewCellIdentifier\";\n\n@implementation FLEXMultilineTableViewCell\n\n- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier\n{\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.textLabel.numberOfLines = 0;\n    }\n    return self;\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n\n    self.textLabel.frame = UIEdgeInsetsInsetRect(self.contentView.bounds, [[self class] labelInsets]);\n}\n\n+ (UIEdgeInsets)labelInsets\n{\n    return UIEdgeInsetsMake(10.0, 15.0, 10.0, 15.0);\n}\n\n+ (CGFloat)preferredHeightWithAttributedText:(NSAttributedString *)attributedText inTableViewWidth:(CGFloat)tableViewWidth style:(UITableViewStyle)style showsAccessory:(BOOL)showsAccessory\n{\n    CGFloat labelWidth = tableViewWidth;\n\n    // Content view inset due to accessory view observed on iOS 8.1 iPhone 6.\n    if (showsAccessory) {\n        labelWidth -= 34.0;\n    }\n\n    UIEdgeInsets labelInsets = [self labelInsets];\n    labelWidth -= (labelInsets.left + labelInsets.right);\n\n    CGSize constrainSize = CGSizeMake(labelWidth, CGFLOAT_MAX);\n    CGFloat preferredLabelHeight = ceil([attributedText boundingRectWithSize:constrainSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size.height);\n    CGFloat preferredCellHeight = preferredLabelHeight + labelInsets.top + labelInsets.bottom + 1.0;\n\n    return preferredCellHeight;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXResources.h",
    "content": "//\n//  FLEXResources.h\n//  FLEX\n//\n//  Created by Ryan Olson on 6/8/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n\n@interface FLEXResources : NSObject\n\n+ (UIImage *)closeIcon;\n+ (UIImage *)dragHandle;\n+ (UIImage *)globeIcon;\n+ (UIImage *)hierarchyIndentPattern;\n+ (UIImage *)listIcon;\n+ (UIImage *)moveIcon;\n+ (UIImage *)selectIcon;\n\n+ (UIImage *)jsonIcon;\n+ (UIImage *)textPlainIcon;\n+ (UIImage *)htmlIcon;\n+ (UIImage *)audioIcon;\n+ (UIImage *)jsIcon;\n+ (UIImage *)plistIcon;\n+ (UIImage *)textIcon;\n+ (UIImage *)videoIcon;\n+ (UIImage *)xmlIcon;\n+ (UIImage *)binaryIcon;\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXResources.m",
    "content": "//\n//  FLEXResources.m\n//  FLEX\n//\n//  Created by Ryan Olson on 6/8/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXResources.h\"\n\nstatic const u_int8_t FLEXCloseIcon[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x06, 0x00, 0x00, 0x00, 0x3b, 0xd6, 0x95, 0x4a, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9c, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x39, 0x30, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc1, 0xe2, 0xd2, 0xc6, 0x00, 0x00, 0x00, 0xb8, 0x49, 0x44, 0x41, 0x54, 0x28, 0x15, 0x9d, 0x92, 0xb1, 0x0d, 0x02, 0x31, 0x10, 0x04, 0x0d, 0x1f, 0x50, 0x01, 0x0d, 0x90, 0x53, 0xdb, 0x8b, 0x2a, 0x48, 0x48, 0x09, 0x49, 0xc8, 0x89, 0xc8, 0xe9, 0xe3, 0x0b, 0xa0, 0x0e, 0xd8, 0xb1, 0x6c, 0xc4, 0x9f, 0xd6, 0x7e, 0xc4, 0x49, 0x2b, 0xdb, 0x77, 0xb7, 0x7b, 0x6b, 0xcb, 0x43, 0x4a, 0xe9, 0x20, 0xdc, 0x84, 0xad, 0xf0, 0x10, 0x7a, 0xb1, 0x52, 0xf1, 0x28, 0x5c, 0x85, 0x17, 0x8d, 0xcf, 0xb2, 0xe1, 0x70, 0x11, 0x68, 0x70, 0x41, 0x9e, 0x3a, 0x7d, 0x00, 0x5e, 0x56, 0xaa, 0x89, 0x96, 0x40, 0x24, 0xd2, 0x87, 0x83, 0x3c, 0xe9, 0x5b, 0x31, 0x0a, 0x38, 0xe2, 0xcc, 0x61, 0xab, 0x61, 0x2d, 0xf1, 0x9e, 0x30, 0xc3, 0x73, 0x38, 0x81, 0x49, 0x95, 0xa5, 0x2b, 0x15, 0xba, 0xbf, 0x42, 0x25, 0xcf, 0xac, 0x7e, 0x18, 0x61, 0x83, 0xd5, 0x38, 0x91, 0x33, 0xf9, 0x6e, 0x38, 0xeb, 0x3f, 0x4d, 0x76, 0xc4, 0xe8, 0xc0, 0x5a, 0x77, 0x44, 0x1a, 0x17, 0x5f, 0xbb, 0x45, 0x24, 0x4f, 0x74, 0xeb, 0xfc, 0x94, 0x7a, 0x2f, 0x56, 0x67, 0xcd, 0x09, 0xe4, 0x1f, 0xf6, 0xf7, 0xdf, 0x1e, 0xca, 0xd4, 0xbd, 0xd6, 0xb3, 0x30, 0x96, 0xb3, 0x16, 0x1b, 0x77, 0x65, 0x37, 0xc2, 0x4e, 0x38, 0xbd, 0x01, 0xa7, 0x78, 0x6a, 0x4b, 0x16, 0xe1, 0xee, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXCloseIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1e, 0x08, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x30, 0xae, 0xa2, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9c, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x39, 0x30, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc1, 0xe2, 0xd2, 0xc6, 0x00, 0x00, 0x01, 0x1d, 0x49, 0x44, 0x41, 0x54, 0x48, 0x0d, 0xc5, 0x97, 0x6b, 0x0e, 0x02, 0x21, 0x0c, 0x84, 0x89, 0x3f, 0xf4, 0xe8, 0x7b, 0x23, 0xe3, 0x8d, 0x38, 0x86, 0x32, 0xc4, 0x6e, 0xd8, 0x86, 0x47, 0x3b, 0x25, 0xd9, 0x4d, 0x2a, 0xb0, 0xb6, 0xf3, 0xb5, 0xd0, 0x18, 0x4c, 0x29, 0xa5, 0x67, 0xb1, 0xa3, 0x58, 0xfe, 0x1b, 0xe6, 0x78, 0xb7, 0xeb, 0x19, 0xea, 0x03, 0xf4, 0x55, 0xf6, 0x2e, 0xeb, 0xd7, 0x06, 0x32, 0x34, 0xa0, 0xa5, 0xf5, 0xc1, 0xac, 0x95, 0xea, 0x2f, 0xb0, 0x8e, 0xc2, 0x47, 0x50, 0x68, 0xe7, 0x19, 0x38, 0x02, 0x9f, 0x41, 0x4f, 0x30, 0xca, 0xc6, 0x62, 0x64, 0xde, 0xca, 0x57, 0x50, 0x70, 0xc0, 0xac, 0x8d, 0xd4, 0x3b, 0x87, 0x36, 0x11, 0x2b, 0xdc, 0x02, 0x85, 0xd6, 0xd9, 0xbc, 0xd6, 0x00, 0xf8, 0x8d, 0x1e, 0x5a, 0x83, 0x0e, 0x2c, 0x99, 0x44, 0x62, 0x6b, 0x21, 0x8c, 0x00, 0x13, 0xd3, 0xdd, 0x35, 0x8f, 0x90, 0xc7, 0xb7, 0x0b, 0xd3, 0x2f, 0x2d, 0x82, 0x9f, 0x12, 0x04, 0x6b, 0x9b, 0x50, 0xcf, 0xad, 0x4d, 0x79, 0xe1, 0x5b, 0xe0, 0x1a, 0xd4, 0xae, 0x29, 0xa8, 0x64, 0xc0, 0xc2, 0x43, 0x50, 0x16, 0xbe, 0x05, 0xda, 0xc2, 0x57, 0xe7, 0x89, 0x6d, 0x86, 0x0f, 0x76, 0x69, 0xf9, 0x3c, 0x96, 0x1e, 0x37, 0x3a, 0x78, 0xcf, 0x79, 0xcb, 0x56, 0x7b, 0xa1, 0xd2, 0xd5, 0x21, 0x38, 0x0b, 0x0d, 0xc1, 0x2d, 0xd0, 0xed, 0x3f, 0x20, 0x16, 0xa8, 0x6c, 0xa5, 0xc7, 0x77, 0xda, 0xa6, 0x8c, 0x10, 0x13, 0x73, 0x49, 0x22, 0x22, 0x40, 0xc7, 0xd2, 0x81, 0x4d, 0xea, 0x6e, 0x0d, 0x5c, 0x43, 0x70, 0x66, 0xd2, 0x8d, 0xbd, 0x51, 0xce, 0xb4, 0xe1, 0x74, 0xa7, 0x56, 0x78, 0xbd, 0xfa, 0x1c, 0x9b, 0xa0, 0x92, 0x89, 0x05, 0x0e, 0xe6, 0xf0, 0x5e, 0x8d, 0xca, 0xad, 0x95, 0x0a, 0x54, 0xc6, 0x15, 0x3c, 0xc3, 0x11, 0x1f, 0x91, 0xed, 0x15, 0x98, 0x1e, 0x67, 0xf0, 0x0a, 0x3e, 0x3a, 0x60, 0xb6, 0x52, 0x2b, 0x1c, 0xcc, 0x7b, 0xfe, 0xb4, 0xfd, 0x00, 0xb3, 0x4a, 0x9f, 0x54, 0x63, 0x5e, 0xe3, 0x04, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXDragHandle[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x26, 0x08, 0x06, 0x00, 0x00, 0x00, 0xfd, 0x5c, 0x0a, 0xf0, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9e, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x38, 0x32, 0x38, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x36, 0x36, 0x38, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x8a, 0x6f, 0x99, 0x54, 0x00, 0x00, 0x00, 0x4b, 0x49, 0x44, 0x41, 0x54, 0x38, 0x11, 0x63, 0x60, 0x60, 0x60, 0xd8, 0x0a, 0xc4, 0xff, 0x09, 0xe0, 0xad, 0x4c, 0x40, 0x05, 0xc4, 0x00, 0x90, 0x41, 0x34, 0x00, 0xa3, 0x6e, 0xa4, 0x4e, 0xa0, 0x8e, 0x86, 0xe3, 0x68, 0x38, 0x22, 0xe7, 0xf5, 0x81, 0xce, 0xd7, 0x9b, 0x80, 0xd1, 0xf1, 0x97, 0x00, 0xde, 0xc4, 0x02, 0x54, 0xc0, 0x0a, 0xc4, 0x84, 0xca, 0x20, 0x56, 0x46, 0xa0, 0x22, 0x10, 0x20, 0xa4, 0xf0, 0x1f, 0x44, 0x19, 0x91, 0xe4, 0xc8, 0x73, 0x23, 0x00, 0x28, 0x34, 0x66, 0xcc, 0x96, 0x10, 0xe2, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXDragHandle2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x6d, 0x54, 0x97, 0x97, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9e, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x38, 0x32, 0x38, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x36, 0x36, 0x38, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x8a, 0x6f, 0x99, 0x54, 0x00, 0x00, 0x00, 0x7c, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, 0xd5, 0xc1, 0x09, 0xc0, 0x30, 0x0c, 0x43, 0x51, 0xd3, 0xed, 0xba, 0xff, 0x08, 0x19, 0xa4, 0x8d, 0x0f, 0xe9, 0x5d, 0x8d, 0x74, 0xca, 0x0f, 0xf8, 0x68, 0x61, 0x93, 0x07, 0xae, 0xaa, 0xba, 0x67, 0x8d, 0x59, 0xcf, 0x66, 0x75, 0x46, 0x67, 0x59, 0xc2, 0xd6, 0x30, 0xe3, 0xea, 0x44, 0xf7, 0xb3, 0xaf, 0xec, 0x1e, 0xf0, 0xc4, 0x3c, 0xfb, 0xa7, 0x38, 0x50, 0xe3, 0xf0, 0x38, 0x8a, 0x38, 0xfc, 0x7d, 0x0a, 0xbe, 0x13, 0x70, 0x1c, 0x9a, 0xc0, 0xc2, 0x38, 0xc4, 0x61, 0x80, 0x95, 0x1c, 0x89, 0x43, 0x1c, 0xca, 0x68, 0x02, 0x0d, 0x38, 0xc4, 0x61, 0x80, 0x95, 0x1c, 0x89, 0x43, 0x1c, 0xca, 0x68, 0x02, 0x0d, 0x38, 0xc4, 0x61, 0x80, 0x95, 0x1c, 0x89, 0x43, 0x1c, 0xca, 0x68, 0x02, 0x0d, 0x38, 0xdc, 0x73, 0xf8, 0x02, 0x86, 0x61, 0x32, 0xdb, 0x80, 0xa1, 0x94, 0xde, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXGlobeIcon[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x08, 0x06, 0x00, 0x00, 0x00, 0x56, 0xce, 0x8e, 0x57, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9c, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x39, 0x30, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc1, 0xe2, 0xd2, 0xc6, 0x00, 0x00, 0x01, 0x4f, 0x49, 0x44, 0x41, 0x54, 0x38, 0x11, 0xad, 0x94, 0x3f, 0x4a, 0x03, 0x41, 0x14, 0x87, 0x93, 0xb4, 0x42, 0x7a, 0x2d, 0x2c, 0xed, 0x85, 0x14, 0x16, 0x41, 0x42, 0x4e, 0x10, 0xb0, 0x13, 0x3c, 0x88, 0x20, 0xa9, 0xbc, 0x82, 0x60, 0x95, 0x5a, 0x2b, 0x0b, 0x6f, 0x90, 0x52, 0x4c, 0xbc, 0x41, 0x0a, 0x0b, 0x15, 0x0b, 0x0f, 0x10, 0x02, 0xf1, 0xfb, 0x96, 0x79, 0xc3, 0xc4, 0x6c, 0xd0, 0x48, 0x7e, 0xf0, 0xed, 0xbe, 0x79, 0xff, 0xf6, 0xcd, 0x6c, 0x36, 0x8d, 0x46, 0xbd, 0xba, 0xb8, 0x87, 0x30, 0x85, 0x79, 0x42, 0x5b, 0x9f, 0xb1, 0x5f, 0xd5, 0x26, 0x63, 0x04, 0x33, 0x78, 0x80, 0x77, 0xb8, 0x80, 0x65, 0xb2, 0xf5, 0x19, 0x33, 0xc7, 0xdc, 0x5a, 0x9d, 0xe0, 0x7d, 0x85, 0x1b, 0x38, 0x82, 0x4f, 0x38, 0x06, 0x65, 0x23, 0x6d, 0x7d, 0xc6, 0xcc, 0x31, 0xd7, 0x9a, 0x15, 0xd9, 0xdd, 0xc0, 0x20, 0x79, 0x2f, 0xb9, 0x9b, 0x1c, 0xb2, 0x91, 0xd2, 0x67, 0x4c, 0x99, 0x6b, 0xcd, 0xca, 0x64, 0x8e, 0x5a, 0x16, 0xbe, 0xb0, 0x3e, 0x85, 0x50, 0x34, 0xd2, 0x67, 0x2c, 0x64, 0x8d, 0xb5, 0x95, 0x3c, 0xbc, 0x19, 0x5c, 0x83, 0x05, 0xdb, 0xf2, 0x45, 0x4d, 0xb7, 0xc5, 0xa5, 0x0f, 0x77, 0x70, 0x05, 0x4d, 0xe8, 0xc1, 0x38, 0xd9, 0xae, 0x45, 0x85, 0x6d, 0xac, 0x57, 0xac, 0x6f, 0xb1, 0xfb, 0x2d, 0x2e, 0x1d, 0x78, 0x86, 0xd0, 0x01, 0xc6, 0x5b, 0x2c, 0x6a, 0xee, 0xbe, 0x49, 0x73, 0x42, 0xd6, 0x76, 0x36, 0x35, 0x32, 0x79, 0x93, 0x7c, 0x48, 0xd9, 0x68, 0xc2, 0xda, 0x61, 0xaa, 0xa7, 0x6f, 0x7b, 0x2e, 0x6b, 0xf9, 0x4e, 0xe4, 0x68, 0x67, 0x10, 0x67, 0x70, 0x8e, 0x7d, 0x5f, 0xac, 0x7f, 0x9e, 0x91, 0x31, 0x73, 0x22, 0xdf, 0xda, 0xc7, 0x68, 0x54, 0x8d, 0x86, 0x43, 0x39, 0xfa, 0x7e, 0x65, 0xd5, 0x5f, 0x8c, 0x95, 0x67, 0x98, 0xcf, 0x38, 0x5e, 0xff, 0x5e, 0xaa, 0x3b, 0xe4, 0xfe, 0x01, 0x3e, 0x24, 0xe4, 0x56, 0x94, 0x3e, 0x63, 0xe6, 0x28, 0x6b, 0xfc, 0xe9, 0xe4, 0xef, 0x6f, 0xc4, 0xe2, 0x09, 0xd6, 0xf6, 0xfe, 0x07, 0xdf, 0x94, 0x9c, 0xac, 0x9d, 0x7d, 0x22, 0x76, 0xdc, 0xc9, 0x47, 0x1b, 0xa3, 0x39, 0x99, 0xdb, 0x74, 0xdf, 0xff, 0xfe, 0x1b, 0x89, 0x66, 0xde, 0x3d, 0xbc, 0x21, 0xb8, 0xff, 0x39, 0x2c, 0x92, 0xad, 0x2f, 0x1f, 0x2c, 0x76, 0xd6, 0x37, 0xcc, 0x0f, 0x82, 0x53, 0x11, 0x25, 0x5b, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXGlobeIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24, 0x08, 0x06, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x98, 0x98, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9c, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x39, 0x30, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc1, 0xe2, 0xd2, 0xc6, 0x00, 0x00, 0x03, 0x7e, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xcd, 0x98, 0x3d, 0x6b, 0x54, 0x51, 0x10, 0x86, 0x8d, 0xb1, 0xf3, 0x83, 0xac, 0x60, 0x61, 0x20, 0x58, 0x88, 0x1f, 0xa8, 0x9d, 0x85, 0x85, 0x58, 0x2e, 0x04, 0x4c, 0x61, 0x6a, 0x05, 0x7f, 0x84, 0x56, 0x0a, 0xd9, 0x3f, 0xa0, 0x90, 0xfc, 0x80, 0xfc, 0x00, 0x3b, 0x85, 0xa4, 0x31, 0x92, 0x46, 0x04, 0x2d, 0x6c, 0x44, 0xc5, 0x0f, 0x62, 0x96, 0x14, 0xa6, 0x52, 0x51, 0x23, 0x04, 0x62, 0x8c, 0xef, 0xb3, 0x39, 0x6f, 0x98, 0x7b, 0x72, 0x37, 0x7b, 0x57, 0x76, 0x13, 0x07, 0xde, 0xcc, 0x9c, 0x99, 0x79, 0x67, 0x86, 0x7b, 0xef, 0x39, 0x7b, 0x6f, 0x06, 0xf6, 0x75, 0x2f, 0x35, 0x51, 0xae, 0x0a, 0x75, 0xe1, 0x82, 0x70, 0x5a, 0x38, 0x28, 0x20, 0xbf, 0x84, 0x0f, 0xc2, 0x6b, 0x61, 0x4e, 0x98, 0x15, 0xbe, 0x09, 0x7d, 0x91, 0x71, 0x55, 0x9d, 0x17, 0xd6, 0x84, 0x8d, 0x8a, 0x20, 0x17, 0x0e, 0xdc, 0x9e, 0xc9, 0x65, 0x55, 0x7a, 0x26, 0x54, 0x1d, 0xa2, 0x5d, 0x1e, 0x35, 0xa8, 0xf5, 0xcf, 0x32, 0x28, 0xe6, 0xa4, 0x90, 0x37, 0xf8, 0x93, 0x7c, 0xeb, 0xd2, 0x13, 0xc2, 0xb9, 0x90, 0x83, 0x8d, 0x8f, 0x18, 0x3c, 0xe7, 0xc6, 0x1a, 0xd4, 0xa4, 0x76, 0x57, 0x32, 0xa4, 0xec, 0xc7, 0x42, 0x2c, 0xb4, 0xaa, 0xf5, 0x94, 0xd0, 0x4c, 0xfe, 0xdb, 0xd2, 0x16, 0xe7, 0x79, 0x4d, 0x0c, 0x5f, 0x53, 0x80, 0x03, 0xd7, 0x39, 0x68, 0x6a, 0xd3, 0xa3, 0x92, 0x90, 0xf8, 0x56, 0x88, 0x05, 0x1e, 0x6a, 0x7d, 0x42, 0xb8, 0x95, 0xfc, 0xaf, 0xa4, 0x0f, 0x08, 0x16, 0xe7, 0x7a, 0x4d, 0x8c, 0x1c, 0xfc, 0x70, 0xe0, 0x52, 0xc3, 0x79, 0x68, 0x7a, 0x74, 0x1c, 0x8a, 0x4b, 0x19, 0xaf, 0x0c, 0x97, 0xbc, 0x21, 0x0c, 0x24, 0x2c, 0x48, 0x53, 0x8c, 0x5d, 0x16, 0xc5, 0x8d, 0xa2, 0x8f, 0x1c, 0xfc, 0x70, 0xcc, 0xa7, 0x56, 0xbc, 0x8d, 0xf4, 0xda, 0xf1, 0xf6, 0x4d, 0x2a, 0xc1, 0xc5, 0x21, 0x5e, 0x17, 0x2c, 0xa3, 0x32, 0x88, 0x2d, 0x0a, 0xfb, 0xed, 0x4c, 0xda, 0x9c, 0xe8, 0x26, 0x87, 0x5c, 0x62, 0x70, 0x2d, 0x37, 0x64, 0xc4, 0xa1, 0xe8, 0x59, 0x2a, 0xec, 0x00, 0x17, 0x46, 0x37, 0xb2, 0xac, 0xe9, 0x14, 0xbf, 0x93, 0xf9, 0x59, 0x9a, 0x97, 0x87, 0xee, 0xa6, 0x18, 0xdc, 0x28, 0xd4, 0x36, 0x07, 0x5d, 0xba, 0xfb, 0x7a, 0xb1, 0xb5, 0x63, 0x93, 0x6e, 0x6c, 0x7a, 0x17, 0x84, 0x83, 0xcb, 0x05, 0xd6, 0x83, 0x6d, 0x5f, 0xbf, 0x74, 0xec, 0x55, 0x38, 0x3c, 0xe7, 0xc3, 0x10, 0xf7, 0x0b, 0xa3, 0x6e, 0x2e, 0x6e, 0xa6, 0xf8, 0x83, 0x92, 0x18, 0x2e, 0x0f, 0x5c, 0x16, 0x86, 0x43, 0x9c, 0x1a, 0xb9, 0xd0, 0xcb, 0x5c, 0x66, 0x68, 0x3d, 0x9c, 0x35, 0xe9, 0x2b, 0x2c, 0x24, 0x04, 0xef, 0xb5, 0xac, 0xe2, 0x9f, 0x33, 0x69, 0xc9, 0x56, 0xed, 0x56, 0xcc, 0x71, 0x8d, 0xc8, 0xa7, 0x17, 0x3d, 0x11, 0x66, 0xa8, 0xb1, 0x13, 0xc6, 0x04, 0x9f, 0x29, 0xcf, 0x65, 0x2f, 0x0b, 0xb9, 0x9c, 0x4d, 0x8e, 0x77, 0x79, 0xa0, 0xc2, 0xda, 0x1c, 0xd7, 0x88, 0x14, 0x7a, 0xbd, 0x48, 0x0e, 0x66, 0x18, 0x63, 0xa0, 0x7a, 0x72, 0xa0, 0x1e, 0x05, 0x3b, 0x9a, 0x27, 0xd3, 0xe2, 0x63, 0x74, 0x56, 0xb4, 0xcd, 0x71, 0x8d, 0x9c, 0xc6, 0x81, 0x69, 0xa9, 0x33, 0xd0, 0x88, 0x57, 0xd2, 0x2f, 0x83, 0x1d, 0xcd, 0x23, 0x69, 0xf1, 0x35, 0x3a, 0x2b, 0xda, 0xe6, 0xb8, 0x46, 0x4e, 0x8b, 0x3d, 0x47, 0x18, 0x68, 0x38, 0x64, 0x7c, 0x0e, 0x76, 0x34, 0x0f, 0xa7, 0xc5, 0xcf, 0xe8, 0xac, 0x68, 0xaf, 0xa4, 0x3c, 0xd7, 0xc8, 0x69, 0xb1, 0xe7, 0x30, 0x47, 0x3a, 0x4d, 0x0e, 0xe5, 0x59, 0x7b, 0xb4, 0x5e, 0xe1, 0x0a, 0xf9, 0x29, 0xdf, 0xa3, 0x19, 0x0a, 0x6d, 0x37, 0x18, 0x28, 0xee, 0xaa, 0xf3, 0x5a, 0xfb, 0x87, 0x30, 0xea, 0x2f, 0x89, 0x76, 0xac, 0x4d, 0x3c, 0x85, 0x4b, 0xb9, 0x70, 0x10, 0x6a, 0xc4, 0x9a, 0xb6, 0xe9, 0x69, 0x59, 0x66, 0xa0, 0xc2, 0x3d, 0x74, 0x24, 0xd3, 0x7e, 0x76, 0xfe, 0xe5, 0xd6, 0xfa, 0xd9, 0x71, 0x8d, 0xac, 0x74, 0xf1, 0x19, 0x66, 0xa0, 0xa5, 0x90, 0x71, 0x31, 0xd8, 0xd1, 0xfc, 0x91, 0x16, 0x47, 0xa3, 0xb3, 0xa2, 0xcd, 0xc1, 0x8b, 0x7c, 0xdf, 0x54, 0xdb, 0xfe, 0xc6, 0x9e, 0x4b, 0x0c, 0xf4, 0x24, 0xa4, 0x5c, 0x0b, 0x76, 0x34, 0x17, 0xd2, 0xe2, 0x54, 0x74, 0x56, 0xb4, 0xcd, 0xf9, 0xd4, 0x26, 0x3f, 0xf6, 0x9c, 0x63, 0xa0, 0x19, 0xe1, 0x77, 0x4a, 0xbe, 0x24, 0x7d, 0x3c, 0xd9, 0x51, 0xed, 0x74, 0xda, 0xc6, 0xbc, 0x32, 0xdb, 0x27, 0xb4, 0x6b, 0xc4, 0x1c, 0x7a, 0xd1, 0x13, 0x61, 0x86, 0x59, 0x06, 0xe2, 0xbb, 0xe9, 0xa9, 0x80, 0xf0, 0xa0, 0xc5, 0x77, 0xe5, 0x96, 0x53, 0x7f, 0xde, 0x27, 0x83, 0x97, 0xf8, 0x6e, 0xc5, 0x1c, 0xd7, 0x88, 0x7c, 0x7a, 0xd1, 0x13, 0x61, 0x86, 0xad, 0x6f, 0xb8, 0x71, 0x2d, 0xfc, 0xab, 0xbb, 0x1e, 0x6c, 0xfb, 0xfa, 0xa5, 0x63, 0x2f, 0x66, 0x28, 0x08, 0x2f, 0x49, 0xfd, 0x6a, 0xdc, 0xa9, 0x2e, 0xbd, 0xb7, 0x09, 0xaf, 0x91, 0x91, 0xd8, 0xc8, 0x32, 0xa6, 0x53, 0x7c, 0xd7, 0x5e, 0x61, 0xe9, 0xcf, 0x0b, 0xb7, 0x87, 0xe2, 0x45, 0x9c, 0x17, 0x72, 0xcb, 0xa8, 0x0c, 0x62, 0x8b, 0x02, 0xcf, 0x5e, 0x14, 0x73, 0xa2, 0x8f, 0x1c, 0x72, 0x89, 0xc1, 0xb5, 0x50, 0x93, 0xda, 0xe6, 0xd0, 0xb3, 0xad, 0x0c, 0x2a, 0xc2, 0xa7, 0x89, 0x93, 0x21, 0x36, 0x04, 0x9f, 0xaa, 0x6c, 0x7f, 0x62, 0xbb, 0xf6, 0x19, 0xa4, 0x5e, 0xad, 0x8f, 0xb7, 0xff, 0xe6, 0x43, 0x91, 0x81, 0x90, 0x21, 0x21, 0x5e, 0x29, 0xae, 0xca, 0xaa, 0x30, 0x25, 0x34, 0x05, 0xd6, 0xf1, 0x78, 0x60, 0x0d, 0x2c, 0xc4, 0x58, 0x37, 0x05, 0x38, 0x70, 0x9d, 0x83, 0xa6, 0x36, 0x3d, 0xba, 0x12, 0x6e, 0x5f, 0x7c, 0xa6, 0x5c, 0xd0, 0xf7, 0x9f, 0x2d, 0x3b, 0x21, 0xec, 0xca, 0x3f, 0x1b, 0xe2, 0xe4, 0xec, 0xbe, 0x5e, 0x1c, 0x09, 0xd4, 0xa0, 0x56, 0xcf, 0x84, 0x83, 0x6b, 0x5e, 0x58, 0x13, 0x7c, 0xb5, 0x3a, 0x69, 0x72, 0xe1, 0x6c, 0x3b, 0xf4, 0xe4, 0x2b, 0x15, 0x1f, 0xdb, 0xa5, 0xc1, 0x36, 0xce, 0x9a, 0xfc, 0x7c, 0xa9, 0xd4, 0x05, 0xde, 0x65, 0xca, 0xfe, 0xa5, 0xf7, 0x46, 0xfe, 0x39, 0x61, 0x46, 0xd8, 0xfa, 0x39, 0x90, 0xdd, 0x51, 0xfe, 0x02, 0x89, 0x7c, 0xcc, 0xd6, 0x15, 0x10, 0x0a, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXHierarchyIndentPattern[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00, 0xf9, 0x3c, 0x0f, 0xcd, 0x00, 0x00, 0x0a, 0x41, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0x9d, 0x96, 0x77, 0x54, 0x53, 0xd9, 0x16, 0x87, 0xcf, 0xbd, 0x37, 0xbd, 0xd0, 0x12, 0x22, 0x20, 0x25, 0xf4, 0x1a, 0x7a, 0x09, 0x20, 0xd2, 0x3b, 0x48, 0x15, 0x04, 0x51, 0x89, 0x49, 0x80, 0x50, 0x02, 0x86, 0x84, 0x26, 0x76, 0x44, 0x05, 0x46, 0x14, 0x11, 0x29, 0x56, 0x64, 0x54, 0xc0, 0x01, 0x47, 0x87, 0x22, 0x63, 0x45, 0x14, 0x0b, 0x83, 0x82, 0x62, 0xd7, 0x09, 0xf2, 0x10, 0x50, 0xc6, 0xc1, 0x51, 0x44, 0x45, 0xe5, 0xdd, 0x8c, 0x6b, 0x09, 0xef, 0xad, 0x35, 0xf3, 0xde, 0x9a, 0xfd, 0xc7, 0x59, 0xdf, 0xd9, 0xe7, 0xb7, 0xd7, 0xd9, 0x67, 0xef, 0x7d, 0xd7, 0xba, 0x00, 0x50, 0xfc, 0x82, 0x04, 0xc2, 0x74, 0x58, 0x01, 0x80, 0x34, 0xa1, 0x58, 0x14, 0xee, 0xeb, 0xc1, 0x5c, 0x12, 0x13, 0xcb, 0xc4, 0xf7, 0x02, 0x18, 0x10, 0x01, 0x0e, 0x58, 0x01, 0xc0, 0xe1, 0x66, 0x66, 0x04, 0x47, 0xf8, 0x44, 0x02, 0xd4, 0xfc, 0xbd, 0x3d, 0x99, 0x99, 0xa8, 0x48, 0xc6, 0xb3, 0xf6, 0xee, 0x2e, 0x80, 0x64, 0xbb, 0xdb, 0x2c, 0xbf, 0x50, 0x26, 0x73, 0xd6, 0xff, 0x7f, 0x91, 0x22, 0x37, 0x43, 0x24, 0x06, 0x00, 0x0a, 0x45, 0xd5, 0x36, 0x3c, 0x7e, 0x26, 0x17, 0xe5, 0x02, 0x94, 0x53, 0xb3, 0xc5, 0x19, 0x32, 0xff, 0x04, 0xca, 0xf4, 0x95, 0x29, 0x32, 0x86, 0x31, 0x32, 0x16, 0xa1, 0x09, 0xa2, 0xac, 0x22, 0xe3, 0xc4, 0xaf, 0x6c, 0xf6, 0xa7, 0xe6, 0x2b, 0xbb, 0xc9, 0x98, 0x97, 0x26, 0xe4, 0xa1, 0x1a, 0x59, 0xce, 0x19, 0xbc, 0x34, 0x9e, 0x8c, 0xbb, 0x50, 0xde, 0x9a, 0x25, 0xe1, 0xa3, 0x8c, 0x04, 0xa1, 0x5c, 0x98, 0x25, 0xe0, 0x67, 0xa3, 0x7c, 0x07, 0x65, 0xbd, 0x54, 0x49, 0x9a, 0x00, 0xe5, 0xf7, 0x28, 0xd3, 0xd3, 0xf8, 0x9c, 0x4c, 0x00, 0x30, 0x14, 0x99, 0x5f, 0xcc, 0xe7, 0x26, 0xa1, 0x6c, 0x89, 0x32, 0x45, 0x14, 0x19, 0xee, 0x89, 0xf2, 0x02, 0x00, 0x08, 0x94, 0xc4, 0x39, 0xbc, 0x72, 0x0e, 0x8b, 0xf9, 0x39, 0x68, 0x9e, 0x00, 0x78, 0xa6, 0x67, 0xe4, 0x8a, 0x04, 0x89, 0x49, 0x62, 0xa6, 0x11, 0xd7, 0x98, 0x69, 0xe5, 0xe8, 0xc8, 0x66, 0xfa, 0xf1, 0xb3, 0x53, 0xf9, 0x62, 0x31, 0x2b, 0x94, 0xc3, 0x4d, 0xe1, 0x88, 0x78, 0x4c, 0xcf, 0xf4, 0xb4, 0x0c, 0x8e, 0x30, 0x17, 0x80, 0xaf, 0x6f, 0x96, 0x45, 0x01, 0x25, 0x59, 0x6d, 0x99, 0x68, 0x91, 0xed, 0xad, 0x1c, 0xed, 0xed, 0x59, 0xd6, 0xe6, 0x68, 0xf9, 0xbf, 0xd9, 0xdf, 0x1e, 0x7e, 0x53, 0xfd, 0x3d, 0xc8, 0x7a, 0xfb, 0x55, 0xf1, 0x26, 0xec, 0xcf, 0x9e, 0x41, 0x8c, 0x9e, 0x59, 0xdf, 0x6c, 0xec, 0xac, 0x2f, 0xbd, 0x16, 0x00, 0xf6, 0x24, 0x5a, 0x9b, 0x1d, 0xb3, 0xbe, 0x95, 0x55, 0x00, 0xb4, 0x6d, 0x06, 0x40, 0xe5, 0xe1, 0xac, 0x4f, 0xef, 0x20, 0x00, 0xf2, 0x05, 0x00, 0xb4, 0xde, 0x9c, 0xf3, 0x1e, 0x86, 0x6c, 0x5e, 0x92, 0xc4, 0xe2, 0x0c, 0x27, 0x0b, 0x8b, 0xec, 0xec, 0x6c, 0x73, 0x01, 0x9f, 0x6b, 0x2e, 0x2b, 0xe8, 0x37, 0xfb, 0x9f, 0x82, 0x6f, 0xca, 0xbf, 0x86, 0x39, 0xf7, 0x99, 0xcb, 0xee, 0xfb, 0x56, 0x3b, 0xa6, 0x17, 0x3f, 0x81, 0x23, 0x49, 0x15, 0x33, 0x65, 0x45, 0xe5, 0xa6, 0xa7, 0xa6, 0x4b, 0x44, 0xcc, 0xcc, 0x0c, 0x0e, 0x97, 0xcf, 0x64, 0xfd, 0xf7, 0x10, 0xff, 0xe3, 0xc0, 0x39, 0x69, 0xcd, 0xc9, 0xc3, 0x2c, 0x9c, 0x9f, 0xc0, 0x17, 0xf1, 0x85, 0xe8, 0x55, 0x51, 0xe8, 0x94, 0x09, 0x84, 0x89, 0x68, 0xbb, 0x85, 0x3c, 0x81, 0x58, 0x90, 0x2e, 0x64, 0x0a, 0x84, 0x7f, 0xd5, 0xe1, 0x7f, 0x18, 0x36, 0x27, 0x07, 0x19, 0x7e, 0x9d, 0x6b, 0x14, 0x68, 0x75, 0x5f, 0x00, 0x7d, 0x85, 0x39, 0x50, 0xb8, 0x49, 0x07, 0xc8, 0x6f, 0x3d, 0x00, 0x43, 0x23, 0x03, 0x24, 0x6e, 0x3f, 0x7a, 0x02, 0x7d, 0xeb, 0x5b, 0x10, 0x31, 0x0a, 0xc8, 0xbe, 0xbc, 0x68, 0xad, 0x91, 0xaf, 0x73, 0x8f, 0x32, 0x7a, 0xfe, 0xe7, 0xfa, 0x1f, 0x0b, 0x5c, 0x8a, 0x6e, 0xe1, 0x4c, 0x41, 0x22, 0x53, 0xe6, 0xf6, 0x0c, 0x8f, 0x64, 0x72, 0x25, 0xa2, 0x2c, 0x19, 0xa3, 0xdf, 0x84, 0x6c, 0xc1, 0x02, 0x12, 0x90, 0x07, 0x74, 0xa0, 0x0a, 0x34, 0x81, 0x2e, 0x30, 0x02, 0x2c, 0x60, 0x0d, 0x1c, 0x80, 0x33, 0x70, 0x03, 0xde, 0x20, 0x00, 0x84, 0x80, 0x48, 0x10, 0x03, 0x96, 0x03, 0x2e, 0x48, 0x02, 0x69, 0x40, 0x04, 0xb2, 0x41, 0x3e, 0xd8, 0x00, 0x0a, 0x41, 0x31, 0xd8, 0x01, 0x76, 0x83, 0x6a, 0x70, 0x00, 0xd4, 0x81, 0x7a, 0xd0, 0x04, 0x4e, 0x82, 0x36, 0x70, 0x06, 0x5c, 0x04, 0x57, 0xc0, 0x0d, 0x70, 0x0b, 0x0c, 0x80, 0x47, 0x40, 0x0a, 0x86, 0xc1, 0x4b, 0x30, 0x01, 0xde, 0x81, 0x69, 0x08, 0x82, 0xf0, 0x10, 0x15, 0xa2, 0x41, 0xaa, 0x90, 0x16, 0xa4, 0x0f, 0x99, 0x42, 0xd6, 0x10, 0x1b, 0x5a, 0x08, 0x79, 0x43, 0x41, 0x50, 0x38, 0x14, 0x03, 0xc5, 0x43, 0x89, 0x90, 0x10, 0x92, 0x40, 0xf9, 0xd0, 0x26, 0xa8, 0x18, 0x2a, 0x83, 0xaa, 0xa1, 0x43, 0x50, 0x3d, 0xf4, 0x23, 0x74, 0x1a, 0xba, 0x08, 0x5d, 0x83, 0xfa, 0xa0, 0x07, 0xd0, 0x20, 0x34, 0x06, 0xfd, 0x01, 0x7d, 0x84, 0x11, 0x98, 0x02, 0xd3, 0x61, 0x0d, 0xd8, 0x00, 0xb6, 0x80, 0xd9, 0xb0, 0x3b, 0x1c, 0x08, 0x47, 0xc2, 0xcb, 0xe0, 0x44, 0x78, 0x15, 0x9c, 0x07, 0x17, 0xc0, 0xdb, 0xe1, 0x4a, 0xb8, 0x16, 0x3e, 0x0e, 0xb7, 0xc2, 0x17, 0xe1, 0x1b, 0xf0, 0x00, 0x2c, 0x85, 0x5f, 0xc2, 0x93, 0x08, 0x40, 0xc8, 0x08, 0x03, 0xd1, 0x46, 0x58, 0x08, 0x1b, 0xf1, 0x44, 0x42, 0x90, 0x58, 0x24, 0x01, 0x11, 0x21, 0x6b, 0x91, 0x22, 0xa4, 0x02, 0xa9, 0x45, 0x9a, 0x90, 0x0e, 0xa4, 0x1b, 0xb9, 0x8d, 0x48, 0x91, 0x71, 0xe4, 0x03, 0x06, 0x87, 0xa1, 0x61, 0x98, 0x18, 0x16, 0xc6, 0x19, 0xe3, 0x87, 0x59, 0x8c, 0xe1, 0x62, 0x56, 0x61, 0xd6, 0x62, 0x4a, 0x30, 0xd5, 0x98, 0x63, 0x98, 0x56, 0x4c, 0x17, 0xe6, 0x36, 0x66, 0x10, 0x33, 0x81, 0xf9, 0x82, 0xa5, 0x62, 0xd5, 0xb1, 0xa6, 0x58, 0x27, 0xac, 0x3f, 0x76, 0x09, 0x36, 0x11, 0x9b, 0x8d, 0x2d, 0xc4, 0x56, 0x60, 0x8f, 0x60, 0x5b, 0xb0, 0x97, 0xb1, 0x03, 0xd8, 0x61, 0xec, 0x3b, 0x1c, 0x0e, 0xc7, 0xc0, 0x19, 0xe2, 0x1c, 0x70, 0x7e, 0xb8, 0x18, 0x5c, 0x32, 0x6e, 0x35, 0xae, 0x04, 0xb7, 0x0f, 0xd7, 0x8c, 0xbb, 0x80, 0xeb, 0xc3, 0x0d, 0xe1, 0x26, 0xf1, 0x78, 0xbc, 0x2a, 0xde, 0x14, 0xef, 0x82, 0x0f, 0xc1, 0x73, 0xf0, 0x62, 0x7c, 0x21, 0xbe, 0x0a, 0x7f, 0x1c, 0x7f, 0x1e, 0xdf, 0x8f, 0x1f, 0xc6, 0xbf, 0x27, 0x90, 0x09, 0x5a, 0x04, 0x6b, 0x82, 0x0f, 0x21, 0x96, 0x20, 0x24, 0x6c, 0x24, 0x54, 0x10, 0x1a, 0x08, 0xe7, 0x08, 0xfd, 0x84, 0x11, 0xc2, 0x34, 0x51, 0x81, 0xa8, 0x4f, 0x74, 0x22, 0x86, 0x10, 0x79, 0xc4, 0x5c, 0x62, 0x29, 0xb1, 0x8e, 0xd8, 0x41, 0xbc, 0x49, 0x1c, 0x26, 0x4e, 0x93, 0x14, 0x49, 0x86, 0x24, 0x17, 0x52, 0x24, 0x29, 0x99, 0xb4, 0x81, 0x54, 0x49, 0x6a, 0x22, 0x5d, 0x26, 0x3d, 0x26, 0xbd, 0x21, 0x93, 0xc9, 0x3a, 0x64, 0x47, 0x72, 0x18, 0x59, 0x40, 0x5e, 0x4f, 0xae, 0x24, 0x9f, 0x20, 0x5f, 0x25, 0x0f, 0x92, 0x3f, 0x50, 0x94, 0x28, 0x26, 0x14, 0x4f, 0x4a, 0x1c, 0x45, 0x42, 0xd9, 0x4e, 0x39, 0x4a, 0xb9, 0x40, 0x79, 0x40, 0x79, 0x43, 0xa5, 0x52, 0x0d, 0xa8, 0x6e, 0xd4, 0x58, 0xaa, 0x98, 0xba, 0x9d, 0x5a, 0x4f, 0xbd, 0x44, 0x7d, 0x4a, 0x7d, 0x2f, 0x47, 0x93, 0x33, 0x97, 0xf3, 0x97, 0xe3, 0xc9, 0xad, 0x93, 0xab, 0x91, 0x6b, 0x95, 0xeb, 0x97, 0x7b, 0x25, 0x4f, 0x94, 0xd7, 0x97, 0x77, 0x97, 0x5f, 0x2e, 0x9f, 0x27, 0x5f, 0x21, 0x7f, 0x4a, 0xfe, 0xa6, 0xfc, 0xb8, 0x02, 0x51, 0xc1, 0x40, 0xc1, 0x53, 0x81, 0xa3, 0xb0, 0x56, 0xa1, 0x46, 0xe1, 0xb4, 0xc2, 0x3d, 0x85, 0x49, 0x45, 0x9a, 0xa2, 0x95, 0x62, 0x88, 0x62, 0x9a, 0x62, 0x89, 0x62, 0x83, 0xe2, 0x35, 0xc5, 0x51, 0x25, 0xbc, 0x92, 0x81, 0x92, 0xb7, 0x12, 0x4f, 0xa9, 0x40, 0xe9, 0xb0, 0xd2, 0x25, 0xa5, 0x21, 0x1a, 0x42, 0xd3, 0xa5, 0x79, 0xd2, 0xb8, 0xb4, 0x4d, 0xb4, 0x3a, 0xda, 0x65, 0xda, 0x30, 0x1d, 0x47, 0x37, 0xa4, 0xfb, 0xd3, 0x93, 0xe9, 0xc5, 0xf4, 0x1f, 0xe8, 0xbd, 0xf4, 0x09, 0x65, 0x25, 0x65, 0x5b, 0xe5, 0x28, 0xe5, 0x1c, 0xe5, 0x1a, 0xe5, 0xb3, 0xca, 0x52, 0x06, 0xc2, 0x30, 0x60, 0xf8, 0x33, 0x52, 0x19, 0xa5, 0x8c, 0x93, 0x8c, 0xbb, 0x8c, 0x8f, 0xf3, 0x34, 0xe6, 0xb9, 0xcf, 0xe3, 0xcf, 0xdb, 0x36, 0xaf, 0x69, 0x5e, 0xff, 0xbc, 0x29, 0x95, 0xf9, 0x2a, 0x6e, 0x2a, 0x7c, 0x95, 0x22, 0x95, 0x66, 0x95, 0x01, 0x95, 0x8f, 0xaa, 0x4c, 0x55, 0x6f, 0xd5, 0x14, 0xd5, 0x9d, 0xaa, 0x6d, 0xaa, 0x4f, 0xd4, 0x30, 0x6a, 0x26, 0x6a, 0x61, 0x6a, 0xd9, 0x6a, 0xfb, 0xd5, 0x2e, 0xab, 0x8d, 0xcf, 0xa7, 0xcf, 0x77, 0x9e, 0xcf, 0x9d, 0x5f, 0x34, 0xff, 0xe4, 0xfc, 0x87, 0xea, 0xb0, 0xba, 0x89, 0x7a, 0xb8, 0xfa, 0x6a, 0xf5, 0xc3, 0xea, 0x3d, 0xea, 0x93, 0x1a, 0x9a, 0x1a, 0xbe, 0x1a, 0x19, 0x1a, 0x55, 0x1a, 0x97, 0x34, 0xc6, 0x35, 0x19, 0x9a, 0x6e, 0x9a, 0xc9, 0x9a, 0xe5, 0x9a, 0xe7, 0x34, 0xc7, 0xb4, 0x68, 0x5a, 0x0b, 0xb5, 0x04, 0x5a, 0xe5, 0x5a, 0xe7, 0xb5, 0x5e, 0x30, 0x95, 0x99, 0xee, 0xcc, 0x54, 0x66, 0x25, 0xb3, 0x8b, 0x39, 0xa1, 0xad, 0xae, 0xed, 0xa7, 0x2d, 0xd1, 0x3e, 0xa4, 0xdd, 0xab, 0x3d, 0xad, 0x63, 0xa8, 0xb3, 0x58, 0x67, 0xa3, 0x4e, 0xb3, 0xce, 0x13, 0x5d, 0x92, 0x2e, 0x5b, 0x37, 0x41, 0xb7, 0x5c, 0xb7, 0x53, 0x77, 0x42, 0x4f, 0x4b, 0x2f, 0x58, 0x2f, 0x5f, 0xaf, 0x51, 0xef, 0xa1, 0x3e, 0x51, 0x9f, 0xad, 0x9f, 0xa4, 0xbf, 0x47, 0xbf, 0x5b, 0x7f, 0xca, 0xc0, 0xd0, 0x20, 0xda, 0x60, 0x8b, 0x41, 0x9b, 0xc1, 0xa8, 0xa1, 0x8a, 0xa1, 0xbf, 0x61, 0x9e, 0x61, 0xa3, 0xe1, 0x63, 0x23, 0xaa, 0x91, 0xab, 0xd1, 0x2a, 0xa3, 0x5a, 0xa3, 0x3b, 0xc6, 0x38, 0x63, 0xb6, 0x71, 0x8a, 0xf1, 0x3e, 0xe3, 0x5b, 0x26, 0xb0, 0x89, 0x9d, 0x49, 0x92, 0x49, 0x8d, 0xc9, 0x4d, 0x53, 0xd8, 0xd4, 0xde, 0x54, 0x60, 0xba, 0xcf, 0xb4, 0xcf, 0x0c, 0x6b, 0xe6, 0x68, 0x26, 0x34, 0xab, 0x35, 0xbb, 0xc7, 0xa2, 0xb0, 0xdc, 0x59, 0x59, 0xac, 0x46, 0xd6, 0xa0, 0x39, 0xc3, 0x3c, 0xc8, 0x7c, 0xa3, 0x79, 0x9b, 0xf9, 0x2b, 0x0b, 0x3d, 0x8b, 0x58, 0x8b, 0x9d, 0x16, 0xdd, 0x16, 0x5f, 0x2c, 0xed, 0x2c, 0x53, 0x2d, 0xeb, 0x2c, 0x1f, 0x59, 0x29, 0x59, 0x05, 0x58, 0x6d, 0xb4, 0xea, 0xb0, 0xfa, 0xc3, 0xda, 0xc4, 0x9a, 0x6b, 0x5d, 0x63, 0x7d, 0xc7, 0x86, 0x6a, 0xe3, 0x63, 0xb3, 0xce, 0xa6, 0xdd, 0xe6, 0xb5, 0xad, 0xa9, 0x2d, 0xdf, 0x76, 0xbf, 0xed, 0x7d, 0x3b, 0x9a, 0x5d, 0xb0, 0xdd, 0x16, 0xbb, 0x4e, 0xbb, 0xcf, 0xf6, 0x0e, 0xf6, 0x22, 0xfb, 0x26, 0xfb, 0x31, 0x07, 0x3d, 0x87, 0x78, 0x87, 0xbd, 0x0e, 0xf7, 0xd8, 0x74, 0x76, 0x28, 0xbb, 0x84, 0x7d, 0xd5, 0x11, 0xeb, 0xe8, 0xe1, 0xb8, 0xce, 0xf1, 0x8c, 0xe3, 0x07, 0x27, 0x7b, 0x27, 0xb1, 0xd3, 0x49, 0xa7, 0xdf, 0x9d, 0x59, 0xce, 0x29, 0xce, 0x0d, 0xce, 0xa3, 0x0b, 0x0c, 0x17, 0xf0, 0x17, 0xd4, 0x2d, 0x18, 0x72, 0xd1, 0x71, 0xe1, 0xb8, 0x1c, 0x72, 0x91, 0x2e, 0x64, 0x2e, 0x8c, 0x5f, 0x78, 0x70, 0xa1, 0xd4, 0x55, 0xdb, 0x95, 0xe3, 0x5a, 0xeb, 0xfa, 0xcc, 0x4d, 0xd7, 0x8d, 0xe7, 0x76, 0xc4, 0x6d, 0xc4, 0xdd, 0xd8, 0x3d, 0xd9, 0xfd, 0xb8, 0xfb, 0x2b, 0x0f, 0x4b, 0x0f, 0x91, 0x47, 0x8b, 0xc7, 0x94, 0xa7, 0x93, 0xe7, 0x1a, 0xcf, 0x0b, 0x5e, 0x88, 0x97, 0xaf, 0x57, 0x91, 0x57, 0xaf, 0xb7, 0x92, 0xf7, 0x62, 0xef, 0x6a, 0xef, 0xa7, 0x3e, 0x3a, 0x3e, 0x89, 0x3e, 0x8d, 0x3e, 0x13, 0xbe, 0x76, 0xbe, 0xab, 0x7d, 0x2f, 0xf8, 0x61, 0xfd, 0x02, 0xfd, 0x76, 0xfa, 0xdd, 0xf3, 0xd7, 0xf0, 0xe7, 0xfa, 0xd7, 0xfb, 0x4f, 0x04, 0x38, 0x04, 0xac, 0x09, 0xe8, 0x0a, 0xa4, 0x04, 0x46, 0x04, 0x56, 0x07, 0x3e, 0x0b, 0x32, 0x09, 0x12, 0x05, 0x75, 0x04, 0xc3, 0xc1, 0x01, 0xc1, 0xbb, 0x82, 0x1f, 0x2f, 0xd2, 0x5f, 0x24, 0x5c, 0xd4, 0x16, 0x02, 0x42, 0xfc, 0x43, 0x76, 0x85, 0x3c, 0x09, 0x35, 0x0c, 0x5d, 0x15, 0xfa, 0x73, 0x18, 0x2e, 0x2c, 0x34, 0xac, 0x26, 0xec, 0x79, 0xb8, 0x55, 0x78, 0x7e, 0x78, 0x77, 0x04, 0x2d, 0x62, 0x45, 0x44, 0x43, 0xc4, 0xbb, 0x48, 0x8f, 0xc8, 0xd2, 0xc8, 0x47, 0x8b, 0x8d, 0x16, 0x4b, 0x16, 0x77, 0x46, 0xc9, 0x47, 0xc5, 0x45, 0xd5, 0x47, 0x4d, 0x45, 0x7b, 0x45, 0x97, 0x45, 0x4b, 0x97, 0x58, 0x2c, 0x59, 0xb3, 0xe4, 0x46, 0x8c, 0x5a, 0x8c, 0x20, 0xa6, 0x3d, 0x16, 0x1f, 0x1b, 0x15, 0x7b, 0x24, 0x76, 0x72, 0xa9, 0xf7, 0xd2, 0xdd, 0x4b, 0x87, 0xe3, 0xec, 0xe2, 0x0a, 0xe3, 0xee, 0x2e, 0x33, 0x5c, 0x96, 0xb3, 0xec, 0xda, 0x72, 0xb5, 0xe5, 0xa9, 0xcb, 0xcf, 0xae, 0x90, 0x5f, 0xc1, 0x59, 0x71, 0x2a, 0x1e, 0x1b, 0x1f, 0x1d, 0xdf, 0x10, 0xff, 0x89, 0x13, 0xc2, 0xa9, 0xe5, 0x4c, 0xae, 0xf4, 0x5f, 0xb9, 0x77, 0xe5, 0x04, 0xd7, 0x93, 0xbb, 0x87, 0xfb, 0x92, 0xe7, 0xc6, 0x2b, 0xe7, 0x8d, 0xf1, 0x5d, 0xf8, 0x65, 0xfc, 0x91, 0x04, 0x97, 0x84, 0xb2, 0x84, 0xd1, 0x44, 0x97, 0xc4, 0x5d, 0x89, 0x63, 0x49, 0xae, 0x49, 0x15, 0x49, 0xe3, 0x02, 0x4f, 0x41, 0xb5, 0xe0, 0x75, 0xb2, 0x5f, 0xf2, 0x81, 0xe4, 0xa9, 0x94, 0x90, 0x94, 0xa3, 0x29, 0x33, 0xa9, 0xd1, 0xa9, 0xcd, 0x69, 0x84, 0xb4, 0xf8, 0xb4, 0xd3, 0x42, 0x25, 0x61, 0x8a, 0xb0, 0x2b, 0x5d, 0x33, 0x3d, 0x27, 0xbd, 0x2f, 0xc3, 0x34, 0xa3, 0x30, 0x43, 0xba, 0xca, 0x69, 0xd5, 0xee, 0x55, 0x13, 0xa2, 0x40, 0xd1, 0x91, 0x4c, 0x28, 0x73, 0x59, 0x66, 0xbb, 0x98, 0x8e, 0xfe, 0x4c, 0xf5, 0x48, 0x8c, 0x24, 0x9b, 0x25, 0x83, 0x59, 0x0b, 0xb3, 0x6a, 0xb2, 0xde, 0x67, 0x47, 0x65, 0x9f, 0xca, 0x51, 0xcc, 0x11, 0xe6, 0xf4, 0xe4, 0x9a, 0xe4, 0x6e, 0xcb, 0x1d, 0xc9, 0xf3, 0xc9, 0xfb, 0x7e, 0x35, 0x66, 0x35, 0x77, 0x75, 0x67, 0xbe, 0x76, 0xfe, 0x86, 0xfc, 0xc1, 0x35, 0xee, 0x6b, 0x0e, 0xad, 0x85, 0xd6, 0xae, 0x5c, 0xdb, 0xb9, 0x4e, 0x77, 0x5d, 0xc1, 0xba, 0xe1, 0xf5, 0xbe, 0xeb, 0x8f, 0x6d, 0x20, 0x6d, 0x48, 0xd9, 0xf0, 0xcb, 0x46, 0xcb, 0x8d, 0x65, 0x1b, 0xdf, 0x6e, 0x8a, 0xde, 0xd4, 0x51, 0xa0, 0x51, 0xb0, 0xbe, 0x60, 0x68, 0xb3, 0xef, 0xe6, 0xc6, 0x42, 0xb9, 0x42, 0x51, 0xe1, 0xbd, 0x2d, 0xce, 0x5b, 0x0e, 0x6c, 0xc5, 0x6c, 0x15, 0x6c, 0xed, 0xdd, 0x66, 0xb3, 0xad, 0x6a, 0xdb, 0x97, 0x22, 0x5e, 0xd1, 0xf5, 0x62, 0xcb, 0xe2, 0x8a, 0xe2, 0x4f, 0x25, 0xdc, 0x92, 0xeb, 0xdf, 0x59, 0x7d, 0x57, 0xf9, 0xdd, 0xcc, 0xf6, 0x84, 0xed, 0xbd, 0xa5, 0xf6, 0xa5, 0xfb, 0x77, 0xe0, 0x76, 0x08, 0x77, 0xdc, 0xdd, 0xe9, 0xba, 0xf3, 0x58, 0x99, 0x62, 0x59, 0x5e, 0xd9, 0xd0, 0xae, 0xe0, 0x5d, 0xad, 0xe5, 0xcc, 0xf2, 0xa2, 0xf2, 0xb7, 0xbb, 0x57, 0xec, 0xbe, 0x56, 0x61, 0x5b, 0x71, 0x60, 0x0f, 0x69, 0x8f, 0x64, 0x8f, 0xb4, 0x32, 0xa8, 0xb2, 0xbd, 0x4a, 0xaf, 0x6a, 0x47, 0xd5, 0xa7, 0xea, 0xa4, 0xea, 0x81, 0x1a, 0x8f, 0x9a, 0xe6, 0xbd, 0xea, 0x7b, 0xb7, 0xed, 0x9d, 0xda, 0xc7, 0xdb, 0xd7, 0xbf, 0xdf, 0x6d, 0x7f, 0xd3, 0x01, 0x8d, 0x03, 0xc5, 0x07, 0x3e, 0x1e, 0x14, 0x1c, 0xbc, 0x7f, 0xc8, 0xf7, 0x50, 0x6b, 0xad, 0x41, 0x6d, 0xc5, 0x61, 0xdc, 0xe1, 0xac, 0xc3, 0xcf, 0xeb, 0xa2, 0xea, 0xba, 0xbf, 0x67, 0x7f, 0x5f, 0x7f, 0x44, 0xed, 0x48, 0xf1, 0x91, 0xcf, 0x47, 0x85, 0x47, 0xa5, 0xc7, 0xc2, 0x8f, 0x75, 0xd5, 0x3b, 0xd4, 0xd7, 0x37, 0xa8, 0x37, 0x94, 0x36, 0xc2, 0x8d, 0x92, 0xc6, 0xb1, 0xe3, 0x71, 0xc7, 0x6f, 0xfd, 0xe0, 0xf5, 0x43, 0x7b, 0x13, 0xab, 0xe9, 0x50, 0x33, 0xa3, 0xb9, 0xf8, 0x04, 0x38, 0x21, 0x39, 0xf1, 0xe2, 0xc7, 0xf8, 0x1f, 0xef, 0x9e, 0x0c, 0x3c, 0xd9, 0x79, 0x8a, 0x7d, 0xaa, 0xe9, 0x27, 0xfd, 0x9f, 0xf6, 0xb6, 0xd0, 0x5a, 0x8a, 0x5a, 0xa1, 0xd6, 0xdc, 0xd6, 0x89, 0xb6, 0xa4, 0x36, 0x69, 0x7b, 0x4c, 0x7b, 0xdf, 0xe9, 0x80, 0xd3, 0x9d, 0x1d, 0xce, 0x1d, 0x2d, 0x3f, 0x9b, 0xff, 0x7c, 0xf4, 0x8c, 0xf6, 0x99, 0x9a, 0xb3, 0xca, 0x67, 0x4b, 0xcf, 0x91, 0xce, 0x15, 0x9c, 0x9b, 0x39, 0x9f, 0x77, 0x7e, 0xf2, 0x42, 0xc6, 0x85, 0xf1, 0x8b, 0x89, 0x17, 0x87, 0x3a, 0x57, 0x74, 0x3e, 0xba, 0xb4, 0xe4, 0xd2, 0x9d, 0xae, 0xb0, 0xae, 0xde, 0xcb, 0x81, 0x97, 0xaf, 0x5e, 0xf1, 0xb9, 0x72, 0xa9, 0xdb, 0xbd, 0xfb, 0xfc, 0x55, 0x97, 0xab, 0x67, 0xae, 0x39, 0x5d, 0x3b, 0x7d, 0x9d, 0x7d, 0xbd, 0xed, 0x86, 0xfd, 0x8d, 0xd6, 0x1e, 0xbb, 0x9e, 0x96, 0x5f, 0xec, 0x7e, 0x69, 0xe9, 0xb5, 0xef, 0x6d, 0xbd, 0xe9, 0x70, 0xb3, 0xfd, 0x96, 0xe3, 0xad, 0x8e, 0xbe, 0x05, 0x7d, 0xe7, 0xfa, 0x5d, 0xfb, 0x2f, 0xde, 0xf6, 0xba, 0x7d, 0xe5, 0x8e, 0xff, 0x9d, 0x1b, 0x03, 0x8b, 0x06, 0xfa, 0xee, 0x2e, 0xbe, 0x7b, 0xff, 0x5e, 0xdc, 0x3d, 0xe9, 0x7d, 0xde, 0xfd, 0xd1, 0x07, 0xa9, 0x0f, 0x5e, 0x3f, 0xcc, 0x7a, 0x38, 0xfd, 0x68, 0xfd, 0x63, 0xec, 0xe3, 0xa2, 0x27, 0x0a, 0x4f, 0x2a, 0x9e, 0xaa, 0x3f, 0xad, 0xfd, 0xd5, 0xf8, 0xd7, 0x66, 0xa9, 0xbd, 0xf4, 0xec, 0xa0, 0xd7, 0x60, 0xcf, 0xb3, 0x88, 0x67, 0x8f, 0x86, 0xb8, 0x43, 0x2f, 0xff, 0x95, 0xf9, 0xaf, 0x4f, 0xc3, 0x05, 0xcf, 0xa9, 0xcf, 0x2b, 0x46, 0xb4, 0x46, 0xea, 0x47, 0xad, 0x47, 0xcf, 0x8c, 0xf9, 0x8c, 0xdd, 0x7a, 0xb1, 0xf4, 0xc5, 0xf0, 0xcb, 0x8c, 0x97, 0xd3, 0xe3, 0x85, 0xbf, 0x29, 0xfe, 0xb6, 0xf7, 0x95, 0xd1, 0xab, 0x9f, 0x7e, 0x77, 0xfb, 0xbd, 0x67, 0x62, 0xc9, 0xc4, 0xf0, 0x6b, 0xd1, 0xeb, 0x99, 0x3f, 0x4a, 0xde, 0xa8, 0xbe, 0x39, 0xfa, 0xd6, 0xf6, 0x6d, 0xe7, 0x64, 0xe8, 0xe4, 0xd3, 0x77, 0x69, 0xef, 0xa6, 0xa7, 0x8a, 0xde, 0xab, 0xbe, 0x3f, 0xf6, 0x81, 0xfd, 0xa1, 0xfb, 0x63, 0xf4, 0xc7, 0x91, 0xe9, 0xec, 0x4f, 0xf8, 0x4f, 0x95, 0x9f, 0x8d, 0x3f, 0x77, 0x7c, 0x09, 0xfc, 0xf2, 0x78, 0x26, 0x6d, 0x66, 0xe6, 0xdf, 0xf7, 0x84, 0xf3, 0xfb, 0x32, 0x3a, 0x59, 0x7e, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa4, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x35, 0x2d, 0x30, 0x32, 0x54, 0x31, 0x31, 0x3a, 0x30, 0x35, 0x3a, 0x35, 0x35, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc0, 0x10, 0xf8, 0x70, 0x00, 0x00, 0x00, 0x10, 0x49, 0x44, 0x41, 0x54, 0x08, 0x1d, 0x63, 0x60, 0x60, 0x60, 0xf8, 0x0f, 0xc4, 0x70, 0x00, 0x00, 0x0d, 0x04, 0x01, 0x00, 0x65, 0x59, 0x09, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXHierarchyIndentPattern2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00, 0xe3, 0x00, 0xef, 0x43, 0x00, 0x00, 0x0a, 0x41, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0x9d, 0x96, 0x77, 0x54, 0x53, 0xd9, 0x16, 0x87, 0xcf, 0xbd, 0x37, 0xbd, 0xd0, 0x12, 0x22, 0x20, 0x25, 0xf4, 0x1a, 0x7a, 0x09, 0x20, 0xd2, 0x3b, 0x48, 0x15, 0x04, 0x51, 0x89, 0x49, 0x80, 0x50, 0x02, 0x86, 0x84, 0x26, 0x76, 0x44, 0x05, 0x46, 0x14, 0x11, 0x29, 0x56, 0x64, 0x54, 0xc0, 0x01, 0x47, 0x87, 0x22, 0x63, 0x45, 0x14, 0x0b, 0x83, 0x82, 0x62, 0xd7, 0x09, 0xf2, 0x10, 0x50, 0xc6, 0xc1, 0x51, 0x44, 0x45, 0xe5, 0xdd, 0x8c, 0x6b, 0x09, 0xef, 0xad, 0x35, 0xf3, 0xde, 0x9a, 0xfd, 0xc7, 0x59, 0xdf, 0xd9, 0xe7, 0xb7, 0xd7, 0xd9, 0x67, 0xef, 0x7d, 0xd7, 0xba, 0x00, 0x50, 0xfc, 0x82, 0x04, 0xc2, 0x74, 0x58, 0x01, 0x80, 0x34, 0xa1, 0x58, 0x14, 0xee, 0xeb, 0xc1, 0x5c, 0x12, 0x13, 0xcb, 0xc4, 0xf7, 0x02, 0x18, 0x10, 0x01, 0x0e, 0x58, 0x01, 0xc0, 0xe1, 0x66, 0x66, 0x04, 0x47, 0xf8, 0x44, 0x02, 0xd4, 0xfc, 0xbd, 0x3d, 0x99, 0x99, 0xa8, 0x48, 0xc6, 0xb3, 0xf6, 0xee, 0x2e, 0x80, 0x64, 0xbb, 0xdb, 0x2c, 0xbf, 0x50, 0x26, 0x73, 0xd6, 0xff, 0x7f, 0x91, 0x22, 0x37, 0x43, 0x24, 0x06, 0x00, 0x0a, 0x45, 0xd5, 0x36, 0x3c, 0x7e, 0x26, 0x17, 0xe5, 0x02, 0x94, 0x53, 0xb3, 0xc5, 0x19, 0x32, 0xff, 0x04, 0xca, 0xf4, 0x95, 0x29, 0x32, 0x86, 0x31, 0x32, 0x16, 0xa1, 0x09, 0xa2, 0xac, 0x22, 0xe3, 0xc4, 0xaf, 0x6c, 0xf6, 0xa7, 0xe6, 0x2b, 0xbb, 0xc9, 0x98, 0x97, 0x26, 0xe4, 0xa1, 0x1a, 0x59, 0xce, 0x19, 0xbc, 0x34, 0x9e, 0x8c, 0xbb, 0x50, 0xde, 0x9a, 0x25, 0xe1, 0xa3, 0x8c, 0x04, 0xa1, 0x5c, 0x98, 0x25, 0xe0, 0x67, 0xa3, 0x7c, 0x07, 0x65, 0xbd, 0x54, 0x49, 0x9a, 0x00, 0xe5, 0xf7, 0x28, 0xd3, 0xd3, 0xf8, 0x9c, 0x4c, 0x00, 0x30, 0x14, 0x99, 0x5f, 0xcc, 0xe7, 0x26, 0xa1, 0x6c, 0x89, 0x32, 0x45, 0x14, 0x19, 0xee, 0x89, 0xf2, 0x02, 0x00, 0x08, 0x94, 0xc4, 0x39, 0xbc, 0x72, 0x0e, 0x8b, 0xf9, 0x39, 0x68, 0x9e, 0x00, 0x78, 0xa6, 0x67, 0xe4, 0x8a, 0x04, 0x89, 0x49, 0x62, 0xa6, 0x11, 0xd7, 0x98, 0x69, 0xe5, 0xe8, 0xc8, 0x66, 0xfa, 0xf1, 0xb3, 0x53, 0xf9, 0x62, 0x31, 0x2b, 0x94, 0xc3, 0x4d, 0xe1, 0x88, 0x78, 0x4c, 0xcf, 0xf4, 0xb4, 0x0c, 0x8e, 0x30, 0x17, 0x80, 0xaf, 0x6f, 0x96, 0x45, 0x01, 0x25, 0x59, 0x6d, 0x99, 0x68, 0x91, 0xed, 0xad, 0x1c, 0xed, 0xed, 0x59, 0xd6, 0xe6, 0x68, 0xf9, 0xbf, 0xd9, 0xdf, 0x1e, 0x7e, 0x53, 0xfd, 0x3d, 0xc8, 0x7a, 0xfb, 0x55, 0xf1, 0x26, 0xec, 0xcf, 0x9e, 0x41, 0x8c, 0x9e, 0x59, 0xdf, 0x6c, 0xec, 0xac, 0x2f, 0xbd, 0x16, 0x00, 0xf6, 0x24, 0x5a, 0x9b, 0x1d, 0xb3, 0xbe, 0x95, 0x55, 0x00, 0xb4, 0x6d, 0x06, 0x40, 0xe5, 0xe1, 0xac, 0x4f, 0xef, 0x20, 0x00, 0xf2, 0x05, 0x00, 0xb4, 0xde, 0x9c, 0xf3, 0x1e, 0x86, 0x6c, 0x5e, 0x92, 0xc4, 0xe2, 0x0c, 0x27, 0x0b, 0x8b, 0xec, 0xec, 0x6c, 0x73, 0x01, 0x9f, 0x6b, 0x2e, 0x2b, 0xe8, 0x37, 0xfb, 0x9f, 0x82, 0x6f, 0xca, 0xbf, 0x86, 0x39, 0xf7, 0x99, 0xcb, 0xee, 0xfb, 0x56, 0x3b, 0xa6, 0x17, 0x3f, 0x81, 0x23, 0x49, 0x15, 0x33, 0x65, 0x45, 0xe5, 0xa6, 0xa7, 0xa6, 0x4b, 0x44, 0xcc, 0xcc, 0x0c, 0x0e, 0x97, 0xcf, 0x64, 0xfd, 0xf7, 0x10, 0xff, 0xe3, 0xc0, 0x39, 0x69, 0xcd, 0xc9, 0xc3, 0x2c, 0x9c, 0x9f, 0xc0, 0x17, 0xf1, 0x85, 0xe8, 0x55, 0x51, 0xe8, 0x94, 0x09, 0x84, 0x89, 0x68, 0xbb, 0x85, 0x3c, 0x81, 0x58, 0x90, 0x2e, 0x64, 0x0a, 0x84, 0x7f, 0xd5, 0xe1, 0x7f, 0x18, 0x36, 0x27, 0x07, 0x19, 0x7e, 0x9d, 0x6b, 0x14, 0x68, 0x75, 0x5f, 0x00, 0x7d, 0x85, 0x39, 0x50, 0xb8, 0x49, 0x07, 0xc8, 0x6f, 0x3d, 0x00, 0x43, 0x23, 0x03, 0x24, 0x6e, 0x3f, 0x7a, 0x02, 0x7d, 0xeb, 0x5b, 0x10, 0x31, 0x0a, 0xc8, 0xbe, 0xbc, 0x68, 0xad, 0x91, 0xaf, 0x73, 0x8f, 0x32, 0x7a, 0xfe, 0xe7, 0xfa, 0x1f, 0x0b, 0x5c, 0x8a, 0x6e, 0xe1, 0x4c, 0x41, 0x22, 0x53, 0xe6, 0xf6, 0x0c, 0x8f, 0x64, 0x72, 0x25, 0xa2, 0x2c, 0x19, 0xa3, 0xdf, 0x84, 0x6c, 0xc1, 0x02, 0x12, 0x90, 0x07, 0x74, 0xa0, 0x0a, 0x34, 0x81, 0x2e, 0x30, 0x02, 0x2c, 0x60, 0x0d, 0x1c, 0x80, 0x33, 0x70, 0x03, 0xde, 0x20, 0x00, 0x84, 0x80, 0x48, 0x10, 0x03, 0x96, 0x03, 0x2e, 0x48, 0x02, 0x69, 0x40, 0x04, 0xb2, 0x41, 0x3e, 0xd8, 0x00, 0x0a, 0x41, 0x31, 0xd8, 0x01, 0x76, 0x83, 0x6a, 0x70, 0x00, 0xd4, 0x81, 0x7a, 0xd0, 0x04, 0x4e, 0x82, 0x36, 0x70, 0x06, 0x5c, 0x04, 0x57, 0xc0, 0x0d, 0x70, 0x0b, 0x0c, 0x80, 0x47, 0x40, 0x0a, 0x86, 0xc1, 0x4b, 0x30, 0x01, 0xde, 0x81, 0x69, 0x08, 0x82, 0xf0, 0x10, 0x15, 0xa2, 0x41, 0xaa, 0x90, 0x16, 0xa4, 0x0f, 0x99, 0x42, 0xd6, 0x10, 0x1b, 0x5a, 0x08, 0x79, 0x43, 0x41, 0x50, 0x38, 0x14, 0x03, 0xc5, 0x43, 0x89, 0x90, 0x10, 0x92, 0x40, 0xf9, 0xd0, 0x26, 0xa8, 0x18, 0x2a, 0x83, 0xaa, 0xa1, 0x43, 0x50, 0x3d, 0xf4, 0x23, 0x74, 0x1a, 0xba, 0x08, 0x5d, 0x83, 0xfa, 0xa0, 0x07, 0xd0, 0x20, 0x34, 0x06, 0xfd, 0x01, 0x7d, 0x84, 0x11, 0x98, 0x02, 0xd3, 0x61, 0x0d, 0xd8, 0x00, 0xb6, 0x80, 0xd9, 0xb0, 0x3b, 0x1c, 0x08, 0x47, 0xc2, 0xcb, 0xe0, 0x44, 0x78, 0x15, 0x9c, 0x07, 0x17, 0xc0, 0xdb, 0xe1, 0x4a, 0xb8, 0x16, 0x3e, 0x0e, 0xb7, 0xc2, 0x17, 0xe1, 0x1b, 0xf0, 0x00, 0x2c, 0x85, 0x5f, 0xc2, 0x93, 0x08, 0x40, 0xc8, 0x08, 0x03, 0xd1, 0x46, 0x58, 0x08, 0x1b, 0xf1, 0x44, 0x42, 0x90, 0x58, 0x24, 0x01, 0x11, 0x21, 0x6b, 0x91, 0x22, 0xa4, 0x02, 0xa9, 0x45, 0x9a, 0x90, 0x0e, 0xa4, 0x1b, 0xb9, 0x8d, 0x48, 0x91, 0x71, 0xe4, 0x03, 0x06, 0x87, 0xa1, 0x61, 0x98, 0x18, 0x16, 0xc6, 0x19, 0xe3, 0x87, 0x59, 0x8c, 0xe1, 0x62, 0x56, 0x61, 0xd6, 0x62, 0x4a, 0x30, 0xd5, 0x98, 0x63, 0x98, 0x56, 0x4c, 0x17, 0xe6, 0x36, 0x66, 0x10, 0x33, 0x81, 0xf9, 0x82, 0xa5, 0x62, 0xd5, 0xb1, 0xa6, 0x58, 0x27, 0xac, 0x3f, 0x76, 0x09, 0x36, 0x11, 0x9b, 0x8d, 0x2d, 0xc4, 0x56, 0x60, 0x8f, 0x60, 0x5b, 0xb0, 0x97, 0xb1, 0x03, 0xd8, 0x61, 0xec, 0x3b, 0x1c, 0x0e, 0xc7, 0xc0, 0x19, 0xe2, 0x1c, 0x70, 0x7e, 0xb8, 0x18, 0x5c, 0x32, 0x6e, 0x35, 0xae, 0x04, 0xb7, 0x0f, 0xd7, 0x8c, 0xbb, 0x80, 0xeb, 0xc3, 0x0d, 0xe1, 0x26, 0xf1, 0x78, 0xbc, 0x2a, 0xde, 0x14, 0xef, 0x82, 0x0f, 0xc1, 0x73, 0xf0, 0x62, 0x7c, 0x21, 0xbe, 0x0a, 0x7f, 0x1c, 0x7f, 0x1e, 0xdf, 0x8f, 0x1f, 0xc6, 0xbf, 0x27, 0x90, 0x09, 0x5a, 0x04, 0x6b, 0x82, 0x0f, 0x21, 0x96, 0x20, 0x24, 0x6c, 0x24, 0x54, 0x10, 0x1a, 0x08, 0xe7, 0x08, 0xfd, 0x84, 0x11, 0xc2, 0x34, 0x51, 0x81, 0xa8, 0x4f, 0x74, 0x22, 0x86, 0x10, 0x79, 0xc4, 0x5c, 0x62, 0x29, 0xb1, 0x8e, 0xd8, 0x41, 0xbc, 0x49, 0x1c, 0x26, 0x4e, 0x93, 0x14, 0x49, 0x86, 0x24, 0x17, 0x52, 0x24, 0x29, 0x99, 0xb4, 0x81, 0x54, 0x49, 0x6a, 0x22, 0x5d, 0x26, 0x3d, 0x26, 0xbd, 0x21, 0x93, 0xc9, 0x3a, 0x64, 0x47, 0x72, 0x18, 0x59, 0x40, 0x5e, 0x4f, 0xae, 0x24, 0x9f, 0x20, 0x5f, 0x25, 0x0f, 0x92, 0x3f, 0x50, 0x94, 0x28, 0x26, 0x14, 0x4f, 0x4a, 0x1c, 0x45, 0x42, 0xd9, 0x4e, 0x39, 0x4a, 0xb9, 0x40, 0x79, 0x40, 0x79, 0x43, 0xa5, 0x52, 0x0d, 0xa8, 0x6e, 0xd4, 0x58, 0xaa, 0x98, 0xba, 0x9d, 0x5a, 0x4f, 0xbd, 0x44, 0x7d, 0x4a, 0x7d, 0x2f, 0x47, 0x93, 0x33, 0x97, 0xf3, 0x97, 0xe3, 0xc9, 0xad, 0x93, 0xab, 0x91, 0x6b, 0x95, 0xeb, 0x97, 0x7b, 0x25, 0x4f, 0x94, 0xd7, 0x97, 0x77, 0x97, 0x5f, 0x2e, 0x9f, 0x27, 0x5f, 0x21, 0x7f, 0x4a, 0xfe, 0xa6, 0xfc, 0xb8, 0x02, 0x51, 0xc1, 0x40, 0xc1, 0x53, 0x81, 0xa3, 0xb0, 0x56, 0xa1, 0x46, 0xe1, 0xb4, 0xc2, 0x3d, 0x85, 0x49, 0x45, 0x9a, 0xa2, 0x95, 0x62, 0x88, 0x62, 0x9a, 0x62, 0x89, 0x62, 0x83, 0xe2, 0x35, 0xc5, 0x51, 0x25, 0xbc, 0x92, 0x81, 0x92, 0xb7, 0x12, 0x4f, 0xa9, 0x40, 0xe9, 0xb0, 0xd2, 0x25, 0xa5, 0x21, 0x1a, 0x42, 0xd3, 0xa5, 0x79, 0xd2, 0xb8, 0xb4, 0x4d, 0xb4, 0x3a, 0xda, 0x65, 0xda, 0x30, 0x1d, 0x47, 0x37, 0xa4, 0xfb, 0xd3, 0x93, 0xe9, 0xc5, 0xf4, 0x1f, 0xe8, 0xbd, 0xf4, 0x09, 0x65, 0x25, 0x65, 0x5b, 0xe5, 0x28, 0xe5, 0x1c, 0xe5, 0x1a, 0xe5, 0xb3, 0xca, 0x52, 0x06, 0xc2, 0x30, 0x60, 0xf8, 0x33, 0x52, 0x19, 0xa5, 0x8c, 0x93, 0x8c, 0xbb, 0x8c, 0x8f, 0xf3, 0x34, 0xe6, 0xb9, 0xcf, 0xe3, 0xcf, 0xdb, 0x36, 0xaf, 0x69, 0x5e, 0xff, 0xbc, 0x29, 0x95, 0xf9, 0x2a, 0x6e, 0x2a, 0x7c, 0x95, 0x22, 0x95, 0x66, 0x95, 0x01, 0x95, 0x8f, 0xaa, 0x4c, 0x55, 0x6f, 0xd5, 0x14, 0xd5, 0x9d, 0xaa, 0x6d, 0xaa, 0x4f, 0xd4, 0x30, 0x6a, 0x26, 0x6a, 0x61, 0x6a, 0xd9, 0x6a, 0xfb, 0xd5, 0x2e, 0xab, 0x8d, 0xcf, 0xa7, 0xcf, 0x77, 0x9e, 0xcf, 0x9d, 0x5f, 0x34, 0xff, 0xe4, 0xfc, 0x87, 0xea, 0xb0, 0xba, 0x89, 0x7a, 0xb8, 0xfa, 0x6a, 0xf5, 0xc3, 0xea, 0x3d, 0xea, 0x93, 0x1a, 0x9a, 0x1a, 0xbe, 0x1a, 0x19, 0x1a, 0x55, 0x1a, 0x97, 0x34, 0xc6, 0x35, 0x19, 0x9a, 0x6e, 0x9a, 0xc9, 0x9a, 0xe5, 0x9a, 0xe7, 0x34, 0xc7, 0xb4, 0x68, 0x5a, 0x0b, 0xb5, 0x04, 0x5a, 0xe5, 0x5a, 0xe7, 0xb5, 0x5e, 0x30, 0x95, 0x99, 0xee, 0xcc, 0x54, 0x66, 0x25, 0xb3, 0x8b, 0x39, 0xa1, 0xad, 0xae, 0xed, 0xa7, 0x2d, 0xd1, 0x3e, 0xa4, 0xdd, 0xab, 0x3d, 0xad, 0x63, 0xa8, 0xb3, 0x58, 0x67, 0xa3, 0x4e, 0xb3, 0xce, 0x13, 0x5d, 0x92, 0x2e, 0x5b, 0x37, 0x41, 0xb7, 0x5c, 0xb7, 0x53, 0x77, 0x42, 0x4f, 0x4b, 0x2f, 0x58, 0x2f, 0x5f, 0xaf, 0x51, 0xef, 0xa1, 0x3e, 0x51, 0x9f, 0xad, 0x9f, 0xa4, 0xbf, 0x47, 0xbf, 0x5b, 0x7f, 0xca, 0xc0, 0xd0, 0x20, 0xda, 0x60, 0x8b, 0x41, 0x9b, 0xc1, 0xa8, 0xa1, 0x8a, 0xa1, 0xbf, 0x61, 0x9e, 0x61, 0xa3, 0xe1, 0x63, 0x23, 0xaa, 0x91, 0xab, 0xd1, 0x2a, 0xa3, 0x5a, 0xa3, 0x3b, 0xc6, 0x38, 0x63, 0xb6, 0x71, 0x8a, 0xf1, 0x3e, 0xe3, 0x5b, 0x26, 0xb0, 0x89, 0x9d, 0x49, 0x92, 0x49, 0x8d, 0xc9, 0x4d, 0x53, 0xd8, 0xd4, 0xde, 0x54, 0x60, 0xba, 0xcf, 0xb4, 0xcf, 0x0c, 0x6b, 0xe6, 0x68, 0x26, 0x34, 0xab, 0x35, 0xbb, 0xc7, 0xa2, 0xb0, 0xdc, 0x59, 0x59, 0xac, 0x46, 0xd6, 0xa0, 0x39, 0xc3, 0x3c, 0xc8, 0x7c, 0xa3, 0x79, 0x9b, 0xf9, 0x2b, 0x0b, 0x3d, 0x8b, 0x58, 0x8b, 0x9d, 0x16, 0xdd, 0x16, 0x5f, 0x2c, 0xed, 0x2c, 0x53, 0x2d, 0xeb, 0x2c, 0x1f, 0x59, 0x29, 0x59, 0x05, 0x58, 0x6d, 0xb4, 0xea, 0xb0, 0xfa, 0xc3, 0xda, 0xc4, 0x9a, 0x6b, 0x5d, 0x63, 0x7d, 0xc7, 0x86, 0x6a, 0xe3, 0x63, 0xb3, 0xce, 0xa6, 0xdd, 0xe6, 0xb5, 0xad, 0xa9, 0x2d, 0xdf, 0x76, 0xbf, 0xed, 0x7d, 0x3b, 0x9a, 0x5d, 0xb0, 0xdd, 0x16, 0xbb, 0x4e, 0xbb, 0xcf, 0xf6, 0x0e, 0xf6, 0x22, 0xfb, 0x26, 0xfb, 0x31, 0x07, 0x3d, 0x87, 0x78, 0x87, 0xbd, 0x0e, 0xf7, 0xd8, 0x74, 0x76, 0x28, 0xbb, 0x84, 0x7d, 0xd5, 0x11, 0xeb, 0xe8, 0xe1, 0xb8, 0xce, 0xf1, 0x8c, 0xe3, 0x07, 0x27, 0x7b, 0x27, 0xb1, 0xd3, 0x49, 0xa7, 0xdf, 0x9d, 0x59, 0xce, 0x29, 0xce, 0x0d, 0xce, 0xa3, 0x0b, 0x0c, 0x17, 0xf0, 0x17, 0xd4, 0x2d, 0x18, 0x72, 0xd1, 0x71, 0xe1, 0xb8, 0x1c, 0x72, 0x91, 0x2e, 0x64, 0x2e, 0x8c, 0x5f, 0x78, 0x70, 0xa1, 0xd4, 0x55, 0xdb, 0x95, 0xe3, 0x5a, 0xeb, 0xfa, 0xcc, 0x4d, 0xd7, 0x8d, 0xe7, 0x76, 0xc4, 0x6d, 0xc4, 0xdd, 0xd8, 0x3d, 0xd9, 0xfd, 0xb8, 0xfb, 0x2b, 0x0f, 0x4b, 0x0f, 0x91, 0x47, 0x8b, 0xc7, 0x94, 0xa7, 0x93, 0xe7, 0x1a, 0xcf, 0x0b, 0x5e, 0x88, 0x97, 0xaf, 0x57, 0x91, 0x57, 0xaf, 0xb7, 0x92, 0xf7, 0x62, 0xef, 0x6a, 0xef, 0xa7, 0x3e, 0x3a, 0x3e, 0x89, 0x3e, 0x8d, 0x3e, 0x13, 0xbe, 0x76, 0xbe, 0xab, 0x7d, 0x2f, 0xf8, 0x61, 0xfd, 0x02, 0xfd, 0x76, 0xfa, 0xdd, 0xf3, 0xd7, 0xf0, 0xe7, 0xfa, 0xd7, 0xfb, 0x4f, 0x04, 0x38, 0x04, 0xac, 0x09, 0xe8, 0x0a, 0xa4, 0x04, 0x46, 0x04, 0x56, 0x07, 0x3e, 0x0b, 0x32, 0x09, 0x12, 0x05, 0x75, 0x04, 0xc3, 0xc1, 0x01, 0xc1, 0xbb, 0x82, 0x1f, 0x2f, 0xd2, 0x5f, 0x24, 0x5c, 0xd4, 0x16, 0x02, 0x42, 0xfc, 0x43, 0x76, 0x85, 0x3c, 0x09, 0x35, 0x0c, 0x5d, 0x15, 0xfa, 0x73, 0x18, 0x2e, 0x2c, 0x34, 0xac, 0x26, 0xec, 0x79, 0xb8, 0x55, 0x78, 0x7e, 0x78, 0x77, 0x04, 0x2d, 0x62, 0x45, 0x44, 0x43, 0xc4, 0xbb, 0x48, 0x8f, 0xc8, 0xd2, 0xc8, 0x47, 0x8b, 0x8d, 0x16, 0x4b, 0x16, 0x77, 0x46, 0xc9, 0x47, 0xc5, 0x45, 0xd5, 0x47, 0x4d, 0x45, 0x7b, 0x45, 0x97, 0x45, 0x4b, 0x97, 0x58, 0x2c, 0x59, 0xb3, 0xe4, 0x46, 0x8c, 0x5a, 0x8c, 0x20, 0xa6, 0x3d, 0x16, 0x1f, 0x1b, 0x15, 0x7b, 0x24, 0x76, 0x72, 0xa9, 0xf7, 0xd2, 0xdd, 0x4b, 0x87, 0xe3, 0xec, 0xe2, 0x0a, 0xe3, 0xee, 0x2e, 0x33, 0x5c, 0x96, 0xb3, 0xec, 0xda, 0x72, 0xb5, 0xe5, 0xa9, 0xcb, 0xcf, 0xae, 0x90, 0x5f, 0xc1, 0x59, 0x71, 0x2a, 0x1e, 0x1b, 0x1f, 0x1d, 0xdf, 0x10, 0xff, 0x89, 0x13, 0xc2, 0xa9, 0xe5, 0x4c, 0xae, 0xf4, 0x5f, 0xb9, 0x77, 0xe5, 0x04, 0xd7, 0x93, 0xbb, 0x87, 0xfb, 0x92, 0xe7, 0xc6, 0x2b, 0xe7, 0x8d, 0xf1, 0x5d, 0xf8, 0x65, 0xfc, 0x91, 0x04, 0x97, 0x84, 0xb2, 0x84, 0xd1, 0x44, 0x97, 0xc4, 0x5d, 0x89, 0x63, 0x49, 0xae, 0x49, 0x15, 0x49, 0xe3, 0x02, 0x4f, 0x41, 0xb5, 0xe0, 0x75, 0xb2, 0x5f, 0xf2, 0x81, 0xe4, 0xa9, 0x94, 0x90, 0x94, 0xa3, 0x29, 0x33, 0xa9, 0xd1, 0xa9, 0xcd, 0x69, 0x84, 0xb4, 0xf8, 0xb4, 0xd3, 0x42, 0x25, 0x61, 0x8a, 0xb0, 0x2b, 0x5d, 0x33, 0x3d, 0x27, 0xbd, 0x2f, 0xc3, 0x34, 0xa3, 0x30, 0x43, 0xba, 0xca, 0x69, 0xd5, 0xee, 0x55, 0x13, 0xa2, 0x40, 0xd1, 0x91, 0x4c, 0x28, 0x73, 0x59, 0x66, 0xbb, 0x98, 0x8e, 0xfe, 0x4c, 0xf5, 0x48, 0x8c, 0x24, 0x9b, 0x25, 0x83, 0x59, 0x0b, 0xb3, 0x6a, 0xb2, 0xde, 0x67, 0x47, 0x65, 0x9f, 0xca, 0x51, 0xcc, 0x11, 0xe6, 0xf4, 0xe4, 0x9a, 0xe4, 0x6e, 0xcb, 0x1d, 0xc9, 0xf3, 0xc9, 0xfb, 0x7e, 0x35, 0x66, 0x35, 0x77, 0x75, 0x67, 0xbe, 0x76, 0xfe, 0x86, 0xfc, 0xc1, 0x35, 0xee, 0x6b, 0x0e, 0xad, 0x85, 0xd6, 0xae, 0x5c, 0xdb, 0xb9, 0x4e, 0x77, 0x5d, 0xc1, 0xba, 0xe1, 0xf5, 0xbe, 0xeb, 0x8f, 0x6d, 0x20, 0x6d, 0x48, 0xd9, 0xf0, 0xcb, 0x46, 0xcb, 0x8d, 0x65, 0x1b, 0xdf, 0x6e, 0x8a, 0xde, 0xd4, 0x51, 0xa0, 0x51, 0xb0, 0xbe, 0x60, 0x68, 0xb3, 0xef, 0xe6, 0xc6, 0x42, 0xb9, 0x42, 0x51, 0xe1, 0xbd, 0x2d, 0xce, 0x5b, 0x0e, 0x6c, 0xc5, 0x6c, 0x15, 0x6c, 0xed, 0xdd, 0x66, 0xb3, 0xad, 0x6a, 0xdb, 0x97, 0x22, 0x5e, 0xd1, 0xf5, 0x62, 0xcb, 0xe2, 0x8a, 0xe2, 0x4f, 0x25, 0xdc, 0x92, 0xeb, 0xdf, 0x59, 0x7d, 0x57, 0xf9, 0xdd, 0xcc, 0xf6, 0x84, 0xed, 0xbd, 0xa5, 0xf6, 0xa5, 0xfb, 0x77, 0xe0, 0x76, 0x08, 0x77, 0xdc, 0xdd, 0xe9, 0xba, 0xf3, 0x58, 0x99, 0x62, 0x59, 0x5e, 0xd9, 0xd0, 0xae, 0xe0, 0x5d, 0xad, 0xe5, 0xcc, 0xf2, 0xa2, 0xf2, 0xb7, 0xbb, 0x57, 0xec, 0xbe, 0x56, 0x61, 0x5b, 0x71, 0x60, 0x0f, 0x69, 0x8f, 0x64, 0x8f, 0xb4, 0x32, 0xa8, 0xb2, 0xbd, 0x4a, 0xaf, 0x6a, 0x47, 0xd5, 0xa7, 0xea, 0xa4, 0xea, 0x81, 0x1a, 0x8f, 0x9a, 0xe6, 0xbd, 0xea, 0x7b, 0xb7, 0xed, 0x9d, 0xda, 0xc7, 0xdb, 0xd7, 0xbf, 0xdf, 0x6d, 0x7f, 0xd3, 0x01, 0x8d, 0x03, 0xc5, 0x07, 0x3e, 0x1e, 0x14, 0x1c, 0xbc, 0x7f, 0xc8, 0xf7, 0x50, 0x6b, 0xad, 0x41, 0x6d, 0xc5, 0x61, 0xdc, 0xe1, 0xac, 0xc3, 0xcf, 0xeb, 0xa2, 0xea, 0xba, 0xbf, 0x67, 0x7f, 0x5f, 0x7f, 0x44, 0xed, 0x48, 0xf1, 0x91, 0xcf, 0x47, 0x85, 0x47, 0xa5, 0xc7, 0xc2, 0x8f, 0x75, 0xd5, 0x3b, 0xd4, 0xd7, 0x37, 0xa8, 0x37, 0x94, 0x36, 0xc2, 0x8d, 0x92, 0xc6, 0xb1, 0xe3, 0x71, 0xc7, 0x6f, 0xfd, 0xe0, 0xf5, 0x43, 0x7b, 0x13, 0xab, 0xe9, 0x50, 0x33, 0xa3, 0xb9, 0xf8, 0x04, 0x38, 0x21, 0x39, 0xf1, 0xe2, 0xc7, 0xf8, 0x1f, 0xef, 0x9e, 0x0c, 0x3c, 0xd9, 0x79, 0x8a, 0x7d, 0xaa, 0xe9, 0x27, 0xfd, 0x9f, 0xf6, 0xb6, 0xd0, 0x5a, 0x8a, 0x5a, 0xa1, 0xd6, 0xdc, 0xd6, 0x89, 0xb6, 0xa4, 0x36, 0x69, 0x7b, 0x4c, 0x7b, 0xdf, 0xe9, 0x80, 0xd3, 0x9d, 0x1d, 0xce, 0x1d, 0x2d, 0x3f, 0x9b, 0xff, 0x7c, 0xf4, 0x8c, 0xf6, 0x99, 0x9a, 0xb3, 0xca, 0x67, 0x4b, 0xcf, 0x91, 0xce, 0x15, 0x9c, 0x9b, 0x39, 0x9f, 0x77, 0x7e, 0xf2, 0x42, 0xc6, 0x85, 0xf1, 0x8b, 0x89, 0x17, 0x87, 0x3a, 0x57, 0x74, 0x3e, 0xba, 0xb4, 0xe4, 0xd2, 0x9d, 0xae, 0xb0, 0xae, 0xde, 0xcb, 0x81, 0x97, 0xaf, 0x5e, 0xf1, 0xb9, 0x72, 0xa9, 0xdb, 0xbd, 0xfb, 0xfc, 0x55, 0x97, 0xab, 0x67, 0xae, 0x39, 0x5d, 0x3b, 0x7d, 0x9d, 0x7d, 0xbd, 0xed, 0x86, 0xfd, 0x8d, 0xd6, 0x1e, 0xbb, 0x9e, 0x96, 0x5f, 0xec, 0x7e, 0x69, 0xe9, 0xb5, 0xef, 0x6d, 0xbd, 0xe9, 0x70, 0xb3, 0xfd, 0x96, 0xe3, 0xad, 0x8e, 0xbe, 0x05, 0x7d, 0xe7, 0xfa, 0x5d, 0xfb, 0x2f, 0xde, 0xf6, 0xba, 0x7d, 0xe5, 0x8e, 0xff, 0x9d, 0x1b, 0x03, 0x8b, 0x06, 0xfa, 0xee, 0x2e, 0xbe, 0x7b, 0xff, 0x5e, 0xdc, 0x3d, 0xe9, 0x7d, 0xde, 0xfd, 0xd1, 0x07, 0xa9, 0x0f, 0x5e, 0x3f, 0xcc, 0x7a, 0x38, 0xfd, 0x68, 0xfd, 0x63, 0xec, 0xe3, 0xa2, 0x27, 0x0a, 0x4f, 0x2a, 0x9e, 0xaa, 0x3f, 0xad, 0xfd, 0xd5, 0xf8, 0xd7, 0x66, 0xa9, 0xbd, 0xf4, 0xec, 0xa0, 0xd7, 0x60, 0xcf, 0xb3, 0x88, 0x67, 0x8f, 0x86, 0xb8, 0x43, 0x2f, 0xff, 0x95, 0xf9, 0xaf, 0x4f, 0xc3, 0x05, 0xcf, 0xa9, 0xcf, 0x2b, 0x46, 0xb4, 0x46, 0xea, 0x47, 0xad, 0x47, 0xcf, 0x8c, 0xf9, 0x8c, 0xdd, 0x7a, 0xb1, 0xf4, 0xc5, 0xf0, 0xcb, 0x8c, 0x97, 0xd3, 0xe3, 0x85, 0xbf, 0x29, 0xfe, 0xb6, 0xf7, 0x95, 0xd1, 0xab, 0x9f, 0x7e, 0x77, 0xfb, 0xbd, 0x67, 0x62, 0xc9, 0xc4, 0xf0, 0x6b, 0xd1, 0xeb, 0x99, 0x3f, 0x4a, 0xde, 0xa8, 0xbe, 0x39, 0xfa, 0xd6, 0xf6, 0x6d, 0xe7, 0x64, 0xe8, 0xe4, 0xd3, 0x77, 0x69, 0xef, 0xa6, 0xa7, 0x8a, 0xde, 0xab, 0xbe, 0x3f, 0xf6, 0x81, 0xfd, 0xa1, 0xfb, 0x63, 0xf4, 0xc7, 0x91, 0xe9, 0xec, 0x4f, 0xf8, 0x4f, 0x95, 0x9f, 0x8d, 0x3f, 0x77, 0x7c, 0x09, 0xfc, 0xf2, 0x78, 0x26, 0x6d, 0x66, 0xe6, 0xdf, 0xf7, 0x84, 0xf3, 0xfb, 0x32, 0x3a, 0x59, 0x7e, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa4, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x35, 0x2d, 0x30, 0x32, 0x54, 0x31, 0x31, 0x3a, 0x30, 0x35, 0x3a, 0x30, 0x36, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x38, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x90, 0x7a, 0xe1, 0x8d, 0x00, 0x00, 0x00, 0x12, 0x49, 0x44, 0x41, 0x54, 0x08, 0x1d, 0x63, 0x60, 0x60, 0x60, 0xf8, 0x0f, 0xc5, 0x40, 0x0a, 0x13, 0x00, 0x00, 0x35, 0xeb, 0x01, 0xff, 0x0f, 0x5e, 0xbc, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXListIcon[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x06, 0x00, 0x00, 0x00, 0xe4, 0x98, 0xef, 0x55, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9c, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x39, 0x30, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc1, 0xe2, 0xd2, 0xc6, 0x00, 0x00, 0x00, 0x65, 0x49, 0x44, 0x41, 0x54, 0x38, 0x11, 0x63, 0x60, 0x60, 0x60, 0x68, 0x05, 0xe2, 0x9f, 0x40, 0xfc, 0x9f, 0x42, 0x0c, 0x32, 0xa3, 0x95, 0x11, 0x48, 0x7c, 0x06, 0x62, 0x1e, 0x20, 0xa6, 0x06, 0xf8, 0xc2, 0x0c, 0x34, 0x05, 0x64, 0x98, 0x39, 0x10, 0x83, 0xd8, 0x94, 0x80, 0x5f, 0x40, 0xcd, 0xfd, 0x94, 0x18, 0x30, 0x84, 0xf5, 0x36, 0x03, 0xdd, 0xfe, 0x0d, 0x88, 0xff, 0x52, 0x88, 0x41, 0x66, 0x34, 0xd3, 0x24, 0x96, 0xf9, 0x81, 0x26, 0x53, 0x23, 0x96, 0x7f, 0x03, 0xcd, 0x99, 0x04, 0x72, 0x21, 0x08, 0x80, 0x68, 0x18, 0x1b, 0x2c, 0x40, 0x06, 0x01, 0xcb, 0x18, 0x64, 0x68, 0xa5, 0xb7, 0x96, 0x11, 0x16, 0xcb, 0x00, 0xa6, 0x38, 0x45, 0xd2, 0xe0, 0x92, 0x71, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXListIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1e, 0x08, 0x06, 0x00, 0x00, 0x00, 0x5e, 0xdd, 0x5c, 0xdd, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9c, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x39, 0x30, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc1, 0xe2, 0xd2, 0xc6, 0x00, 0x00, 0x00, 0x94, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, 0x96, 0xc1, 0x09, 0x80, 0x30, 0x14, 0x43, 0xbf, 0x0a, 0x6e, 0xe0, 0xc1, 0x5d, 0x1c, 0xb0, 0x13, 0x38, 0xa2, 0x8e, 0xa1, 0x89, 0x87, 0xd2, 0x7a, 0xfc, 0x5e, 0x22, 0x44, 0x08, 0xf4, 0x0b, 0xc2, 0x23, 0x8d, 0x4d, 0x23, 0x22, 0x66, 0xa8, 0x40, 0x07, 0x74, 0x89, 0x88, 0x2c, 0x64, 0x22, 0xdb, 0xb3, 0x50, 0x01, 0x7b, 0x73, 0x94, 0x01, 0x80, 0xa4, 0x5d, 0x49, 0x2a, 0xf8, 0x9c, 0xa3, 0x20, 0x54, 0x87, 0x34, 0x61, 0x5a, 0xa0, 0xad, 0x7b, 0xab, 0x33, 0xec, 0x44, 0x61, 0x10, 0xa5, 0x7f, 0x12, 0x1d, 0xbf, 0x4c, 0x62, 0x07, 0xec, 0x40, 0xce, 0x01, 0xf9, 0x63, 0x86, 0x67, 0xe0, 0xbb, 0x03, 0x55, 0x66, 0x77, 0x71, 0x2e, 0x74, 0xcd, 0x57, 0xee, 0xe2, 0x64, 0xbe, 0x79, 0x05, 0xac, 0x17, 0xd6, 0xc6, 0x50, 0x2f, 0xed, 0x80, 0x1d, 0xf8, 0xa5, 0x03, 0xee, 0x62, 0x6c, 0x5b, 0xb6, 0xdb, 0xdd, 0xc5, 0x9f, 0x33, 0xef, 0x2e, 0x4e, 0xe6, 0xaf, 0x76, 0xf1, 0x0d, 0xa7, 0xae, 0x59, 0xeb, 0x22, 0xc6, 0xba, 0x58, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXMoveIcon[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x17, 0xa5, 0x96, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9c, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x39, 0x30, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc1, 0xe2, 0xd2, 0xc6, 0x00, 0x00, 0x01, 0x2f, 0x49, 0x44, 0x41, 0x54, 0x38, 0x11, 0xb5, 0x95, 0x31, 0x4e, 0x03, 0x41, 0x0c, 0x45, 0x87, 0x40, 0xfa, 0x88, 0x13, 0xa4, 0xa1, 0xe2, 0x0e, 0x88, 0x94, 0xd4, 0x1c, 0x21, 0x1d, 0x07, 0x80, 0x33, 0x40, 0x49, 0x41, 0xc7, 0x11, 0xe8, 0x22, 0xa1, 0x54, 0x41, 0x94, 0xf4, 0x14, 0x11, 0x12, 0xe4, 0x04, 0x5c, 0x00, 0x09, 0x78, 0x4f, 0x9a, 0x41, 0x93, 0xdd, 0xcd, 0x32, 0xcb, 0x86, 0x2f, 0x7d, 0xd9, 0xe3, 0xb1, 0x7f, 0x2c, 0xaf, 0x47, 0x09, 0xa1, 0x0c, 0xfb, 0xa4, 0xcd, 0xa0, 0x76, 0x2b, 0x18, 0xa2, 0xb2, 0x80, 0x5f, 0xd1, 0x7a, 0xee, 0x8d, 0x5b, 0x14, 0x14, 0x4c, 0xf4, 0xdc, 0x0b, 0xe7, 0x54, 0x27, 0xb1, 0xdc, 0x1a, 0xdf, 0x88, 0xdd, 0x8d, 0x37, 0x21, 0x1c, 0x70, 0x77, 0x06, 0x5f, 0xa1, 0x79, 0x23, 0xb8, 0x82, 0x4f, 0x70, 0x1c, 0xed, 0x3b, 0xf6, 0xcf, 0xb8, 0xa1, 0xd2, 0x4e, 0xb5, 0xbf, 0x62, 0xd0, 0x90, 0x61, 0x87, 0x5d, 0x50, 0xcb, 0xaf, 0x8a, 0x3a, 0xab, 0xeb, 0x2e, 0x8a, 0x31, 0x7f, 0x6d, 0xc6, 0x49, 0xd4, 0x35, 0xf1, 0xab, 0x5e, 0xc2, 0x14, 0xc3, 0x2d, 0x82, 0xf9, 0xd6, 0x59, 0xaf, 0x4e, 0xd8, 0x81, 0x2e, 0xf4, 0x1d, 0x3c, 0x86, 0x62, 0x05, 0xef, 0x75, 0x32, 0x1c, 0xe1, 0x1f, 0xc2, 0x67, 0xf8, 0x98, 0xc5, 0x75, 0x4f, 0xe0, 0x58, 0x07, 0x3c, 0xc0, 0x53, 0x1d, 0x5f, 0x4a, 0xbe, 0x2e, 0x7d, 0xfd, 0xd9, 0xbf, 0x75, 0x6a, 0xb7, 0x69, 0xa6, 0x76, 0x39, 0x37, 0x50, 0x41, 0xdb, 0x4a, 0x99, 0x6f, 0xdd, 0xcf, 0x4c, 0xf7, 0x62, 0xf1, 0x07, 0x76, 0x0a, 0x97, 0x70, 0x12, 0x63, 0xa5, 0xe6, 0x93, 0xc4, 0x0b, 0x78, 0xd5, 0x56, 0x50, 0xdb, 0x3b, 0x92, 0xdb, 0x3a, 0xad, 0xe5, 0x37, 0xad, 0xcf, 0x4b, 0xdb, 0x2f, 0x36, 0xdc, 0x75, 0xca, 0xb7, 0x03, 0x57, 0xcb, 0x99, 0xbd, 0x41, 0xe7, 0xa6, 0xf5, 0x6c, 0xbc, 0xd6, 0x21, 0xb1, 0x22, 0xf8, 0x52, 0x14, 0xab, 0x72, 0xed, 0x05, 0x15, 0x29, 0x55, 0x92, 0xfc, 0xaa, 0xb9, 0xa8, 0xe7, 0xde, 0x18, 0xa2, 0xb0, 0x80, 0x0a, 0x6b, 0x3d, 0x6f, 0x05, 0x9d, 0xfe, 0xa3, 0xbe, 0x01, 0xe4, 0xf1, 0x5c, 0xce, 0x72, 0x04, 0x22, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXMoveIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xc5, 0xc3, 0xc9, 0x5b, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9c, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x39, 0x30, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc1, 0xe2, 0xd2, 0xc6, 0x00, 0x00, 0x02, 0x26, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xdd, 0x99, 0x3b, 0x4e, 0x03, 0x31, 0x14, 0x45, 0x13, 0x84, 0x44, 0x56, 0x00, 0x0b, 0xa0, 0xa5, 0x46, 0x84, 0x0e, 0xaa, 0x6c, 0x01, 0x04, 0x3b, 0x48, 0x07, 0x0b, 0x08, 0x3d, 0xbb, 0xe0, 0xbb, 0x8b, 0x74, 0x04, 0x7a, 0x7a, 0xd2, 0x42, 0x47, 0x47, 0x81, 0x04, 0xf7, 0x84, 0x38, 0x7a, 0x71, 0x66, 0x3c, 0x33, 0x61, 0x26, 0x36, 0x5c, 0xe9, 0xc6, 0x9f, 0x67, 0xbf, 0x77, 0xe5, 0xdf, 0xd8, 0x4a, 0xab, 0x55, 0x3f, 0xfa, 0x72, 0x09, 0x93, 0x46, 0x4f, 0xea, 0x3e, 0xa7, 0x24, 0x9f, 0x24, 0x76, 0xa4, 0xea, 0x5d, 0xfc, 0x9a, 0x92, 0x3c, 0x75, 0x49, 0x61, 0x53, 0x6a, 0xc6, 0xa2, 0x13, 0xe9, 0x52, 0xea, 0xb0, 0x25, 0x81, 0x8e, 0x54, 0x8c, 0x44, 0x27, 0xce, 0x4f, 0xb1, 0xd1, 0x26, 0x3a, 0xee, 0xa4, 0xc0, 0x17, 0xe7, 0x97, 0x69, 0x13, 0x15, 0x03, 0x45, 0xf7, 0x45, 0xe5, 0x95, 0x69, 0x1b, 0x05, 0xc7, 0x8a, 0x9a, 0x27, 0x2a, 0xaf, 0x9e, 0x3e, 0x2b, 0xc5, 0xbe, 0xa2, 0x7d, 0x88, 0x79, 0x82, 0xf2, 0xea, 0xe9, 0x43, 0xdf, 0xca, 0x68, 0x57, 0xee, 0xf1, 0xd3, 0xe1, 0x54, 0x49, 0xd6, 0x6e, 0xbe, 0xf4, 0xfc, 0x9d, 0x7b, 0x65, 0x8a, 0x6f, 0xe2, 0x55, 0x46, 0x7d, 0xb0, 0x6a, 0x59, 0xa1, 0x79, 0x4e, 0x19, 0x49, 0x8b, 0xda, 0xfc, 0xaf, 0x59, 0xaf, 0x29, 0xe7, 0xff, 0x95, 0xd0, 0xae, 0x46, 0x9a, 0x35, 0xd9, 0x14, 0xf0, 0x4d, 0x8c, 0x20, 0x8a, 0x46, 0x94, 0xe3, 0x64, 0x28, 0x66, 0x6d, 0x9c, 0xa0, 0xe3, 0x0a, 0x46, 0x7c, 0x13, 0x23, 0x78, 0x74, 0x85, 0x84, 0x0e, 0xd4, 0xf9, 0x46, 0xdc, 0x10, 0x9b, 0x06, 0x31, 0x88, 0x35, 0xa8, 0x12, 0x88, 0xef, 0xf2, 0xad, 0x68, 0xcf, 0xc2, 0xb3, 0x92, 0x0e, 0x6c, 0x1f, 0xf2, 0x65, 0x80, 0x6f, 0xdb, 0x8f, 0xd8, 0x0b, 0x77, 0x03, 0x7f, 0x44, 0xdd, 0x34, 0x1c, 0x95, 0x89, 0xd0, 0x50, 0x1b, 0x62, 0x0f, 0xc5, 0xb9, 0xe5, 0x66, 0x85, 0x72, 0x77, 0x7c, 0x12, 0xf7, 0xc4, 0xd8, 0x40, 0x03, 0x5a, 0x16, 0xee, 0xb3, 0x3d, 0x55, 0xda, 0x4b, 0xaf, 0x9d, 0x8a, 0x98, 0x79, 0x34, 0xa1, 0x6d, 0x82, 0xbe, 0x7e, 0x79, 0x3e, 0xc4, 0x14, 0x14, 0x8a, 0x8d, 0xb6, 0xbe, 0x9d, 0xfa, 0x89, 0xea, 0xd4, 0x7f, 0xfe, 0xc4, 0xd4, 0xbb, 0x41, 0x64, 0xe1, 0x8e, 0xc5, 0xac, 0x69, 0x58, 0xe5, 0xf1, 0xe4, 0xe2, 0xa3, 0x65, 0xb6, 0x99, 0xec, 0xd4, 0x3f, 0xcb, 0xb0, 0x2b, 0x3e, 0x8a, 0xb1, 0x81, 0x06, 0xb4, 0xa0, 0x69, 0x02, 0x2b, 0x94, 0x0a, 0xee, 0x8a, 0x07, 0xe2, 0x3d, 0x85, 0x48, 0x20, 0x36, 0x1a, 0xd0, 0x32, 0x83, 0x2f, 0x14, 0x03, 0xb7, 0x70, 0x0e, 0xdd, 0x0b, 0x0a, 0x2b, 0x06, 0x31, 0x89, 0x8d, 0x86, 0x4a, 0xe0, 0xa2, 0x40, 0xa7, 0xa6, 0xd7, 0x28, 0x31, 0x82, 0x97, 0x92, 0xf5, 0x02, 0xd9, 0x7c, 0x77, 0xc7, 0xe2, 0x76, 0x41, 0xbb, 0xdf, 0x98, 0x99, 0xe2, 0x43, 0xf1, 0x21, 0xe4, 0xa4, 0x1d, 0x32, 0x2e, 0x61, 0x63, 0xc7, 0x5a, 0xd4, 0xe6, 0x3f, 0x6b, 0x8d, 0xda, 0x40, 0xc9, 0xe4, 0xff, 0x8c, 0xd0, 0xa2, 0x35, 0x9a, 0x37, 0xa2, 0x27, 0x32, 0x6c, 0xe5, 0x19, 0x4d, 0x7d, 0xd6, 0x26, 0x7c, 0x95, 0xfd, 0xda, 0xb4, 0x69, 0x34, 0xdb, 0x95, 0x77, 0x76, 0xaa, 0xfb, 0x8a, 0x94, 0x4d, 0xe9, 0x43, 0xdf, 0x95, 0x82, 0xe3, 0xa4, 0xac, 0x40, 0xd7, 0x2e, 0x78, 0x04, 0x35, 0xa9, 0x7e, 0x50, 0x41, 0x2c, 0x6d, 0xa3, 0xc2, 0x7f, 0x5f, 0xb9, 0xd1, 0xb3, 0x29, 0x6d, 0xa2, 0xa3, 0x23, 0x05, 0x23, 0xd1, 0x0a, 0xb3, 0x79, 0x6c, 0xb4, 0x49, 0x02, 0x3c, 0xc4, 0x5e, 0x44, 0x2b, 0x90, 0x3c, 0x75, 0x73, 0x8f, 0x34, 0x95, 0xa3, 0x83, 0xbb, 0xa3, 0x7d, 0x77, 0x25, 0xf9, 0x67, 0x83, 0x1b, 0xa5, 0x9e, 0x32, 0xc9, 0xff, 0x7d, 0xe3, 0xc4, 0xf2, 0x58, 0x84, 0xb5, 0xe2, 0x1b, 0xb0, 0x4b, 0x43, 0x5f, 0xe1, 0x68, 0x89, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXSelectIcon[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x11, 0x08, 0x06, 0x00, 0x00, 0x00, 0xed, 0xc8, 0x9d, 0x9f, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9c, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x39, 0x30, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc1, 0xe2, 0xd2, 0xc6, 0x00, 0x00, 0x00, 0xf4, 0x49, 0x44, 0x41, 0x54, 0x28, 0x15, 0x95, 0x92, 0xc1, 0x0a, 0x01, 0x61, 0x14, 0x85, 0x27, 0x45, 0x64, 0xa3, 0x94, 0x2c, 0xac, 0xa4, 0x44, 0x51, 0x16, 0xd6, 0xf6, 0xca, 0xc6, 0x23, 0x78, 0x02, 0x25, 0x2f, 0x61, 0xc9, 0xc6, 0xde, 0x0b, 0xd8, 0x51, 0xbc, 0x82, 0xc8, 0x4e, 0xa1, 0xa4, 0xac, 0x94, 0x6c, 0x88, 0x14, 0xdf, 0xd5, 0xdc, 0xfa, 0x1b, 0x33, 0x98, 0x53, 0xdf, 0xdc, 0xeb, 0xfe, 0xe7, 0x5c, 0x63, 0x8c, 0x65, 0x59, 0x56, 0x17, 0x72, 0xe0, 0x4b, 0x01, 0xdb, 0xbd, 0xa4, 0xf6, 0x20, 0xee, 0x27, 0x5d, 0xc5, 0xfc, 0xb4, 0x39, 0x51, 0x9b, 0x10, 0x84, 0x9f, 0x8a, 0xe0, 0xb8, 0x82, 0x86, 0xa5, 0xae, 0xa0, 0x06, 0x3f, 0x35, 0xc6, 0x61, 0x06, 0xb5, 0x9f, 0x32, 0x2f, 0x7c, 0x4b, 0xcb, 0xed, 0xa9, 0xd9, 0x59, 0x1f, 0x9c, 0xf5, 0x21, 0xe1, 0xb6, 0x20, 0xfb, 0x25, 0xa8, 0x8b, 0xce, 0x78, 0xda, 0x10, 0x72, 0x2e, 0xd8, 0xfe, 0x11, 0x96, 0x25, 0x1b, 0xa8, 0xeb, 0xdf, 0x21, 0x4b, 0x46, 0x72, 0xf9, 0x43, 0x49, 0x3c, 0x61, 0xd3, 0x27, 0x4f, 0x51, 0x6f, 0xcb, 0xab, 0xae, 0xf1, 0x14, 0xcd, 0x90, 0xf4, 0x51, 0xb8, 0x81, 0x57, 0x68, 0xc6, 0x59, 0x0c, 0x5c, 0x35, 0x61, 0xea, 0x15, 0xbc, 0x70, 0x56, 0x76, 0x4d, 0x31, 0x6c, 0x39, 0x82, 0xf2, 0x26, 0xed, 0x8d, 0xd9, 0x81, 0x3e, 0x05, 0x1f, 0xca, 0x33, 0xd1, 0x6f, 0x5c, 0xd0, 0xa7, 0x21, 0x03, 0x47, 0x63, 0x3e, 0xa7, 0x97, 0x9f, 0xf5, 0xa1, 0x1d, 0x93, 0x01, 0xc8, 0xab, 0xa8, 0xaa, 0xd0, 0xdc, 0x41, 0x97, 0x0e, 0xf5, 0xc0, 0xac, 0x25, 0xf3, 0x83, 0xd1, 0x37, 0xe8, 0x35, 0x28, 0xd5, 0x97, 0x3a, 0xb8, 0xdf, 0xe1, 0x17, 0xaf, 0x54, 0x62, 0xf7, 0x88, 0x7e, 0xaa, 0x27, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXSelectIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x22, 0x08, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x7d, 0xb9, 0x49, 0x00, 0x00, 0x0c, 0x45, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0xad, 0x57, 0x77, 0x58, 0x53, 0xd7, 0x1b, 0xfe, 0xee, 0x48, 0x02, 0x21, 0x09, 0x23, 0x10, 0x01, 0x19, 0x61, 0x2f, 0x51, 0xf6, 0x94, 0xbd, 0x05, 0x05, 0x99, 0x42, 0x1d, 0x84, 0x24, 0x90, 0x30, 0x62, 0x08, 0x04, 0x15, 0xf7, 0x28, 0xad, 0x60, 0x1d, 0xa8, 0x38, 0x70, 0x54, 0xb4, 0x2a, 0xe2, 0xaa, 0x03, 0x90, 0x3a, 0x10, 0x71, 0x5b, 0x14, 0xb7, 0x75, 0x14, 0xb5, 0x28, 0x28, 0xb5, 0x38, 0x70, 0xa1, 0xf2, 0x3b, 0x37, 0x0c, 0xfb, 0xf4, 0x69, 0xff, 0xfb, 0xdd, 0xe7, 0x39, 0xe7, 0xbe, 0x79, 0xbf, 0xef, 0x7c, 0xf7, 0xfd, 0xbe, 0x7b, 0xee, 0xc9, 0x39, 0x00, 0x9a, 0xb6, 0x02, 0xb9, 0x3c, 0x17, 0xd7, 0x02, 0xc8, 0x93, 0x15, 0x2a, 0xe2, 0x23, 0x82, 0xf9, 0x13, 0x52, 0xd3, 0xf8, 0x8c, 0x07, 0x80, 0x83, 0x01, 0x70, 0xc0, 0x0d, 0x48, 0x81, 0xb0, 0x40, 0x1e, 0x14, 0x17, 0x17, 0x03, 0xff, 0x79, 0xbd, 0xbd, 0x09, 0x18, 0x65, 0xbc, 0xe6, 0x48, 0xc5, 0xfa, 0x4f, 0xb7, 0x7f, 0x37, 0x68, 0x8b, 0xc4, 0x05, 0x42, 0x00, 0x2c, 0x0e, 0x99, 0x33, 0x44, 0x05, 0xc2, 0x3c, 0x84, 0x0f, 0x01, 0x90, 0x1c, 0xa1, 0x5c, 0x51, 0x08, 0x40, 0x6b, 0x46, 0xbc, 0xc5, 0xb4, 0x42, 0x39, 0x85, 0x3b, 0x10, 0xd6, 0x55, 0x20, 0x81, 0x08, 0x7f, 0xa2, 0x70, 0x96, 0x0a, 0xd3, 0x91, 0x7a, 0xd0, 0xcd, 0xe8, 0xc7, 0x96, 0x2a, 0x9f, 0xc4, 0xf8, 0x10, 0x00, 0xba, 0x17, 0x80, 0x1a, 0x4b, 0x20, 0x50, 0x64, 0x01, 0x70, 0x42, 0x11, 0xcf, 0x2f, 0x12, 0x66, 0xa1, 0x38, 0x1c, 0x11, 0xc2, 0x4e, 0x32, 0x91, 0x54, 0x86, 0xf0, 0x2a, 0x84, 0xfd, 0x85, 0x12, 0x01, 0xe2, 0x38, 0xd7, 0x11, 0x1e, 0x91, 0x97, 0x37, 0x15, 0x61, 0x4d, 0x04, 0xc1, 0x36, 0xe3, 0x6f, 0x71, 0xb2, 0xfe, 0x86, 0x05, 0x82, 0x8c, 0xa1, 0x98, 0x02, 0x41, 0xd6, 0x10, 0xee, 0xcf, 0x85, 0x1a, 0x0a, 0x6a, 0xa1, 0xd2, 0x02, 0x79, 0xae, 0x60, 0x86, 0xea, 0xc7, 0xff, 0xb3, 0xcb, 0xcb, 0x55, 0xa2, 0x7a, 0xa9, 0x2e, 0x33, 0xd4, 0xb3, 0x24, 0x8a, 0xc8, 0x78, 0x74, 0xd7, 0x45, 0x75, 0xdb, 0x90, 0x33, 0x35, 0x9a, 0xc2, 0x2c, 0x84, 0xf7, 0xcb, 0x32, 0xc6, 0xc5, 0x22, 0xac, 0x83, 0xf0, 0x51, 0x29, 0x95, 0x71, 0x3f, 0x6e, 0x91, 0x28, 0x23, 0x93, 0x10, 0xa6, 0xfc, 0xdb, 0x84, 0x05, 0x21, 0xa8, 0x96, 0xc0, 0x43, 0xf8, 0x8d, 0x48, 0x10, 0x1a, 0x8d, 0xb0, 0x11, 0x00, 0xce, 0x54, 0xe6, 0x24, 0x05, 0x0d, 0x60, 0x6b, 0x81, 0x02, 0x21, 0x95, 0x3f, 0x1e, 0x2c, 0x2d, 0x8c, 0x4a, 0x1c, 0xc0, 0xc9, 0x8a, 0xa9, 0xf1, 0x03, 0xf1, 0xf1, 0x6c, 0x59, 0xee, 0x38, 0x6a, 0x7e, 0xa0, 0x38, 0xf8, 0x2c, 0x89, 0x38, 0x6a, 0x10, 0x97, 0x8b, 0x0b, 0xc2, 0x12, 0x10, 0x8f, 0x34, 0xe0, 0xd9, 0x99, 0xd2, 0xf0, 0x28, 0x84, 0xd1, 0xbb, 0xc2, 0x77, 0x16, 0x4b, 0x12, 0x53, 0x10, 0x46, 0x3a, 0xf1, 0xfa, 0x22, 0x69, 0xf2, 0x38, 0x84, 0x39, 0x08, 0x37, 0x17, 0xe4, 0x24, 0x50, 0x1a, 0xa8, 0x38, 0x57, 0x8b, 0x25, 0x21, 0x14, 0xaf, 0xf2, 0x51, 0x28, 0xe3, 0x29, 0xcd, 0x96, 0x88, 0xef, 0xc8, 0x54, 0x84, 0x53, 0x39, 0x22, 0x1f, 0x82, 0x95, 0x57, 0x80, 0x90, 0x2a, 0x3e, 0x61, 0x2e, 0x14, 0xa8, 0x9e, 0xa5, 0x8f, 0x78, 0xb7, 0x42, 0x49, 0x62, 0x24, 0xe2, 0xd1, 0x58, 0x22, 0x46, 0x24, 0x0e, 0x0d, 0x43, 0x18, 0x3d, 0x97, 0x98, 0x20, 0x96, 0x25, 0x0d, 0xe8, 0x21, 0x24, 0xf2, 0xc2, 0x60, 0x2a, 0x0e, 0xe5, 0x5f, 0x2c, 0xcf, 0x55, 0xcd, 0x6f, 0xa4, 0x93, 0x28, 0x17, 0xe7, 0x46, 0x50, 0xbc, 0x39, 0xc2, 0xdb, 0x0a, 0x8a, 0x12, 0x06, 0xc7, 0x9e, 0x29, 0x54, 0x24, 0x52, 0x3c, 0xaa, 0x1b, 0x71, 0x33, 0x5b, 0x30, 0x86, 0x9a, 0xaf, 0x48, 0x33, 0xf1, 0x4c, 0x5e, 0x18, 0x47, 0xd5, 0x84, 0xd2, 0xf3, 0x1e, 0x62, 0x20, 0x04, 0x42, 0x81, 0x0f, 0x4a, 0xd4, 0x32, 0x60, 0x2a, 0x64, 0x83, 0xb4, 0xa5, 0xab, 0xae, 0x0b, 0xfd, 0xea, 0xb7, 0x84, 0x83, 0x00, 0x14, 0x90, 0x05, 0x62, 0x70, 0x1c, 0x60, 0x06, 0x47, 0xa4, 0xa8, 0x2c, 0x32, 0xd4, 0x27, 0x40, 0x31, 0xfc, 0x09, 0x32, 0xe4, 0x53, 0x30, 0x34, 0x2e, 0x58, 0x65, 0x15, 0x43, 0x11, 0xe2, 0x3f, 0x0f, 0xb1, 0xfd, 0x63, 0x1d, 0x21, 0x53, 0x65, 0x2d, 0x52, 0x8d, 0xc8, 0x81, 0x27, 0xe8, 0x09, 0x79, 0xa4, 0x21, 0xe9, 0x4f, 0xfa, 0x92, 0x31, 0xa8, 0x0f, 0x44, 0xcd, 0x85, 0xf4, 0x22, 0xbd, 0x07, 0xc7, 0xf1, 0x35, 0x07, 0x75, 0xd2, 0xc3, 0xe8, 0xa1, 0xf4, 0x48, 0x7a, 0x38, 0xdd, 0x6e, 0x90, 0x01, 0x21, 0x52, 0x9d, 0x8b, 0x9a, 0x02, 0xa4, 0xff, 0xc2, 0x45, 0x23, 0x9b, 0x18, 0x65, 0xa7, 0x40, 0xbd, 0x6c, 0x30, 0x87, 0xaf, 0xf1, 0x68, 0x4f, 0x68, 0xad, 0xb4, 0x47, 0xb4, 0x1b, 0xb4, 0x36, 0xda, 0x1d, 0x48, 0x86, 0x3f, 0x54, 0x51, 0x06, 0x32, 0x9d, 0x22, 0x5d, 0xa0, 0x18, 0x54, 0x30, 0x14, 0x79, 0x2c, 0xb4, 0xa1, 0x68, 0xfd, 0x55, 0x11, 0xa3, 0x8a, 0xc9, 0xa0, 0x73, 0xd0, 0x87, 0xb4, 0x46, 0xaa, 0xdd, 0xc9, 0x60, 0xd2, 0x0f, 0xe9, 0x47, 0xda, 0x49, 0x1e, 0x69, 0x08, 0x8e, 0xa4, 0x1b, 0xca, 0x24, 0x88, 0x0c, 0x40, 0xb9, 0xb9, 0x23, 0x76, 0xb0, 0x7a, 0x94, 0x6a, 0xe5, 0x90, 0xb6, 0xaf, 0xb5, 0x1c, 0xac, 0xfb, 0xa0, 0x1f, 0xa5, 0x9a, 0xff, 0xb7, 0x1c, 0x07, 0x78, 0x8e, 0x3d, 0xc7, 0x7d, 0x40, 0x45, 0xc6, 0x60, 0x56, 0xe8, 0x4d, 0x0e, 0x56, 0xe2, 0x9f, 0x51, 0xbe, 0x5a, 0xa4, 0x20, 0x42, 0x5e, 0xd1, 0xff, 0xf4, 0x24, 0xbe, 0x27, 0x0e, 0x12, 0x67, 0x89, 0x93, 0xc4, 0x79, 0xe2, 0x28, 0x51, 0x07, 0x7c, 0xe2, 0x04, 0x51, 0x4f, 0x5c, 0x22, 0x8e, 0x51, 0x78, 0x40, 0x73, 0xb8, 0xaa, 0x3a, 0x59, 0x43, 0x4f, 0x8b, 0x57, 0x55, 0x34, 0x07, 0xe5, 0x20, 0x1d, 0xf4, 0x71, 0xaa, 0x71, 0xea, 0x74, 0xfa, 0x34, 0xf8, 0x6b, 0x28, 0x57, 0x01, 0x62, 0x28, 0x05, 0xd4, 0x3b, 0x40, 0xf3, 0xbf, 0x50, 0x3c, 0xbd, 0x10, 0xcd, 0x3f, 0x08, 0x99, 0x2a, 0x9f, 0xa1, 0x90, 0x66, 0x49, 0x0a, 0xf9, 0x41, 0x68, 0x15, 0x16, 0xf3, 0xa3, 0x64, 0xc2, 0x91, 0x23, 0xf8, 0x2e, 0x4e, 0xce, 0x6e, 0x00, 0xd4, 0x9a, 0x4e, 0xf9, 0x00, 0xbc, 0xe6, 0xa9, 0xd6, 0x6a, 0x8c, 0x77, 0xe1, 0x2b, 0x97, 0xdf, 0x08, 0xe0, 0x5d, 0x8a, 0xd6, 0x00, 0x6a, 0x39, 0xe5, 0x53, 0x5e, 0x00, 0x02, 0x0b, 0x80, 0x23, 0x4f, 0x00, 0xb8, 0x6f, 0xbf, 0x72, 0x16, 0xaf, 0xd0, 0x27, 0xb5, 0x1c, 0xe0, 0xd8, 0x15, 0xa1, 0x52, 0x51, 0xd4, 0xef, 0x47, 0x52, 0x37, 0x1a, 0x30, 0xd1, 0x82, 0xa9, 0x8b, 0xfe, 0x31, 0x4c, 0xc0, 0x02, 0x6c, 0x51, 0x4e, 0x2e, 0xe0, 0x01, 0xbe, 0x10, 0x08, 0x61, 0x30, 0x06, 0x62, 0x21, 0x11, 0x52, 0x61, 0x32, 0xaa, 0xba, 0x04, 0xf2, 0x90, 0xea, 0x69, 0x30, 0x0b, 0xe6, 0x43, 0x09, 0x94, 0xc1, 0x72, 0x58, 0x0d, 0xeb, 0x61, 0x33, 0x6c, 0x85, 0x9d, 0xb0, 0x07, 0x0e, 0x40, 0x1d, 0x1c, 0x85, 0x93, 0x70, 0x06, 0x2e, 0xc2, 0x15, 0xb8, 0x01, 0x77, 0xd1, 0xdc, 0x68, 0x87, 0xe7, 0xd0, 0x0d, 0x6f, 0xa1, 0x17, 0xc3, 0x30, 0x06, 0xc6, 0xc6, 0xb8, 0x98, 0x01, 0x66, 0x8a, 0x59, 0x61, 0x0e, 0x98, 0x0b, 0xe6, 0x85, 0xf9, 0x63, 0x61, 0x58, 0x0c, 0x16, 0x8f, 0xa5, 0x62, 0xe9, 0x58, 0x16, 0x26, 0xc3, 0x94, 0xd8, 0x2c, 0x6c, 0x21, 0x56, 0x86, 0x95, 0x63, 0xeb, 0xb1, 0x2d, 0x58, 0x35, 0xf6, 0x33, 0x76, 0x04, 0x3b, 0x89, 0x9d, 0xc7, 0x5a, 0xb1, 0x3b, 0xd8, 0x43, 0xac, 0x13, 0x7b, 0x85, 0x7d, 0xc4, 0x09, 0x9c, 0x85, 0xeb, 0xe2, 0xc6, 0xb8, 0x35, 0x3e, 0x0a, 0xf7, 0xc2, 0x83, 0xf0, 0x68, 0x3c, 0x11, 0x9f, 0x84, 0x67, 0xe1, 0xf9, 0x78, 0x31, 0xbe, 0x08, 0x5f, 0x8a, 0xaf, 0xc5, 0xab, 0xf0, 0xdd, 0x78, 0x2d, 0x7e, 0x12, 0xbf, 0x88, 0xdf, 0xc0, 0xdb, 0xf0, 0xe7, 0x78, 0x0f, 0x01, 0x84, 0x06, 0xc1, 0x23, 0xcc, 0x08, 0x47, 0xc2, 0x8b, 0x08, 0x21, 0x62, 0x89, 0x34, 0x22, 0x93, 0x50, 0x10, 0x73, 0x88, 0x52, 0xa2, 0x82, 0xa8, 0x22, 0xf6, 0x12, 0x0d, 0xe8, 0x5d, 0x5f, 0x23, 0xda, 0x88, 0x2e, 0xe2, 0x03, 0x49, 0x27, 0xb9, 0x24, 0x9f, 0x74, 0x44, 0xf3, 0x33, 0x92, 0x4c, 0x22, 0x85, 0x64, 0x3e, 0x39, 0x87, 0x5c, 0x42, 0xae, 0x27, 0x77, 0x92, 0xb5, 0x64, 0x33, 0x79, 0x8d, 0x7c, 0x48, 0x76, 0x93, 0x5f, 0x68, 0x6c, 0x9a, 0x11, 0xcd, 0x81, 0xe6, 0x43, 0x8b, 0xa2, 0x4d, 0xa0, 0x65, 0xd1, 0xa6, 0xd1, 0x4a, 0x68, 0x15, 0xb4, 0xed, 0xb4, 0xc3, 0xb4, 0xd3, 0xe8, 0xdb, 0x69, 0xa7, 0xbd, 0xa5, 0xd3, 0xe9, 0x3c, 0xba, 0x0d, 0xdd, 0x13, 0x7d, 0x9b, 0xa9, 0xf4, 0x6c, 0xfa, 0x4c, 0xfa, 0x12, 0xfa, 0x46, 0xfa, 0x3e, 0x7a, 0x23, 0xbd, 0x95, 0xfe, 0x98, 0xde, 0xc3, 0x60, 0x30, 0x0c, 0x18, 0x0e, 0x0c, 0x3f, 0x46, 0x2c, 0x43, 0xc0, 0x28, 0x64, 0x94, 0x30, 0xd6, 0x31, 0x76, 0x33, 0x4e, 0x30, 0xae, 0x32, 0xda, 0x19, 0xef, 0xd5, 0x34, 0xd4, 0x4c, 0xd5, 0x5c, 0xd4, 0xc2, 0xd5, 0xd2, 0xd4, 0x64, 0x6a, 0x0b, 0xd4, 0x2a, 0xd4, 0x76, 0xa9, 0x1d, 0x57, 0xbb, 0xaa, 0xf6, 0x54, 0xad, 0x57, 0x5d, 0x4b, 0xdd, 0x4a, 0xdd, 0x47, 0x3d, 0x56, 0x5d, 0xa4, 0x3e, 0x43, 0x7d, 0x99, 0xfa, 0x36, 0xf5, 0x06, 0xf5, 0xcb, 0xea, 0xed, 0xea, 0xbd, 0x4c, 0x6d, 0xa6, 0x0d, 0xd3, 0x8f, 0x99, 0xc8, 0xcc, 0x66, 0xce, 0x67, 0xae, 0x65, 0xee, 0x65, 0x9e, 0x66, 0xde, 0x63, 0xbe, 0xd6, 0xd0, 0xd0, 0x30, 0xd7, 0xf0, 0xd6, 0x18, 0xaf, 0x21, 0xd5, 0x98, 0xa7, 0xb1, 0x56, 0x63, 0xbf, 0xc6, 0x39, 0x8d, 0x87, 0x1a, 0x1f, 0x58, 0x3a, 0x2c, 0x7b, 0x56, 0x08, 0x6b, 0x22, 0x4b, 0xc9, 0x5a, 0xca, 0xda, 0xc1, 0x6a, 0x64, 0xdd, 0x61, 0xbd, 0x66, 0xb3, 0xd9, 0xd6, 0xec, 0x40, 0x76, 0x1a, 0xbb, 0x90, 0xbd, 0x94, 0x5d, 0xcd, 0x3e, 0xc5, 0x7e, 0xc0, 0x7e, 0xcf, 0xe1, 0x72, 0x46, 0x72, 0xa2, 0x38, 0x22, 0xce, 0x5c, 0x4e, 0x25, 0xa7, 0x96, 0x73, 0x95, 0xf3, 0x42, 0x53, 0x5d, 0xd3, 0x4a, 0x33, 0x48, 0x73, 0xb2, 0x66, 0xb1, 0x66, 0x85, 0xe6, 0x41, 0xcd, 0xcb, 0x9a, 0x5d, 0x5a, 0xea, 0x5a, 0xd6, 0x5a, 0x21, 0x5a, 0x02, 0xad, 0x39, 0x5a, 0x95, 0x5a, 0x47, 0xb4, 0x6e, 0x69, 0xf5, 0x68, 0x73, 0xb5, 0x9d, 0xb5, 0x63, 0xb5, 0xf3, 0xb4, 0x97, 0x68, 0xef, 0xd2, 0x3e, 0xaf, 0xdd, 0xa1, 0xc3, 0xd0, 0xb1, 0xd6, 0x09, 0xd3, 0x11, 0xe9, 0x2c, 0xd2, 0xd9, 0xaa, 0x73, 0x4a, 0xe7, 0x31, 0x97, 0xe0, 0x5a, 0x70, 0x43, 0xb8, 0x42, 0xee, 0x42, 0xee, 0x36, 0xee, 0x69, 0x6e, 0xbb, 0x2e, 0x5d, 0xd7, 0x46, 0x37, 0x4a, 0x37, 0x5b, 0xb7, 0x4c, 0x77, 0x8f, 0x6e, 0x8b, 0x6e, 0xb7, 0x9e, 0x8e, 0x9e, 0x9b, 0x5e, 0xb2, 0xde, 0x74, 0xbd, 0x4a, 0xbd, 0x63, 0x7a, 0x6d, 0x3c, 0x82, 0x67, 0xcd, 0x8b, 0xe2, 0xe5, 0xf2, 0x96, 0xf1, 0x0e, 0xf0, 0x6e, 0xf2, 0x3e, 0x0e, 0x33, 0x1e, 0x16, 0x34, 0x4c, 0x3c, 0x6c, 0xf1, 0xb0, 0xbd, 0xc3, 0xae, 0x0e, 0x7b, 0xa7, 0x3f, 0x5c, 0x3f, 0x50, 0x5f, 0xac, 0x5f, 0xaa, 0xbf, 0x4f, 0xff, 0x86, 0xfe, 0x47, 0x03, 0xbe, 0x41, 0x98, 0x41, 0x8e, 0xc1, 0x0a, 0x83, 0x3a, 0x83, 0xfb, 0x86, 0xa4, 0xa1, 0xbd, 0xe1, 0x78, 0xc3, 0x69, 0x86, 0x9b, 0x0c, 0x4f, 0x1b, 0x76, 0x0d, 0xd7, 0x1d, 0xee, 0x3b, 0x5c, 0x38, 0xbc, 0x74, 0xf8, 0x81, 0xe1, 0xbf, 0x19, 0xe1, 0x46, 0xf6, 0x46, 0xf1, 0x46, 0x33, 0x8d, 0xb6, 0x1a, 0x5d, 0x32, 0xea, 0x31, 0x36, 0x31, 0x8e, 0x30, 0x96, 0x1b, 0xaf, 0x33, 0x3e, 0x65, 0xdc, 0x65, 0xc2, 0x33, 0x09, 0x34, 0xc9, 0x36, 0x59, 0x65, 0x72, 0xdc, 0xa4, 0xd3, 0x94, 0x6b, 0xea, 0x6f, 0x2a, 0x35, 0x5d, 0x65, 0x7a, 0xc2, 0xf4, 0x19, 0x5f, 0x8f, 0x1f, 0xc4, 0xcf, 0xe5, 0xaf, 0xe5, 0x37, 0xf3, 0xbb, 0xcd, 0x8c, 0xcc, 0x22, 0xcd, 0x94, 0x66, 0x5b, 0xcc, 0x5a, 0xcc, 0x7a, 0xcd, 0x6d, 0xcc, 0x93, 0xcc, 0x17, 0x98, 0xef, 0x33, 0xbf, 0x6f, 0xc1, 0xb4, 0xf0, 0xb2, 0xc8, 0xb4, 0x58, 0x65, 0xd1, 0x64, 0xd1, 0x6d, 0x69, 0x6a, 0x39, 0xd6, 0x72, 0x96, 0x65, 0x8d, 0xe5, 0x6f, 0x56, 0xea, 0x56, 0x5e, 0x56, 0x12, 0xab, 0x35, 0x56, 0x67, 0xad, 0xde, 0x59, 0xdb, 0x58, 0xa7, 0x58, 0x7f, 0x67, 0x5d, 0x67, 0xdd, 0x61, 0xa3, 0x6f, 0x13, 0x65, 0x53, 0x6c, 0x53, 0x63, 0x73, 0xcf, 0x96, 0x6d, 0x1b, 0x60, 0x9b, 0x6f, 0x5b, 0x65, 0x7b, 0xdd, 0x8e, 0x6e, 0xe7, 0x65, 0x97, 0x63, 0xb7, 0xd1, 0xee, 0x8a, 0x3d, 0x6e, 0xef, 0x6e, 0x2f, 0xb1, 0xaf, 0xb4, 0xbf, 0xec, 0x80, 0x3b, 0x78, 0x38, 0x48, 0x1d, 0x36, 0x3a, 0xb4, 0x8e, 0xa0, 0x8d, 0xf0, 0x1e, 0x21, 0x1b, 0x51, 0x35, 0xe2, 0x96, 0x23, 0xcb, 0x31, 0xc8, 0xb1, 0xc8, 0xb1, 0xc6, 0xf1, 0xe1, 0x48, 0xde, 0xc8, 0x98, 0x91, 0x0b, 0x46, 0xd6, 0x8d, 0x7c, 0x31, 0xca, 0x72, 0x54, 0xda, 0xa8, 0x15, 0xa3, 0xce, 0x8e, 0xfa, 0xe2, 0xe4, 0xee, 0x94, 0xeb, 0xb4, 0xcd, 0xe9, 0xae, 0xb3, 0x8e, 0xf3, 0x18, 0xe7, 0x05, 0xce, 0x0d, 0xce, 0xaf, 0x5c, 0xec, 0x5d, 0x84, 0x2e, 0x95, 0x2e, 0xd7, 0x5d, 0xd9, 0xae, 0xe1, 0xae, 0x73, 0x5d, 0xeb, 0x5d, 0x5f, 0xba, 0x39, 0xb8, 0x89, 0xdd, 0x36, 0xb9, 0xdd, 0x76, 0xe7, 0xba, 0x8f, 0x75, 0xff, 0xce, 0xbd, 0xc9, 0xfd, 0xb3, 0x87, 0xa7, 0x87, 0xc2, 0x63, 0xaf, 0x47, 0xa7, 0xa7, 0xa5, 0x67, 0xba, 0xe7, 0x06, 0xcf, 0x5b, 0x5e, 0xba, 0x5e, 0x71, 0x5e, 0x4b, 0xbc, 0xce, 0x79, 0xd3, 0xbc, 0x83, 0xbd, 0xe7, 0x7a, 0x1f, 0xf5, 0xfe, 0xe0, 0xe3, 0xe1, 0x53, 0xe8, 0x73, 0xc0, 0xe7, 0x2f, 0x5f, 0x47, 0xdf, 0x1c, 0xdf, 0x5d, 0xbe, 0x1d, 0xa3, 0x6d, 0x46, 0x8b, 0x47, 0x6f, 0x1b, 0xfd, 0xd8, 0xcf, 0xdc, 0x4f, 0xe0, 0xb7, 0xc5, 0xaf, 0xcd, 0x9f, 0xef, 0x9f, 0xee, 0xff, 0xa3, 0x7f, 0x5b, 0x80, 0x59, 0x80, 0x20, 0xa0, 0x2a, 0xe0, 0x51, 0xa0, 0x45, 0xa0, 0x28, 0x70, 0x7b, 0xe0, 0xd3, 0x20, 0xbb, 0xa0, 0xec, 0xa0, 0xdd, 0x41, 0x2f, 0x82, 0x9d, 0x82, 0x15, 0xc1, 0x87, 0x83, 0xdf, 0x85, 0xf8, 0x84, 0xcc, 0x0e, 0x69, 0x0c, 0x25, 0x42, 0x23, 0x42, 0x4b, 0x43, 0x5b, 0xc2, 0x74, 0xc2, 0x92, 0xc2, 0xd6, 0x87, 0x3d, 0x08, 0x37, 0x0f, 0xcf, 0x0a, 0xaf, 0x09, 0xef, 0x8e, 0x70, 0x8f, 0x98, 0x19, 0xd1, 0x18, 0x49, 0x8b, 0x8c, 0x8e, 0x5c, 0x11, 0x79, 0x2b, 0xca, 0x38, 0x4a, 0x18, 0x55, 0x1d, 0xd5, 0x3d, 0xc6, 0x73, 0xcc, 0xec, 0x31, 0xcd, 0xd1, 0xac, 0xe8, 0x84, 0xe8, 0xf5, 0xd1, 0x8f, 0x62, 0xec, 0x63, 0x14, 0x31, 0x0d, 0x63, 0xf1, 0xb1, 0x63, 0xc6, 0xae, 0x1c, 0x7b, 0x6f, 0x9c, 0xd5, 0x38, 0xd9, 0xb8, 0xba, 0x58, 0x88, 0x8d, 0x8a, 0x5d, 0x19, 0x7b, 0x3f, 0xce, 0x26, 0x2e, 0x3f, 0xee, 0x97, 0xf1, 0xf4, 0xf1, 0x71, 0xe3, 0x2b, 0xc7, 0x3f, 0x89, 0x77, 0x8e, 0x9f, 0x15, 0x7f, 0x36, 0x81, 0x9b, 0x30, 0x25, 0x61, 0x57, 0xc2, 0xdb, 0xc4, 0xe0, 0xc4, 0x65, 0x89, 0x77, 0x93, 0x6c, 0x93, 0x94, 0x49, 0x4d, 0xc9, 0x9a, 0xc9, 0x13, 0x93, 0xab, 0x93, 0xdf, 0xa5, 0x84, 0xa6, 0x94, 0xa7, 0xb4, 0x4d, 0x18, 0x35, 0x61, 0xf6, 0x84, 0x8b, 0xa9, 0x86, 0xa9, 0xd2, 0xd4, 0xfa, 0x34, 0x46, 0x5a, 0x72, 0xda, 0xf6, 0xb4, 0x9e, 0x6f, 0xc2, 0xbe, 0x59, 0xfd, 0x4d, 0xfb, 0x44, 0xf7, 0x89, 0x25, 0x13, 0x6f, 0x4e, 0xb2, 0x99, 0x34, 0x7d, 0xd2, 0xf9, 0xc9, 0x86, 0x93, 0x73, 0x27, 0x1f, 0x9b, 0xa2, 0x39, 0x45, 0x30, 0xe5, 0x60, 0x3a, 0x2d, 0x3d, 0x25, 0x7d, 0x57, 0xfa, 0x27, 0x41, 0xac, 0xa0, 0x4a, 0xd0, 0x93, 0x11, 0x95, 0xb1, 0x21, 0xa3, 0x5b, 0x18, 0x22, 0x5c, 0x23, 0x7c, 0x2e, 0x0a, 0x14, 0xad, 0x12, 0x75, 0x8a, 0xfd, 0xc4, 0xe5, 0xe2, 0xa7, 0x99, 0x7e, 0x99, 0xe5, 0x99, 0x1d, 0x59, 0x7e, 0x59, 0x2b, 0xb3, 0x3a, 0x25, 0x01, 0x92, 0x0a, 0x49, 0x97, 0x34, 0x44, 0xba, 0x5e, 0xfa, 0x32, 0x3b, 0x32, 0x7b, 0x73, 0xf6, 0xbb, 0x9c, 0xd8, 0x9c, 0x1d, 0x39, 0x7d, 0xb9, 0x29, 0xb9, 0xfb, 0xf2, 0xd4, 0xf2, 0xd2, 0xf3, 0x8e, 0xc8, 0x74, 0x64, 0x39, 0xb2, 0xe6, 0xa9, 0x26, 0x53, 0xa7, 0x4f, 0x6d, 0x95, 0x3b, 0xc8, 0x4b, 0xe4, 0x6d, 0xf9, 0x3e, 0xf9, 0xab, 0xf3, 0xbb, 0x15, 0xd1, 0x8a, 0xed, 0x05, 0x58, 0xc1, 0xa4, 0x82, 0xfa, 0x42, 0x5d, 0xb4, 0x79, 0xbe, 0xa4, 0xb4, 0x55, 0x7e, 0xab, 0x7c, 0x58, 0xe4, 0x5f, 0x54, 0x59, 0xf4, 0x7e, 0x5a, 0xf2, 0xb4, 0x83, 0xd3, 0xb5, 0xa7, 0xcb, 0xa6, 0x5f, 0x9a, 0x61, 0x3f, 0x63, 0xf1, 0x8c, 0xa7, 0xc5, 0xe1, 0xc5, 0x3f, 0xcd, 0x24, 0x67, 0x0a, 0x67, 0x36, 0xcd, 0x32, 0x9b, 0x35, 0x7f, 0xd6, 0xc3, 0xd9, 0x41, 0xb3, 0xb7, 0xcc, 0xc1, 0xe6, 0x64, 0xcc, 0x69, 0x9a, 0x6b, 0x31, 0x77, 0xd1, 0xdc, 0xf6, 0x79, 0x11, 0xf3, 0x76, 0xce, 0x67, 0xce, 0xcf, 0x99, 0xff, 0xeb, 0x02, 0xa7, 0x05, 0xe5, 0x0b, 0xde, 0x2c, 0x4c, 0x59, 0xd8, 0xb0, 0xc8, 0x78, 0xd1, 0xbc, 0x45, 0x8f, 0xbf, 0x8d, 0xf8, 0xb6, 0xa6, 0x84, 0x53, 0xa2, 0x28, 0xb9, 0xf5, 0x9d, 0xef, 0x77, 0x9b, 0xbf, 0x27, 0xbf, 0x97, 0x7e, 0xdf, 0xb2, 0xd8, 0x75, 0xf1, 0xba, 0xc5, 0x5f, 0x4a, 0x45, 0xa5, 0x17, 0xca, 0x9c, 0xca, 0x2a, 0xca, 0x3e, 0x2d, 0x11, 0x2e, 0xb9, 0xf0, 0x83, 0xf3, 0x0f, 0x6b, 0x7f, 0xe8, 0x5b, 0x9a, 0xb9, 0xb4, 0x65, 0x99, 0xc7, 0xb2, 0x4d, 0xcb, 0xe9, 0xcb, 0x65, 0xcb, 0x6f, 0xae, 0x08, 0x58, 0xb1, 0xb3, 0x5c, 0xbb, 0xbc, 0xb8, 0xfc, 0xf1, 0xca, 0xb1, 0x2b, 0x6b, 0x57, 0xf1, 0x57, 0x95, 0xae, 0x7a, 0xb3, 0x7a, 0xca, 0xea, 0xf3, 0x15, 0x6e, 0x15, 0x9b, 0xd7, 0x30, 0xd7, 0x28, 0xd7, 0xb4, 0xad, 0x8d, 0x59, 0x5b, 0xbf, 0xce, 0x72, 0xdd, 0xf2, 0x75, 0x9f, 0xd6, 0x4b, 0xd6, 0xdf, 0xa8, 0x0c, 0xae, 0xdc, 0xb7, 0xc1, 0x68, 0xc3, 0xe2, 0x0d, 0xef, 0x36, 0x8a, 0x36, 0x5e, 0xdd, 0x14, 0xb8, 0x69, 0xef, 0x66, 0xe3, 0xcd, 0x65, 0x9b, 0x3f, 0xfe, 0x28, 0xfd, 0xf1, 0xf6, 0x96, 0x88, 0x2d, 0xb5, 0x55, 0xd6, 0x55, 0x15, 0x5b, 0xe9, 0x5b, 0x8b, 0xb6, 0x3e, 0xd9, 0x96, 0xbc, 0xed, 0xec, 0x4f, 0x5e, 0x3f, 0x55, 0x6f, 0x37, 0xdc, 0x5e, 0xb6, 0xfd, 0xf3, 0x0e, 0xd9, 0x8e, 0xb6, 0x9d, 0xf1, 0x3b, 0x9b, 0xab, 0x3d, 0xab, 0xab, 0x77, 0x19, 0xed, 0x5a, 0x56, 0x83, 0xd7, 0x28, 0x6b, 0x3a, 0x77, 0x4f, 0xdc, 0x7d, 0x65, 0x4f, 0xe8, 0x9e, 0xfa, 0xbd, 0x8e, 0x7b, 0xb7, 0xec, 0xe3, 0xed, 0x2b, 0xdb, 0x0f, 0xfb, 0x95, 0xfb, 0x9f, 0xfd, 0x9c, 0xfe, 0xf3, 0xcd, 0x03, 0xd1, 0x07, 0x9a, 0x0e, 0x7a, 0x1d, 0xdc, 0x7b, 0xc8, 0xea, 0xd0, 0x86, 0xc3, 0xdc, 0xc3, 0xa5, 0xb5, 0x58, 0xed, 0x8c, 0xda, 0xee, 0x3a, 0x49, 0x5d, 0x5b, 0x7d, 0x6a, 0x7d, 0xeb, 0x91, 0x31, 0x47, 0x9a, 0x1a, 0x7c, 0x1b, 0x0e, 0xff, 0x32, 0xf2, 0x97, 0x1d, 0x47, 0xcd, 0x8e, 0x56, 0x1e, 0xd3, 0x3b, 0xb6, 0xec, 0x38, 0xf3, 0xf8, 0xa2, 0xe3, 0x7d, 0x27, 0x8a, 0x4f, 0xf4, 0x34, 0xca, 0x1b, 0xbb, 0x4e, 0x66, 0x9d, 0x7c, 0xdc, 0x34, 0xa5, 0xe9, 0xee, 0xa9, 0x09, 0xa7, 0xae, 0x37, 0x8f, 0x6f, 0x6e, 0x39, 0x1d, 0x7d, 0xfa, 0xdc, 0x99, 0xf0, 0x33, 0xa7, 0xce, 0x06, 0x9d, 0x3d, 0x71, 0xce, 0xef, 0xdc, 0xd1, 0xf3, 0x3e, 0xe7, 0x8f, 0x5c, 0xf0, 0xba, 0x50, 0x77, 0xd1, 0xe3, 0x62, 0xed, 0x25, 0xf7, 0x4b, 0x87, 0x7f, 0x75, 0xff, 0xf5, 0x70, 0x8b, 0x47, 0x4b, 0xed, 0x65, 0xcf, 0xcb, 0xf5, 0x57, 0xbc, 0xaf, 0x34, 0xb4, 0x8e, 0x6e, 0x3d, 0x7e, 0x35, 0xe0, 0xea, 0xc9, 0x6b, 0xa1, 0xd7, 0xce, 0x5c, 0x8f, 0xba, 0x7e, 0xf1, 0xc6, 0xb8, 0x1b, 0xad, 0x37, 0x93, 0x6e, 0xde, 0xbe, 0x35, 0xf1, 0x56, 0xdb, 0x6d, 0xd1, 0xed, 0x8e, 0x3b, 0xb9, 0x77, 0x5e, 0xfe, 0x56, 0xf4, 0x5b, 0xef, 0xdd, 0x79, 0xf7, 0x68, 0xf7, 0x4a, 0xef, 0x6b, 0xdd, 0xaf, 0x78, 0x60, 0xf4, 0xa0, 0xea, 0x77, 0xbb, 0xdf, 0xf7, 0xb5, 0x79, 0xb4, 0x1d, 0x7b, 0x18, 0xfa, 0xf0, 0xd2, 0xa3, 0x84, 0x47, 0x77, 0x1f, 0x0b, 0x1f, 0x3f, 0xff, 0xa3, 0xe0, 0x8f, 0x4f, 0xed, 0x8b, 0x9e, 0xb0, 0x9f, 0x54, 0x3c, 0x35, 0x7d, 0x5a, 0xdd, 0xe1, 0xd2, 0x71, 0xb4, 0x33, 0xbc, 0xf3, 0xca, 0xb3, 0x6f, 0x9e, 0xb5, 0x3f, 0x97, 0x3f, 0xef, 0xed, 0x2a, 0xf9, 0x53, 0xfb, 0xcf, 0x0d, 0x2f, 0x6c, 0x5f, 0x1c, 0xfa, 0x2b, 0xf0, 0xaf, 0x4b, 0xdd, 0x13, 0xba, 0xdb, 0x5f, 0x2a, 0x5e, 0xf6, 0xbd, 0x5a, 0xf2, 0xda, 0xe0, 0xf5, 0x8e, 0x37, 0x6e, 0x6f, 0x9a, 0x7a, 0xe2, 0x7a, 0x1e, 0xbc, 0xcd, 0x7b, 0xdb, 0xfb, 0xae, 0xf4, 0xbd, 0xc1, 0xfb, 0x9d, 0x1f, 0xbc, 0x3e, 0x9c, 0xfd, 0x98, 0xf2, 0xf1, 0x69, 0xef, 0xb4, 0x4f, 0x8c, 0x4f, 0x6b, 0x3f, 0xdb, 0x7d, 0x6e, 0xf8, 0x12, 0xfd, 0xe5, 0x5e, 0x5f, 0x5e, 0x5f, 0x9f, 0x5c, 0xa0, 0x10, 0xa8, 0xf6, 0x02, 0x04, 0xea, 0xf1, 0xcc, 0x4c, 0x80, 0x57, 0x3b, 0x00, 0xd8, 0xa9, 0x68, 0xef, 0x70, 0x05, 0x80, 0xc9, 0xe9, 0x3f, 0x73, 0xa9, 0x3c, 0xb0, 0xfe, 0x73, 0x22, 0xc2, 0xd8, 0x40, 0xa3, 0xe8, 0x7f, 0xe0, 0xfe, 0x73, 0x19, 0x65, 0x40, 0x7b, 0x08, 0xd8, 0x11, 0x08, 0x90, 0x34, 0x0f, 0x20, 0xa6, 0x11, 0x60, 0x13, 0x6a, 0x56, 0x08, 0xb3, 0xd0, 0x9d, 0xda, 0x7e, 0x27, 0x06, 0x02, 0xee, 0xea, 0x3a, 0xd4, 0x10, 0x43, 0x5d, 0x05, 0x99, 0xae, 0x2e, 0x2a, 0x80, 0xb1, 0x14, 0x68, 0x6b, 0xf2, 0xbe, 0xaf, 0xef, 0xb5, 0x31, 0x00, 0xa3, 0x01, 0xe0, 0xb3, 0xa2, 0xaf, 0xaf, 0x77, 0x63, 0x5f, 0xdf, 0xe7, 0x6d, 0x68, 0xaf, 0x7e, 0x07, 0xa0, 0x31, 0xbf, 0xff, 0xac, 0x47, 0x79, 0x53, 0x67, 0xc8, 0x1f, 0xd1, 0x7e, 0x1e, 0xe0, 0x7c, 0xcb, 0x92, 0x79, 0xd4, 0xfd, 0xef, 0xd7, 0xff, 0x00, 0x53, 0x9d, 0x6a, 0xc0, 0x3e, 0x1f, 0x78, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01, 0x49, 0x52, 0x24, 0xf0, 0x00, 0x00, 0x01, 0x9c, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x39, 0x30, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc1, 0xe2, 0xd2, 0xc6, 0x00, 0x00, 0x02, 0x01, 0x49, 0x44, 0x41, 0x54, 0x48, 0x0d, 0xbd, 0x96, 0xcf, 0x2b, 0x05, 0x51, 0x14, 0xc7, 0x1f, 0x3d, 0xf2, 0x33, 0x0b, 0x85, 0x52, 0xb6, 0x42, 0xc4, 0x42, 0xd6, 0x96, 0x8a, 0x12, 0x0b, 0xca, 0x1f, 0x41, 0x42, 0xb1, 0x61, 0x85, 0x35, 0x29, 0x85, 0x94, 0x8d, 0x62, 0x69, 0x23, 0x24, 0x29, 0x65, 0x4b, 0x51, 0x16, 0x44, 0x84, 0x2c, 0x94, 0x84, 0xfc, 0xf6, 0x39, 0xf5, 0x4e, 0x6e, 0xd3, 0x1b, 0xef, 0xde, 0x37, 0x33, 0x4e, 0x7d, 0x3b, 0x77, 0xe6, 0x9e, 0x73, 0x3e, 0x77, 0xee, 0xcc, 0xdc, 0x7b, 0x63, 0xb1, 0x58, 0x6c, 0x0a, 0x55, 0xa1, 0x7f, 0xb1, 0xcc, 0x04, 0xe5, 0x10, 0x3f, 0x8d, 0x8a, 0xff, 0x83, 0xda, 0x02, 0xe4, 0x3b, 0xa1, 0x7b, 0x7c, 0x1f, 0xca, 0x42, 0x91, 0x59, 0x2e, 0x95, 0x5f, 0x90, 0x42, 0xc5, 0x9f, 0xa0, 0x36, 0x14, 0x99, 0xad, 0x53, 0xd9, 0x04, 0x6a, 0x7b, 0x8b, 0xfb, 0xb5, 0x51, 0x50, 0x7b, 0x7d, 0x80, 0x02, 0xfe, 0x40, 0xb3, 0xa8, 0x04, 0x85, 0x66, 0x95, 0x54, 0xd2, 0xa7, 0xf2, 0xf3, 0x0f, 0xc4, 0x0c, 0xa2, 0xec, 0xb0, 0xa8, 0x67, 0x16, 0x50, 0x19, 0xcc, 0x29, 0xea, 0x08, 0x03, 0x3a, 0x63, 0x09, 0xd4, 0x19, 0xd8, 0x21, 0xbe, 0x21, 0x08, 0x58, 0xbe, 0x4a, 0x2d, 0x66, 0xeb, 0x3f, 0xc9, 0x59, 0x40, 0x65, 0xe9, 0x80, 0xf3, 0x49, 0x7a, 0x45, 0xb6, 0x30, 0x33, 0xee, 0x91, 0xbc, 0x11, 0x94, 0x83, 0x9c, 0x6c, 0x93, 0x68, 0xb3, 0x90, 0x6b, 0xfb, 0x9c, 0xfc, 0x2e, 0x17, 0x62, 0x7f, 0x40, 0xa0, 0x0e, 0x70, 0x8f, 0x3a, 0x8d, 0x36, 0xe0, 0xea, 0x90, 0x80, 0x02, 0xfe, 0x42, 0x4b, 0xa8, 0x1c, 0xfd, 0x69, 0x17, 0xf4, 0xea, 0x48, 0xc3, 0xf0, 0x4f, 0xd4, 0x1b, 0x45, 0x79, 0x7e, 0x54, 0x59, 0x55, 0xc2, 0x00, 0x79, 0x6b, 0x5c, 0x52, 0xb7, 0x47, 0xb7, 0x27, 0x13, 0x2e, 0xeb, 0x6a, 0x14, 0x56, 0x44, 0xd1, 0xe7, 0x64, 0x85, 0x0b, 0xb9, 0xf9, 0x86, 0xbc, 0x23, 0x0c, 0x72, 0x7d, 0x4c, 0x3d, 0x59, 0x3e, 0x7d, 0x6d, 0x9b, 0x9e, 0x20, 0x00, 0x33, 0x77, 0x95, 0x5a, 0x05, 0xbe, 0xa4, 0x44, 0xc7, 0x50, 0x08, 0x40, 0xd9, 0x65, 0x64, 0xb1, 0xb7, 0x32, 0xd9, 0x03, 0xcd, 0x51, 0xba, 0xb6, 0xef, 0xc8, 0x6f, 0xb6, 0x22, 0x19, 0x41, 0x57, 0x69, 0x42, 0xe5, 0xf4, 0x50, 0x63, 0xd4, 0xb1, 0x6e, 0xce, 0xa7, 0x09, 0x94, 0xd9, 0x90, 0x6f, 0xc0, 0xf9, 0x5c, 0xd4, 0x19, 0x00, 0x28, 0xd0, 0x39, 0xe4, 0x64, 0xf2, 0xdf, 0xbc, 0x23, 0xd7, 0xf7, 0x67, 0xc6, 0xcb, 0xda, 0xec, 0x64, 0xbb, 0x44, 0x9b, 0x05, 0xbc, 0xed, 0x0d, 0xfa, 0xff, 0xda, 0xb8, 0x65, 0xbf, 0x6c, 0x75, 0x21, 0x0e, 0xfb, 0x00, 0x65, 0x61, 0x1e, 0x47, 0xb2, 0x52, 0x89, 0xd6, 0x90, 0x77, 0x30, 0x7a, 0x2d, 0x7b, 0x65, 0x1d, 0xb2, 0xb2, 0x7a, 0xa2, 0x34, 0x51, 0xbd, 0x1c, 0xa6, 0xda, 0x3d, 0xd9, 0xf2, 0x63, 0x1f, 0x24, 0x89, 0xd5, 0x1c, 0xd9, 0x10, 0x4a, 0x3d, 0x39, 0x49, 0x2f, 0x33, 0xb8, 0x7b, 0x8d, 0x34, 0xf1, 0x88, 0xb6, 0xdf, 0x12, 0x55, 0x41, 0xdf, 0xad, 0x11, 0xab, 0x39, 0xea, 0xf7, 0xe9, 0xb3, 0x3a, 0x11, 0x2c, 0x26, 0x8a, 0xac, 0xe0, 0x53, 0x2d, 0x51, 0x4d, 0xc4, 0xc8, 0x7f, 0xa8, 0x10, 0xaf, 0x9f, 0xa0, 0x2f, 0xa5, 0xc9, 0x91, 0x70, 0x20, 0x65, 0xd4, 0x6f, 0x40, 0x37, 0x4d, 0x2f, 0x48, 0xaf, 0x6f, 0x7e, 0xc3, 0xc2, 0x6d, 0x8d, 0xf9, 0x40, 0x65, 0xca, 0x23, 0x31, 0x79, 0xf7, 0xcb, 0x48, 0x9f, 0x4c, 0xbd, 0xd5, 0x94, 0xa6, 0x3b, 0xa2, 0x38, 0x89, 0x93, 0x48, 0x9e, 0x4a, 0xa6, 0x52, 0x60, 0xf1, 0x1f, 0x65, 0x5c, 0x9e, 0x8b, 0x0f, 0xbf, 0xa0, 0x23, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXJSONIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa8, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x30, 0x39, 0x54, 0x32, 0x32, 0x3a, 0x30, 0x32, 0x3a, 0x32, 0x33, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x03, 0x64, 0xa2, 0xe8, 0x00, 0x00, 0x06, 0x37, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x59, 0x7b, 0x48, 0x57, 0x57, 0x1c, 0x3f, 0xc7, 0x47, 0x3e, 0xf2, 0x31, 0xc9, 0x50, 0xdb, 0x56, 0x13, 0x73, 0x59, 0x3e, 0x57, 0x46, 0x66, 0xe2, 0x28, 0x1b, 0x51, 0x6a, 0x2a, 0xb1, 0xcd, 0x6a, 0x43, 0xaa, 0x8d, 0x06, 0xe5, 0xa0, 0xac, 0x86, 0x8c, 0xcd, 0xbf, 0x4c, 0xb3, 0x65, 0x81, 0xb4, 0xd2, 0xa6, 0x11, 0xe8, 0x60, 0xb4, 0x2d, 0x96, 0x2e, 0xb6, 0x08, 0x35, 0x62, 0x15, 0x3e, 0x96, 0xda, 0x16, 0xe1, 0x7c, 0xe2, 0x62, 0x51, 0x12, 0xe5, 0x2f, 0xcd, 0xf7, 0xdd, 0xe7, 0xfe, 0xce, 0xe5, 0x78, 0xfb, 0xa9, 0xf7, 0xfe, 0x7e, 0xbf, 0x7b, 0xf6, 0x08, 0x7e, 0x87, 0xb8, 0x7c, 0xcf, 0xf7, 0x7c, 0xce, 0xf7, 0x7d, 0xbe, 0xe7, 0xf4, 0x93, 0x4a, 0x92, 0x44, 0x5e, 0xe4, 0xe1, 0xf4, 0x22, 0x1b, 0x2f, 0xdb, 0xee, 0x70, 0xe0, 0xbf, 0xce, 0xa0, 0x23, 0x03, 0x8e, 0x0c, 0x18, 0x8c, 0x80, 0xa3, 0x84, 0x0c, 0x06, 0xd0, 0xf0, 0x76, 0x17, 0xc3, 0x12, 0x14, 0x01, 0xb5, 0xbf, 0x93, 0xeb, 0x7f, 0x48, 0xa3, 0xe3, 0xf2, 0x34, 0x29, 0x9c, 0xbe, 0xb9, 0xd4, 0x52, 0xf0, 0xe7, 0xdf, 0x2a, 0x37, 0x66, 0xd0, 0x4b, 0xf4, 0x9d, 0x38, 0x32, 0xcf, 0xcb, 0x12, 0x60, 0xdf, 0x5c, 0x8c, 0x03, 0x39, 0x55, 0x52, 0x45, 0xfd, 0xd4, 0x8d, 0xee, 0xe5, 0x3e, 0x83, 0x03, 0x25, 0x3f, 0x73, 0x80, 0xf4, 0xc5, 0x8f, 0xf4, 0xa7, 0x4f, 0x68, 0x68, 0xa0, 0x7d, 0x36, 0x3f, 0xb7, 0x4b, 0xc0, 0x19, 0x68, 0xe8, 0x24, 0x6a, 0xeb, 0x9f, 0x13, 0x3f, 0xcb, 0xe4, 0xd1, 0x53, 0x29, 0xf7, 0x1b, 0xee, 0xcf, 0x2c, 0x20, 0xeb, 0xd8, 0x02, 0x32, 0x00, 0x07, 0xf8, 0x28, 0xc8, 0x74, 0x7a, 0x2b, 0x82, 0xcc, 0xf3, 0xe6, 0x8c, 0x29, 0xe2, 0xd7, 0xc3, 0x4e, 0x4f, 0x86, 0xc8, 0xc7, 0xe7, 0xa4, 0xdb, 0x7d, 0xb2, 0xe9, 0x0d, 0x1d, 0x53, 0x4b, 0x46, 0x28, 0x01, 0x0e, 0x98, 0x9e, 0x29, 0xb1, 0xf4, 0xf5, 0xa4, 0x1f, 0x25, 0xcd, 0x6a, 0x4c, 0xf0, 0x7c, 0x79, 0x69, 0x6b, 0x3c, 0xbd, 0x6d, 0x8e, 0xbd, 0x69, 0x18, 0xbb, 0xe8, 0xac, 0x68, 0xab, 0x17, 0x04, 0x94, 0x10, 0xd7, 0xe5, 0x31, 0x87, 0x93, 0xb3, 0x12, 0xee, 0xae, 0xb3, 0x2e, 0xd9, 0xb7, 0x20, 0xd2, 0x01, 0xfb, 0x2c, 0x30, 0xb8, 0xcb, 0xe1, 0x00, 0x21, 0x8f, 0x06, 0x95, 0x20, 0xba, 0x3a, 0xeb, 0x47, 0x53, 0x8d, 0x79, 0x3c, 0xa4, 0x8f, 0xd7, 0x45, 0x18, 0xcd, 0xc0, 0xfd, 0x27, 0xa4, 0xe6, 0x96, 0xa2, 0x65, 0x49, 0x90, 0xae, 0x3a, 0xb2, 0x64, 0xc1, 0x14, 0xa6, 0xac, 0x76, 0x8a, 0xb6, 0x9b, 0x32, 0xe4, 0x40, 0xf1, 0x25, 0xb2, 0xea, 0x33, 0xe9, 0xfe, 0x63, 0xb9, 0x0b, 0x79, 0xcc, 0xa1, 0x39, 0xc9, 0xfa, 0x5d, 0x25, 0x36, 0x98, 0x6c, 0x8c, 0x56, 0x60, 0x05, 0x3f, 0x4c, 0xae, 0xcb, 0x97, 0x7a, 0xfb, 0xed, 0x36, 0x5e, 0xde, 0x68, 0xc8, 0x81, 0xe6, 0x6e, 0x69, 0xc0, 0xdc, 0x43, 0xfd, 0xbd, 0x69, 0xd9, 0x07, 0x34, 0x6e, 0xb1, 0xbe, 0x29, 0x94, 0x92, 0xb2, 0x0f, 0xe9, 0xa6, 0x18, 0xc5, 0x87, 0x5b, 0x3d, 0xd2, 0xa3, 0xa7, 0xfa, 0xbb, 0x34, 0x10, 0x86, 0x1c, 0x48, 0x8f, 0xa5, 0xe1, 0xaf, 0xc8, 0xa6, 0xf4, 0x9b, 0xa4, 0xf7, 0xbf, 0x9c, 0xfc, 0xae, 0x41, 0x43, 0x91, 0xb2, 0x34, 0x3c, 0x46, 0x36, 0x16, 0x4a, 0x97, 0x5a, 0xe4, 0xa4, 0xb9, 0xb9, 0xd2, 0xf7, 0x12, 0xe8, 0x02, 0x3f, 0xfd, 0x5d, 0x1a, 0x08, 0x43, 0x0e, 0xbc, 0xbd, 0x8a, 0xd4, 0x7e, 0x4a, 0x23, 0x5f, 0x55, 0xc2, 0x79, 0xa6, 0x4e, 0xb9, 0xd1, 0x34, 0xf4, 0x5d, 0x6f, 0x27, 0xbf, 0xfd, 0xa9, 0xc0, 0x4a, 0x77, 0xd1, 0x92, 0x2c, 0x1a, 0xe0, 0xab, 0x01, 0xd7, 0x5f, 0x32, 0xe4, 0x00, 0xc4, 0xcf, 0x71, 0x21, 0x49, 0x11, 0x8a, 0x1a, 0x6b, 0xaa, 0x59, 0x8d, 0xd9, 0x14, 0xa3, 0x6f, 0x9f, 0x2e, 0xc2, 0xa8, 0x03, 0xb2, 0x0f, 0x56, 0x74, 0xcf, 0x19, 0xed, 0x50, 0xb7, 0xd4, 0x19, 0x01, 0xd6, 0x30, 0x05, 0x38, 0x60, 0x8d, 0x9a, 0x7f, 0x0e, 0xe3, 0x70, 0x40, 0x15, 0x5b, 0xd3, 0x33, 0x32, 0xa9, 0x77, 0x8c, 0x85, 0xdc, 0xbe, 0x2a, 0x9d, 0x44, 0xc0, 0x73, 0x7a, 0xbe, 0x0f, 0xba, 0x90, 0x6c, 0xf8, 0xe0, 0x88, 0x94, 0x7d, 0x8e, 0xac, 0x5b, 0x86, 0xde, 0x4a, 0xc2, 0x54, 0x37, 0x2e, 0xd3, 0xf7, 0x7d, 0x23, 0x19, 0x78, 0x46, 0xca, 0x6a, 0x15, 0x17, 0xcd, 0xbb, 0xd4, 0x96, 0xd8, 0x49, 0x0b, 0x70, 0x20, 0x71, 0x29, 0x71, 0x71, 0xa6, 0xe3, 0x13, 0xb2, 0x65, 0x5f, 0xff, 0x22, 0xe1, 0x5f, 0x6e, 0x9a, 0xd3, 0x74, 0x07, 0x76, 0x95, 0x4d, 0xaa, 0x6d, 0x4c, 0x0a, 0x57, 0xcf, 0xec, 0xa7, 0x05, 0x9c, 0x81, 0xd7, 0x03, 0x49, 0xd1, 0x56, 0x8a, 0x5b, 0xc9, 0x7a, 0x2b, 0xde, 0x78, 0x8d, 0x1e, 0x7e, 0xd7, 0x06, 0xbc, 0x86, 0x64, 0x2a, 0xea, 0xe7, 0xf5, 0xbf, 0x1e, 0x93, 0xe6, 0x6e, 0xc2, 0x7e, 0x95, 0x58, 0xf6, 0xf2, 0x0c, 0x25, 0x74, 0xa1, 0x49, 0x31, 0x03, 0x37, 0xd7, 0xea, 0xc5, 0x04, 0x6f, 0x0a, 0x21, 0x43, 0x98, 0x03, 0x42, 0xac, 0xb1, 0x43, 0x88, 0x80, 0x12, 0xb2, 0x43, 0xab, 0xc0, 0x2d, 0x0e, 0x07, 0x04, 0x06, 0xd3, 0x2e, 0x51, 0x8e, 0x0c, 0xd8, 0x15, 0x36, 0x81, 0x9b, 0x6c, 0xcb, 0xc0, 0x57, 0xe6, 0x21, 0x50, 0xbd, 0x71, 0x51, 0x36, 0xb4, 0xd1, 0x91, 0x91, 0x11, 0x4f, 0x4f, 0x4f, 0x67, 0x67, 0xe7, 0xa1, 0xa1, 0x21, 0x17, 0x17, 0x01, 0x57, 0xb8, 0x71, 0xeb, 0x21, 0xc1, 0x36, 0x3b, 0x7c, 0x7d, 0x7d, 0x3d, 0x3c, 0x3c, 0xfe, 0x3f, 0xd6, 0xc3, 0x01, 0x1b, 0x32, 0x00, 0xf4, 0xe4, 0xa4, 0xfc, 0x9e, 0x71, 0x72, 0xd2, 0x2f, 0x3c, 0x20, 0xad, 0x81, 0x41, 0x9a, 0xc1, 0xa1, 0x6f, 0xca, 0xb5, 0x6b, 0xd7, 0xd6, 0xae, 0x5d, 0xbb, 0xca, 0x3c, 0x56, 0x9b, 0xc7, 0xb1, 0x63, 0xc7, 0x2c, 0xb4, 0x56, 0x57, 0x57, 0x67, 0x65, 0x65, 0x05, 0x04, 0x04, 0xa0, 0xc6, 0x56, 0xae, 0x5c, 0x19, 0x15, 0x15, 0xb5, 0x79, 0xf3, 0x66, 0x35, 0xe6, 0xde, 0xbd, 0x7b, 0x3b, 0x76, 0xec, 0x08, 0x0b, 0x0b, 0xf3, 0xf2, 0xf2, 0x8a, 0x89, 0x89, 0x39, 0x74, 0xe8, 0xd0, 0xe0, 0xa0, 0xf2, 0x7b, 0xd8, 0xd9, 0xb3, 0x67, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xea, 0xeb, 0xeb, 0x33, 0x33, 0x33, 0xfd, 0xfc, 0xfc, 0x16, 0x2e, 0x5c, 0x58, 0x5a, 0x5a, 0xaa, 0xde, 0xae, 0x45, 0xe3, 0x2d, 0xa4, 0x3d, 0xf2, 0xf3, 0xf3, 0x2d, 0xf6, 0x6f, 0xdb, 0xb6, 0x4d, 0xbd, 0xe5, 0xca, 0x95, 0x2b, 0x0c, 0xb0, 0x61, 0xc3, 0x86, 0xf5, 0xeb, 0xd7, 0x53, 0xf3, 0x2b, 0x07, 0xb6, 0x72, 0x4c, 0x73, 0x73, 0xb3, 0x8f, 0x8f, 0x8f, 0x85, 0x90, 0xe0, 0xe0, 0xe0, 0xfe, 0xfe, 0x7e, 0x60, 0x52, 0x52, 0x52, 0xd8, 0x12, 0x4c, 0xe7, 0x18, 0x08, 0xb9, 0x73, 0xe7, 0x0e, 0x97, 0xa0, 0x41, 0x10, 0x8d, 0x35, 0xb6, 0x84, 0x23, 0x7b, 0xf9, 0xf2, 0xe5, 0x0b, 0xe6, 0xb1, 0x65, 0xcb, 0x16, 0xe8, 0xb0, 0x70, 0xe0, 0xe0, 0xc1, 0x83, 0x60, 0x86, 0x87, 0x87, 0x33, 0x7c, 0x77, 0x77, 0xf7, 0xce, 0x9d, 0x3b, 0x91, 0x10, 0x36, 0x1d, 0x1b, 0x1b, 0x8b, 0x88, 0x90, 0xff, 0xdb, 0x1f, 0x14, 0x14, 0x74, 0xf2, 0xe4, 0xc9, 0x8e, 0x8e, 0x8e, 0xbc, 0xbc, 0x3c, 0x1c, 0x24, 0x2e, 0xe7, 0xc1, 0x83, 0x07, 0xc8, 0x2b, 0xa6, 0xee, 0xee, 0xee, 0xe5, 0xe5, 0xe5, 0xc8, 0x83, 0xbf, 0xbf, 0x3f, 0xa6, 0x47, 0x8f, 0x1e, 0x65, 0x12, 0xb4, 0xbf, 0xfa, 0x0e, 0xa8, 0xf7, 0xe7, 0xe6, 0xe6, 0x72, 0xc5, 0x9c, 0x7f, 0xfe, 0xfc, 0x79, 0x30, 0x31, 0x50, 0x39, 0xd9, 0xd9, 0xd9, 0x15, 0x15, 0x15, 0x5d, 0x5d, 0x5d, 0x7c, 0xb5, 0xad, 0xad, 0x8d, 0xad, 0x16, 0x17, 0x17, 0x73, 0xe6, 0xf6, 0xed, 0xdb, 0xc1, 0x84, 0xc5, 0xe3, 0xe3, 0xe3, 0x60, 0x66, 0x64, 0x64, 0x60, 0x9a, 0x9c, 0x9c, 0xcc, 0x00, 0xa9, 0xa9, 0xa9, 0x98, 0xee, 0xdb, 0xb7, 0x8f, 0xe3, 0x35, 0x08, 0xfd, 0x33, 0xc0, 0xd4, 0x6b, 0x7c, 0xd3, 0xd3, 0xd3, 0x13, 0x12, 0x12, 0x00, 0x80, 0xad, 0x25, 0x25, 0x25, 0x08, 0x7f, 0x48, 0x48, 0xc8, 0x9e, 0x3d, 0x7b, 0xd8, 0x96, 0xbb, 0x77, 0xef, 0x32, 0x22, 0x2d, 0x2d, 0x8d, 0x0b, 0x61, 0xf4, 0xf0, 0xf0, 0x70, 0x4f, 0x4f, 0x0f, 0x67, 0xae, 0x58, 0xb1, 0x82, 0xd1, 0x8b, 0x16, 0x2d, 0x02, 0x81, 0x55, 0xbe, 0xa4, 0x41, 0x08, 0x70, 0x00, 0x5d, 0x15, 0x35, 0xd6, 0xda, 0xda, 0x8a, 0xa3, 0x99, 0x98, 0x98, 0xe8, 0xea, 0xea, 0x8a, 0x80, 0x9d, 0x3a, 0x75, 0x0a, 0xb5, 0x04, 0xc5, 0xa8, 0x1c, 0xa6, 0xbe, 0xb1, 0xb1, 0x91, 0xdb, 0xc1, 0x68, 0x14, 0x7a, 0x60, 0xe0, 0xd4, 0x1f, 0xfa, 0x78, 0xd7, 0x62, 0xa7, 0x88, 0x83, 0xb5, 0x09, 0x01, 0x0e, 0xa0, 0x36, 0xd0, 0x37, 0x70, 0x54, 0x8e, 0x1c, 0x39, 0x72, 0xf5, 0xea, 0xd5, 0xce, 0xce, 0x4e, 0xd4, 0x06, 0x7c, 0xa8, 0xab, 0xab, 0x83, 0x6e, 0xd4, 0x95, 0xb7, 0xb7, 0xfc, 0x37, 0x33, 0x24, 0xa7, 0xaf, 0xaf, 0x0f, 0x44, 0x4b, 0x4b, 0x4b, 0x55, 0x55, 0x15, 0x08, 0xb4, 0xa3, 0xb9, 0x73, 0xe7, 0x82, 0x00, 0x18, 0x5f, 0xd6, 0xa3, 0x39, 0xc1, 0x98, 0x98, 0xea, 0x0c, 0xe0, 0xac, 0x1f, 0x33, 0x9e, 0x81, 0xbd, 0x7b, 0xf7, 0x42, 0x87, 0x9b, 0x9b, 0x1b, 0xaa, 0xb6, 0xb2, 0xb2, 0xf2, 0xc0, 0x81, 0x03, 0x98, 0x22, 0x9c, 0xa8, 0x28, 0x26, 0xf9, 0xf4, 0xe9, 0xd3, 0xcc, 0x08, 0xe4, 0x2a, 0x3a, 0x3a, 0x9a, 0xd1, 0xb8, 0xd1, 0x6f, 0xdc, 0xb8, 0x01, 0xc0, 0xfe, 0xfd, 0xfb, 0x39, 0x07, 0x87, 0xb8, 0xa8, 0xa8, 0x88, 0xa5, 0x02, 0x79, 0x28, 0x2c, 0x2c, 0xd4, 0xb5, 0xcd, 0xb6, 0x9b, 0x78, 0xc6, 0xba, 0x44, 0x8b, 0x84, 0x32, 0x18, 0x77, 0xfc, 0xf8, 0x71, 0x66, 0x0a, 0xda, 0x48, 0x41, 0x41, 0x41, 0x64, 0x64, 0x24, 0x9b, 0xee, 0xde, 0xbd, 0x1b, 0x18, 0x38, 0xdf, 0xdb, 0xdb, 0x8b, 0x4a, 0x03, 0x13, 0xe5, 0x7e, 0xe2, 0xc4, 0x09, 0xf4, 0x7e, 0xd0, 0xf0, 0x04, 0x63, 0x62, 0x62, 0x02, 0xb5, 0x07, 0x39, 0xb0, 0x1e, 0xa2, 0x46, 0x47, 0x47, 0xf1, 0xb5, 0xaa, 0x96, 0x74, 0x5d, 0x54, 0x03, 0x58, 0xbb, 0xc8, 0xc9, 0xc9, 0x51, 0x33, 0x4d, 0x26, 0x13, 0x9a, 0x23, 0xfa, 0x49, 0x7b, 0x7b, 0xfb, 0xcd, 0x9b, 0x37, 0xf1, 0xc5, 0xab, 0x49, 0x0d, 0xe0, 0xf4, 0xc3, 0x87, 0x0f, 0x91, 0x96, 0x81, 0x81, 0x01, 0xce, 0x31, 0x4e, 0xe8, 0x67, 0xe0, 0xe2, 0xc5, 0x8b, 0x4d, 0x4d, 0x4d, 0xb8, 0x65, 0x1b, 0x1a, 0x1a, 0x6a, 0x6a, 0x6a, 0x10, 0xb3, 0x35, 0x6b, 0xd6, 0xb0, 0xd0, 0xb2, 0x2f, 0x2e, 0x57, 0x0c, 0xd0, 0xa1, 0xa1, 0xa1, 0x6a, 0xfe, 0x74, 0x1a, 0x99, 0xc1, 0x98, 0xce, 0x37, 0xc4, 0xd1, 0x8d, 0x81, 0xc5, 0xa3, 0x80, 0xdf, 0x50, 0xba, 0x1b, 0xff, 0x1d, 0x80, 0xfe, 0x63, 0x0e, 0x37, 0x25, 0xfa, 0x09, 0x1a, 0x36, 0xae, 0xfa, 0xd8, 0xd8, 0xd8, 0xe5, 0xcb, 0x97, 0x1b, 0x0a, 0x98, 0xe8, 0xcd, 0xfa, 0x0e, 0x88, 0xd6, 0x28, 0x58, 0x9e, 0x80, 0x7b, 0x40, 0xb0, 0x45, 0x36, 0x8a, 0x73, 0x38, 0x60, 0x63, 0xc0, 0x84, 0xc3, 0x1d, 0x19, 0x10, 0x1e, 0x52, 0x1b, 0x05, 0x3a, 0x32, 0x60, 0x63, 0xc0, 0x84, 0xc3, 0x5f, 0xf8, 0x0c, 0xfc, 0x0d, 0x80, 0x98, 0xbd, 0xed, 0xf7, 0x50, 0xda, 0x08, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXTextPlainIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa8, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x30, 0x39, 0x54, 0x32, 0x32, 0x3a, 0x30, 0x32, 0x3a, 0x34, 0x33, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x04, 0xa5, 0xd6, 0xff, 0x00, 0x00, 0x05, 0x7b, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x58, 0x5b, 0x48, 0x23, 0x57, 0x18, 0xce, 0x24, 0x31, 0xf1, 0x52, 0xad, 0x31, 0x78, 0xdf, 0xd6, 0x2a, 0xb6, 0x52, 0xad, 0x28, 0x8a, 0xe8, 0x82, 0x62, 0xe9, 0x45, 0xa5, 0x45, 0xf0, 0x82, 0x58, 0x41, 0xb4, 0xed, 0x83, 0x0f, 0xe2, 0x83, 0x6f, 0x8a, 0x20, 0xb8, 0x3e, 0x28, 0x05, 0x45, 0x7d, 0x12, 0x84, 0x82, 0x8a, 0x88, 0x22, 0x0a, 0xbe, 0x54, 0xb4, 0xc2, 0x3e, 0xe9, 0x82, 0x37, 0x50, 0x1a, 0x45, 0x2a, 0x5e, 0x8a, 0xdd, 0x20, 0x58, 0x35, 0xb1, 0x8a, 0x49, 0x4c, 0xd2, 0x2f, 0x7b, 0xe2, 0x38, 0x3b, 0xc6, 0x89, 0x33, 0x39, 0xac, 0x2b, 0x9d, 0xf3, 0x30, 0xfc, 0xe7, 0xfc, 0xdf, 0x7f, 0xff, 0xcf, 0x3f, 0x93, 0x30, 0x4e, 0xa7, 0x53, 0xf1, 0x94, 0x97, 0xf2, 0x29, 0x3b, 0xef, 0xf2, 0x5d, 0x0e, 0xe0, 0xb1, 0x2b, 0x28, 0x57, 0x40, 0xae, 0x80, 0x8f, 0x19, 0x90, 0x5b, 0xc8, 0xc7, 0x04, 0xfa, 0x2c, 0x2e, 0x57, 0xc0, 0xe7, 0x14, 0xfa, 0xa8, 0x40, 0xae, 0x80, 0x8f, 0x09, 0xf4, 0x59, 0x5c, 0xed, 0xb3, 0x06, 0x97, 0x02, 0xa7, 0x43, 0xf1, 0x7a, 0xc3, 0x61, 0x32, 0x3a, 0x9d, 0x0e, 0x2f, 0x9f, 0x86, 0x8c, 0x92, 0xf9, 0x30, 0x86, 0x89, 0x49, 0x55, 0x32, 0x94, 0x6a, 0x4f, 0x27, 0x80, 0xfd, 0x57, 0xf6, 0xdf, 0x5e, 0x58, 0x1e, 0x9e, 0x8b, 0xef, 0x5e, 0x68, 0xe3, 0x9f, 0xab, 0x1e, 0x8e, 0x17, 0x40, 0xd2, 0xc9, 0x83, 0xf9, 0xc8, 0x4b, 0xe2, 0x79, 0x1e, 0x98, 0x8d, 0xe2, 0xf0, 0x3c, 0x71, 0xee, 0x96, 0x4e, 0x05, 0x6c, 0x57, 0x6e, 0x9d, 0xfe, 0x21, 0x4c, 0xa0, 0x8e, 0xc1, 0xc6, 0xf2, 0xaf, 0xf3, 0xe2, 0x1f, 0xb7, 0x97, 0x41, 0x7a, 0xa5, 0xf6, 0x03, 0x17, 0xe0, 0xf2, 0xd4, 0x79, 0x65, 0x76, 0x1d, 0x5e, 0x8b, 0xa8, 0x96, 0x4b, 0x50, 0x60, 0xd1, 0x09, 0xc0, 0x6e, 0x71, 0xfb, 0xfa, 0xc5, 0xf7, 0xea, 0xec, 0x9f, 0xfc, 0x60, 0x6f, 0x73, 0xc6, 0xfe, 0xb2, 0xc7, 0xed, 0x66, 0xf6, 0x8f, 0x7e, 0x9f, 0x17, 0xba, 0x1a, 0xe6, 0xd5, 0xaf, 0xb6, 0xb5, 0x71, 0x1b, 0x88, 0xeb, 0x1b, 0xbc, 0x80, 0x67, 0x0f, 0x64, 0xd1, 0x69, 0xa1, 0x6b, 0xab, 0xdb, 0x9c, 0x4a, 0xe3, 0x4a, 0xff, 0x7d, 0x4b, 0xe5, 0x0a, 0xcd, 0xb5, 0xec, 0x37, 0x78, 0xb2, 0xf5, 0xe5, 0x49, 0x29, 0x80, 0x9b, 0x96, 0x60, 0x5d, 0xf4, 0xe8, 0x93, 0x5a, 0xeb, 0x0e, 0x8f, 0x0d, 0xd8, 0x23, 0x4c, 0xd4, 0x21, 0x9d, 0x00, 0x74, 0x1f, 0xb9, 0x3d, 0x0b, 0x89, 0x12, 0xaa, 0x80, 0x3e, 0xc1, 0x6d, 0x2e, 0xf4, 0x99, 0x10, 0x4c, 0x54, 0x00, 0x74, 0xee, 0x40, 0xd2, 0x37, 0x6a, 0xcb, 0x85, 0x42, 0xa9, 0x52, 0x7c, 0x22, 0x38, 0x1c, 0x9f, 0xa5, 0x29, 0x9f, 0xff, 0xac, 0xb9, 0xb6, 0x3a, 0x93, 0xbe, 0xa6, 0x63, 0x17, 0xa1, 0xd2, 0x51, 0xa4, 0x0d, 0x56, 0x64, 0x55, 0x7b, 0x57, 0xa5, 0xd2, 0x28, 0x32, 0x7e, 0xf0, 0x0e, 0x13, 0x55, 0x01, 0x3a, 0x2d, 0x24, 0xca, 0x24, 0x5d, 0xb0, 0x1c, 0x00, 0xdd, 0x7c, 0x8a, 0xd7, 0xf6, 0xe4, 0x2b, 0x40, 0xf9, 0x4a, 0x59, 0xce, 0x15, 0x27, 0x7f, 0x39, 0x90, 0x47, 0xd3, 0x6b, 0xd7, 0x93, 0x2c, 0xd3, 0xdf, 0x0e, 0xa3, 0x81, 0xc1, 0xe0, 0xd4, 0x7d, 0xac, 0xc4, 0x75, 0xa7, 0xbb, 0x18, 0x8a, 0xff, 0x8d, 0xfe, 0xf9, 0xd2, 0xfe, 0xfb, 0x2f, 0x56, 0x81, 0x2f, 0x6a, 0x7c, 0x4b, 0x7f, 0xdb, 0xac, 0xf9, 0xf4, 0x4b, 0x3a, 0xdf, 0xa1, 0x24, 0x11, 0x34, 0x5b, 0xc8, 0x68, 0x70, 0x08, 0x78, 0x0f, 0x7b, 0xe0, 0x1a, 0xff, 0xb8, 0xad, 0x0c, 0x95, 0x52, 0xd0, 0x0c, 0xe0, 0xb3, 0xaf, 0x54, 0xfa, 0x78, 0x21, 0x85, 0xe0, 0x02, 0x43, 0xc5, 0x6f, 0x56, 0x09, 0xcd, 0x16, 0x62, 0x95, 0xbe, 0x4b, 0x42, 0x28, 0x61, 0xef, 0xd2, 0x0f, 0xc9, 0xb6, 0xe4, 0x00, 0x24, 0xa7, 0x8e, 0x92, 0xa0, 0x5c, 0x01, 0x4a, 0x89, 0x94, 0xac, 0xe6, 0xff, 0x5d, 0x81, 0xeb, 0x37, 0xcb, 0xe1, 0x90, 0xfe, 0x6e, 0x5a, 0x5d, 0x5d, 0x6d, 0x6f, 0x6f, 0x3f, 0x3a, 0x3a, 0x92, 0x5c, 0x01, 0x05, 0x3e, 0x25, 0x24, 0xac, 0x9d, 0x9d, 0x9d, 0xb0, 0xb0, 0x30, 0x62, 0x35, 0x34, 0x34, 0x54, 0x82, 0x06, 0x22, 0x52, 0x55, 0x55, 0x05, 0x25, 0xc3, 0xc3, 0xc3, 0x92, 0x35, 0x48, 0x6c, 0xa1, 0xe0, 0xe0, 0xe0, 0xa4, 0xa4, 0xa4, 0x98, 0x98, 0x18, 0x98, 0xbf, 0xb8, 0xb8, 0x90, 0x9c, 0x3f, 0xe8, 0x51, 0xa9, 0x54, 0x91, 0x91, 0x91, 0x92, 0x35, 0x48, 0xac, 0x00, 0x49, 0xd8, 0xca, 0xca, 0x0a, 0x0c, 0xfb, 0xf9, 0xf9, 0x09, 0xe7, 0x0f, 0x3d, 0x26, 0x00, 0xb0, 0x5a, 0xad, 0x02, 0x5c, 0xaf, 0x2c, 0x0f, 0x15, 0x68, 0x6d, 0x6d, 0xcd, 0xce, 0xce, 0x2e, 0x28, 0x28, 0x58, 0x5a, 0x5a, 0xca, 0xc9, 0xc9, 0x09, 0x0c, 0x0c, 0x4c, 0x4d, 0x4d, 0xed, 0xea, 0xea, 0x12, 0xd5, 0xeb, 0x5b, 0x5b, 0x5b, 0xb5, 0xb5, 0xb5, 0x59, 0x59, 0x59, 0xc8, 0x31, 0x34, 0xa4, 0xa7, 0xa7, 0x4f, 0x4f, 0x4f, 0x73, 0xd3, 0x3c, 0x37, 0x37, 0x97, 0x9f, 0x9f, 0x0f, 0x43, 0xb9, 0xb9, 0xb9, 0xbd, 0xbd, 0xbd, 0x5c, 0xd6, 0xe9, 0xe9, 0x69, 0x49, 0x49, 0x09, 0x58, 0xf5, 0xf5, 0xf5, 0x93, 0x93, 0x93, 0xb0, 0x1e, 0x14, 0x14, 0x54, 0x54, 0x54, 0x64, 0x34, 0x1a, 0xb9, 0x30, 0x37, 0x7d, 0x37, 0xc4, 0xf8, 0xf8, 0x78, 0xc2, 0x83, 0x18, 0x57, 0xa0, 0xba, 0xba, 0x9a, 0x07, 0x16, 0xa8, 0x00, 0x22, 0x87, 0x2c, 0xc3, 0x30, 0x88, 0x21, 0x22, 0x22, 0x02, 0xb4, 0x56, 0xab, 0xdd, 0xdf, 0xdf, 0x67, 0x35, 0x34, 0x37, 0x37, 0xb3, 0xca, 0x11, 0x2a, 0x7b, 0x0e, 0x82, 0xa8, 0x05, 0x17, 0xc1, 0xab, 0xd5, 0xb7, 0xbf, 0x58, 0x2a, 0x2b, 0x2b, 0xb9, 0x30, 0x42, 0x7b, 0x68, 0xa1, 0xdd, 0xdd, 0x5d, 0xd2, 0x94, 0x3a, 0x9d, 0x6e, 0x60, 0x60, 0x60, 0x63, 0x63, 0xa3, 0xb4, 0xb4, 0x94, 0x18, 0x9b, 0x9f, 0x9f, 0xe7, 0xaa, 0x10, 0x08, 0x60, 0x6a, 0x6a, 0xaa, 0xbb, 0xbb, 0xfb, 0xf0, 0xf0, 0x10, 0x78, 0x8b, 0xc5, 0x42, 0x62, 0xe0, 0x5e, 0xd6, 0xf3, 0xf3, 0xf3, 0x99, 0x99, 0x19, 0xa2, 0x99, 0x17, 0x00, 0x44, 0x46, 0x46, 0x46, 0x88, 0xc5, 0xc2, 0xc2, 0x42, 0x58, 0xa9, 0xab, 0xab, 0xc3, 0x16, 0x09, 0xe5, 0x5a, 0x27, 0xb4, 0x87, 0x00, 0xc0, 0x48, 0x48, 0x48, 0x80, 0x00, 0x2a, 0x48, 0x40, 0xc7, 0xc7, 0xc7, 0xb8, 0x6a, 0x38, 0x69, 0x6a, 0x6a, 0xe2, 0xaa, 0x10, 0x08, 0x00, 0x30, 0x44, 0xdb, 0xd1, 0xd1, 0xd1, 0xd8, 0xd8, 0xd8, 0xd6, 0xd6, 0x96, 0x96, 0x96, 0x06, 0xf1, 0xce, 0xce, 0x4e, 0xae, 0x38, 0x68, 0x28, 0xc4, 0xf9, 0xdd, 0x00, 0xd6, 0xd7, 0xd7, 0x71, 0x8e, 0xb5, 0xbc, 0xbc, 0x0c, 0x18, 0xa6, 0x2d, 0xd9, 0x9a, 0x4c, 0x26, 0x9e, 0x86, 0xdb, 0x02, 0x11, 0x04, 0xf7, 0x89, 0x1e, 0x25, 0x5b, 0xbd, 0x5e, 0x9f, 0x92, 0x92, 0x82, 0x52, 0x20, 0xa3, 0x5c, 0xc0, 0x7d, 0xb4, 0xcd, 0x66, 0x2b, 0x2e, 0x2e, 0x9e, 0x9d, 0x9d, 0x05, 0x40, 0xa3, 0xd1, 0xa0, 0x91, 0x50, 0x04, 0xd0, 0x76, 0xbb, 0xfd, 0x3e, 0x91, 0xfb, 0xce, 0x33, 0x33, 0x33, 0xc1, 0x8a, 0x8b, 0x8b, 0x23, 0x80, 0xab, 0xab, 0xab, 0x90, 0x90, 0x10, 0x2e, 0xd8, 0xc3, 0x25, 0x66, 0xd9, 0x0b, 0x0b, 0x0b, 0x84, 0xc6, 0xad, 0xda, 0xdc, 0xdc, 0x04, 0xcd, 0x5e, 0x0f, 0x16, 0xe3, 0x91, 0x40, 0x03, 0x10, 0xef, 0x27, 0x26, 0x26, 0x90, 0xb3, 0xcb, 0xcb, 0xcb, 0xb2, 0xb2, 0x32, 0x8f, 0x48, 0xaf, 0x87, 0x08, 0x1e, 0x18, 0xf2, 0xf4, 0x08, 0x16, 0x0a, 0x60, 0x74, 0x74, 0x74, 0x6c, 0x6c, 0x6c, 0x6f, 0x6f, 0xaf, 0xa1, 0xa1, 0x01, 0xef, 0x5c, 0xc8, 0xa3, 0x23, 0x59, 0x2d, 0x38, 0x61, 0x33, 0xca, 0xa5, 0x01, 0xc0, 0x08, 0xc2, 0x33, 0x3c, 0x3c, 0x1c, 0x2d, 0xee, 0xef, 0xef, 0x8f, 0x41, 0x79, 0x72, 0x72, 0x82, 0x13, 0x54, 0x9f, 0x15, 0x07, 0x0d, 0x29, 0x32, 0xd9, 0xb8, 0x34, 0x01, 0xb0, 0x48, 0x42, 0xb0, 0x03, 0x90, 0x3d, 0x67, 0xf5, 0x08, 0xdd, 0x81, 0x5b, 0xd0, 0x1b, 0xaa, 0xa6, 0xa6, 0x06, 0xf2, 0x58, 0x66, 0xb3, 0x39, 0x36, 0x36, 0x96, 0xc7, 0xc5, 0x16, 0x93, 0x97, 0x00, 0x06, 0x07, 0x07, 0x09, 0x37, 0x23, 0x23, 0xa3, 0xa2, 0xa2, 0x82, 0x05, 0xe3, 0x8d, 0x31, 0x34, 0x34, 0x04, 0x0c, 0x2a, 0x13, 0x10, 0x10, 0xc0, 0xd3, 0x80, 0x66, 0xeb, 0xef, 0xef, 0x07, 0xf7, 0xe0, 0xe0, 0x00, 0xf3, 0x83, 0x70, 0x13, 0x13, 0x13, 0xcf, 0xce, 0xce, 0xa2, 0xa3, 0xa3, 0xc9, 0x16, 0xd3, 0x05, 0xd6, 0x89, 0x15, 0xf2, 0x14, 0xaa, 0x40, 0x4b, 0x4b, 0x4b, 0x5e, 0x5e, 0x5e, 0x54, 0x54, 0x14, 0x66, 0x62, 0x4f, 0x4f, 0x0f, 0xeb, 0x16, 0x74, 0x91, 0x3b, 0xcd, 0xf3, 0x80, 0x2d, 0x34, 0x06, 0x2e, 0x8a, 0x86, 0xc9, 0xb3, 0xb6, 0xb6, 0x06, 0x5f, 0xd1, 0xc1, 0x7d, 0x7d, 0x7d, 0xe8, 0x5d, 0x48, 0x91, 0x4a, 0x42, 0x50, 0xa9, 0xe4, 0x9b, 0x66, 0xc5, 0xc1, 0x45, 0x30, 0x44, 0x39, 0x86, 0x2f, 0xd2, 0xcf, 0xdd, 0xc2, 0xef, 0xb7, 0xec, 0x72, 0xa3, 0x61, 0x69, 0x32, 0x85, 0x16, 0x17, 0x17, 0xd9, 0x13, 0x09, 0x04, 0x1a, 0xcc, 0x60, 0x30, 0xdc, 0x9d, 0x1b, 0x12, 0x54, 0x09, 0x88, 0xf0, 0xa7, 0x10, 0xec, 0xe1, 0xe5, 0x87, 0x27, 0xa2, 0x1c, 0x1f, 0x1f, 0xdf, 0xde, 0xde, 0x2e, 0x2f, 0x2f, 0xc7, 0x0b, 0xe5, 0xad, 0xa0, 0x1f, 0xb6, 0x41, 0x8e, 0x93, 0x93, 0x93, 0x1f, 0x86, 0xf5, 0x01, 0xc5, 0x0b, 0x0e, 0x6f, 0x2e, 0x9e, 0x32, 0x74, 0x0e, 0x0f, 0xf3, 0x5e, 0x6d, 0xf9, 0x15, 0xc0, 0x47, 0x08, 0xbe, 0x2e, 0xf1, 0x9a, 0x24, 0x61, 0xa0, 0x71, 0x31, 0xd1, 0x79, 0x21, 0xbd, 0x57, 0x5b, 0xf9, 0x7f, 0xa1, 0xc7, 0x2e, 0x07, 0x7f, 0x96, 0x3d, 0xb6, 0x3f, 0xa2, 0xed, 0xcb, 0x01, 0x88, 0x4e, 0x19, 0x65, 0x01, 0xb9, 0x02, 0x94, 0x13, 0x2a, 0x5a, 0x9d, 0x5c, 0x01, 0xd1, 0x29, 0xa3, 0x2c, 0xf0, 0x1f, 0x15, 0xdc, 0xd7, 0x70, 0xbb, 0x15, 0xe8, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXHTMLIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa8, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x30, 0x39, 0x54, 0x32, 0x33, 0x3a, 0x30, 0x32, 0x3a, 0x39, 0x35, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x3c, 0x50, 0x22, 0x3f, 0x00, 0x00, 0x05, 0xe7, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x59, 0x6b, 0x4c, 0x5b, 0x55, 0x1c, 0xa7, 0xa5, 0xe5, 0xe5, 0x78, 0xb5, 0x94, 0xf2, 0x4a, 0x00, 0x91, 0x47, 0xd8, 0x32, 0x51, 0x24, 0x7c, 0x70, 0x20, 0xf2, 0x34, 0x31, 0x13, 0x1f, 0x0c, 0x30, 0x2c, 0xbc, 0x24, 0xca, 0xc6, 0x07, 0x1e, 0x09, 0x1f, 0xf8, 0x60, 0x42, 0x4c, 0xd0, 0x84, 0x98, 0x98, 0xf1, 0xc5, 0x69, 0x54, 0x60, 0x3a, 0x82, 0x3a, 0x5d, 0x98, 0x24, 0xdb, 0x88, 0x01, 0x24, 0x3a, 0x32, 0xca, 0x63, 0x4c, 0x26, 0x8f, 0x05, 0x48, 0x86, 0x06, 0x28, 0x14, 0x4a, 0x5b, 0x1e, 0x85, 0xb6, 0xf8, 0x83, 0xa3, 0xd7, 0x6b, 0xcb, 0x6e, 0x6f, 0x7b, 0xe9, 0x08, 0xc9, 0x3d, 0x69, 0x2e, 0xff, 0xf3, 0x3b, 0xff, 0xf7, 0xff, 0x7f, 0xce, 0x69, 0x2f, 0x82, 0xdd, 0xdd, 0x5d, 0xa7, 0xe3, 0x3c, 0x84, 0xc7, 0xd9, 0xf9, 0x3d, 0xdf, 0xf9, 0x00, 0x8e, 0xba, 0x82, 0x7c, 0x05, 0xf8, 0x0a, 0x70, 0xcc, 0x00, 0xdf, 0x42, 0x1c, 0x13, 0xc8, 0x59, 0x9c, 0xaf, 0x00, 0xe7, 0x14, 0x72, 0x54, 0xc0, 0x57, 0x80, 0x63, 0x02, 0x39, 0x8b, 0xf3, 0x15, 0x38, 0x28, 0x85, 0xab, 0x86, 0x15, 0x4b, 0x78, 0xdd, 0xa4, 0x33, 0x39, 0x99, 0x2c, 0x71, 0x8e, 0xc8, 0x21, 0x57, 0xe0, 0xc1, 0xc6, 0x68, 0xed, 0xec, 0xc5, 0x94, 0xfb, 0xcf, 0x5b, 0xba, 0x35, 0xa0, 0xbd, 0x93, 0x3c, 0xfa, 0xec, 0x67, 0x0b, 0x97, 0x34, 0x46, 0xb5, 0xe5, 0xaa, 0xdd, 0x88, 0xe0, 0x50, 0x7e, 0x0f, 0x20, 0xb5, 0xb7, 0x57, 0x7f, 0x6a, 0x5e, 0xb8, 0xac, 0xd0, 0xf6, 0xc3, 0x15, 0x57, 0xa1, 0xdb, 0xc4, 0x0b, 0x0b, 0x66, 0x3e, 0xf5, 0xac, 0x75, 0x95, 0x4e, 0xe6, 0x02, 0x74, 0x77, 0xf6, 0x78, 0x53, 0x9a, 0x57, 0x1c, 0x50, 0xfe, 0x8c, 0x5b, 0xb4, 0x19, 0x8f, 0x1d, 0x53, 0x91, 0x1d, 0x32, 0x74, 0x91, 0x35, 0xa3, 0xba, 0x7d, 0xa9, 0xf5, 0xeb, 0xc5, 0x2f, 0xfe, 0xd2, 0xcf, 0xd1, 0x71, 0x06, 0x7a, 0xd3, 0xb8, 0x71, 0x55, 0xd9, 0x8c, 0xcf, 0x19, 0xef, 0x94, 0x12, 0xf9, 0x85, 0x54, 0x9f, 0x2c, 0x06, 0x66, 0xab, 0x4b, 0xf6, 0x07, 0xf0, 0x70, 0x73, 0xa2, 0x65, 0xf1, 0xf2, 0x75, 0xd5, 0x77, 0x70, 0x88, 0x6e, 0xc6, 0xdf, 0x25, 0xe0, 0x9c, 0x5f, 0x01, 0x1d, 0x21, 0x74, 0x8c, 0xfb, 0xc9, 0x37, 0xfc, 0xf2, 0x6e, 0xae, 0xdc, 0xd8, 0x32, 0x6d, 0x12, 0xe4, 0xd7, 0xb5, 0x5e, 0x7c, 0xc2, 0xdc, 0x9e, 0x2e, 0x94, 0xbf, 0x7b, 0x4e, 0x56, 0x70, 0x42, 0xe8, 0x69, 0x29, 0x65, 0x15, 0xb1, 0xb9, 0x85, 0x76, 0x9d, 0x76, 0x7b, 0xd4, 0x5d, 0xcd, 0x8b, 0x9f, 0xc2, 0x36, 0x5d, 0xbb, 0x58, 0x28, 0x4e, 0xf5, 0x79, 0x25, 0xd7, 0xef, 0x7c, 0x8a, 0x4f, 0x86, 0xf0, 0xf1, 0xbf, 0x93, 0xb4, 0xc6, 0xb5, 0x0e, 0xd5, 0xb5, 0xf6, 0xa5, 0x2b, 0x0f, 0xd6, 0x47, 0xe9, 0xe2, 0x27, 0x9c, 0x3d, 0x11, 0x43, 0x91, 0xfc, 0xbd, 0x50, 0xd7, 0x70, 0x3a, 0x6e, 0x95, 0xb6, 0x39, 0x80, 0xe2, 0xa9, 0x9c, 0x5f, 0xd4, 0x3f, 0xd3, 0xf5, 0x46, 0x7b, 0xc4, 0xe6, 0xca, 0xce, 0xbf, 0x2e, 0xcd, 0x93, 0x88, 0xa4, 0x74, 0x9c, 0x99, 0xfe, 0x63, 0xe3, 0x3e, 0xc2, 0x40, 0x30, 0x1a, 0xc3, 0x7f, 0x7b, 0x5a, 0x20, 0x10, 0x7c, 0x14, 0x76, 0x29, 0x4f, 0x56, 0xc8, 0x2c, 0x4b, 0x5f, 0xb5, 0xf9, 0x14, 0x5a, 0x35, 0xa8, 0x28, 0xf9, 0x2c, 0xc9, 0xd9, 0x8e, 0x93, 0x3d, 0xb7, 0x4e, 0xdd, 0x29, 0x95, 0x5f, 0xb4, 0xc9, 0x7b, 0x68, 0x88, 0xf5, 0x38, 0xfd, 0x41, 0xe8, 0xc7, 0x03, 0xcf, 0x4d, 0x7c, 0x12, 0xf1, 0x79, 0xb8, 0x5b, 0x04, 0xd1, 0x89, 0x13, 0x45, 0x65, 0x58, 0xa6, 0xf4, 0xb3, 0x21, 0xec, 0xdf, 0x03, 0xd0, 0xde, 0xad, 0xbe, 0x85, 0x6e, 0x79, 0xdb, 0xbf, 0x38, 0xc9, 0xeb, 0x65, 0x36, 0xc6, 0xcc, 0x78, 0xf4, 0xbb, 0x5b, 0x9d, 0xaa, 0xeb, 0xdf, 0x2e, 0x5d, 0x99, 0xdd, 0x9a, 0x36, 0x5b, 0x62, 0x3f, 0xb5, 0x39, 0x80, 0x7c, 0x59, 0x91, 0x6a, 0x67, 0x99, 0x9c, 0x39, 0x3b, 0xa6, 0x9d, 0x9b, 0x2b, 0x1d, 0xf8, 0x84, 0xb8, 0x86, 0xe6, 0xcb, 0x0a, 0xd1, 0xc4, 0xfe, 0xe2, 0x00, 0x36, 0xb6, 0xff, 0xed, 0x9f, 0xef, 0x35, 0x86, 0x35, 0x3a, 0x7f, 0xa2, 0xd7, 0x8b, 0x67, 0x6c, 0xcc, 0x85, 0xcd, 0x7b, 0x00, 0xf6, 0xcc, 0x4e, 0x7d, 0xca, 0x03, 0x91, 0x40, 0x84, 0x33, 0x31, 0xdf, 0xbf, 0xe8, 0x25, 0xef, 0xf4, 0x03, 0xf7, 0xb1, 0xce, 0xa4, 0xbd, 0xa1, 0xfa, 0xa1, 0x5d, 0xd9, 0xf2, 0xfb, 0xfa, 0x3d, 0x4a, 0x0a, 0x84, 0x8b, 0xd0, 0xe5, 0x35, 0x69, 0x4e, 0x89, 0xbc, 0x1c, 0x7d, 0x45, 0xc7, 0xd9, 0xd0, 0xf6, 0x04, 0x40, 0xe9, 0x1d, 0xdb, 0xb8, 0x87, 0xcb, 0xab, 0x73, 0xe5, 0xc7, 0x6d, 0xd3, 0x36, 0x05, 0x82, 0x08, 0x75, 0x0b, 0xef, 0x3d, 0x3d, 0x42, 0x47, 0x40, 0x8f, 0xe8, 0x14, 0x05, 0x93, 0xd9, 0x66, 0x67, 0xae, 0x4c, 0xec, 0x5f, 0x20, 0x7f, 0xa7, 0xc0, 0xbf, 0xd4, 0x4f, 0x24, 0x33, 0xe3, 0x67, 0x39, 0xe5, 0x14, 0x00, 0xb1, 0xb1, 0xbc, 0xa3, 0xbc, 0xaa, 0xfc, 0xea, 0x1b, 0xe5, 0x97, 0xcb, 0x3b, 0x4b, 0x04, 0x61, 0xbe, 0x89, 0x09, 0xcf, 0xa9, 0xa7, 0xe2, 0x4a, 0x02, 0xca, 0xcf, 0x4a, 0xde, 0x12, 0x0b, 0xc4, 0x2c, 0x7d, 0x3d, 0x98, 0x0d, 0x1b, 0xff, 0x50, 0x86, 0xde, 0xa4, 0xbf, 0xb6, 0xd4, 0xf6, 0xea, 0x58, 0x72, 0xd8, 0x5d, 0xef, 0x68, 0x85, 0xdc, 0x52, 0x67, 0xb7, 0xfa, 0x36, 0x96, 0x22, 0x06, 0x24, 0x17, 0x1e, 0x16, 0xe2, 0x7b, 0x91, 0x25, 0x83, 0x7d, 0x88, 0x93, 0x7d, 0x62, 0x0c, 0x52, 0x77, 0x35, 0xbf, 0x55, 0x4e, 0x97, 0x59, 0x32, 0x00, 0xff, 0xf0, 0xd1, 0xfb, 0x7f, 0xea, 0x1f, 0x59, 0x2e, 0x71, 0x41, 0x0e, 0xa1, 0x85, 0x0e, 0xae, 0xec, 0x93, 0x42, 0x6d, 0xbe, 0xc8, 0x9e, 0x94, 0x63, 0x6c, 0xed, 0xf0, 0x01, 0xb0, 0xcd, 0x94, 0xa3, 0xf8, 0xf8, 0x0a, 0x38, 0x2a, 0xb3, 0x6c, 0xf5, 0xf2, 0x15, 0x60, 0x9b, 0x29, 0x47, 0xf1, 0x1d, 0xfb, 0x0a, 0xb0, 0xfa, 0x3a, 0x8d, 0x9b, 0xd2, 0x68, 0x34, 0x0a, 0xf7, 0x87, 0xa3, 0x32, 0xb9, 0xaf, 0xd7, 0x60, 0x30, 0xe0, 0xaf, 0x4d, 0x86, 0xac, 0x57, 0x60, 0x7c, 0x7c, 0x5c, 0x2a, 0x95, 0x8a, 0xc5, 0x62, 0x99, 0x8c, 0xe9, 0x0b, 0x23, 0x6c, 0xf7, 0xf4, 0xf4, 0xcc, 0xcf, 0xcf, 0xdb, 0x17, 0xe1, 0xf4, 0xf4, 0x34, 0xb1, 0x02, 0x43, 0x20, 0xd8, 0x2b, 0xb1, 0x1e, 0x80, 0x97, 0x97, 0x57, 0x48, 0x48, 0x08, 0x34, 0x6a, 0x34, 0x1a, 0x06, 0xbd, 0x5d, 0x5d, 0x5d, 0xa9, 0xa9, 0xa9, 0x65, 0x65, 0x65, 0x0c, 0x3c, 0x0c, 0x4b, 0x9e, 0x9e, 0x9e, 0xd1, 0xd1, 0xd1, 0x41, 0x41, 0x41, 0xe0, 0x59, 0x5f, 0x5f, 0x67, 0xe0, 0x34, 0x5f, 0x62, 0xf3, 0x45, 0x6a, 0x68, 0x68, 0x08, 0x62, 0x22, 0x91, 0x88, 0x81, 0xb9, 0xa5, 0xa5, 0x05, 0x3c, 0x09, 0x09, 0x09, 0x0c, 0x3c, 0x56, 0x97, 0x06, 0x07, 0x07, 0xa1, 0x04, 0x45, 0xb0, 0xca, 0x49, 0x31, 0x58, 0xaf, 0x00, 0x34, 0x52, 0xa3, 0xad, 0xad, 0x2d, 0x32, 0x32, 0x12, 0xd9, 0xca, 0xce, 0xce, 0x56, 0x2a, 0x95, 0x14, 0x8e, 0x36, 0x9b, 0x98, 0x98, 0xc0, 0x54, 0xab, 0xd5, 0xf6, 0xee, 0x8f, 0x81, 0x81, 0x01, 0xd2, 0xd0, 0xd8, 0x3c, 0x39, 0x39, 0x39, 0x89, 0x89, 0x89, 0x8d, 0x8d, 0x8d, 0xe9, 0xe9, 0xe9, 0x90, 0xad, 0xac, 0xac, 0xac, 0xad, 0xad, 0x95, 0x48, 0x24, 0x59, 0x59, 0x59, 0xfd, 0xfd, 0x7b, 0x6f, 0xf2, 0x38, 0x0d, 0x2a, 0x14, 0x06, 0x82, 0x54, 0x00, 0x66, 0x9c, 0x9d, 0x9d, 0x29, 0x63, 0x75, 0x75, 0x75, 0x44, 0x64, 0x78, 0x78, 0x98, 0x02, 0xe9, 0x44, 0x43, 0x43, 0x03, 0x18, 0x96, 0x97, 0x99, 0xde, 0x32, 0x44, 0x45, 0x45, 0xd1, 0xed, 0x3a, 0xbc, 0x02, 0x19, 0x19, 0x19, 0xc8, 0x74, 0x4d, 0x4d, 0x0d, 0x1c, 0xed, 0xec, 0xec, 0x24, 0xee, 0x62, 0x87, 0x24, 0x25, 0x25, 0xc9, 0xe5, 0x72, 0x4c, 0x5d, 0x5d, 0x5d, 0x51, 0x22, 0x8c, 0xb8, 0xb8, 0x38, 0xb4, 0x13, 0x10, 0xec, 0xc8, 0xf6, 0xf6, 0x76, 0x10, 0x38, 0x5b, 0xc6, 0xc6, 0xc6, 0xd2, 0xd2, 0xd2, 0x40, 0x27, 0x27, 0x27, 0x4f, 0x4d, 0x4d, 0x01, 0xc1, 0x53, 0xaf, 0xd7, 0x03, 0xb1, 0x7f, 0xd0, 0x13, 0xf0, 0x38, 0x9a, 0xaa, 0x00, 0x32, 0x04, 0x1e, 0x85, 0x42, 0x41, 0xec, 0xad, 0xae, 0xae, 0x52, 0x22, 0x0c, 0x7b, 0x60, 0x64, 0x64, 0xef, 0xf7, 0x71, 0x4c, 0x4c, 0x0c, 0x98, 0xab, 0xab, 0xab, 0x41, 0xd7, 0xd7, 0xd7, 0x83, 0x0e, 0x0c, 0x0c, 0x04, 0xbd, 0xb0, 0xb0, 0x40, 0x29, 0x71, 0x6c, 0x05, 0xb0, 0x89, 0xe3, 0xe3, 0xe3, 0x61, 0x92, 0x1c, 0x4a, 0x20, 0xb6, 0xb7, 0xff, 0xf7, 0x5b, 0x1e, 0x08, 0xc3, 0xf0, 0xf0, 0xf0, 0xc0, 0x2a, 0xde, 0xbd, 0xe1, 0x49, 0xa7, 0x4d, 0x26, 0x4e, 0xff, 0x34, 0xb0, 0x6d, 0x13, 0x13, 0xff, 0x88, 0x13, 0x66, 0xbe, 0xa2, 0x1f, 0x80, 0xe8, 0x74, 0x3a, 0x33, 0xdc, 0xd1, 0x53, 0x56, 0x01, 0xa0, 0xc4, 0x74, 0x3f, 0xa8, 0x29, 0x45, 0x60, 0xd5, 0xdb, 0xdb, 0x1b, 0x4f, 0xf4, 0xf4, 0xec, 0xec, 0x2c, 0xda, 0xba, 0xbb, 0xbb, 0xbb, 0xa2, 0xa2, 0xa2, 0xb5, 0xb5, 0x15, 0x20, 0x61, 0xa3, 0x33, 0xd3, 0x69, 0x4a, 0x33, 0x4e, 0x2d, 0x1c, 0x59, 0x64, 0x4a, 0xa7, 0x29, 0x86, 0x83, 0x09, 0xe8, 0x62, 0x1e, 0x33, 0x33, 0x33, 0xbe, 0xbe, 0xbe, 0x44, 0x38, 0x36, 0x36, 0x56, 0xad, 0x56, 0x93, 0xde, 0x05, 0x02, 0x02, 0xb7, 0x1b, 0x11, 0x9f, 0x9c, 0x9c, 0x24, 0x3c, 0x28, 0x85, 0xbb, 0xbb, 0x3b, 0xa1, 0x33, 0x33, 0x33, 0x37, 0x37, 0x37, 0x03, 0x02, 0xfe, 0x79, 0x5d, 0x57, 0x55, 0x55, 0x45, 0x0e, 0x00, 0xec, 0xf5, 0xbe, 0xbe, 0x3e, 0x72, 0x6d, 0x61, 0x6f, 0x40, 0x49, 0x70, 0x70, 0x30, 0x11, 0xa1, 0x3f, 0x21, 0xce, 0xec, 0x1b, 0x56, 0xad, 0x57, 0x00, 0x3d, 0x8a, 0xee, 0x27, 0x7a, 0xc9, 0x5d, 0x86, 0x8b, 0x86, 0x4c, 0xc9, 0x8d, 0x43, 0x68, 0x1c, 0x88, 0x4d, 0x4d, 0x4d, 0x38, 0xe6, 0xc1, 0x8f, 0x0a, 0xc0, 0x2d, 0xdc, 0xca, 0xcd, 0xcd, 0xcd, 0xb0, 0x41, 0xc4, 0xd1, 0x78, 0x88, 0x0d, 0xf7, 0x3a, 0xf8, 0x81, 0x80, 0x0d, 0xcc, 0xa0, 0xc9, 0xd1, 0x4c, 0x3f, 0xa0, 0x89, 0x42, 0x3c, 0x0f, 0xec, 0x55, 0x6a, 0x95, 0x10, 0x87, 0xfc, 0x56, 0x02, 0xee, 0xce, 0xcd, 0xcd, 0xa1, 0x62, 0xc4, 0x39, 0x33, 0x63, 0x8e, 0x98, 0x1e, 0x72, 0x00, 0x8e, 0x70, 0x91, 0x59, 0xa7, 0xf5, 0x16, 0x62, 0x96, 0x3f, 0xf2, 0x55, 0x3e, 0x80, 0xa3, 0x2e, 0x01, 0x5f, 0x01, 0xbe, 0x02, 0x1c, 0x33, 0xc0, 0xb7, 0x10, 0xc7, 0x04, 0x72, 0x16, 0xe7, 0x2b, 0xc0, 0x39, 0x85, 0x1c, 0x15, 0x1c, 0xfb, 0x0a, 0xfc, 0x0d, 0x0a, 0x08, 0x48, 0x44, 0xec, 0xf6, 0xcb, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXAudioIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x32, 0x39, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xa6, 0xa8, 0x92, 0xdf, 0x00, 0x00, 0x09, 0x77, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x99, 0x57, 0x4c, 0x94, 0x4b, 0x14, 0xc7, 0xd9, 0xa2, 0xd2, 0x44, 0x40, 0x2c, 0x14, 0x51, 0xc0, 0xa8, 0xd8, 0x30, 0x8a, 0x77, 0xc5, 0xcb, 0xb5, 0xbc, 0x20, 0xf6, 0x68, 0xa2, 0x89, 0x3d, 0x24, 0xbe, 0x58, 0x5e, 0x7c, 0xd0, 0x18, 0xbd, 0x46, 0xe3, 0x8b, 0x4f, 0x1a, 0x8d, 0x31, 0xea, 0x83, 0x35, 0x6a, 0x2c, 0xb9, 0x24, 0x46, 0x0d, 0x8a, 0x41, 0x54, 0x04, 0x0d, 0x08, 0x42, 0x58, 0x69, 0xa2, 0xec, 0x52, 0xa4, 0x08, 0xb2, 0x74, 0x41, 0x81, 0xfb, 0x93, 0xb9, 0x99, 0x7c, 0x77, 0x29, 0xba, 0x1f, 0x4d, 0x93, 0xfd, 0xb2, 0xd9, 0x9c, 0x99, 0x39, 0x33, 0xdf, 0xf9, 0x9f, 0x36, 0x73, 0xe6, 0xd3, 0xb4, 0xb7, 0xb7, 0x3b, 0xfc, 0xce, 0x8f, 0xf6, 0x77, 0x16, 0xfe, 0xbb, 0xec, 0x76, 0x00, 0x83, 0x6d, 0x41, 0xbb, 0x05, 0x6c, 0xb4, 0x40, 0x65, 0x65, 0x65, 0x7e, 0x7e, 0xfe, 0xb7, 0x6f, 0xdf, 0x6c, 0x9c, 0xd7, 0x2d, 0xbb, 0xa6, 0x6f, 0xb3, 0x50, 0x71, 0x71, 0x71, 0xb5, 0xc5, 0xa2, 0xd7, 0xe9, 0xbc, 0xc7, 0x7a, 0xbb, 0x7b, 0xb8, 0x2b, 0x5f, 0xcb, 0x8b, 0x34, 0x1a, 0x4d, 0x5d, 0x5d, 0xdd, 0xf3, 0xe7, 0xcf, 0x1b, 0x1b, 0x1b, 0x97, 0x2e, 0x5d, 0xea, 0xea, 0xea, 0xaa, 0x64, 0x50, 0x47, 0xf7, 0x25, 0x80, 0x9c, 0x9c, 0x9c, 0x4c, 0xa3, 0xd1, 0xa1, 0x5d, 0xd3, 0xdc, 0xd2, 0xac, 0xd7, 0xeb, 0x02, 0x03, 0x02, 0xa6, 0x4f, 0x9f, 0xee, 0xec, 0xec, 0x2c, 0x24, 0x43, 0xf4, 0xf2, 0xf2, 0x72, 0x3f, 0x3f, 0x3f, 0xad, 0x56, 0xfb, 0xf0, 0xe1, 0xc3, 0xcf, 0x9f, 0x3f, 0xaf, 0x5f, 0xbf, 0x5e, 0x8e, 0xaa, 0x93, 0x9e, 0x59, 0xba, 0x23, 0x47, 0x8e, 0xa8, 0x9e, 0xac, 0x9c, 0xd8, 0xd0, 0xd0, 0x90, 0x9a, 0x9a, 0x86, 0x9a, 0x1f, 0x3f, 0x8e, 0x8d, 0x7f, 0x12, 0x57, 0x55, 0x59, 0xd9, 0xd4, 0xd8, 0x44, 0xa7, 0x97, 0xd7, 0x28, 0x27, 0x27, 0x47, 0x38, 0xf5, 0x7a, 0x3d, 0x42, 0xbf, 0x79, 0xf3, 0xc6, 0xdb, 0xdb, 0x7b, 0xda, 0xb4, 0x69, 0xa0, 0xcd, 0xcd, 0xcd, 0x9d, 0x31, 0x63, 0x86, 0x72, 0x11, 0x15, 0x74, 0x9f, 0x01, 0x30, 0x9b, 0xcd, 0x38, 0x46, 0x7c, 0x7c, 0x7c, 0x74, 0xf4, 0x3f, 0xc8, 0xf1, 0xb9, 0xba, 0xda, 0x64, 0x36, 0xe1, 0xeb, 0xad, 0xad, 0xad, 0x63, 0xc6, 0x8c, 0x71, 0x72, 0x72, 0x42, 0xfd, 0x82, 0x78, 0xf5, 0xea, 0xd5, 0xf8, 0xf1, 0xe3, 0x27, 0x4c, 0x98, 0xf0, 0xe2, 0xc5, 0x8b, 0xa1, 0x43, 0x87, 0xfa, 0xf8, 0xf8, 0xa8, 0x90, 0x5b, 0x4e, 0xe9, 0x33, 0x00, 0x65, 0x65, 0x65, 0xb5, 0xb5, 0x75, 0x0f, 0x1e, 0xdc, 0xd7, 0x68, 0x1c, 0xc6, 0x8e, 0x1d, 0xeb, 0xe2, 0xe2, 0x82, 0xca, 0x09, 0x09, 0x8b, 0xa5, 0x1a, 0x0c, 0xe3, 0xc6, 0x8d, 0x1b, 0x36, 0x6c, 0x98, 0xd1, 0x68, 0x0c, 0x08, 0x08, 0xc0, 0x85, 0xc0, 0x30, 0x67, 0xce, 0x1c, 0x7a, 0x9e, 0x3d, 0x7b, 0x36, 0x75, 0xea, 0x54, 0x47, 0xc7, 0xef, 0x26, 0x52, 0xf7, 0xf4, 0x59, 0x1a, 0x45, 0x2c, 0x44, 0x47, 0x14, 0x6f, 0x6f, 0x1f, 0x4f, 0x4f, 0x4f, 0x0f, 0x0f, 0x8f, 0x11, 0x23, 0x46, 0xb8, 0xbb, 0xbb, 0x17, 0x14, 0x14, 0x20, 0x6e, 0x42, 0x42, 0x02, 0xee, 0x0e, 0x0c, 0x5c, 0x28, 0x38, 0x38, 0x18, 0x6c, 0xa9, 0xa9, 0xa9, 0xb3, 0x66, 0xcd, 0xa2, 0x93, 0x51, 0x75, 0xa2, 0x8b, 0x59, 0x7d, 0x03, 0xa0, 0xa9, 0xa9, 0x29, 0x3b, 0x3b, 0x1b, 0xe9, 0x3d, 0x3c, 0xdc, 0xbd, 0xbc, 0xbc, 0x46, 0x8e, 0x1c, 0x29, 0x31, 0xd0, 0x24, 0x6f, 0x26, 0x25, 0x25, 0xbe, 0x7e, 0xfd, 0x1a, 0x6f, 0x01, 0xd5, 0xbb, 0x77, 0xef, 0x16, 0x2e, 0x5c, 0x98, 0x96, 0x96, 0x56, 0x5f, 0x5f, 0x3f, 0x7f, 0xfe, 0xfc, 0xcc, 0xcc, 0x4c, 0xe2, 0x5b, 0x35, 0x86, 0xbe, 0x01, 0x40, 0x76, 0x7f, 0xff, 0xfe, 0xbd, 0x4e, 0xa7, 0x77, 0x77, 0xf7, 0x70, 0x73, 0x73, 0x43, 0xf1, 0xc2, 0x02, 0xd0, 0xc3, 0x87, 0x0f, 0x87, 0xce, 0xcb, 0x7b, 0xf7, 0xf2, 0xe5, 0x4b, 0xc2, 0x60, 0xf2, 0xe4, 0xc9, 0x26, 0x93, 0x89, 0x90, 0x20, 0x0c, 0x92, 0x92, 0x92, 0xa6, 0x4c, 0x99, 0x82, 0x11, 0x80, 0x34, 0xc8, 0x00, 0x4a, 0x4a, 0x3e, 0xf2, 0x23, 0x64, 0x51, 0x3c, 0xd9, 0x1d, 0xb9, 0x79, 0x80, 0x21, 0x09, 0x9d, 0x4e, 0x47, 0xda, 0x49, 0x4c, 0x4c, 0x1c, 0x32, 0x64, 0x08, 0x59, 0x08, 0xad, 0x13, 0x03, 0x44, 0xc8, 0xd7, 0xaf, 0x5f, 0xf1, 0xa8, 0xbc, 0xbc, 0x3c, 0xe2, 0x44, 0x1d, 0x86, 0x3e, 0xb0, 0x00, 0xef, 0x36, 0x99, 0x0a, 0xb0, 0x40, 0x5d, 0x5d, 0x2d, 0x79, 0x86, 0x26, 0x18, 0x04, 0x0c, 0x30, 0xe0, 0x33, 0x18, 0x61, 0xd4, 0xa8, 0x51, 0x44, 0x79, 0x46, 0x46, 0x06, 0xa2, 0xa3, 0xf5, 0xaa, 0xaa, 0x2a, 0x8c, 0x80, 0x77, 0x7d, 0xf8, 0xf0, 0x81, 0x20, 0xa6, 0x59, 0x5b, 0x5b, 0x3b, 0x38, 0x00, 0x2c, 0x16, 0x4b, 0x4c, 0xcc, 0xc3, 0x94, 0x94, 0x94, 0xaa, 0xaa, 0x4a, 0x93, 0xc9, 0x4c, 0x98, 0xea, 0xf5, 0x43, 0xd8, 0x71, 0x9b, 0x9b, 0x9b, 0x09, 0x6b, 0x81, 0x44, 0xfc, 0xe3, 0x48, 0xa4, 0x5a, 0xbc, 0x85, 0x7e, 0x68, 0xbc, 0x2e, 0x28, 0x28, 0xa8, 0xb0, 0xb0, 0x10, 0x84, 0xc4, 0x34, 0xf0, 0x06, 0x01, 0x00, 0x81, 0x6b, 0x36, 0x97, 0x14, 0x14, 0x98, 0xd8, 0xb0, 0xf0, 0x9f, 0x8c, 0x8c, 0x74, 0x12, 0x28, 0xe2, 0xd2, 0x24, 0xcd, 0xe3, 0xdc, 0x6d, 0x6d, 0x6d, 0x68, 0x9a, 0x07, 0x1a, 0x77, 0xa2, 0x1f, 0xa8, 0x9f, 0x3e, 0x7d, 0x22, 0x9a, 0x2b, 0x2a, 0x2a, 0x60, 0x26, 0x7c, 0xd9, 0xfb, 0xb0, 0x5b, 0x69, 0x69, 0xe9, 0x40, 0x03, 0xa8, 0xa9, 0xa9, 0x49, 0x4f, 0x37, 0x56, 0x56, 0x56, 0x39, 0x38, 0x68, 0x5a, 0x5b, 0xbf, 0x7b, 0xff, 0xdb, 0xb7, 0x6f, 0x11, 0xc8, 0xc7, 0xc7, 0x1b, 0x47, 0x9f, 0x39, 0x73, 0x66, 0x64, 0x64, 0x24, 0xbb, 0x01, 0x62, 0xb1, 0x5b, 0x91, 0xf2, 0xc9, 0x51, 0x10, 0xd5, 0xd5, 0xd5, 0x64, 0x52, 0xd2, 0x14, 0xbb, 0x1e, 0xa3, 0x3c, 0x98, 0x8b, 0xa8, 0x50, 0x9d, 0x88, 0xd4, 0xc7, 0x00, 0xdb, 0x56, 0x43, 0x43, 0x3d, 0xa2, 0x18, 0x0c, 0x86, 0xc6, 0xc6, 0x26, 0xd2, 0x0b, 0x61, 0x90, 0x9c, 0x9c, 0x82, 0x63, 0xb4, 0xb4, 0xb4, 0x20, 0x37, 0x7e, 0x42, 0xaa, 0xc1, 0x97, 0x90, 0x1b, 0x48, 0xf8, 0x09, 0xc6, 0xe1, 0x34, 0x61, 0x36, 0x17, 0x62, 0x2e, 0x3c, 0x07, 0x5f, 0x42, 0x74, 0x2c, 0xc0, 0x22, 0x8c, 0xaa, 0xb3, 0x80, 0xca, 0x69, 0xbc, 0xcc, 0xd5, 0xd5, 0x05, 0xd3, 0x07, 0x05, 0x05, 0xea, 0x74, 0xd0, 0xae, 0x44, 0x2a, 0xe1, 0x88, 0x7c, 0x48, 0x8c, 0xe8, 0x29, 0x29, 0xaf, 0xbf, 0x7c, 0xf9, 0xc2, 0xfe, 0x80, 0xac, 0xe8, 0x1e, 0x35, 0xf3, 0x20, 0x25, 0xcd, 0xb2, 0xf2, 0x52, 0xa0, 0x8a, 0x70, 0x1f, 0x3d, 0x7a, 0x34, 0xd8, 0xf0, 0x31, 0xa6, 0x0c, 0x34, 0x00, 0x5e, 0x89, 0xe8, 0x1a, 0x4d, 0x9b, 0xb3, 0xb3, 0xcb, 0x82, 0x05, 0x0b, 0xee, 0xdd, 0xbb, 0xb7, 0x6b, 0xd7, 0xae, 0xe6, 0xe6, 0x96, 0xec, 0xec, 0x9c, 0xe0, 0xe0, 0x29, 0xf1, 0xf1, 0x4f, 0xb0, 0x8f, 0x88, 0x0d, 0x24, 0x43, 0xcd, 0x3c, 0x10, 0x88, 0x5b, 0x5e, 0x56, 0x86, 0xfb, 0xe1, 0x63, 0x44, 0x08, 0x61, 0x00, 0x2a, 0x10, 0x62, 0x2b, 0x75, 0x00, 0xd4, 0xbb, 0x10, 0xef, 0x43, 0xf1, 0x45, 0x45, 0x85, 0xc8, 0xf5, 0xe7, 0x9f, 0xe1, 0xf8, 0x74, 0x71, 0xf1, 0x47, 0xb2, 0x26, 0x82, 0x92, 0x16, 0x03, 0x02, 0x82, 0xb2, 0xb2, 0xb2, 0xf1, 0x6c, 0xfc, 0x07, 0xad, 0x23, 0x6b, 0x07, 0x84, 0x76, 0xdc, 0x06, 0x7f, 0x03, 0x1a, 0x04, 0xa2, 0x33, 0xca, 0x3a, 0xc4, 0x37, 0x48, 0x06, 0x01, 0xc0, 0xa4, 0x49, 0x93, 0xd2, 0xde, 0xa4, 0x7f, 0x2c, 0xa9, 0x68, 0x6b, 0xd3, 0x86, 0x86, 0xce, 0x4d, 0x4c, 0x4c, 0x40, 0xe7, 0x1d, 0x19, 0xe6, 0x93, 0x9f, 0x9f, 0x2f, 0x25, 0x01, 0xc9, 0x91, 0x2d, 0x8c, 0xdd, 0x4a, 0x60, 0x60, 0x8b, 0x00, 0x09, 0x7e, 0x65, 0xa9, 0xb1, 0x60, 0x04, 0x29, 0x31, 0x66, 0x81, 0x4d, 0x36, 0x6d, 0x22, 0x7a, 0x65, 0x01, 0xd4, 0xe6, 0xe4, 0xe8, 0x94, 0x90, 0xf0, 0x9c, 0xfd, 0x28, 0x34, 0xd4, 0x80, 0x7c, 0x89, 0x89, 0x2f, 0xc8, 0x8f, 0x15, 0x15, 0xe5, 0x9c, 0xe1, 0xfe, 0x30, 0x18, 0xd8, 0x9e, 0xc0, 0x40, 0x30, 0xf0, 0x10, 0x1b, 0x04, 0x37, 0x0f, 0x04, 0xa7, 0x20, 0xbc, 0xcb, 0x26, 0x41, 0xbb, 0x63, 0xee, 0x15, 0x00, 0x16, 0x0d, 0x0b, 0x33, 0x64, 0x65, 0x19, 0x39, 0x48, 0xa0, 0xd7, 0xad, 0x5b, 0xa3, 0x38, 0x2f, 0xc4, 0xc6, 0x3e, 0x4a, 0x4e, 0x4e, 0xbe, 0x7f, 0xff, 0x7e, 0x6d, 0x4d, 0x4d, 0x44, 0xc4, 0x12, 0xdc, 0x89, 0x1c, 0x8f, 0xc4, 0xf8, 0x18, 0x0f, 0x6c, 0x18, 0x41, 0xab, 0xd5, 0xf1, 0xdf, 0x9d, 0x4c, 0x36, 0xf5, 0xf7, 0x0a, 0x00, 0x6e, 0x4d, 0x1e, 0x5c, 0xbe, 0x2c, 0x32, 0x37, 0x2f, 0x27, 0x24, 0x64, 0xc6, 0xaa, 0x55, 0xcb, 0x0f, 0x1e, 0xfc, 0xdb, 0xd1, 0xd1, 0xc9, 0xd7, 0xd7, 0xd7, 0xc7, 0xc7, 0x97, 0xda, 0x17, 0x7d, 0x87, 0x87, 0xff, 0x85, 0xfa, 0x39, 0xc0, 0x61, 0x17, 0x72, 0x14, 0xff, 0x6c, 0x6a, 0xe4, 0x4d, 0xdc, 0xc6, 0x26, 0x41, 0xbb, 0x63, 0x56, 0x5f, 0xd0, 0x20, 0x3d, 0x5a, 0x44, 0x44, 0x7f, 0x7f, 0x7f, 0x9d, 0x4e, 0x63, 0x34, 0x66, 0xb2, 0x5f, 0x79, 0x7a, 0x8e, 0x1c, 0xee, 0xe6, 0xa6, 0xd5, 0x68, 0xe7, 0xcd, 0x33, 0x40, 0x37, 0x35, 0x35, 0xe2, 0xdc, 0x41, 0x41, 0x13, 0x21, 0x38, 0xb1, 0x71, 0x1a, 0x25, 0x76, 0x57, 0xad, 0x5c, 0xe5, 0xef, 0x3f, 0x8e, 0x13, 0x91, 0x6a, 0xbf, 0x57, 0x82, 0x51, 0x59, 0xd4, 0x23, 0x3d, 0xab, 0xe0, 0xf4, 0x00, 0xc0, 0x2b, 0x68, 0xb2, 0x0d, 0xf3, 0x20, 0x13, 0xea, 0x9f, 0x38, 0x71, 0x22, 0x99, 0x91, 0x14, 0x44, 0x0c, 0xe0, 0x36, 0xf8, 0x4f, 0x6b, 0x6b, 0x3b, 0x2d, 0x0e, 0x11, 0x1c, 0xef, 0x28, 0x16, 0x28, 0x7a, 0xc2, 0xc2, 0xe6, 0x75, 0xf8, 0x12, 0x65, 0x90, 0x46, 0x29, 0x90, 0xad, 0x74, 0xaf, 0x00, 0x20, 0x01, 0xe9, 0x05, 0x00, 0x88, 0x08, 0x01, 0x18, 0x12, 0x0e, 0x18, 0xc0, 0x43, 0x7e, 0xe4, 0xf8, 0x80, 0x9f, 0xd0, 0x0f, 0x8c, 0xfc, 0xfc, 0xf7, 0xf5, 0x0d, 0xf5, 0xe4, 0x4d, 0xac, 0x86, 0x11, 0x42, 0x43, 0x43, 0x39, 0x9f, 0x02, 0x12, 0x7a, 0x70, 0x00, 0x08, 0x3d, 0x21, 0x28, 0x0f, 0x30, 0x04, 0x12, 0xfe, 0x69, 0x22, 0x90, 0xc8, 0xf1, 0x82, 0x87, 0x4e, 0x80, 0x61, 0x2b, 0x40, 0x82, 0x04, 0x0c, 0x88, 0x2e, 0x8e, 0x46, 0xbd, 0x97, 0x9e, 0x57, 0xa8, 0xb4, 0x80, 0xad, 0x86, 0xee, 0x3f, 0xfe, 0x5e, 0x65, 0xa1, 0xfe, 0x13, 0xeb, 0xe7, 0x57, 0xb6, 0x03, 0xf8, 0x79, 0x5d, 0xf5, 0x0f, 0xa7, 0xdd, 0x02, 0xfd, 0xa3, 0xd7, 0x9f, 0x5f, 0xd5, 0x6e, 0x81, 0x1f, 0xe9, 0x4a, 0x6c, 0x11, 0x6c, 0x67, 0x9d, 0x19, 0xb9, 0x5d, 0x3c, 0x7a, 0xf4, 0x28, 0xe7, 0x8b, 0xce, 0x43, 0x36, 0xf4, 0x74, 0xec, 0x45, 0xfd, 0xf5, 0x77, 0xe0, 0xc0, 0x01, 0x79, 0xe0, 0xd9, 0xb1, 0x63, 0x87, 0xd5, 0x6b, 0x36, 0x6c, 0xd8, 0x80, 0xa0, 0x57, 0xaf, 0x5e, 0xb5, 0xea, 0xb7, 0xa9, 0xd9, 0xbf, 0x2e, 0x44, 0xa1, 0x48, 0x8d, 0xcf, 0x85, 0x05, 0x82, 0xb2, 0x0d, 0x5b, 0xe9, 0x95, 0x32, 0x1a, 0x78, 0x14, 0xc7, 0x56, 0xfd, 0xb6, 0x35, 0x7b, 0x86, 0x2b, 0x4e, 0x07, 0x3d, 0xf3, 0xfc, 0x70, 0xf4, 0xc4, 0x89, 0x13, 0xc8, 0xb4, 0x79, 0xf3, 0xe6, 0xce, 0x9c, 0x9c, 0x32, 0x3a, 0x77, 0xda, 0xd4, 0xd3, 0x85, 0x05, 0xb8, 0xae, 0xda, 0xb6, 0x6d, 0xdb, 0xdc, 0xb9, 0x73, 0xd1, 0x10, 0x67, 0x77, 0x2e, 0xc1, 0xef, 0xde, 0xbd, 0x2b, 0xb5, 0x72, 0xec, 0xd8, 0xb1, 0x79, 0x1d, 0x0f, 0x55, 0x0b, 0x9d, 0xe7, 0xcf, 0x9f, 0x0f, 0xa3, 0xa8, 0x31, 0x18, 0xa8, 0x60, 0x24, 0x0f, 0xc4, 0xad, 0x5b, 0xb7, 0xb6, 0x6c, 0xd9, 0x12, 0x11, 0x11, 0xc1, 0x17, 0xa0, 0xce, 0xba, 0x8f, 0x8d, 0x8d, 0xe5, 0x82, 0x9a, 0x59, 0xe1, 0xe1, 0xe1, 0x27, 0x4f, 0x9e, 0x54, 0x4e, 0x14, 0x74, 0x49, 0x49, 0x49, 0x54, 0x54, 0x14, 0x47, 0x6e, 0xca, 0x6e, 0x04, 0xd8, 0xb7, 0x6f, 0x5f, 0xb7, 0x15, 0x5c, 0x67, 0xb8, 0x88, 0xc7, 0x2a, 0x9c, 0xc9, 0xc0, 0xc0, 0xb5, 0x07, 0x34, 0x67, 0x2f, 0x2a, 0x12, 0xc1, 0x29, 0x3f, 0x0a, 0xdd, 0xbe, 0x7d, 0x9b, 0x9e, 0x25, 0x4b, 0x96, 0x88, 0x57, 0x1e, 0x3f, 0x7e, 0x5c, 0x2e, 0xb5, 0x7d, 0xfb, 0x76, 0xd1, 0x29, 0xfe, 0xc5, 0x79, 0x53, 0x69, 0x81, 0xfd, 0xfb, 0xf7, 0x4b, 0x06, 0x94, 0x25, 0x27, 0x0a, 0x82, 0xe0, 0xa6, 0xcc, 0x97, 0x0c, 0x82, 0xe0, 0xcb, 0x08, 0xb7, 0x91, 0x56, 0x9c, 0x34, 0xff, 0xbb, 0xf0, 0x50, 0x0e, 0x44, 0x47, 0x47, 0x23, 0x0d, 0x57, 0xc7, 0x74, 0x52, 0xbf, 0x0a, 0x0c, 0x32, 0xd4, 0xb8, 0xcd, 0x0c, 0x0c, 0x0c, 0x64, 0x51, 0x01, 0x80, 0x1c, 0x32, 0x7b, 0xf6, 0x6c, 0x9a, 0x12, 0x80, 0x34, 0x17, 0xda, 0xbd, 0x78, 0xf1, 0xe2, 0xe2, 0xc5, 0x8b, 0x85, 0x04, 0x9b, 0x36, 0x6d, 0x92, 0x6f, 0xa1, 0x54, 0x88, 0x89, 0x89, 0x59, 0xb3, 0x66, 0x0d, 0x43, 0x56, 0x00, 0x38, 0x90, 0xf3, 0x69, 0x90, 0x7e, 0x6a, 0xbd, 0x33, 0x67, 0xce, 0xf0, 0x6d, 0xe1, 0xf0, 0xe1, 0xc3, 0x5c, 0x1c, 0xd1, 0xb3, 0x71, 0xe3, 0x46, 0xb9, 0x82, 0x24, 0xba, 0xb8, 0xd8, 0x62, 0xdd, 0xb8, 0xb8, 0x38, 0x24, 0xa6, 0xfc, 0xa3, 0xfe, 0x60, 0x21, 0x08, 0x6c, 0x2a, 0xe4, 0xe0, 0xfa, 0x96, 0x4e, 0x68, 0xa1, 0x57, 0xe0, 0x59, 0x45, 0xe1, 0xa5, 0x4b, 0x97, 0x18, 0xa5, 0x9f, 0xcf, 0x47, 0x1c, 0x98, 0xf1, 0x04, 0xee, 0x49, 0xb9, 0xd6, 0x15, 0xd3, 0xc5, 0x3f, 0x8e, 0xc1, 0xc5, 0xe3, 0xd3, 0xa7, 0x4f, 0x95, 0x9d, 0x82, 0xc6, 0x81, 0xf9, 0x12, 0x05, 0xbd, 0x77, 0xef, 0xde, 0x9d, 0x3b, 0x77, 0x42, 0xe0, 0x84, 0xc0, 0xb8, 0x7e, 0xfd, 0x3a, 0x9a, 0xe5, 0x58, 0x2e, 0xd3, 0x9a, 0xe0, 0xb7, 0x06, 0x80, 0x02, 0x56, 0xae, 0x5c, 0xf9, 0xe8, 0xd1, 0x23, 0x86, 0x29, 0x4a, 0x90, 0x12, 0x23, 0x40, 0x33, 0x53, 0x4c, 0xf8, 0xe1, 0x3f, 0x75, 0x3d, 0x3c, 0xcb, 0x96, 0x2d, 0x43, 0x7a, 0xc1, 0xbc, 0x62, 0xc5, 0x0a, 0x74, 0xf9, 0xc3, 0x89, 0x82, 0x41, 0x4c, 0x87, 0x5e, 0xbd, 0x7a, 0xb5, 0x9c, 0x02, 0x0d, 0x00, 0x51, 0x5b, 0x93, 0xd6, 0x64, 0x3f, 0x84, 0x75, 0x10, 0x5f, 0xbb, 0x76, 0x4d, 0x48, 0x7f, 0xe7, 0xce, 0x1d, 0xae, 0x6e, 0x28, 0x08, 0xd7, 0xae, 0x5d, 0xab, 0x9c, 0x00, 0x2d, 0x74, 0xc0, 0x75, 0x83, 0xe8, 0x27, 0x3c, 0x94, 0x0c, 0x68, 0x97, 0x26, 0xd7, 0x2a, 0xb2, 0x53, 0x49, 0xcb, 0xce, 0xee, 0x08, 0x0c, 0x2e, 0x86, 0xb8, 0xc7, 0x96, 0x3c, 0x82, 0x46, 0x9b, 0x9d, 0xef, 0xbf, 0xac, 0x01, 0x60, 0x41, 0xa6, 0x51, 0x34, 0xe1, 0x48, 0x94, 0x7c, 0xa4, 0x39, 0xae, 0x12, 0xe8, 0xc1, 0xe7, 0xe4, 0x72, 0x22, 0x2a, 0xf8, 0x48, 0x4a, 0x27, 0x6e, 0x20, 0xa6, 0x48, 0x06, 0x3e, 0xbd, 0xc0, 0xc9, 0x28, 0xdf, 0x63, 0x20, 0x78, 0x37, 0x0e, 0x29, 0xe7, 0x0a, 0x02, 0x66, 0xf6, 0x66, 0x72, 0x34, 0x4d, 0x25, 0x4d, 0x93, 0x2b, 0x47, 0xb2, 0x1f, 0xc4, 0xe9, 0xd3, 0xa7, 0x8b, 0x8a, 0x8a, 0x20, 0xd2, 0xd3, 0xd3, 0x51, 0x3f, 0x04, 0xe9, 0x88, 0xdb, 0x6c, 0x88, 0xff, 0x3d, 0xcc, 0x57, 0x3e, 0x97, 0x2f, 0x5f, 0x16, 0xc3, 0x84, 0xe6, 0xba, 0x75, 0xeb, 0xa8, 0xd0, 0x45, 0x93, 0xea, 0xf6, 0xca, 0x95, 0x2b, 0x82, 0x93, 0xfd, 0x5f, 0x74, 0xf2, 0xd9, 0x5d, 0x10, 0xfc, 0xe3, 0x6f, 0x37, 0x6f, 0xde, 0x84, 0x81, 0x28, 0x97, 0xaf, 0x21, 0x0f, 0x4a, 0x06, 0xf4, 0x77, 0xe8, 0xd0, 0x21, 0x18, 0xb0, 0xad, 0x08, 0x4a, 0x39, 0x24, 0xa6, 0x9f, 0x3d, 0x7b, 0x56, 0xac, 0x7f, 0xee, 0xdc, 0x39, 0x31, 0x44, 0xfd, 0x19, 0x12, 0x12, 0x22, 0x68, 0xcc, 0xce, 0x57, 0x36, 0xc1, 0xa0, 0xfc, 0xb7, 0xce, 0x42, 0x28, 0x66, 0xf7, 0xee, 0xdd, 0x42, 0xc7, 0xcc, 0xe4, 0x2b, 0xe2, 0xa9, 0x53, 0xa7, 0x48, 0x6a, 0x58, 0xe3, 0xc2, 0x85, 0x0b, 0x62, 0x26, 0xce, 0x43, 0x0a, 0x17, 0xeb, 0x2e, 0x5a, 0xb4, 0x68, 0xcf, 0x9e, 0x3d, 0xd0, 0xec, 0x18, 0xe8, 0x49, 0x30, 0xf0, 0x26, 0xbe, 0x7c, 0x09, 0x06, 0x5c, 0x82, 0x4c, 0x2f, 0xaa, 0x64, 0x09, 0x40, 0x22, 0x14, 0x3c, 0xfc, 0x93, 0xa9, 0x25, 0x00, 0x16, 0xb9, 0x71, 0xe3, 0x86, 0xf2, 0xba, 0x17, 0xab, 0xf2, 0xa1, 0x56, 0x29, 0xb7, 0xa4, 0xbb, 0xae, 0x89, 0x31, 0x2e, 0xc1, 0x84, 0x82, 0x3b, 0xe7, 0x63, 0xf9, 0x4a, 0x34, 0x0d, 0x2a, 0x09, 0x55, 0xf6, 0x4b, 0x82, 0x0b, 0x39, 0x76, 0x1f, 0x62, 0x4e, 0xe4, 0x2b, 0xd9, 0xff, 0xf3, 0x04, 0x89, 0x9f, 0x45, 0x48, 0x62, 0xc2, 0xa9, 0xba, 0x9c, 0xd8, 0x35, 0x80, 0x2e, 0x59, 0x7f, 0xcd, 0x4e, 0xeb, 0x20, 0xfe, 0x35, 0xa5, 0xec, 0x41, 0x2a, 0x3b, 0x80, 0x1e, 0x94, 0x33, 0x20, 0x43, 0x76, 0x0b, 0x0c, 0x88, 0x9a, 0x7b, 0x78, 0x89, 0xdd, 0x02, 0x3d, 0x28, 0x67, 0x40, 0x86, 0xec, 0x16, 0x18, 0x10, 0x35, 0xf7, 0xf0, 0x12, 0xbb, 0x05, 0x7a, 0x50, 0xce, 0x80, 0x0c, 0xfd, 0x0b, 0xbe, 0x35, 0x47, 0x3f, 0x08, 0xc9, 0x3b, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXJSIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x38, 0x38, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x0e, 0x0a, 0xaa, 0x03, 0x00, 0x00, 0x05, 0x39, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x58, 0x7d, 0x48, 0x5b, 0x57, 0x14, 0xcf, 0x8b, 0x2f, 0x31, 0xd1, 0x1a, 0x4d, 0xb4, 0x06, 0xc7, 0xfc, 0x88, 0x55, 0x59, 0x97, 0x5a, 0xf1, 0xb3, 0x43, 0x83, 0xba, 0x32, 0x97, 0x0d, 0x3a, 0x0b, 0x2b, 0x08, 0x75, 0x65, 0x82, 0x8c, 0xc1, 0xdc, 0x1f, 0xab, 0x48, 0xdd, 0x64, 0x62, 0x19, 0x6e, 0x73, 0xc2, 0xa6, 0x83, 0x6e, 0x38, 0x46, 0xff, 0x28, 0xc3, 0x75, 0x6b, 0x51, 0x36, 0x54, 0x56, 0x23, 0x88, 0x3a, 0x3b, 0xa1, 0x22, 0xd4, 0xd8, 0xc9, 0x28, 0x9b, 0x1f, 0x0c, 0xad, 0x4c, 0xa3, 0xb5, 0x89, 0x71, 0xd1, 0x7c, 0xb8, 0x63, 0x9f, 0xbc, 0x3c, 0x93, 0x98, 0x9b, 0xbc, 0x7b, 0xcd, 0x10, 0xde, 0x23, 0x84, 0x73, 0xcf, 0xfb, 0xdd, 0x73, 0x7e, 0xbf, 0x73, 0xee, 0xbb, 0x2f, 0xb9, 0xd4, 0xce, 0xce, 0x8e, 0xe8, 0x28, 0x5f, 0xe2, 0xa3, 0x4c, 0x7e, 0x97, 0xbb, 0x20, 0xe0, 0xff, 0xee, 0xa0, 0xd0, 0x01, 0xa1, 0x03, 0x98, 0x15, 0x10, 0x96, 0x10, 0x66, 0x01, 0xb1, 0xa7, 0xd3, 0xd8, 0x11, 0xf6, 0x02, 0xac, 0x8f, 0x19, 0xcc, 0x13, 0xbf, 0xba, 0xec, 0xdb, 0x30, 0x56, 0x16, 0xe9, 0xa3, 0x5f, 0x78, 0xc9, 0x23, 0xf2, 0xfc, 0x17, 0x57, 0x18, 0x8f, 0x34, 0xfe, 0x99, 0xf8, 0x73, 0x97, 0x68, 0xe5, 0x71, 0x0f, 0x00, 0xbf, 0x21, 0x19, 0x01, 0xb3, 0x1f, 0xbf, 0xb3, 0x74, 0xeb, 0x1b, 0x96, 0x41, 0x58, 0x64, 0x94, 0xb7, 0x80, 0xc5, 0x1b, 0x9f, 0xb3, 0x80, 0x85, 0x6f, 0x3f, 0xc9, 0xfc, 0xee, 0xae, 0x5c, 0xf3, 0x1c, 0xeb, 0xe1, 0x6d, 0x10, 0x78, 0x06, 0x2c, 0xc6, 0x31, 0x2e, 0xfb, 0x40, 0xa8, 0xd8, 0xd7, 0x57, 0xe7, 0x5a, 0x2f, 0x07, 0x82, 0x44, 0x62, 0x08, 0x74, 0xc0, 0x32, 0x39, 0xc6, 0xa6, 0x49, 0xfd, 0xe0, 0x4b, 0xa5, 0xee, 0x55, 0x5a, 0x19, 0xc7, 0x7a, 0x58, 0x23, 0xf7, 0x97, 0x3f, 0x1d, 0xe6, 0xf5, 0xbf, 0xae, 0xbe, 0x65, 0x7d, 0x68, 0x04, 0x27, 0x77, 0x16, 0x8b, 0xe1, 0x61, 0x10, 0xe8, 0x80, 0x63, 0xc3, 0xcc, 0x24, 0xa6, 0x15, 0x31, 0x09, 0x6f, 0xbc, 0x27, 0x4b, 0xce, 0xa0, 0x15, 0x2a, 0x6f, 0x2a, 0xb2, 0xc4, 0xb4, 0x63, 0xda, 0xbc, 0xf8, 0xf3, 0x55, 0xcc, 0x2d, 0x87, 0xd5, 0xe2, 0x8d, 0xe1, 0xe1, 0x21, 0x20, 0x80, 0xcd, 0x2a, 0x0e, 0x97, 0xb3, 0xf6, 0x41, 0x46, 0x20, 0x98, 0x83, 0xe6, 0xfa, 0xf4, 0x93, 0x14, 0xe0, 0x33, 0xc1, 0x61, 0x3b, 0x05, 0x01, 0x22, 0x91, 0x63, 0x7d, 0x95, 0x29, 0x33, 0x45, 0x4b, 0x90, 0xf5, 0x16, 0x4b, 0xdc, 0x18, 0x87, 0x79, 0x0d, 0x89, 0x47, 0x02, 0x70, 0x3b, 0xb0, 0xbd, 0xf2, 0x68, 0x75, 0xf0, 0x27, 0x26, 0x4d, 0xc4, 0x89, 0xe7, 0x91, 0xf9, 0xe4, 0xa9, 0x6e, 0xcc, 0xd2, 0xcd, 0xaf, 0x90, 0x78, 0x24, 0x00, 0x4b, 0xc0, 0xc2, 0xf5, 0x4f, 0xef, 0x97, 0x9f, 0xdc, 0x5e, 0x59, 0x82, 0x34, 0x61, 0x32, 0x79, 0xe2, 0xdb, 0x1f, 0x22, 0xf3, 0x45, 0x9d, 0x3e, 0xa3, 0x2a, 0x7d, 0x8d, 0x81, 0xfd, 0xfd, 0xf5, 0xd5, 0xa9, 0x8b, 0xf9, 0x5b, 0x0b, 0xb3, 0xc8, 0x59, 0x7e, 0x00, 0x58, 0x02, 0x36, 0xa6, 0xee, 0x31, 0x7b, 0xa8, 0x44, 0x75, 0x3c, 0xe3, 0xb3, 0xce, 0xa8, 0x6c, 0x9d, 0x9f, 0x4c, 0x7b, 0xb7, 0x28, 0x71, 0x46, 0xeb, 0xf7, 0xb1, 0x2f, 0x96, 0x33, 0x43, 0xcb, 0xef, 0x13, 0xf6, 0x27, 0x7b, 0x2b, 0x10, 0x3d, 0xd7, 0x17, 0x02, 0x4b, 0x40, 0xac, 0xbe, 0x22, 0x32, 0x23, 0x13, 0xc2, 0xda, 0xd7, 0x56, 0xfe, 0xb8, 0x7c, 0xc1, 0x74, 0xe7, 0x07, 0x5f, 0x29, 0xf6, 0xf9, 0x5c, 0x5b, 0xff, 0x3e, 0x78, 0x53, 0xb7, 0x3a, 0xd4, 0x03, 0x5e, 0xb1, 0x34, 0x5c, 0xfd, 0x7a, 0x75, 0xb8, 0xfa, 0xd9, 0x7d, 0x88, 0x60, 0x07, 0x70, 0x2a, 0x81, 0x73, 0xb9, 0xb6, 0x6d, 0xf7, 0x2f, 0x64, 0xdd, 0x3d, 0x25, 0x82, 0xcf, 0xd4, 0xa5, 0x42, 0x64, 0xa8, 0xc7, 0xbf, 0xf5, 0x33, 0x60, 0xf8, 0x36, 0x19, 0x6e, 0x23, 0xf1, 0x48, 0x00, 0x56, 0x07, 0xa0, 0x58, 0x94, 0x24, 0x5c, 0xa9, 0x7b, 0x85, 0xa9, 0x9a, 0x6d, 0x71, 0x0e, 0x59, 0x3e, 0xdb, 0x82, 0x1b, 0xa3, 0x3a, 0x7b, 0x1e, 0x89, 0x47, 0x02, 0x70, 0x05, 0x40, 0x02, 0x4a, 0x22, 0x45, 0xa6, 0xf1, 0x09, 0xa0, 0x68, 0x9e, 0x13, 0xb9, 0xd1, 0x08, 0x08, 0xe0, 0x86, 0x0b, 0xbd, 0x2d, 0x08, 0xe0, 0xd4, 0xdc, 0x69, 0x35, 0x8b, 0x5c, 0x4e, 0x8e, 0xc3, 0x87, 0xe9, 0x34, 0x3f, 0xf6, 0xe1, 0xc5, 0x70, 0x11, 0xf8, 0x3f, 0x20, 0x8d, 0x55, 0x33, 0x04, 0x9c, 0x9b, 0x56, 0xf8, 0xb9, 0x1f, 0x53, 0xf8, 0x72, 0x64, 0xc6, 0x69, 0xf9, 0x09, 0xad, 0x07, 0x2b, 0x53, 0xff, 0x8f, 0x4e, 0xcb, 0x93, 0x47, 0x37, 0xaf, 0x31, 0x7e, 0x69, 0x6c, 0xbc, 0x07, 0x80, 0xdf, 0x90, 0x80, 0x80, 0xe8, 0x33, 0x67, 0x29, 0x9a, 0xde, 0x71, 0x38, 0x80, 0xc1, 0x3f, 0x3f, 0xdf, 0x80, 0x4f, 0xd2, 0xbb, 0x1f, 0x25, 0x7a, 0x09, 0x78, 0x78, 0xe5, 0x22, 0x97, 0x62, 0x4c, 0xa1, 0x9e, 0x3b, 0xe4, 0x6d, 0x13, 0x78, 0x06, 0xe4, 0x9a, 0x93, 0xa9, 0x0d, 0xd7, 0xe0, 0xad, 0x14, 0x38, 0x89, 0xa8, 0x53, 0x79, 0x9a, 0xf7, 0xdb, 0x03, 0xc7, 0xfb, 0x41, 0x52, 0xf0, 0xa6, 0xf0, 0x73, 0x3b, 0xf0, 0x5b, 0xdb, 0xcb, 0x8b, 0x1b, 0x0f, 0xee, 0x31, 0xa7, 0x12, 0x91, 0xe9, 0x99, 0x3e, 0x96, 0x90, 0xe1, 0x16, 0x13, 0x4d, 0x1a, 0x97, 0xa0, 0xc8, 0xd1, 0x89, 0x28, 0x02, 0xb5, 0x83, 0x80, 0xc4, 0x04, 0x04, 0x2e, 0x95, 0x2c, 0x92, 0x4c, 0x19, 0xc8, 0x72, 0x0a, 0x2a, 0x9a, 0x20, 0x20, 0xa8, 0x72, 0x1d, 0x02, 0x58, 0xe8, 0xc0, 0x21, 0x14, 0x35, 0xa8, 0x90, 0x84, 0x3b, 0x70, 0xfd, 0xe9, 0x15, 0x14, 0x03, 0x4c, 0x30, 0xc9, 0x6d, 0x74, 0x6b, 0x6b, 0x2b, 0x22, 0x22, 0x22, 0x2c, 0x2c, 0x6c, 0x73, 0x73, 0x93, 0xa6, 0x09, 0xbc, 0xe3, 0x03, 0xd1, 0x46, 0x38, 0x4d, 0x74, 0x74, 0xb4, 0x5c, 0x2e, 0x0f, 0x19, 0x7b, 0x50, 0x48, 0xb2, 0x03, 0x10, 0xce, 0xe5, 0x72, 0xc1, 0xb7, 0x58, 0x8c, 0x5e, 0x99, 0x80, 0x0c, 0x04, 0x86, 0x6c, 0x02, 0x81, 0x0e, 0x8c, 0x8e, 0x8e, 0x36, 0x35, 0x35, 0xc1, 0xb2, 0x61, 0x93, 0x55, 0x54, 0x54, 0xd4, 0xd5, 0xd5, 0xb1, 0x43, 0x30, 0x7a, 0x7b, 0x7b, 0xbb, 0xba, 0xba, 0xfa, 0xfb, 0xfb, 0x2d, 0x16, 0x8b, 0x56, 0xab, 0x85, 0xc5, 0x96, 0x94, 0x94, 0xd4, 0xd7, 0xd7, 0xc7, 0xc5, 0xf0, 0xb3, 0xc9, 0x08, 0x18, 0x1e, 0x1e, 0xe6, 0xa6, 0x4f, 0x4b, 0x4b, 0xe3, 0x0e, 0x07, 0x07, 0x07, 0xcb, 0xcb, 0x77, 0xcf, 0x51, 0xf4, 0x7a, 0xbd, 0xd3, 0xe9, 0x84, 0x21, 0xfc, 0x00, 0xb3, 0xdb, 0xed, 0x5c, 0x0c, 0x6f, 0x9b, 0x80, 0x80, 0xda, 0xda, 0xda, 0xfc, 0xfc, 0x7c, 0xab, 0xd5, 0x0a, 0x24, 0x3a, 0x3b, 0x3b, 0xbb, 0xbb, 0xbb, 0x3d, 0xd8, 0x18, 0x0c, 0x06, 0xf0, 0x40, 0xe1, 0xa1, 0x03, 0x60, 0xcc, 0xcf, 0xcf, 0x37, 0x37, 0x37, 0x83, 0x12, 0x0f, 0x18, 0xbf, 0x21, 0x01, 0x01, 0xf0, 0xd4, 0x96, 0x95, 0x95, 0x31, 0xe9, 0xc7, 0xc7, 0xc7, 0xbd, 0x79, 0x14, 0x14, 0x14, 0x80, 0x73, 0x7a, 0x7a, 0x3a, 0x2b, 0x2b, 0xab, 0xa4, 0xa4, 0x24, 0x3b, 0x3b, 0xbb, 0xb1, 0xb1, 0x51, 0xa3, 0xd1, 0x78, 0x23, 0xf9, 0x78, 0x90, 0x07, 0x2f, 0x41, 0x01, 0x1a, 0x1a, 0x1a, 0x80, 0x44, 0x65, 0x65, 0x25, 0x77, 0x16, 0xac, 0x16, 0x9d, 0x6e, 0xdf, 0xa1, 0x1d, 0x45, 0x51, 0x35, 0x35, 0x35, 0x5c, 0x0c, 0x6f, 0x1b, 0xbd, 0x5d, 0xf0, 0xa9, 0xca, 0xfe, 0x39, 0xb0, 0xab, 0x0e, 0x0c, 0x0c, 0x18, 0x8d, 0xc6, 0xfa, 0xfa, 0xfa, 0xe2, 0xe2, 0x62, 0x89, 0x44, 0x02, 0x74, 0x3b, 0x3a, 0x3a, 0xe6, 0xe6, 0xdc, 0x67, 0x44, 0xfb, 0x67, 0x04, 0x31, 0x0a, 0x85, 0x80, 0xb6, 0xb6, 0x36, 0xd8, 0x73, 0x60, 0x9b, 0x6a, 0x6d, 0x6d, 0x1d, 0x19, 0x19, 0x99, 0x99, 0x99, 0x91, 0xc9, 0x64, 0xa0, 0x61, 0x68, 0x68, 0x28, 0x08, 0xa6, 0x07, 0x40, 0x09, 0x3c, 0x03, 0x07, 0x44, 0x76, 0xbb, 0xa1, 0xd2, 0x26, 0x93, 0xa9, 0xb4, 0xb4, 0x14, 0x96, 0x4d, 0x6e, 0x6e, 0xee, 0xe4, 0xe4, 0xa4, 0xcd, 0x66, 0x83, 0x97, 0x00, 0x3c, 0xfa, 0x6e, 0x10, 0x5f, 0x8b, 0xb0, 0x00, 0x60, 0xe6, 0xcd, 0x44, 0xa1, 0x50, 0xc0, 0xa2, 0x87, 0x85, 0xd4, 0xde, 0xbe, 0xf7, 0x3f, 0x38, 0x2e, 0x2e, 0xae, 0xa5, 0xa5, 0x25, 0x33, 0x73, 0xf7, 0x60, 0x18, 0xf3, 0x22, 0x2c, 0x00, 0xb6, 0x48, 0x20, 0x94, 0x90, 0x90, 0xc0, 0xa5, 0x05, 0x4f, 0x76, 0x75, 0x75, 0x75, 0x4a, 0x4a, 0xca, 0xec, 0xec, 0xec, 0xda, 0xda, 0x9a, 0x4a, 0xa5, 0x4a, 0x4e, 0x4e, 0x96, 0x4a, 0x09, 0x9c, 0x2b, 0x42, 0x16, 0x02, 0x02, 0x7a, 0x7a, 0x7a, 0x26, 0x26, 0x26, 0xd4, 0x6a, 0x35, 0xec, 0xa1, 0xcc, 0xcb, 0xb5, 0xa8, 0xa8, 0x88, 0x2b, 0xe0, 0xd8, 0xd3, 0x0b, 0x3c, 0xe9, 0xe9, 0xe9, 0x5c, 0x3f, 0x19, 0x9b, 0xf7, 0xfe, 0xc5, 0x4e, 0x64, 0xde, 0xb2, 0x2c, 0x9b, 0xaa, 0xaa, 0x2a, 0xf6, 0x56, 0x08, 0x0c, 0x02, 0x3f, 0xe6, 0x96, 0x97, 0x97, 0x61, 0x3f, 0x81, 0xc5, 0xa3, 0x54, 0x2a, 0xf3, 0xf2, 0xf2, 0x72, 0x72, 0x72, 0x58, 0x31, 0x21, 0x30, 0x08, 0x08, 0x08, 0x01, 0x4b, 0x3f, 0x29, 0x42, 0xf1, 0x1e, 0xf0, 0x93, 0x1e, 0xff, 0x96, 0x20, 0x00, 0xbf, 0x86, 0x78, 0x11, 0x84, 0x0e, 0xe0, 0xd5, 0x0f, 0x7f, 0xb6, 0xd0, 0x01, 0xfc, 0x1a, 0xe2, 0x45, 0x38, 0xf2, 0x1d, 0xf8, 0x0f, 0x1c, 0x65, 0x73, 0xb3, 0xdd, 0xbe, 0x50, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXPlistIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x33, 0x35, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc8, 0x4f, 0xd5, 0xc2, 0x00, 0x00, 0x06, 0xa8, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x58, 0x7b, 0x4c, 0x53, 0x57, 0x18, 0xb7, 0xef, 0x77, 0x91, 0x87, 0x82, 0x20, 0x68, 0x01, 0xd1, 0xf8, 0x20, 0x6e, 0x09, 0xd1, 0x44, 0xc1, 0xcc, 0xa0, 0xce, 0x4c, 0x0d, 0xfc, 0xb7, 0x11, 0xa6, 0x93, 0xb0, 0x65, 0x53, 0x18, 0x31, 0x41, 0xcd, 0x4c, 0x4c, 0x96, 0x25, 0xfe, 0xb3, 0xa0, 0x46, 0x8c, 0x61, 0x03, 0x5f, 0x7f, 0xb0, 0x31, 0x46, 0x74, 0x31, 0x6e, 0xcb, 0x62, 0x80, 0x6c, 0x73, 0x8a, 0x12, 0xc5, 0xa0, 0x19, 0xbe, 0x98, 0x48, 0x43, 0x71, 0x56, 0x94, 0xd2, 0x07, 0xa5, 0x94, 0xb6, 0xfb, 0xe1, 0x71, 0xb7, 0x87, 0xdb, 0xf6, 0xda, 0x7b, 0x5b, 0x75, 0x66, 0xbd, 0x69, 0x9a, 0xef, 0x7c, 0x8f, 0xdf, 0xf9, 0x5e, 0xe7, 0x3b, 0xed, 0x15, 0xf9, 0x7c, 0xbe, 0x69, 0xaf, 0xf3, 0x23, 0x7e, 0x9d, 0x9d, 0x9f, 0xf4, 0x3d, 0x16, 0xc0, 0xab, 0xae, 0x60, 0xac, 0x02, 0xb1, 0x0a, 0x44, 0x98, 0x81, 0x58, 0x0b, 0x45, 0x98, 0xc0, 0x88, 0xcd, 0x63, 0x15, 0x88, 0x38, 0x85, 0x11, 0x02, 0xc4, 0x2a, 0x10, 0x61, 0x02, 0x23, 0x36, 0x8f, 0x55, 0x20, 0x58, 0x0a, 0x87, 0xdc, 0xde, 0x40, 0xb6, 0xcd, 0xe3, 0xf3, 0x04, 0x72, 0x23, 0xe6, 0x44, 0xb9, 0x02, 0x5d, 0xd6, 0xf1, 0x0f, 0xba, 0x1f, 0xcf, 0x6b, 0x37, 0x05, 0x3a, 0xf6, 0xfb, 0xe3, 0xb1, 0xcc, 0x36, 0xd3, 0x97, 0x7f, 0x59, 0x87, 0x83, 0x85, 0x17, 0xa8, 0x1f, 0x26, 0x47, 0x14, 0x95, 0xff, 0x03, 0x48, 0xed, 0x0f, 0x0f, 0x46, 0x0f, 0xf5, 0xd9, 0xfe, 0x78, 0x32, 0x86, 0x8d, 0x95, 0x12, 0x91, 0x73, 0x7d, 0x06, 0xcb, 0x83, 0x9f, 0xcc, 0xce, 0x0d, 0x9d, 0x66, 0x30, 0xd5, 0x12, 0xf1, 0xfb, 0xb3, 0x35, 0x9f, 0x1a, 0x74, 0x0b, 0xb5, 0x32, 0x96, 0x8e, 0x80, 0xa5, 0x54, 0x80, 0x0d, 0x6d, 0xf2, 0xc4, 0xed, 0x3d, 0x6a, 0xb4, 0x1f, 0xb9, 0x6f, 0x33, 0x3a, 0x27, 0x68, 0x3e, 0x07, 0x3d, 0xea, 0xf1, 0x7e, 0xdd, 0x6f, 0xc3, 0xa7, 0x70, 0x86, 0xaa, 0xca, 0xa0, 0x7b, 0x67, 0xa6, 0x4a, 0xc4, 0xa1, 0xfd, 0x3c, 0x91, 0xf0, 0x00, 0xfe, 0xb4, 0xbb, 0x6b, 0xfb, 0x6c, 0x8d, 0x03, 0x0e, 0x38, 0x44, 0xef, 0x32, 0x4b, 0x29, 0xdd, 0x9a, 0xae, 0xa1, 0x39, 0x84, 0xce, 0xd5, 0xcb, 0x4b, 0x67, 0x6b, 0x4f, 0x3d, 0x18, 0x75, 0xfe, 0xab, 0xdf, 0xfa, 0xc8, 0x89, 0x4f, 0xb6, 0x46, 0x56, 0x31, 0x57, 0xb7, 0x35, 0x5d, 0xab, 0x97, 0x0a, 0x09, 0x84, 0x77, 0x0b, 0xc1, 0xd9, 0x9f, 0xcd, 0x4e, 0x74, 0x0b, 0xf6, 0xa6, 0xbd, 0x94, 0x89, 0x45, 0x1b, 0x92, 0x55, 0x65, 0xe9, 0xda, 0xf5, 0x33, 0x55, 0x12, 0x5a, 0x30, 0x95, 0xb6, 0x4c, 0xf8, 0xbe, 0x35, 0x39, 0x8e, 0x1a, 0x6d, 0xd7, 0x46, 0xc6, 0x69, 0x89, 0x4e, 0x2a, 0x46, 0x0c, 0x95, 0x06, 0x5d, 0xb6, 0x9a, 0x5f, 0x4e, 0x79, 0x07, 0xb0, 0xbe, 0xd3, 0xfc, 0x8b, 0x79, 0x8a, 0xeb, 0x8b, 0xf5, 0x72, 0xf8, 0x5d, 0x9a, 0xa6, 0x99, 0x21, 0xe7, 0x31, 0x12, 0xae, 0x59, 0xdd, 0x08, 0x03, 0xc1, 0x58, 0xa8, 0x33, 0x2d, 0x12, 0x89, 0xea, 0x73, 0x13, 0xca, 0xd3, 0xb5, 0x74, 0x6c, 0xdc, 0x34, 0xbf, 0x70, 0x81, 0x35, 0x34, 0xee, 0x6f, 0x98, 0xe2, 0x59, 0xea, 0xcf, 0xb2, 0xe3, 0xf2, 0xe2, 0xe4, 0xdc, 0x7b, 0x04, 0x95, 0xbe, 0xa1, 0x97, 0x1d, 0x59, 0x9c, 0x50, 0xb3, 0x30, 0x1e, 0x4d, 0xf5, 0xc5, 0xdd, 0x91, 0xbb, 0x76, 0x37, 0xd4, 0x30, 0x51, 0xcc, 0x2e, 0x3f, 0x7e, 0x50, 0x43, 0x16, 0x93, 0x77, 0x00, 0xb4, 0xfd, 0x8f, 0x0f, 0x9d, 0xe2, 0x69, 0xa2, 0x8f, 0xe6, 0x68, 0xd7, 0x24, 0x29, 0x05, 0xf4, 0xaf, 0xd3, 0xeb, 0xfb, 0x7e, 0x70, 0x14, 0x33, 0x80, 0x78, 0x4f, 0x23, 0x87, 0x4f, 0xf3, 0x0e, 0xe0, 0xc3, 0x0c, 0xad, 0xd9, 0xe5, 0x21, 0x33, 0xc7, 0xed, 0xf5, 0x9d, 0x7a, 0xe0, 0xc0, 0x67, 0xae, 0x5a, 0x5a, 0x9e, 0x81, 0x83, 0xa8, 0x49, 0x55, 0x70, 0xf4, 0xbf, 0xdf, 0x2b, 0xd2, 0x3f, 0xdf, 0x98, 0x1c, 0x23, 0x54, 0xff, 0x40, 0x5c, 0x90, 0xa8, 0x5c, 0x33, 0x43, 0xe9, 0xd7, 0x0b, 0x83, 0xe2, 0x7d, 0x06, 0x80, 0xc9, 0x9a, 0xfa, 0xcc, 0x2e, 0x52, 0xb1, 0x08, 0x33, 0x11, 0x11, 0xbe, 0x1d, 0xe2, 0x1c, 0x5b, 0x27, 0x7c, 0x4d, 0x83, 0x8e, 0x06, 0xa3, 0xfd, 0xaa, 0xc5, 0xc5, 0x58, 0x81, 0x90, 0x8b, 0x45, 0xef, 0xa5, 0x69, 0xaa, 0x0c, 0x7a, 0xf4, 0x15, 0xcd, 0x0f, 0x87, 0x16, 0x12, 0x00, 0x83, 0x7b, 0x75, 0x64, 0x1c, 0xe3, 0xa8, 0x79, 0xd0, 0x31, 0xee, 0x9d, 0xf2, 0x76, 0x2c, 0x4b, 0x23, 0xeb, 0x7d, 0x2b, 0x95, 0x51, 0x23, 0x44, 0x87, 0x65, 0xbc, 0xb0, 0xe3, 0x21, 0x6b, 0xe6, 0x26, 0x2b, 0x24, 0x9f, 0xcc, 0xd5, 0x7d, 0x3c, 0x47, 0x97, 0xcc, 0x67, 0x00, 0xd0, 0xc8, 0x11, 0x05, 0x40, 0x80, 0xfe, 0x76, 0x79, 0xbf, 0xea, 0xb7, 0xd5, 0xf5, 0xdb, 0xd0, 0x5a, 0x84, 0xc3, 0x7d, 0x13, 0x13, 0x9d, 0x37, 0xe3, 0x14, 0xb8, 0xc5, 0xde, 0x4d, 0xd3, 0xc8, 0x05, 0x9c, 0x1e, 0x2a, 0x02, 0xde, 0x67, 0x80, 0xb2, 0x7d, 0x46, 0xa6, 0x28, 0xc4, 0x9f, 0xe7, 0xc4, 0x61, 0x1c, 0x7d, 0x37, 0xe8, 0x38, 0xd4, 0x67, 0x65, 0x0d, 0x78, 0x96, 0xbe, 0x44, 0x24, 0x2a, 0x4a, 0x51, 0xc3, 0xf5, 0xfc, 0x04, 0x05, 0x4b, 0x24, 0x70, 0x89, 0xc9, 0x15, 0xdd, 0xe7, 0xb7, 0xc7, 0x63, 0x25, 0x5d, 0x8f, 0x02, 0x31, 0xc1, 0xaf, 0xee, 0x19, 0xbe, 0x3f, 0x3a, 0x11, 0x28, 0x8a, 0x84, 0x13, 0x85, 0x16, 0x12, 0x98, 0xb9, 0x28, 0x99, 0xf1, 0xb8, 0x3b, 0xa3, 0xb4, 0x63, 0x94, 0x61, 0x62, 0x01, 0x44, 0x39, 0xa1, 0xbc, 0xe1, 0x62, 0x15, 0xe0, 0x9d, 0xb2, 0x28, 0x1b, 0xc4, 0x2a, 0x10, 0xe5, 0x84, 0xf2, 0x86, 0xfb, 0x7f, 0x57, 0x60, 0xe2, 0xe9, 0xe3, 0xf5, 0x86, 0xfc, 0x0b, 0x02, 0xf9, 0x81, 0x03, 0x07, 0x4e, 0x9f, 0x3e, 0xcd, 0x3b, 0xb1, 0xe1, 0x1b, 0x08, 0xbb, 0xc6, 0x7b, 0x7b, 0x7b, 0x13, 0x12, 0x12, 0xc8, 0x2e, 0xd3, 0xa7, 0x4f, 0x0f, 0x05, 0x72, 0xfb, 0xf6, 0x6d, 0xe8, 0x64, 0x66, 0x66, 0x86, 0x52, 0xe0, 0xe0, 0xbb, 0xdd, 0xee, 0xf6, 0xf6, 0xf6, 0xc1, 0xc1, 0x41, 0x0e, 0x1d, 0x88, 0x04, 0xb6, 0x90, 0x4e, 0xa7, 0x9b, 0x3f, 0x7f, 0x7e, 0x6a, 0xea, 0xe4, 0x6f, 0x66, 0x87, 0xc3, 0x11, 0x2a, 0x5f, 0x72, 0xb9, 0x5c, 0xa1, 0x50, 0xa4, 0xa5, 0xa5, 0x85, 0x52, 0xe0, 0xe0, 0x9f, 0x3b, 0x77, 0x6e, 0xf5, 0xea, 0xd5, 0xe5, 0xe5, 0xe5, 0x1c, 0x3a, 0x93, 0x22, 0xee, 0xf8, 0xb8, 0xa5, 0x57, 0xae, 0x5c, 0x01, 0x82, 0x4c, 0x26, 0xe3, 0x50, 0x43, 0x22, 0x39, 0xa4, 0xb4, 0xc8, 0xe3, 0xf1, 0xd0, 0xcb, 0x93, 0x27, 0x4f, 0x02, 0x3c, 0x2f, 0x2f, 0x8f, 0x66, 0x06, 0xd2, 0x41, 0x2a, 0xb0, 0x77, 0xef, 0xde, 0x65, 0xcb, 0x96, 0xad, 0x5d, 0xbb, 0xb6, 0xb3, 0xb3, 0x73, 0xf9, 0xf2, 0xe5, 0x6a, 0xb5, 0x7a, 0xc9, 0x92, 0x25, 0x35, 0x35, 0x35, 0x1c, 0xbd, 0x8e, 0x9d, 0x02, 0x9f, 0xcd, 0x9b, 0x37, 0x03, 0x67, 0xc5, 0x8a, 0x15, 0x2b, 0x57, 0xae, 0xb4, 0x58, 0x2c, 0x2c, 0x85, 0xb3, 0x67, 0xcf, 0x6e, 0xd9, 0xb2, 0x25, 0x39, 0x39, 0x19, 0xf8, 0xf0, 0x32, 0x37, 0x37, 0x77, 0xd3, 0xa6, 0x4d, 0x8c, 0xce, 0xcd, 0x9b, 0x37, 0x6f, 0xdd, 0xba, 0x85, 0xa5, 0xcd, 0x66, 0xfb, 0xf5, 0xe9, 0x03, 0x67, 0x70, 0xa2, 0x18, 0x05, 0x3f, 0x11, 0x18, 0x93, 0xc1, 0x60, 0x20, 0x62, 0x8d, 0x66, 0xca, 0xfb, 0xa9, 0xd2, 0xd2, 0x52, 0x96, 0x32, 0x47, 0x05, 0xb0, 0xb1, 0x54, 0xea, 0xff, 0xb3, 0xd1, 0xd7, 0xd7, 0x47, 0xdb, 0xb6, 0xb6, 0xb6, 0x92, 0x2d, 0xd6, 0xad, 0x5b, 0x57, 0x58, 0x58, 0x88, 0xb7, 0x29, 0x58, 0x2e, 0x58, 0xb0, 0x80, 0xe8, 0x74, 0x75, 0x75, 0xf9, 0xfd, 0xa3, 0xa8, 0x7d, 0xfb, 0xf6, 0xd1, 0x20, 0x84, 0x0e, 0xd2, 0x42, 0xf7, 0xee, 0xdd, 0x43, 0x62, 0x60, 0x18, 0x1f, 0x1f, 0x5f, 0x5f, 0x5f, 0x7f, 0xfd, 0xfa, 0xf5, 0xe2, 0xe2, 0x62, 0x82, 0x83, 0x8d, 0x69, 0x08, 0x8e, 0x00, 0xa0, 0x76, 0xe3, 0xc6, 0x8d, 0xe6, 0xe6, 0x66, 0x62, 0xc8, 0x0a, 0x60, 0xe7, 0xce, 0x9d, 0xe0, 0x2f, 0x5a, 0xb4, 0x88, 0xa0, 0x41, 0x5a, 0x56, 0x56, 0x86, 0x82, 0x90, 0xa5, 0xd9, 0x6c, 0xce, 0xcf, 0xcf, 0x27, 0x3e, 0xe0, 0x08, 0xcd, 0x7b, 0xfa, 0x2c, 0x5d, 0xba, 0x14, 0xa7, 0x82, 0x28, 0xd0, 0xdf, 0x41, 0x02, 0x80, 0x18, 0x73, 0x03, 0x1b, 0x6c, 0xdb, 0xb6, 0x8d, 0xa8, 0x0e, 0x0d, 0x0d, 0x49, 0x24, 0x93, 0xaf, 0x1b, 0x76, 0xef, 0xde, 0x4d, 0x1b, 0x73, 0x07, 0x00, 0x4d, 0xa7, 0xf3, 0xd9, 0x2b, 0x30, 0x56, 0x00, 0x2d, 0x2d, 0x2d, 0x24, 0x30, 0x74, 0x4e, 0x65, 0x65, 0xe5, 0xf1, 0xe3, 0xc7, 0x91, 0x35, 0x1a, 0x19, 0xb4, 0xf0, 0x33, 0x40, 0xa0, 0xf1, 0xbd, 0x6a, 0xd5, 0x2a, 0x42, 0x27, 0x26, 0x26, 0x22, 0x5b, 0xa0, 0x07, 0x06, 0x06, 0x18, 0x69, 0x24, 0x44, 0x51, 0x51, 0x11, 0x0e, 0x06, 0x10, 0x50, 0xde, 0xc3, 0x87, 0x0f, 0x23, 0xfd, 0x59, 0x59, 0x59, 0xdb, 0xb7, 0x6f, 0x17, 0x80, 0x19, 0xe4, 0x10, 0x33, 0x28, 0x17, 0x2e, 0x5c, 0x20, 0xf4, 0xf0, 0xf0, 0x70, 0x4f, 0x4f, 0x0f, 0x68, 0xe6, 0x78, 0x30, 0x3a, 0xc2, 0x08, 0x1c, 0x0f, 0xf4, 0x43, 0x77, 0x77, 0xf7, 0xae, 0x5d, 0xbb, 0x0a, 0x0a, 0x0a, 0xc8, 0x1c, 0xab, 0xab, 0xab, 0x43, 0xa1, 0x18, 0x40, 0xb1, 0x78, 0xd2, 0x37, 0xbb, 0xdd, 0xce, 0x70, 0x82, 0x13, 0xac, 0xc2, 0x91, 0x25, 0x69, 0xa1, 0xa4, 0xa4, 0xa4, 0xa6, 0xa6, 0x26, 0x14, 0xb7, 0xa4, 0xa4, 0x84, 0x18, 0x9f, 0x3f, 0x7f, 0x9e, 0xd1, 0xc7, 0x7c, 0xbc, 0x7c, 0xf9, 0x32, 0xf8, 0xd8, 0x1e, 0x34, 0x46, 0x04, 0x23, 0x22, 0x04, 0x38, 0x38, 0xca, 0xc4, 0x10, 0x17, 0x1f, 0x3d, 0x4f, 0xf7, 0xef, 0xdf, 0x0f, 0xf0, 0x8e, 0x8e, 0x0e, 0xa2, 0x69, 0x34, 0x1a, 0x95, 0xca, 0xc9, 0xf7, 0x59, 0xc7, 0x8e, 0x1d, 0x63, 0x40, 0xce, 0x9c, 0x39, 0x03, 0x0e, 0x5a, 0x17, 0x0e, 0x8c, 0x8d, 0x8d, 0xb5, 0xb5, 0xb5, 0xa1, 0xa5, 0xd1, 0x57, 0x8c, 0x02, 0x21, 0xb8, 0xce, 0x00, 0xd9, 0x9b, 0xf9, 0xc6, 0x58, 0x24, 0x36, 0x56, 0xab, 0x35, 0xe8, 0xdd, 0x84, 0xc9, 0xcb, 0xa0, 0x63, 0x32, 0x32, 0x86, 0x0c, 0x91, 0x9d, 0x9d, 0xed, 0x72, 0xb9, 0xa0, 0x53, 0x51, 0x51, 0x01, 0x26, 0x0e, 0xe8, 0x8e, 0x1d, 0x3b, 0x1a, 0x1b, 0x1b, 0xab, 0xab, 0xab, 0xb1, 0x44, 0xca, 0xd1, 0x51, 0x0c, 0x02, 0xb9, 0xc5, 0x09, 0x5f, 0xa5, 0x52, 0x11, 0x10, 0x7a, 0x0b, 0xa2, 0xc9, 0x15, 0xc0, 0x9e, 0x3d, 0x7b, 0x30, 0x0d, 0x52, 0x52, 0x52, 0x70, 0x1b, 0x1c, 0x3c, 0x78, 0x10, 0xf7, 0x00, 0xb1, 0x41, 0x00, 0x19, 0x19, 0x19, 0x04, 0x91, 0xfe, 0xc6, 0x4c, 0x64, 0xb6, 0xc7, 0x0d, 0x40, 0x8b, 0x08, 0x9d, 0x93, 0x93, 0x83, 0x5c, 0x42, 0x07, 0xc8, 0x18, 0x9d, 0xf4, 0x98, 0x46, 0x41, 0x1a, 0x1a, 0x1a, 0x18, 0x73, 0x42, 0xd4, 0xd6, 0xd6, 0xe2, 0xca, 0x87, 0x2d, 0x62, 0xc3, 0x90, 0xc5, 0xad, 0x6c, 0x32, 0x99, 0x58, 0x3a, 0x5c, 0x01, 0x5c, 0xbc, 0x78, 0x91, 0xa5, 0x1d, 0xad, 0x25, 0x5a, 0x0b, 0x4d, 0x85, 0x1e, 0xbb, 0x73, 0xe7, 0xce, 0xa5, 0x4b, 0x97, 0xf0, 0x4d, 0x2a, 0x13, 0x88, 0x8f, 0xac, 0xf5, 0xf7, 0xf7, 0x23, 0x65, 0x81, 0x22, 0xc2, 0x61, 0x07, 0x80, 0x2b, 0x13, 0x8d, 0x88, 0xb1, 0x83, 0xb8, 0xab, 0xaa, 0xaa, 0x4e, 0x9c, 0x38, 0xc1, 0x61, 0x1c, 0x0a, 0xf4, 0x65, 0xf2, 0xd9, 0x01, 0xe0, 0xe6, 0x62, 0x95, 0x3e, 0xf0, 0xdc, 0xbc, 0x4c, 0xff, 0x9e, 0xbb, 0x97, 0xff, 0xb6, 0x27, 0x7e, 0x63, 0x42, 0xe3, 0xd7, 0x25, 0x33, 0x3d, 0xf4, 0x7a, 0xfd, 0xc6, 0x8d, 0x1b, 0x59, 0x21, 0xfd, 0xa7, 0x96, 0xb1, 0x37, 0x73, 0xaf, 0xba, 0x1c, 0x5c, 0x37, 0xf1, 0xab, 0xf6, 0x2d, 0xac, 0xfd, 0x63, 0x01, 0x84, 0x95, 0xa6, 0x17, 0xa8, 0x14, 0xab, 0xc0, 0x0b, 0x4c, 0x6e, 0x58, 0xd0, 0xb1, 0x0a, 0x84, 0x95, 0xa6, 0x17, 0xa8, 0xf4, 0x0f, 0x7b, 0x3c, 0x70, 0xd0, 0xa5, 0xfc, 0x34, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXTextIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x38, 0x33, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xd4, 0x6c, 0xf8, 0x31, 0x00, 0x00, 0x05, 0x4f, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x59, 0x5b, 0x2c, 0x6c, 0x57, 0x18, 0x9e, 0x61, 0xce, 0x5c, 0x5c, 0xe2, 0x5a, 0xd7, 0x10, 0x97, 0x53, 0xd7, 0xba, 0x3d, 0xd0, 0x3e, 0x20, 0x2a, 0x82, 0x88, 0x22, 0x1e, 0x08, 0xaa, 0x24, 0x08, 0x21, 0x12, 0x11, 0x91, 0xf4, 0xa9, 0x69, 0x1a, 0xf5, 0x26, 0x22, 0xc1, 0x83, 0x04, 0x91, 0xa6, 0x09, 0x5e, 0x2a, 0x8d, 0x34, 0x91, 0xa0, 0xe1, 0xd4, 0x83, 0x07, 0xd2, 0x70, 0x8a, 0xe8, 0x11, 0xe2, 0x1a, 0x8a, 0xc1, 0x30, 0x86, 0x41, 0xbf, 0xb1, 0xcc, 0xea, 0x9c, 0x33, 0xec, 0xd9, 0x33, 0xb3, 0x9c, 0x46, 0xb2, 0x57, 0x64, 0xe7, 0x5f, 0xff, 0xff, 0xfd, 0xf7, 0xb5, 0xd6, 0xac, 0xbd, 0x89, 0xef, 0xee, 0xee, 0x44, 0x2f, 0x79, 0xd8, 0xbc, 0xe4, 0xe0, 0x75, 0xb1, 0x0b, 0x09, 0xfc, 0xdf, 0x1d, 0x14, 0x3a, 0x20, 0x74, 0xc0, 0xca, 0x0a, 0x08, 0x4b, 0xc8, 0xca, 0x02, 0x5a, 0xad, 0x2e, 0x74, 0xc0, 0xea, 0x12, 0x5a, 0x69, 0x40, 0xe8, 0x80, 0x95, 0x05, 0xb4, 0x5a, 0x5d, 0x62, 0xb5, 0x05, 0x9d, 0x01, 0xad, 0xe8, 0x6e, 0x4a, 0xa5, 0x7c, 0xa7, 0x51, 0xdf, 0x9a, 0xba, 0x1a, 0xda, 0x88, 0xc5, 0xaf, 0x65, 0x8a, 0x24, 0x07, 0x67, 0x89, 0x48, 0xcc, 0xc4, 0x35, 0x9b, 0x04, 0x7e, 0x3d, 0xf9, 0x27, 0xff, 0xdd, 0x9f, 0xfc, 0x03, 0xfa, 0x25, 0x38, 0x26, 0xd7, 0xe9, 0x13, 0xfe, 0x78, 0x0e, 0x24, 0x9b, 0x3d, 0xb0, 0xae, 0x51, 0x73, 0xf8, 0x30, 0x16, 0xad, 0x99, 0x89, 0x37, 0xb6, 0x40, 0x39, 0x6c, 0x3a, 0x70, 0x7e, 0x7b, 0x43, 0x2c, 0xba, 0x49, 0xa4, 0x9e, 0xaf, 0xa4, 0xa0, 0x8f, 0xb5, 0xd7, 0xbb, 0xd7, 0x1a, 0xc2, 0xf4, 0x91, 0xca, 0x9c, 0x6d, 0x5f, 0x81, 0xde, 0xbb, 0xd6, 0x1c, 0x69, 0xaf, 0x41, 0x5c, 0xdc, 0xde, 0x12, 0x91, 0xf5, 0x4f, 0x36, 0x1d, 0x50, 0xeb, 0x03, 0xaa, 0x76, 0xf7, 0x7d, 0x1b, 0xfe, 0x05, 0xfe, 0xbe, 0xf7, 0x09, 0xa6, 0xc1, 0xfd, 0xe0, 0x1d, 0x4c, 0x98, 0x95, 0xee, 0xbe, 0x84, 0xa9, 0xbe, 0x7b, 0x48, 0x98, 0x62, 0x2c, 0x26, 0x18, 0x25, 0x70, 0xf7, 0x50, 0x51, 0x99, 0x0d, 0x97, 0x41, 0xb9, 0xf8, 0x41, 0x7a, 0xa9, 0x4f, 0xd8, 0xe2, 0xb8, 0xa9, 0x22, 0x97, 0x3f, 0x0a, 0x32, 0x49, 0xa8, 0xf5, 0x4b, 0x88, 0x86, 0xf8, 0xa8, 0x8a, 0x42, 0x9f, 0x1e, 0xed, 0xd8, 0xa3, 0x30, 0xb3, 0x98, 0x6c, 0x12, 0x08, 0x95, 0xdb, 0x13, 0xaf, 0x81, 0x32, 0x05, 0x87, 0xfb, 0x68, 0x85, 0x23, 0x91, 0x86, 0xc8, 0xed, 0x38, 0x60, 0x66, 0x89, 0xd8, 0x6c, 0xe2, 0x6f, 0x5c, 0xbd, 0x4f, 0x6e, 0xb4, 0x38, 0xda, 0xbf, 0x72, 0x72, 0xe7, 0x70, 0xff, 0xa5, 0xa3, 0xcb, 0x8f, 0xbe, 0xaf, 0x51, 0xfe, 0xaf, 0x5d, 0xbd, 0x38, 0x60, 0x66, 0x89, 0xd8, 0x24, 0xe0, 0x6a, 0x2b, 0xf9, 0xce, 0x2b, 0xd0, 0xa4, 0x63, 0x85, 0xd8, 0xe6, 0x5b, 0xcf, 0x00, 0x93, 0x30, 0xb3, 0x00, 0x6c, 0x96, 0x90, 0x59, 0x2e, 0xd9, 0x82, 0x85, 0x04, 0xd8, 0xd6, 0xd3, 0x7c, 0x6b, 0x2f, 0xbe, 0x03, 0x6c, 0x36, 0x31, 0x2d, 0xdc, 0xd1, 0x8d, 0xf6, 0xaf, 0x4b, 0x15, 0xa6, 0x7f, 0x6b, 0x2e, 0x28, 0x73, 0x55, 0x73, 0xf1, 0xe6, 0x5c, 0x29, 0x16, 0x89, 0xc3, 0xe5, 0xf6, 0xd8, 0xee, 0x94, 0xcf, 0x84, 0x10, 0x33, 0xfc, 0x36, 0xfa, 0xf3, 0xf1, 0x5e, 0xe9, 0xfa, 0x5b, 0x8e, 0x1b, 0x35, 0xee, 0xd2, 0x3f, 0x05, 0x7c, 0x56, 0xe4, 0xe2, 0xc9, 0x24, 0x74, 0x62, 0x84, 0xe5, 0x12, 0xfa, 0x43, 0x75, 0xc2, 0x11, 0x3d, 0xfc, 0x41, 0xfa, 0x46, 0xa5, 0x64, 0x18, 0x3d, 0x4c, 0xb1, 0x4c, 0xa0, 0xc4, 0xd5, 0x2b, 0x4a, 0xe1, 0xc0, 0x11, 0x1f, 0xa4, 0xc0, 0x70, 0x00, 0x2c, 0x10, 0xb1, 0x5c, 0x42, 0x16, 0xb8, 0xb7, 0x5e, 0x85, 0x65, 0x07, 0xac, 0x8f, 0xc6, 0x02, 0x0b, 0x42, 0x02, 0x16, 0x14, 0x8d, 0xa9, 0x8a, 0xd0, 0x01, 0xa6, 0xe5, 0xb4, 0xc0, 0x98, 0xd0, 0x01, 0x0b, 0x8a, 0xc6, 0x54, 0x85, 0x6f, 0x07, 0xb4, 0x5a, 0xed, 0xe4, 0xe4, 0xe4, 0xee, 0xee, 0x2e, 0x53, 0xef, 0xef, 0x19, 0xdb, 0xd8, 0xd8, 0x98, 0x9a, 0x9a, 0x32, 0xfb, 0x6a, 0x03, 0x05, 0x3e, 0x63, 0x74, 0x74, 0x14, 0xde, 0xb2, 0xb2, 0xb2, 0xf8, 0x80, 0x2d, 0xc3, 0xc4, 0xc7, 0xc7, 0xc3, 0xc5, 0xec, 0xec, 0xac, 0x59, 0xea, 0x7c, 0x3b, 0x70, 0x70, 0x70, 0x00, 0xeb, 0xe4, 0xf9, 0x5e, 0xdd, 0xd8, 0x4d, 0x2c, 0x73, 0xc1, 0x2b, 0x81, 0xa5, 0xa5, 0xa5, 0xe5, 0xe5, 0x65, 0x84, 0x7a, 0x76, 0x76, 0xf6, 0xfb, 0xfd, 0x40, 0x9d, 0xb0, 0xa8, 0x0c, 0x83, 0x3f, 0x3d, 0x3d, 0x6d, 0x6c, 0x6c, 0x8c, 0x89, 0x89, 0x71, 0x70, 0x70, 0x88, 0x8c, 0x8c, 0x6c, 0x6e, 0x6e, 0x3e, 0x3f, 0x3f, 0xa7, 0x80, 0xfa, 0xfa, 0xfa, 0xcf, 0xef, 0x47, 0x45, 0x45, 0x05, 0x0a, 0x5c, 0x54, 0x54, 0x84, 0x59, 0x62, 0x62, 0xe2, 0xe0, 0xe0, 0x20, 0x30, 0x2a, 0x95, 0x6a, 0x7a, 0x7a, 0xfa, 0xf2, 0xf2, 0x12, 0xf4, 0xc2, 0xc2, 0x02, 0x71, 0xb1, 0xb3, 0xb3, 0x43, 0xd5, 0xb9, 0x08, 0x93, 0xfd, 0x9a, 0x9b, 0x9b, 0x7b, 0x54, 0xbf, 0xa5, 0xa5, 0x85, 0xea, 0x62, 0x6f, 0xf8, 0xf9, 0xf9, 0x11, 0x98, 0x9b, 0x9b, 0x1b, 0x21, 0x22, 0x22, 0x22, 0x90, 0x03, 0x30, 0x48, 0xd5, 0xde, 0xfe, 0xe1, 0xbb, 0x8b, 0x4c, 0x26, 0x53, 0x2a, 0x95, 0x36, 0xfa, 0x0f, 0x44, 0x25, 0x25, 0x25, 0x00, 0xe4, 0xe4, 0xe4, 0x18, 0xbb, 0xb0, 0xb3, 0xb3, 0xbb, 0xba, 0xba, 0xa2, 0x2e, 0x9e, 0x22, 0x44, 0x4f, 0x09, 0x28, 0x7f, 0x7f, 0x7f, 0x3f, 0x29, 0x29, 0xc9, 0xd3, 0x53, 0x77, 0x89, 0x87, 0xfb, 0x4f, 0xef, 0x47, 0x6c, 0x6c, 0xec, 0xd8, 0xd8, 0x18, 0xc5, 0xe4, 0xe5, 0xe5, 0x41, 0x9a, 0x96, 0x96, 0xb6, 0xb5, 0xb5, 0x05, 0xe6, 0xfc, 0xfc, 0xbc, 0xaf, 0xaf, 0xee, 0x2b, 0x62, 0x53, 0x53, 0x13, 0xc1, 0xa0, 0x81, 0x65, 0x65, 0x65, 0xe0, 0x24, 0x24, 0x24, 0x1c, 0x1f, 0x1f, 0x87, 0x87, 0x87, 0x4b, 0xa5, 0xd2, 0xde, 0xde, 0xde, 0xa3, 0xa3, 0x23, 0x00, 0x3a, 0x3a, 0x3a, 0xc2, 0xc2, 0xc2, 0x24, 0x12, 0xdd, 0xbb, 0x8e, 0x8f, 0x8f, 0x0f, 0x71, 0x51, 0x58, 0x58, 0x48, 0xed, 0x73, 0x10, 0xa6, 0x13, 0x20, 0xca, 0xfd, 0xfd, 0xfd, 0xb0, 0x8e, 0x7d, 0x66, 0x6c, 0x4b, 0xad, 0x56, 0xdb, 0xda, 0xda, 0x42, 0xda, 0xde, 0xde, 0xfe, 0x9b, 0x7e, 0x60, 0xa9, 0x80, 0x13, 0x1d, 0x1d, 0x4d, 0xf1, 0xe8, 0x43, 0x66, 0x66, 0x26, 0x98, 0x5e, 0x5e, 0xba, 0x1b, 0x75, 0x5f, 0x5f, 0x1f, 0x15, 0x11, 0x22, 0x20, 0x20, 0x00, 0x7c, 0x9c, 0x16, 0x1f, 0xf0, 0xb9, 0xa7, 0x0c, 0x5e, 0xf0, 0x56, 0x57, 0x57, 0x6f, 0x6e, 0x74, 0x1f, 0x6b, 0x1b, 0x1a, 0x1a, 0xf0, 0x34, 0x1c, 0x17, 0x17, 0xff, 0xbd, 0x58, 0x22, 0xc9, 0xa1, 0xa1, 0xa1, 0xc0, 0xc0, 0xc0, 0xbd, 0xbd, 0xbd, 0x94, 0x94, 0x94, 0xf2, 0xf2, 0x72, 0x43, 0xa4, 0xc5, 0x34, 0xdf, 0x04, 0xc8, 0xaa, 0xc5, 0x6e, 0x33, 0xf6, 0x84, 0xa6, 0x13, 0x66, 0x4f, 0x4f, 0x4f, 0x54, 0x54, 0x14, 0x05, 0x20, 0xe2, 0x90, 0x90, 0x10, 0x3a, 0x05, 0xd1, 0xd6, 0xd6, 0x76, 0x78, 0x78, 0x28, 0x97, 0xcb, 0xb1, 0x4d, 0x3b, 0x3b, 0x3b, 0xeb, 0xea, 0xea, 0x0c, 0xa5, 0x1c, 0x2e, 0x0c, 0x61, 0x1f, 0xd2, 0xdc, 0x0d, 0xa2, 0xd2, 0x91, 0x91, 0x11, 0x68, 0x22, 0xa6, 0xb5, 0xb5, 0x35, 0x1c, 0x17, 0xe3, 0xe3, 0xe3, 0xb5, 0xb5, 0xb5, 0x58, 0x57, 0x04, 0x10, 0x1a, 0x1a, 0x0a, 0x69, 0x7a, 0x7a, 0x3a, 0xd9, 0xb5, 0x60, 0x2e, 0x2e, 0x2e, 0x56, 0x57, 0x57, 0xb7, 0xb6, 0xb6, 0x52, 0x0b, 0xdd, 0xdd, 0xdd, 0xc0, 0xe0, 0xe4, 0x81, 0xc8, 0xd9, 0xd9, 0x19, 0xe1, 0x0e, 0x0f, 0x0f, 0x53, 0x29, 0x88, 0xb8, 0xb8, 0x38, 0x00, 0xaa, 0xaa, 0xaa, 0xb0, 0xd8, 0xd6, 0xd7, 0xd7, 0xbb, 0xba, 0xba, 0x4a, 0x4b, 0x4b, 0x91, 0xb0, 0x21, 0xc6, 0x98, 0xe6, 0xbb, 0x07, 0x56, 0x56, 0x56, 0x60, 0x1d, 0x03, 0x8e, 0x15, 0x8a, 0x87, 0x2f, 0xb8, 0x88, 0x98, 0x58, 0xc4, 0x8f, 0xb4, 0x58, 0xac, 0xfb, 0x9f, 0x17, 0x44, 0xa9, 0xa9, 0xa9, 0x64, 0x07, 0x63, 0x5a, 0x50, 0x50, 0x40, 0x00, 0xd8, 0xdf, 0x3a, 0x65, 0x91, 0x28, 0x3f, 0x3f, 0x1f, 0x9b, 0xd8, 0xdb, 0xdb, 0x9b, 0x4c, 0x33, 0x32, 0x32, 0x68, 0x4c, 0xc5, 0xc5, 0xc5, 0x84, 0x49, 0x8f, 0x2c, 0x4c, 0x67, 0x66, 0x66, 0x28, 0xe0, 0x51, 0x82, 0x6f, 0x02, 0x50, 0xc6, 0x59, 0xe1, 0xe8, 0xa8, 0xfb, 0xbc, 0x8c, 0x1c, 0x70, 0x68, 0x54, 0x56, 0x56, 0x6e, 0x6f, 0x6f, 0x53, 0xa3, 0x13, 0x13, 0x13, 0x38, 0x9a, 0x48, 0x04, 0x00, 0xe0, 0x9c, 0xa9, 0xa9, 0xa9, 0x21, 0x87, 0x0c, 0x30, 0xf8, 0x09, 0x27, 0xa2, 0xdc, 0xdc, 0x5c, 0x24, 0xe0, 0xe1, 0xe1, 0x81, 0x29, 0x72, 0xce, 0xce, 0xce, 0xa6, 0x16, 0x50, 0xf5, 0xe4, 0xe4, 0x64, 0x02, 0x73, 0x72, 0x72, 0x42, 0x21, 0x06, 0x06, 0x06, 0xa8, 0xf4, 0x29, 0xc2, 0xbc, 0x77, 0x62, 0x58, 0xd9, 0xdc, 0xdc, 0x74, 0x71, 0x71, 0x21, 0x99, 0x10, 0x67, 0x86, 0x4f, 0xfc, 0x9c, 0xe1, 0x4a, 0x13, 0x14, 0x14, 0x64, 0x58, 0x45, 0x43, 0x80, 0x49, 0x1a, 0xdb, 0x0c, 0xcb, 0xc6, 0xdf, 0xdf, 0x9f, 0xb4, 0xd4, 0x24, 0xde, 0xbc, 0x04, 0x4c, 0x9a, 0xfb, 0xf8, 0x00, 0x5e, 0x57, 0x89, 0x8f, 0x1f, 0x16, 0x7f, 0x8f, 0x42, 0x02, 0xfc, 0x6b, 0xf5, 0x3c, 0x48, 0xa1, 0x03, 0xcf, 0x53, 0x57, 0xfe, 0x56, 0x85, 0x0e, 0xf0, 0xaf, 0xd5, 0xf3, 0x20, 0x85, 0x0e, 0x3c, 0x4f, 0x5d, 0xf9, 0x5b, 0x15, 0x3a, 0xc0, 0xbf, 0x56, 0xcf, 0x83, 0xfc, 0x17, 0xab, 0x70, 0xa9, 0x05, 0xf0, 0x5c, 0xd1, 0x77, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXVideoIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x37, 0x39, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xcc, 0x4b, 0x33, 0xb9, 0x00, 0x00, 0x09, 0x5f, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x59, 0x7b, 0x4c, 0x54, 0xd9, 0x19, 0x9f, 0x99, 0x7b, 0x67, 0x18, 0x9e, 0x83, 0xc0, 0xcc, 0x30, 0x83, 0x2c, 0xa2, 0x80, 0x3c, 0x15, 0x96, 0xe2, 0xae, 0x8f, 0xd4, 0xf5, 0x11, 0x13, 0xb7, 0xb6, 0x31, 0xa6, 0xd5, 0x08, 0x6a, 0xb4, 0xba, 0x3e, 0x6a, 0x1a, 0x13, 0x63, 0xac, 0x35, 0x21, 0x9a, 0xfe, 0x63, 0x62, 0x8d, 0xb1, 0x35, 0x46, 0x8d, 0xd1, 0xac, 0xa6, 0x35, 0xd1, 0xa6, 0x66, 0xdd, 0x9a, 0xad, 0x31, 0x0d, 0x6e, 0xa3, 0x8d, 0x6f, 0x08, 0x6f, 0x99, 0x05, 0x11, 0x81, 0x85, 0x79, 0xc0, 0xbc, 0x98, 0xc7, 0xbd, 0x33, 0xf7, 0x4e, 0x7f, 0x77, 0xce, 0xee, 0x75, 0x32, 0x28, 0x8f, 0x19, 0x08, 0x6b, 0x32, 0x07, 0xb8, 0x7c, 0xe7, 0x9c, 0xef, 0x3b, 0xe7, 0xfb, 0x7d, 0xdf, 0x77, 0xce, 0x77, 0xee, 0xb9, 0xd2, 0x40, 0x20, 0x20, 0xf9, 0x90, 0x8b, 0xec, 0x43, 0x56, 0x5e, 0xd0, 0x3d, 0x06, 0x60, 0xa6, 0x3d, 0x18, 0xf3, 0x40, 0xcc, 0x03, 0x51, 0x5a, 0x60, 0x86, 0x43, 0xe8, 0xd9, 0xb3, 0x67, 0x83, 0x83, 0x83, 0xd1, 0x60, 0x98, 0x19, 0x00, 0x0c, 0xc3, 0xb4, 0xb6, 0x77, 0x9d, 0xf9, 0xeb, 0xc5, 0x23, 0x7f, 0xfc, 0xc3, 0xed, 0xdb, 0x5f, 0x45, 0x03, 0x80, 0x8e, 0x46, 0x78, 0xb2, 0xb2, 0x83, 0x83, 0x16, 0xe3, 0x90, 0xcd, 0x60, 0xe8, 0xf9, 0xde, 0x62, 0x4d, 0x4e, 0x4e, 0xee, 0x1d, 0xb4, 0xf5, 0xf5, 0x7e, 0xff, 0xe2, 0xc5, 0x8b, 0xc9, 0x8e, 0x13, 0xca, 0x1f, 0x15, 0x80, 0xbb, 0x77, 0xef, 0x32, 0x5e, 0x6f, 0x5c, 0x42, 0xb2, 0xcb, 0xed, 0x95, 0x4a, 0xa5, 0x18, 0x97, 0xa6, 0x69, 0xa5, 0x52, 0x91, 0x9c, 0x94, 0xa4, 0xce, 0x48, 0xcb, 0xd4, 0x6a, 0x92, 0x92, 0x92, 0xd0, 0xd8, 0xdf, 0x6f, 0x6c, 0x6c, 0xed, 0xec, 0x37, 0x59, 0x19, 0x2f, 0x23, 0x95, 0xd1, 0x1f, 0x65, 0xeb, 0xca, 0xb4, 0x6a, 0x9e, 0x93, 0x98, 0x4c, 0x96, 0x21, 0xab, 0xfd, 0xf1, 0xe3, 0xc7, 0x0e, 0x87, 0x23, 0x25, 0x25, 0x25, 0x54, 0xad, 0x89, 0xd3, 0x51, 0x01, 0x18, 0x1a, 0x1a, 0xea, 0xea, 0xfc, 0x4e, 0x9d, 0x53, 0x2e, 0x97, 0xcb, 0xe7, 0xcc, 0xce, 0xc0, 0xa1, 0x84, 0x65, 0x39, 0x37, 0xe3, 0xb3, 0xd8, 0x6c, 0xcd, 0x86, 0x01, 0x9b, 0xfd, 0x89, 0x67, 0xc4, 0xe9, 0xb0, 0x19, 0xfb, 0x8c, 0xb6, 0xb4, 0x0c, 0x5d, 0x41, 0x5e, 0xee, 0xec, 0xac, 0xcc, 0xa4, 0xe4, 0x44, 0xc0, 0x18, 0x30, 0x5a, 0xad, 0x56, 0x67, 0xf7, 0xeb, 0x3e, 0xa9, 0x4c, 0x3e, 0x38, 0x68, 0xec, 0xea, 0xea, 0xaa, 0xa8, 0xa8, 0x98, 0xb8, 0xd2, 0xa1, 0x9c, 0x51, 0x01, 0x50, 0x05, 0x8b, 0x5e, 0xa7, 0xcb, 0xc9, 0xd6, 0xe6, 0xe7, 0xea, 0x29, 0x19, 0xdc, 0x00, 0x3f, 0x08, 0x0f, 0x9e, 0x97, 0x70, 0x5c, 0x80, 0xf1, 0xb1, 0x76, 0xa7, 0xbb, 0x7f, 0xc0, 0xdc, 0xfa, 0xb2, 0xeb, 0xf5, 0xab, 0xae, 0xde, 0xbe, 0x3e, 0xf4, 0x26, 0x26, 0x26, 0x3b, 0x9c, 0xae, 0xef, 0xda, 0x5b, 0xf4, 0x9a, 0xa4, 0x3f, 0x1d, 0xaf, 0x8d, 0x53, 0x50, 0x5a, 0xad, 0x36, 0x54, 0xa7, 0x49, 0xd1, 0x51, 0x01, 0xa8, 0xab, 0xab, 0x63, 0x3d, 0x9e, 0xf8, 0xb4, 0x5c, 0x4d, 0xba, 0xca, 0x6e, 0x77, 0xd0, 0x32, 0x4a, 0x4a, 0x41, 0x7b, 0x19, 0x0d, 0x24, 0x40, 0x23, 0x91, 0xc4, 0xc9, 0xa9, 0xcc, 0x8c, 0x94, 0x2c, 0xad, 0x6a, 0x51, 0x79, 0x01, 0xc3, 0xfa, 0x7b, 0x7a, 0x07, 0x9a, 0x5a, 0x0d, 0xf7, 0x1f, 0xd4, 0x1b, 0xda, 0x1b, 0xaa, 0x7f, 0xfd, 0xf9, 0x6f, 0xb7, 0x57, 0xc3, 0x75, 0x93, 0x52, 0x77, 0x34, 0x73, 0x54, 0x00, 0x1a, 0x1a, 0x1a, 0x1c, 0x56, 0x2b, 0x9d, 0xf2, 0x51, 0x6e, 0x4e, 0xae, 0xd5, 0xee, 0xa2, 0x64, 0x28, 0xd0, 0x5f, 0x22, 0x10, 0xf8, 0x93, 0x0a, 0x0f, 0x50, 0x14, 0x25, 0x21, 0xf4, 0x6c, 0x9d, 0x7a, 0xb6, 0x5e, 0xf3, 0xf3, 0x25, 0x95, 0x4f, 0xea, 0x5f, 0xb6, 0xb7, 0xb5, 0x3e, 0x7b, 0xd1, 0xb4, 0xe4, 0xd3, 0xca, 0xd1, 0x3a, 0x4d, 0xaa, 0x25, 0x2a, 0x00, 0x1e, 0x8f, 0x47, 0x4a, 0xd1, 0x0c, 0xcb, 0xf5, 0xf4, 0x9b, 0x38, 0xde, 0x27, 0xa7, 0x69, 0xb9, 0x9c, 0xa2, 0x69, 0x4a, 0x4e, 0x09, 0x4f, 0xc1, 0x17, 0x14, 0x01, 0x22, 0x38, 0xe6, 0x47, 0x54, 0x52, 0x84, 0xd8, 0xa7, 0x1f, 0x17, 0x16, 0xe4, 0xcd, 0xfe, 0xe6, 0xde, 0xa3, 0xaf, 0xbf, 0xf9, 0x0f, 0xcd, 0x3b, 0xf7, 0xed, 0xdb, 0x97, 0x95, 0x95, 0x35, 0x29, 0xbd, 0x45, 0xe6, 0xa8, 0x00, 0x64, 0x66, 0x66, 0x42, 0x43, 0x9b, 0xd5, 0xf2, 0x8f, 0x7f, 0xfe, 0xab, 0xb4, 0xa4, 0x38, 0x0b, 0xb1, 0x92, 0x9c, 0xa8, 0x4a, 0x49, 0x50, 0x25, 0x27, 0xc4, 0xc7, 0x2b, 0x04, 0x00, 0xf8, 0x09, 0x16, 0xc1, 0x1d, 0x32, 0xf8, 0x41, 0x08, 0x2c, 0x50, 0x41, 0x5a, 0xb6, 0xf8, 0x93, 0x8a, 0x53, 0xa7, 0xeb, 0x92, 0x65, 0xce, 0xa6, 0xa6, 0xa6, 0x99, 0x01, 0x70, 0xf2, 0xe4, 0x49, 0xa4, 0xa4, 0x53, 0xa7, 0xff, 0xd2, 0xd3, 0xd1, 0xa8, 0xd5, 0xaa, 0x0b, 0x8b, 0xe7, 0x27, 0x26, 0xd0, 0x71, 0x71, 0x4a, 0xa8, 0xe8, 0xf7, 0x07, 0xa4, 0xd2, 0x80, 0xa0, 0x2e, 0x60, 0xc8, 0xa4, 0x3c, 0x4f, 0xd0, 0x70, 0xa8, 0x52, 0x94, 0x54, 0xc6, 0x07, 0x38, 0xce, 0xef, 0xf3, 0xb1, 0x0a, 0x05, 0x9d, 0xae, 0x4a, 0x17, 0x82, 0x2c, 0xd2, 0x12, 0x95, 0x07, 0x0a, 0x0a, 0x0a, 0x30, 0x6f, 0xda, 0xac, 0x59, 0x99, 0x5a, 0xb5, 0x32, 0x4e, 0x9e, 0xa8, 0xa4, 0x52, 0x92, 0xe2, 0x3b, 0x0d, 0x2f, 0x47, 0x1c, 0xc3, 0x89, 0x49, 0x49, 0x64, 0x3f, 0x12, 0x00, 0x08, 0x19, 0x22, 0xe8, 0x08, 0x81, 0x90, 0xb8, 0xdd, 0x6e, 0x8d, 0x36, 0xb3, 0xb0, 0xa8, 0x94, 0xe3, 0x78, 0xaf, 0xcb, 0x5b, 0xf7, 0xfc, 0xf1, 0x2f, 0xd6, 0xfd, 0x52, 0xe8, 0x88, 0xa8, 0x44, 0x05, 0x80, 0xcc, 0x18, 0x90, 0x04, 0x54, 0xaa, 0xd4, 0x00, 0xcf, 0xf9, 0x18, 0x6c, 0x9b, 0x72, 0x1f, 0xeb, 0x5b, 0xbe, 0x7c, 0x79, 0x5a, 0x5a, 0x3a, 0x72, 0x1c, 0xb4, 0x86, 0xe6, 0x34, 0x25, 0xc3, 0x53, 0x22, 0x81, 0x43, 0x64, 0xf1, 0x4a, 0x65, 0x6f, 0x7f, 0x7f, 0x73, 0x6b, 0x1b, 0x03, 0xfb, 0xe3, 0x97, 0xf5, 0x19, 0x4d, 0xc6, 0x68, 0x5e, 0x6b, 0xa7, 0x00, 0x00, 0x76, 0xcf, 0x0c, 0xb5, 0x9a, 0xe7, 0x39, 0xb7, 0x87, 0x89, 0x53, 0xca, 0x19, 0x96, 0x0d, 0x48, 0xa9, 0xcb, 0x97, 0x2e, 0x74, 0xb4, 0x37, 0x05, 0xfd, 0x20, 0xc5, 0x82, 0x86, 0xa2, 0x00, 0x33, 0x3c, 0x6c, 0x59, 0xf7, 0xab, 0xdf, 0xfc, 0x6c, 0xd1, 0x12, 0x96, 0xf5, 0xb3, 0x00, 0xcb, 0xf8, 0x59, 0x24, 0x0a, 0xbb, 0x23, 0x1a, 0x00, 0x53, 0x70, 0x98, 0xc3, 0x8e, 0xa3, 0xd5, 0x68, 0xfc, 0x7e, 0x0e, 0xeb, 0xc1, 0xeb, 0x15, 0xdc, 0xe0, 0x74, 0xba, 0xe5, 0x0a, 0x79, 0x4d, 0xcd, 0xe6, 0x3d, 0xbb, 0xbf, 0x58, 0xb7, 0xee, 0x73, 0x43, 0xc7, 0x4b, 0xb3, 0xd9, 0x58, 0x55, 0x55, 0x69, 0x36, 0x19, 0x5f, 0xf7, 0xf4, 0xb0, 0x1c, 0x0f, 0x3c, 0x5e, 0x2f, 0xcb, 0xb0, 0x3e, 0x9e, 0x27, 0x77, 0x0a, 0x91, 0x5f, 0x2c, 0x4c, 0x01, 0x00, 0xb9, 0x9c, 0xd6, 0x68, 0xb5, 0x7e, 0xbf, 0x1f, 0x1e, 0xf0, 0x7a, 0xa0, 0x16, 0xeb, 0x74, 0x8e, 0x28, 0xe4, 0xf2, 0xfc, 0xfc, 0xfc, 0xd2, 0x92, 0x12, 0xbd, 0x5e, 0xf7, 0xaa, 0xfb, 0xd5, 0x67, 0x9f, 0x2d, 0x37, 0x18, 0x0c, 0x26, 0x8b, 0xd9, 0xef, 0xe7, 0x3d, 0x6e, 0xaf, 0x00, 0x80, 0x65, 0xbd, 0x8c, 0x8f, 0xf7, 0x73, 0x11, 0x45, 0xfe, 0x5b, 0xa1, 0x29, 0x08, 0x21, 0x8a, 0xa6, 0x34, 0x6a, 0x35, 0xc7, 0x75, 0xc2, 0x01, 0x0c, 0x93, 0x80, 0xf0, 0xc0, 0xd9, 0xce, 0x64, 0xb6, 0x7c, 0xfb, 0x6d, 0x9d, 0x5e, 0x9f, 0xdd, 0xd2, 0xda, 0x1c, 0x17, 0x17, 0x67, 0xe8, 0x30, 0x48, 0xa4, 0x92, 0x8a, 0xf2, 0x72, 0x97, 0xdb, 0xed, 0x72, 0x7b, 0x58, 0x9f, 0x1f, 0xda, 0xc3, 0x09, 0x7e, 0xde, 0xff, 0x56, 0x97, 0x88, 0xa8, 0x29, 0x00, 0x40, 0x53, 0x74, 0x7a, 0x3a, 0xb6, 0xc2, 0x60, 0xfa, 0x52, 0x20, 0x97, 0xd1, 0xd0, 0xaf, 0xec, 0xe3, 0xa5, 0x76, 0xbb, 0xb5, 0xcf, 0xcc, 0xa4, 0xeb, 0x8a, 0x0e, 0xd7, 0xfe, 0x19, 0x51, 0x8e, 0x83, 0x2a, 0x96, 0xad, 0x5a, 0xa3, 0x19, 0x71, 0xb9, 0x20, 0x82, 0xbd, 0x15, 0x8d, 0x3c, 0xcf, 0xc3, 0x75, 0x08, 0xbf, 0x88, 0x94, 0x17, 0x84, 0xa6, 0x00, 0x00, 0x96, 0xaf, 0x5e, 0xa7, 0x4d, 0x49, 0x55, 0x69, 0x35, 0x50, 0x2f, 0xdd, 0xed, 0x1c, 0x52, 0xa9, 0x52, 0x32, 0x34, 0x6a, 0xa4, 0x01, 0x21, 0x7f, 0x61, 0xdf, 0xa7, 0x29, 0x09, 0x94, 0x0d, 0xf0, 0xd8, 0x8b, 0xc0, 0x3c, 0x64, 0x36, 0xa5, 0xce, 0x52, 0xcd, 0x52, 0xa5, 0x3a, 0xdd, 0x01, 0x5a, 0xae, 0x28, 0x2a, 0x2a, 0x8a, 0xf8, 0x2c, 0x1d, 0x2d, 0x00, 0x28, 0x85, 0xbd, 0x25, 0x5e, 0x19, 0xff, 0xdf, 0xff, 0x3d, 0xf1, 0x30, 0xfc, 0x90, 0xc3, 0x23, 0xa1, 0xdd, 0x43, 0x76, 0x37, 0x6d, 0xb4, 0x8f, 0xb0, 0x32, 0xf4, 0x06, 0x01, 0x08, 0x89, 0x80, 0xc7, 0x5e, 0x8b, 0xe5, 0x8a, 0x7f, 0x52, 0xc9, 0x88, 0xc3, 0x6e, 0x32, 0xdb, 0xe8, 0x04, 0x4b, 0x7b, 0x5b, 0xdb, 0xc1, 0xdf, 0x7f, 0xb1, 0x64, 0xd1, 0x02, 0x8d, 0x46, 0x13, 0xb1, 0x07, 0x04, 0x3f, 0x46, 0x26, 0xec, 0xf3, 0xf9, 0x90, 0x92, 0x46, 0x46, 0x46, 0xcc, 0x66, 0x4b, 0x43, 0x63, 0xd3, 0xc9, 0x93, 0xa7, 0xcc, 0x96, 0x21, 0xe4, 0x54, 0xa4, 0x58, 0xc1, 0xee, 0x38, 0x2d, 0x08, 0x23, 0x23, 0x0f, 0x08, 0xc3, 0x07, 0xa9, 0xe0, 0x3f, 0xa1, 0xc6, 0x23, 0x85, 0xc1, 0x1b, 0xc5, 0x85, 0x05, 0x7f, 0xff, 0xdb, 0x97, 0x19, 0x19, 0x6a, 0x9c, 0x49, 0x11, 0x60, 0x42, 0xcf, 0xe4, 0x4b, 0x84, 0x62, 0x64, 0x22, 0x44, 0x30, 0xc7, 0x71, 0x0a, 0x85, 0x1c, 0x47, 0xb3, 0xdf, 0xed, 0xdd, 0x69, 0x32, 0x99, 0x84, 0xa0, 0x41, 0xce, 0x22, 0x56, 0x79, 0x8f, 0x65, 0xd0, 0x8f, 0x13, 0x2a, 0xf8, 0xf2, 0xf2, 0xf3, 0x81, 0xd0, 0xeb, 0xf5, 0x46, 0xac, 0x3d, 0xd4, 0x88, 0xdc, 0x03, 0x10, 0x86, 0x9e, 0xc0, 0x80, 0x02, 0x02, 0x56, 0x14, 0x54, 0x9f, 0x64, 0x01, 0xfe, 0x1f, 0x30, 0x4f, 0x52, 0x50, 0x64, 0x8f, 0x0a, 0x80, 0x38, 0xca, 0x0c, 0x12, 0x53, 0x90, 0xc8, 0x66, 0x50, 0x7b, 0x4c, 0x1d, 0x03, 0x30, 0xb3, 0xf6, 0x8f, 0x79, 0x60, 0xa6, 0xed, 0x1f, 0xf3, 0xc0, 0x87, 0xec, 0x01, 0x9c, 0x21, 0x4f, 0x9f, 0x3e, 0x7d, 0xeb, 0xd6, 0xad, 0xb1, 0x41, 0x20, 0xcd, 0x05, 0xcf, 0x9b, 0xd1, 0x1e, 0x9b, 0xdf, 0x3b, 0x0b, 0x92, 0x68, 0x64, 0xa5, 0xa3, 0xa3, 0x03, 0x83, 0xce, 0x9d, 0x3b, 0x77, 0x0c, 0xf1, 0xa3, 0x47, 0x8f, 0x8a, 0x37, 0x0e, 0xb8, 0xfc, 0x19, 0x83, 0x33, 0xe2, 0xae, 0xc8, 0xf3, 0x80, 0x42, 0xa1, 0xc0, 0x9b, 0xca, 0xd8, 0xf7, 0x39, 0x39, 0x39, 0x39, 0xf3, 0xe6, 0xcd, 0x4b, 0x4b, 0x4b, 0x03, 0x54, 0x5c, 0x41, 0xbf, 0xd7, 0x8a, 0xd1, 0x74, 0x44, 0x0c, 0x1d, 0x82, 0x38, 0x90, 0x4e, 0x44, 0x1c, 0x91, 0x06, 0x0d, 0xb7, 0x6c, 0xd9, 0x32, 0x11, 0xe6, 0xc9, 0xf2, 0x84, 0x7b, 0xe0, 0xc8, 0x91, 0x23, 0x9f, 0x04, 0xcb, 0x9a, 0x35, 0x6b, 0xda, 0xda, 0xda, 0x9e, 0x3f, 0x7f, 0xbe, 0x6a, 0xd5, 0x2a, 0x34, 0x2c, 0x5d, 0xba, 0xf4, 0xda, 0xb5, 0x6b, 0xa2, 0xa5, 0xb6, 0x6d, 0xdb, 0x46, 0x1a, 0x97, 0x2d, 0x5b, 0x66, 0xb3, 0xd9, 0xc4, 0x76, 0x91, 0xb8, 0x71, 0xe3, 0xc6, 0xd6, 0xad, 0x5b, 0x31, 0xc8, 0xf1, 0xe3, 0xc7, 0x47, 0xdb, 0x1e, 0x2d, 0x07, 0x0f, 0x1e, 0x5c, 0xb8, 0x70, 0x21, 0x3e, 0x20, 0x94, 0x94, 0x94, 0x1c, 0x3e, 0x7c, 0xd8, 0xe5, 0x72, 0x89, 0xb2, 0x20, 0xfa, 0xfb, 0xfb, 0x77, 0xec, 0xd8, 0x51, 0x58, 0x58, 0x08, 0x86, 0xf2, 0xf2, 0xf2, 0xd1, 0x0c, 0x6f, 0x99, 0xc3, 0x10, 0xeb, 0x74, 0x3a, 0xb1, 0xef, 0xea, 0xd5, 0xab, 0x67, 0xcf, 0x9e, 0x15, 0xab, 0x1b, 0x36, 0x6c, 0x20, 0xcc, 0x4e, 0xa7, 0x33, 0xf4, 0x00, 0xdc, 0xdd, 0xdd, 0x1d, 0x36, 0xc8, 0xae, 0x5d, 0xbb, 0x44, 0x29, 0x10, 0xe4, 0x94, 0x2a, 0x7a, 0x60, 0x60, 0x60, 0x20, 0x3b, 0x3b, 0x9b, 0x30, 0xe0, 0x5d, 0x94, 0x10, 0xc5, 0xc5, 0xc5, 0xc0, 0x40, 0xc6, 0xc1, 0x37, 0x9b, 0xd1, 0xef, 0x68, 0xb9, 0xb9, 0xb9, 0x16, 0x8b, 0x25, 0x6c, 0x22, 0x54, 0x85, 0x23, 0x71, 0x68, 0xe9, 0xec, 0xec, 0x2c, 0x2d, 0x2d, 0xc5, 0xa0, 0xbb, 0x77, 0xef, 0x46, 0x84, 0xe0, 0xa6, 0x64, 0xf3, 0xe6, 0xcd, 0xa8, 0x6e, 0xda, 0xb4, 0x29, 0x54, 0xbe, 0xb9, 0xb9, 0x19, 0x36, 0x26, 0x73, 0x87, 0x01, 0xb8, 0x7d, 0xfb, 0x36, 0x69, 0x87, 0x73, 0xae, 0x5c, 0xb9, 0xb2, 0x62, 0xc5, 0x0a, 0x52, 0xad, 0xa9, 0xa9, 0x21, 0x13, 0xad, 0x5f, 0xbf, 0x1e, 0x2d, 0xab, 0x57, 0xaf, 0xee, 0xeb, 0xeb, 0x43, 0x0b, 0xae, 0xb8, 0xc9, 0x42, 0x3a, 0x74, 0xe8, 0x10, 0xaa, 0x98, 0x94, 0x28, 0x00, 0x53, 0x9e, 0x3b, 0x77, 0x0e, 0xfa, 0x1c, 0x3b, 0x76, 0x2c, 0x3e, 0x3e, 0x1e, 0x22, 0xd5, 0xd5, 0xd5, 0xa1, 0xaa, 0x12, 0x3a, 0x1c, 0x00, 0x5a, 0x2f, 0x5e, 0xbc, 0x08, 0x6e, 0x7c, 0x32, 0x01, 0x8d, 0xf3, 0x3a, 0x16, 0x22, 0x4c, 0x88, 0x3d, 0x27, 0x4c, 0x18, 0x57, 0xd3, 0x44, 0xb3, 0x30, 0x00, 0x44, 0x3f, 0xbc, 0x25, 0x42, 0x96, 0x88, 0x60, 0x04, 0x70, 0x12, 0x00, 0x90, 0x22, 0xfb, 0xd2, 0x99, 0x33, 0x67, 0xfe, 0xfd, 0x63, 0xd9, 0xb9, 0x73, 0x27, 0x18, 0x16, 0x2c, 0x58, 0x00, 0x7e, 0x5c, 0xf4, 0x92, 0x61, 0xb1, 0x72, 0xc4, 0x19, 0x21, 0x8b, 0x46, 0xa5, 0x52, 0x89, 0x1d, 0x59, 0x6c, 0x24, 0xc4, 0x3b, 0x00, 0x20, 0x42, 0xf0, 0x05, 0x0e, 0x02, 0xf5, 0xf5, 0xf5, 0x77, 0xee, 0xdc, 0x01, 0xb1, 0x76, 0xed, 0xda, 0x30, 0x31, 0x54, 0xdf, 0x07, 0x00, 0x81, 0x0b, 0x91, 0xed, 0xdb, 0xb7, 0x8b, 0x22, 0xfb, 0xf7, 0xef, 0x47, 0x0b, 0x01, 0x20, 0xea, 0x87, 0x96, 0xb0, 0x92, 0x97, 0x97, 0x07, 0x91, 0x9b, 0x37, 0x6f, 0x92, 0x76, 0x7c, 0x77, 0x12, 0x47, 0x10, 0x1b, 0xe1, 0x10, 0xb1, 0x91, 0x10, 0xef, 0x78, 0xa5, 0xc4, 0xba, 0x41, 0xbc, 0x9e, 0x3f, 0x7f, 0xfe, 0xf2, 0xe5, 0xcb, 0x3d, 0x3d, 0x3d, 0x18, 0xee, 0xc0, 0x81, 0x03, 0x61, 0x93, 0x8d, 0x51, 0x85, 0x38, 0x7a, 0xe1, 0x16, 0x91, 0x27, 0x94, 0xd6, 0xeb, 0xf5, 0xa4, 0xfd, 0xd2, 0xa5, 0x4b, 0x65, 0x65, 0x65, 0x22, 0x0f, 0xdc, 0x42, 0xae, 0x8a, 0xc5, 0x45, 0x88, 0x4f, 0xc8, 0x48, 0x32, 0x84, 0x01, 0x34, 0x08, 0x04, 0x02, 0x2e, 0xf4, 0x45, 0x91, 0x1f, 0x88, 0x30, 0x40, 0xa4, 0xda, 0xd8, 0xd8, 0x88, 0x6e, 0xf8, 0x01, 0xef, 0x7b, 0xb0, 0x28, 0x79, 0x69, 0x0c, 0xe5, 0x84, 0x2b, 0xe1, 0x28, 0x32, 0x04, 0xac, 0x12, 0xba, 0x9f, 0xee, 0xd9, 0xb3, 0x07, 0xed, 0x50, 0xe8, 0xe1, 0xc3, 0x87, 0x10, 0x79, 0xfa, 0xf4, 0x29, 0xd2, 0x05, 0x5a, 0xc4, 0x35, 0x30, 0x7f, 0xfe, 0x7c, 0x54, 0xb1, 0x41, 0x89, 0xab, 0xb6, 0xa5, 0xa5, 0x05, 0x52, 0x27, 0x4e, 0x9c, 0x00, 0xbf, 0xdd, 0x6e, 0x27, 0xfe, 0xc7, 0xbe, 0xf7, 0xe6, 0xcd, 0x1b, 0xb4, 0x60, 0x91, 0x10, 0xd8, 0x24, 0xaa, 0x43, 0xd5, 0x00, 0xfd, 0x8e, 0x10, 0x22, 0x1c, 0x8b, 0x17, 0x2f, 0x26, 0xfa, 0x61, 0x25, 0x85, 0xc9, 0x54, 0x55, 0x55, 0x91, 0xae, 0xd0, 0x27, 0x02, 0x00, 0x2b, 0x1e, 0x9c, 0x98, 0x35, 0x31, 0x31, 0x91, 0x74, 0x91, 0x70, 0x22, 0x34, 0xec, 0x57, 0x5b, 0x5b, 0x0b, 0x86, 0xfb, 0xf7, 0xef, 0x93, 0x7d, 0x09, 0x4b, 0x73, 0xe5, 0xca, 0x95, 0x62, 0x2a, 0xdc, 0xb8, 0x71, 0x23, 0x99, 0xe8, 0xc2, 0x85, 0x0b, 0x44, 0x04, 0x7b, 0x1d, 0xb6, 0x5a, 0x42, 0xc3, 0x22, 0x8f, 0x1e, 0x3d, 0x0a, 0xd3, 0x04, 0xd5, 0xf7, 0x02, 0xb8, 0x77, 0xef, 0x5e, 0x6a, 0x6a, 0x2a, 0xd6, 0x1f, 0x2e, 0x4e, 0xc2, 0xc4, 0x90, 0x01, 0xc8, 0xa0, 0xa1, 0x4f, 0x04, 0x00, 0xee, 0x17, 0x08, 0x27, 0x66, 0xc2, 0x75, 0x15, 0xe9, 0x45, 0x48, 0x60, 0xbd, 0xc2, 0x93, 0xd0, 0x86, 0x00, 0x00, 0x0f, 0xbe, 0x0e, 0x62, 0x77, 0x27, 0x0c, 0xe8, 0x02, 0xf3, 0xde, 0xbd, 0x7b, 0x87, 0x87, 0x87, 0xc5, 0x89, 0xae, 0x5f, 0xbf, 0x4e, 0x96, 0x3e, 0xe1, 0xa9, 0xac, 0xac, 0x7c, 0xf0, 0xe0, 0x81, 0xd8, 0x1b, 0x4a, 0x8c, 0xf5, 0x52, 0x8f, 0xcf, 0xc0, 0x30, 0x15, 0x39, 0x08, 0x84, 0xea, 0x3a, 0x41, 0x1a, 0xfb, 0x3d, 0x82, 0x04, 0x47, 0x09, 0x62, 0xef, 0xd1, 0x52, 0x48, 0x67, 0x58, 0x63, 0x08, 0x74, 0xd1, 0x63, 0x61, 0x3c, 0xd8, 0xb8, 0x31, 0xc8, 0x9c, 0x39, 0x73, 0x48, 0x50, 0x85, 0xf5, 0x92, 0xea, 0x58, 0x00, 0xde, 0x29, 0xf0, 0x53, 0x6b, 0x0c, 0x3f, 0x4a, 0xfc, 0xd4, 0xf4, 0x1b, 0x57, 0x9f, 0x18, 0x80, 0x71, 0x4d, 0x34, 0xcd, 0x0c, 0x31, 0x0f, 0x4c, 0xb3, 0x81, 0xc7, 0x1d, 0x3e, 0xe6, 0x81, 0x71, 0x4d, 0x34, 0xcd, 0x0c, 0x31, 0x0f, 0x4c, 0xb3, 0x81, 0xc7, 0x1d, 0x3e, 0xe6, 0x81, 0x71, 0x4d, 0x34, 0xcd, 0x0c, 0xff, 0x07, 0x71, 0xef, 0x64, 0x50, 0x13, 0xcd, 0x1c, 0x52, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXXMLIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x30, 0x39, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x9d, 0x3c, 0x78, 0xe3, 0x00, 0x00, 0x05, 0x7c, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x58, 0x59, 0x4c, 0x1b, 0x57, 0x14, 0xc5, 0x0b, 0xbb, 0xc1, 0x26, 0xa2, 0x31, 0x56, 0x58, 0x4c, 0xb1, 0x1b, 0x37, 0x15, 0x8e, 0x42, 0x05, 0x94, 0x25, 0x88, 0x25, 0x6c, 0x05, 0x52, 0x14, 0x0a, 0xfd, 0xa8, 0x08, 0x1f, 0x91, 0xe0, 0x83, 0x02, 0xa2, 0x2a, 0x6a, 0xfb, 0xd3, 0x82, 0x00, 0x15, 0x3e, 0x8a, 0x8a, 0x10, 0x42, 0x42, 0x4a, 0xbf, 0x10, 0x12, 0x84, 0x06, 0xd5, 0x12, 0x15, 0x5b, 0x49, 0x0a, 0x51, 0x31, 0x34, 0xdd, 0x00, 0xa5, 0xb5, 0x4d, 0x42, 0x83, 0xa1, 0x24, 0x0a, 0xc4, 0x94, 0x60, 0x03, 0xb6, 0xb1, 0x7b, 0x9d, 0x57, 0xdc, 0x67, 0x9b, 0x24, 0xe3, 0x19, 0x3b, 0x08, 0x69, 0x46, 0x23, 0xfb, 0xbe, 0xf3, 0xee, 0xbd, 0xef, 0xdc, 0x7b, 0xdf, 0x32, 0x33, 0x0c, 0xb3, 0xd9, 0xec, 0x71, 0x9c, 0x2f, 0xe6, 0x71, 0x26, 0x6f, 0xe1, 0x4e, 0x07, 0x70, 0xd4, 0x15, 0xa4, 0x2b, 0x40, 0x57, 0x80, 0x62, 0x06, 0xe8, 0x29, 0x44, 0x31, 0x81, 0x94, 0xcd, 0xe9, 0x0a, 0x50, 0x4e, 0x21, 0x45, 0x07, 0x74, 0x05, 0x28, 0x26, 0x90, 0xb2, 0x39, 0x5d, 0x81, 0xc3, 0x52, 0xa8, 0xff, 0x67, 0xdb, 0x11, 0x36, 0xea, 0x76, 0x3d, 0x4c, 0xae, 0x7f, 0xf2, 0x75, 0x71, 0x05, 0x36, 0x15, 0xcb, 0xb7, 0x9b, 0xbe, 0x1e, 0x2e, 0xfe, 0xd4, 0x31, 0x80, 0xf5, 0xdf, 0x94, 0xdf, 0x15, 0x7d, 0xac, 0xec, 0x19, 0x36, 0x3c, 0xd1, 0x39, 0xf6, 0x92, 0x46, 0xd8, 0xa4, 0x2d, 0x6d, 0x0c, 0x4d, 0xe6, 0xd5, 0x1f, 0x7e, 0x51, 0xf5, 0x8d, 0xad, 0xff, 0xae, 0x02, 0x9c, 0xe5, 0xed, 0x69, 0xd3, 0x7b, 0xd0, 0xd0, 0x3d, 0xd8, 0x98, 0xeb, 0xbc, 0x76, 0xe7, 0xaa, 0x2c, 0x3c, 0x37, 0x41, 0x5c, 0x72, 0x21, 0x40, 0x28, 0x38, 0xe8, 0x21, 0xff, 0x4f, 0x35, 0x00, 0xc3, 0x96, 0x76, 0x49, 0x36, 0xb5, 0xf8, 0xcd, 0x04, 0x90, 0x23, 0xc8, 0xc2, 0xb8, 0xbb, 0x77, 0x6f, 0xf0, 0x26, 0xdc, 0xfc, 0xb8, 0x33, 0xa2, 0x92, 0x4c, 0x41, 0x92, 0x94, 0xa0, 0xe1, 0xa1, 0x6a, 0xe4, 0x03, 0xd8, 0x5a, 0xfa, 0x7b, 0xb1, 0x7f, 0x7c, 0x79, 0x58, 0x0e, 0x84, 0x70, 0xd7, 0xbe, 0xc1, 0x3c, 0x61, 0x7e, 0x32, 0x8e, 0x20, 0x99, 0x2b, 0x0a, 0x8b, 0xc8, 0x49, 0x58, 0xb9, 0xf9, 0xf3, 0xfe, 0xae, 0x1e, 0x21, 0x0f, 0x67, 0xef, 0xc0, 0xcd, 0x09, 0xe3, 0x8b, 0xde, 0x4d, 0x07, 0x13, 0xb6, 0x9f, 0x8f, 0xa3, 0xd5, 0x0b, 0x11, 0x86, 0xd3, 0xaf, 0x94, 0x66, 0xf3, 0xda, 0x8f, 0xf3, 0x8b, 0xfd, 0x63, 0x30, 0x36, 0xee, 0x9d, 0xc9, 0x66, 0x0b, 0x92, 0xa5, 0xc2, 0xfc, 0xf3, 0x82, 0x84, 0x68, 0x0f, 0x26, 0x03, 0xef, 0xc2, 0x65, 0xc3, 0xf6, 0x8e, 0x7a, 0x54, 0x0e, 0x45, 0xd3, 0x28, 0xee, 0xe3, 0xb8, 0xa7, 0xbf, 0xaf, 0x30, 0x2f, 0x49, 0x54, 0x9c, 0xe1, 0x1f, 0x7a, 0x12, 0xc7, 0x5f, 0x28, 0x3b, 0x1d, 0xc0, 0xad, 0x0f, 0xbf, 0x7a, 0x30, 0x3d, 0x8f, 0xfb, 0xe5, 0x46, 0x85, 0x42, 0xfe, 0x20, 0xbb, 0x5e, 0x3c, 0x0e, 0x8e, 0x3f, 0x5f, 0xde, 0x54, 0x2e, 0x43, 0x18, 0x10, 0x8c, 0x1e, 0x5b, 0xd3, 0x0c, 0x06, 0xe3, 0xcd, 0x4f, 0xca, 0x84, 0x17, 0xcf, 0x3f, 0xdf, 0x16, 0xef, 0x75, 0x7a, 0x0a, 0xe9, 0x37, 0xff, 0xdf, 0x22, 0x4f, 0xa5, 0xc6, 0x48, 0x2e, 0xe7, 0x05, 0xbd, 0x2e, 0xc4, 0x3d, 0x12, 0x94, 0x79, 0xaf, 0x85, 0x9f, 0xfb, 0xe8, 0xfd, 0xb3, 0x55, 0x25, 0x30, 0xa9, 0xfe, 0xb8, 0x2a, 0x7b, 0xa2, 0x7e, 0x08, 0x86, 0x30, 0x1d, 0x76, 0x35, 0x5b, 0x04, 0x3d, 0x20, 0x35, 0xa7, 0x03, 0xc0, 0xbd, 0xaf, 0xdd, 0x9a, 0x63, 0x30, 0x98, 0x91, 0x85, 0x29, 0xfc, 0xb8, 0x37, 0x70, 0x9c, 0xa0, 0x6c, 0xda, 0x33, 0xa8, 0xbf, 0xff, 0x69, 0x49, 0x36, 0x89, 0xd8, 0x13, 0xb4, 0xb2, 0x53, 0x73, 0x3a, 0x80, 0xc8, 0x77, 0x52, 0x20, 0x49, 0x68, 0xcf, 0x31, 0x19, 0x8d, 0x2b, 0x37, 0x6e, 0xc3, 0xed, 0x2f, 0x08, 0x06, 0x1c, 0x26, 0xb1, 0x4f, 0x30, 0xcf, 0x6e, 0x80, 0x43, 0x9b, 0x68, 0xfe, 0x2c, 0x8f, 0xc8, 0x0d, 0xdb, 0x36, 0x67, 0xc2, 0x2b, 0xe7, 0x4e, 0x3b, 0x9b, 0x0b, 0xa7, 0xd7, 0x80, 0x85, 0x90, 0xed, 0xae, 0x6f, 0xa5, 0xc8, 0x64, 0xb3, 0x04, 0x89, 0x52, 0x88, 0x24, 0xe4, 0xad, 0xc3, 0xd7, 0x31, 0x1c, 0xc6, 0xea, 0xd1, 0x99, 0x7b, 0xdf, 0x4e, 0x6a, 0xfe, 0xfc, 0xcb, 0x6a, 0x05, 0x02, 0xd3, 0x93, 0x1d, 0x9e, 0x15, 0x2f, 0x2a, 0xb9, 0x00, 0xf3, 0x0a, 0xc7, 0x89, 0xc8, 0xa4, 0x02, 0x38, 0x70, 0xbc, 0xa9, 0xb8, 0xaf, 0xea, 0x1b, 0x57, 0x8f, 0xcf, 0x9a, 0x0c, 0xc6, 0x03, 0xcc, 0xf2, 0xcf, 0x09, 0x3d, 0x99, 0x73, 0xed, 0x0b, 0x1c, 0x01, 0xf9, 0xf1, 0xc2, 0xdd, 0xc9, 0xaa, 0x2f, 0xed, 0xf6, 0x5c, 0x9f, 0x13, 0xdc, 0xa8, 0x4b, 0xa9, 0xaf, 0x5e, 0x4a, 0xf5, 0x0e, 0x0a, 0xb4, 0xd3, 0x27, 0xd8, 0x74, 0x7a, 0x0a, 0xe1, 0x7e, 0x79, 0xa7, 0x23, 0x62, 0x3f, 0xbb, 0x22, 0xfd, 0xa0, 0xf8, 0x2e, 0x1c, 0x4c, 0xd7, 0x6f, 0xec, 0x3e, 0xfe, 0x6f, 0xfd, 0xed, 0x3c, 0xd2, 0xe0, 0x6a, 0x48, 0xd6, 0x6f, 0x69, 0x71, 0xf6, 0x41, 0x92, 0x08, 0x71, 0x49, 0x66, 0x58, 0x66, 0x1c, 0x83, 0xcd, 0x72, 0x54, 0x26, 0x8e, 0x50, 0x0a, 0x00, 0x0d, 0xe3, 0x7d, 0x22, 0xf0, 0xcc, 0x95, 0x8b, 0x92, 0xcb, 0x6f, 0xab, 0xc7, 0x66, 0xe1, 0x68, 0xb3, 0xdb, 0xe0, 0xed, 0xa8, 0x30, 0x58, 0xcc, 0x53, 0x29, 0x31, 0xa2, 0xf7, 0x2e, 0x04, 0x9f, 0x15, 0xdb, 0x75, 0x91, 0x6c, 0xc2, 0xce, 0xe5, 0xda, 0xeb, 0xd1, 0xaf, 0x8a, 0x99, 0xcf, 0xbb, 0x1d, 0x7d, 0x02, 0x3e, 0xd7, 0xd1, 0xaf, 0x5d, 0x5b, 0x77, 0xec, 0xa2, 0x82, 0x50, 0x5a, 0x03, 0x24, 0x73, 0xe6, 0x52, 0x33, 0x17, 0x3f, 0x4e, 0xbb, 0x94, 0x1b, 0x21, 0x67, 0x74, 0x00, 0x84, 0xd2, 0xe4, 0x46, 0x25, 0xba, 0x02, 0x6e, 0x4c, 0x2e, 0x21, 0xd7, 0x74, 0x05, 0x08, 0xa5, 0xc9, 0x8d, 0x4a, 0xc7, 0xbe, 0x02, 0x2e, 0x78, 0x94, 0x20, 0x9d, 0xde, 0xfd, 0xfd, 0x7d, 0x38, 0x83, 0xc1, 0x9c, 0xcd, 0x26, 0x4f, 0xe3, 0xc8, 0x2a, 0x50, 0x5d, 0x5d, 0xed, 0xe5, 0xe5, 0xe5, 0xf9, 0xf4, 0x6a, 0x6f, 0x6f, 0x27, 0x9d, 0x85, 0x23, 0x0b, 0x20, 0x32, 0x32, 0x32, 0x2a, 0x2a, 0xca, 0xd7, 0xd7, 0x17, 0xa8, 0x6b, 0xb5, 0xda, 0xe3, 0x17, 0x40, 0x6d, 0x6d, 0xad, 0x52, 0xa9, 0xcc, 0xc8, 0xc8, 0x20, 0x4d, 0x1d, 0x19, 0x92, 0xa9, 0xc0, 0xf4, 0xf4, 0x74, 0x7a, 0x7a, 0x7a, 0x7c, 0x7c, 0x7c, 0x72, 0x72, 0xf2, 0xd4, 0xd4, 0xd4, 0xc8, 0xc8, 0x48, 0x62, 0x62, 0x22, 0x34, 0x8b, 0x8a, 0x8a, 0x76, 0x76, 0x76, 0x64, 0x32, 0x59, 0x52, 0x52, 0x52, 0x5a, 0x5a, 0x5a, 0x67, 0x67, 0x27, 0x9f, 0xcf, 0x17, 0x8b, 0xc5, 0xbd, 0xbd, 0xbd, 0x31, 0x31, 0x31, 0x21, 0x21, 0x21, 0xf5, 0xf5, 0xf5, 0x7b, 0x7b, 0x36, 0x1f, 0x91, 0x28, 0xb2, 0xb7, 0x98, 0x93, 0x78, 0x94, 0x6d, 0x69, 0x69, 0xb1, 0x0e, 0xdc, 0xd4, 0xd4, 0x54, 0x57, 0x57, 0x67, 0x6d, 0xaa, 0x54, 0xaa, 0xaa, 0xaa, 0x2a, 0x6b, 0xd3, 0x51, 0x80, 0x60, 0xf0, 0x11, 0xf3, 0xf3, 0xf3, 0x41, 0xa7, 0xb9, 0xb9, 0x19, 0x07, 0x9d, 0x92, 0xc9, 0x54, 0xa0, 0xa6, 0xa6, 0x66, 0x70, 0x70, 0x90, 0xc7, 0xb3, 0xbc, 0xbf, 0x4b, 0xa5, 0x52, 0x89, 0x44, 0x02, 0x42, 0x6e, 0x6e, 0xee, 0xcc, 0xcc, 0x8c, 0x48, 0x24, 0x6a, 0x6c, 0x6c, 0x84, 0x6a, 0x00, 0x52, 0x5a, 0x5a, 0x3a, 0x3e, 0x3e, 0x0e, 0x02, 0x5c, 0x43, 0x43, 0x43, 0xe5, 0xe5, 0xe5, 0x20, 0xcc, 0xcf, 0xdb, 0x7c, 0x53, 0x7a, 0xda, 0x49, 0xe9, 0x87, 0xcc, 0xfe, 0xe5, 0xe3, 0xe3, 0x53, 0x58, 0x58, 0xc8, 0xe5, 0x72, 0xb3, 0xb3, 0xb3, 0xcb, 0xca, 0xca, 0x74, 0x3a, 0x5d, 0x74, 0x74, 0x74, 0x5f, 0x5f, 0x5f, 0x40, 0x40, 0x00, 0x70, 0x01, 0x1c, 0x66, 0x0b, 0x08, 0x79, 0x79, 0x79, 0xb1, 0xb1, 0xb1, 0x20, 0xc0, 0x4e, 0x93, 0x95, 0x95, 0xb5, 0xb2, 0xb2, 0x02, 0xb2, 0x46, 0x73, 0xc8, 0xdb, 0x26, 0xe0, 0xa4, 0x2f, 0x32, 0x15, 0x40, 0x83, 0xc1, 0x2c, 0x6f, 0x68, 0x68, 0x00, 0x42, 0x30, 0xad, 0x3b, 0x3a, 0x3a, 0x10, 0x7b, 0x9c, 0x87, 0x9f, 0x9f, 0x1f, 0x7c, 0x69, 0x03, 0x04, 0x02, 0x80, 0x9d, 0x1e, 0xc9, 0x26, 0x93, 0x09, 0xd7, 0xa1, 0x2e, 0x93, 0x0f, 0x00, 0x32, 0xda, 0xd5, 0xd5, 0x05, 0xd5, 0x00, 0x12, 0x15, 0x15, 0x15, 0x1b, 0x1b, 0x44, 0xbf, 0x4e, 0x53, 0x27, 0x8d, 0x7b, 0x20, 0x19, 0x00, 0xd0, 0xcd, 0xc9, 0xc9, 0x59, 0x5d, 0x5d, 0x1d, 0x18, 0x18, 0xa8, 0xac, 0xac, 0x54, 0x28, 0x14, 0x05, 0x05, 0x05, 0xd6, 0xed, 0x1c, 0x56, 0x21, 0x8c, 0x81, 0x7e, 0xf1, 0xc1, 0x70, 0x19, 0x4a, 0x61, 0x34, 0x1a, 0x91, 0x0e, 0x2e, 0xe3, 0x3a, 0x84, 0x64, 0xa7, 0x96, 0x3c, 0x52, 0x86, 0xa5, 0x89, 0x12, 0x0f, 0xc7, 0x90, 0x5c, 0x2e, 0x6f, 0x6d, 0x6d, 0x45, 0x23, 0x41, 0x73, 0x62, 0x62, 0xa2, 0xad, 0xad, 0x0d, 0xcd, 0x96, 0xc0, 0xc0, 0xc0, 0x85, 0x85, 0x05, 0xd4, 0x05, 0x4b, 0xbc, 0xbb, 0xbb, 0x1b, 0x64, 0x16, 0x8b, 0xd5, 0xd3, 0xd3, 0x03, 0x26, 0x8e, 0x8f, 0x0f, 0x1c, 0x0e, 0x67, 0x74, 0x74, 0xd4, 0x59, 0x3e, 0x64, 0x2a, 0x00, 0xfc, 0xe0, 0x29, 0x00, 0xd8, 0x80, 0x00, 0x59, 0xd4, 0xeb, 0xf5, 0x88, 0xb1, 0x15, 0x64, 0x32, 0x2d, 0x6e, 0x81, 0x22, 0x5c, 0xe8, 0xac, 0x05, 0x04, 0x2d, 0x12, 0x08, 0x00, 0x28, 0x82, 0x3e, 0x32, 0x41, 0xe1, 0xa1, 0x5f, 0x47, 0x04, 0xef, 0x7d, 0x96, 0x4c, 0x7f, 0x95, 0x78, 0x56, 0x66, 0x5e, 0x16, 0x4e, 0x66, 0x0a, 0xbd, 0x2c, 0x6e, 0x84, 0xc6, 0xa1, 0x03, 0x20, 0x94, 0x26, 0x37, 0x2a, 0xd1, 0x15, 0x70, 0x63, 0x72, 0x09, 0xb9, 0xa6, 0x2b, 0x40, 0x28, 0x4d, 0x6e, 0x54, 0xa2, 0x2b, 0xe0, 0xc6, 0xe4, 0x12, 0x72, 0x4d, 0x57, 0x80, 0x50, 0x9a, 0xdc, 0xa8, 0xf4, 0x2f, 0x8a, 0xf9, 0x6c, 0x7c, 0x9d, 0x47, 0x95, 0x15, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\nstatic const u_int8_t FLEXBinaryIcon2x[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x32, 0x31, 0x54, 0x32, 0x31, 0x3a, 0x30, 0x32, 0x3a, 0x38, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xce, 0xc3, 0x0a, 0xd6, 0x00, 0x00, 0x05, 0xc2, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x59, 0x6f, 0x48, 0x64, 0x55, 0x14, 0x3f, 0x33, 0xe3, 0x8c, 0x63, 0xce, 0x44, 0x6e, 0x5b, 0xae, 0xd9, 0x22, 0xa8, 0x59, 0xae, 0x08, 0x91, 0x9a, 0x1b, 0xea, 0x87, 0x30, 0xd1, 0x45, 0x03, 0x29, 0x58, 0x61, 0x2b, 0xe9, 0x93, 0x89, 0x84, 0x44, 0x11, 0x51, 0x7d, 0x0b, 0x4a, 0x21, 0xb2, 0xed, 0x8b, 0xfa, 0x29, 0xa8, 0x2c, 0xf1, 0x83, 0x4a, 0x1b, 0xad, 0x6c, 0x61, 0x05, 0x9b, 0xc9, 0x36, 0xba, 0x9b, 0xe8, 0x1a, 0xa2, 0x28, 0xfe, 0xd7, 0x36, 0xf3, 0xcf, 0x6c, 0x3a, 0xce, 0x8c, 0x33, 0x9d, 0x3b, 0xf7, 0xcd, 0x9d, 0xf7, 0xe6, 0xcd, 0xcc, 0xfb, 0x3b, 0xc4, 0xc2, 0xbb, 0x1f, 0xc6, 0x73, 0xcf, 0xfd, 0x9d, 0xdf, 0xb9, 0xe7, 0x9c, 0xfb, 0xe7, 0x71, 0x35, 0x05, 0x83, 0x41, 0xb8, 0x97, 0x9b, 0xf9, 0x5e, 0x9e, 0x3c, 0x99, 0xbb, 0x11, 0xc0, 0xff, 0x5d, 0x41, 0xa3, 0x02, 0x46, 0x05, 0x34, 0x66, 0xc0, 0x58, 0x42, 0x1a, 0x13, 0xa8, 0xd9, 0x5c, 0x46, 0x05, 0x0e, 0xff, 0x82, 0xe0, 0x89, 0x66, 0x47, 0x3c, 0x02, 0x5d, 0x09, 0x53, 0x78, 0xc4, 0x42, 0x71, 0x67, 0x16, 0x7e, 0x7a, 0x13, 0xb6, 0x26, 0xe0, 0x68, 0x07, 0x52, 0xec, 0x70, 0xfa, 0x1c, 0x94, 0xbc, 0x01, 0x45, 0xaf, 0x08, 0x41, 0xbc, 0x1e, 0x06, 0x39, 0xf0, 0x1c, 0x78, 0xdd, 0x60, 0x3f, 0x05, 0x17, 0x7f, 0xe0, 0x0d, 0x84, 0x45, 0xa5, 0x84, 0xb3, 0x7d, 0x30, 0x71, 0x99, 0x18, 0x9f, 0x7f, 0x17, 0x0a, 0x5e, 0x0c, 0xb3, 0x44, 0xff, 0x8d, 0x13, 0x00, 0x1a, 0x5f, 0x7b, 0x0d, 0x7c, 0x87, 0x1c, 0xdc, 0xef, 0x81, 0xad, 0x9b, 0xf0, 0x7d, 0x33, 0x2c, 0xff, 0x08, 0x17, 0x3e, 0x07, 0x53, 0x2c, 0xab, 0xc5, 0xab, 0xb0, 0xf2, 0x0b, 0xc1, 0xa7, 0x67, 0x72, 0x56, 0xfc, 0x3f, 0x8a, 0x09, 0x83, 0x30, 0xf9, 0x19, 0x6c, 0x4d, 0x12, 0x8e, 0xc3, 0x3b, 0x7c, 0xa6, 0x28, 0x39, 0xd6, 0x12, 0x3a, 0xdc, 0x86, 0x6b, 0x2d, 0xdc, 0xec, 0x6d, 0xe9, 0x90, 0xf3, 0x2c, 0x38, 0x1f, 0xe1, 0xcc, 0x66, 0xbe, 0x82, 0x99, 0x2f, 0xa2, 0x28, 0x48, 0x77, 0x7d, 0x0c, 0xae, 0xbe, 0x1a, 0x43, 0x4f, 0x55, 0x4a, 0x09, 0x4f, 0x3c, 0x84, 0x6d, 0x73, 0x22, 0x2e, 0x21, 0x6f, 0x20, 0x56, 0x2e, 0x7f, 0xff, 0x18, 0x7c, 0x47, 0x04, 0xe3, 0xcc, 0x86, 0x97, 0xc7, 0xc1, 0x79, 0x96, 0xec, 0x81, 0x2b, 0x4d, 0x30, 0x37, 0x48, 0x94, 0xe3, 0x1f, 0x42, 0x51, 0x33, 0x98, 0xad, 0x44, 0x9e, 0xfd, 0x1a, 0xb6, 0x27, 0x61, 0xfd, 0x37, 0xd8, 0xb8, 0x41, 0xba, 0xf1, 0x9a, 0x4c, 0xc2, 0xbb, 0xeb, 0x70, 0xab, 0x1b, 0xdc, 0xab, 0xb0, 0xf0, 0x1d, 0x78, 0xf6, 0xe2, 0x91, 0x45, 0xe9, 0x45, 0x15, 0x08, 0x78, 0xe1, 0x56, 0x0f, 0x07, 0x2a, 0x7f, 0x87, 0xcc, 0x1e, 0x9b, 0xc9, 0x02, 0xd5, 0x97, 0xc1, 0x6c, 0x21, 0xf2, 0xde, 0x12, 0x2c, 0x5c, 0x21, 0x02, 0xb6, 0xdb, 0x5f, 0x82, 0xeb, 0x53, 0x89, 0xd9, 0xcb, 0x27, 0x3c, 0x58, 0x81, 0xf1, 0x8f, 0x00, 0x8b, 0x2c, 0x7b, 0xf6, 0x38, 0x05, 0x51, 0x00, 0xee, 0xb5, 0xc8, 0xd2, 0xcf, 0xbd, 0x10, 0x9a, 0x66, 0xe8, 0xc7, 0xf1, 0x28, 0x3c, 0x54, 0xcc, 0x75, 0xff, 0x99, 0x8b, 0xe8, 0x25, 0x25, 0xdd, 0x09, 0x85, 0x1e, 0x45, 0x4b, 0x08, 0xd3, 0x40, 0x1b, 0xe6, 0xfb, 0x81, 0x3c, 0x01, 0xf8, 0xd4, 0xe3, 0xb0, 0xfd, 0x07, 0xd1, 0x30, 0xcc, 0xf3, 0xdf, 0x80, 0xff, 0x98, 0xc3, 0xb8, 0x3e, 0x01, 0x57, 0x97, 0x00, 0x4f, 0x3b, 0x0c, 0x2c, 0x49, 0x78, 0xa6, 0x04, 0xda, 0xd6, 0x23, 0x0c, 0xdd, 0xd9, 0x11, 0x39, 0xbe, 0x24, 0x0e, 0x60, 0x99, 0x03, 0xdb, 0xee, 0xc7, 0xa5, 0x23, 0x30, 0xc4, 0xf3, 0x91, 0xb6, 0x83, 0x30, 0xc6, 0xfe, 0x60, 0x04, 0x60, 0x73, 0x46, 0x64, 0xbe, 0xc4, 0xc0, 0x92, 0x84, 0x66, 0x1b, 0x38, 0xc2, 0xa7, 0x05, 0x9f, 0x21, 0xa1, 0x2c, 0x5a, 0x42, 0x77, 0x37, 0x38, 0xbc, 0x59, 0x14, 0x1b, 0xd3, 0x30, 0x4c, 0x42, 0x6a, 0x6e, 0x90, 0x81, 0x99, 0x39, 0xb3, 0x62, 0x1a, 0x86, 0x61, 0x43, 0xb2, 0x05, 0x51, 0x00, 0x16, 0x3b, 0x67, 0x7b, 0xe2, 0x8d, 0x26, 0x61, 0x1a, 0x86, 0x89, 0x46, 0xc4, 0xea, 0x33, 0x30, 0x33, 0x67, 0x28, 0xa6, 0x61, 0x18, 0x36, 0x24, 0x5b, 0x10, 0x05, 0x90, 0x8a, 0x2b, 0x27, 0xd4, 0x7c, 0xff, 0x42, 0xd0, 0x2f, 0xe0, 0x39, 0x0e, 0x1f, 0x6d, 0x0c, 0x23, 0x18, 0x8e, 0xd3, 0x61, 0x60, 0xbd, 0x08, 0x85, 0x7e, 0x44, 0x01, 0x64, 0x3c, 0xc6, 0x01, 0x02, 0x7e, 0x72, 0x62, 0xf2, 0xdb, 0xee, 0x3c, 0xd7, 0x63, 0x18, 0xfe, 0x68, 0x3c, 0x99, 0x81, 0xf5, 0x22, 0x14, 0x3a, 0x12, 0x05, 0xf0, 0xf0, 0x93, 0xc0, 0x96, 0xe6, 0xca, 0xcf, 0x11, 0x30, 0xde, 0xa6, 0x7f, 0xdf, 0xe6, 0xba, 0x67, 0x4a, 0x23, 0x7a, 0x49, 0x49, 0x77, 0x42, 0xa1, 0x47, 0x51, 0x00, 0x78, 0x56, 0x9c, 0xbb, 0xc4, 0x61, 0x6e, 0x74, 0x82, 0x3f, 0x74, 0x25, 0x63, 0x1f, 0x2f, 0x60, 0x7a, 0x62, 0xde, 0x77, 0x1a, 0x9e, 0xb8, 0x28, 0x24, 0x49, 0xd8, 0xd3, 0x9d, 0x50, 0xe8, 0x4d, 0x74, 0xd4, 0xe0, 0xf0, 0x33, 0xef, 0x93, 0x6f, 0x84, 0xc0, 0x09, 0x59, 0x42, 0x3d, 0x67, 0xc9, 0x74, 0xd7, 0xae, 0xc3, 0x9d, 0x19, 0xce, 0xb0, 0xec, 0x2d, 0xb0, 0x3a, 0x84, 0x24, 0x52, 0x3d, 0xdd, 0x09, 0x79, 0x0e, 0x45, 0x15, 0xc0, 0xb1, 0x8c, 0x02, 0x38, 0xff, 0x1e, 0x87, 0xc1, 0x6f, 0x69, 0xfc, 0xb2, 0x60, 0xb3, 0xcf, 0x7a, 0x1a, 0x9e, 0x7a, 0x9d, 0x67, 0x2e, 0x4f, 0xd4, 0x9d, 0x90, 0xe7, 0x36, 0x56, 0x00, 0x38, 0x5c, 0xf9, 0x01, 0xbc, 0xf0, 0x6d, 0xe4, 0x23, 0x14, 0x35, 0xd6, 0x34, 0x28, 0x7f, 0x1b, 0x5e, 0xfa, 0x55, 0x71, 0xfa, 0xa9, 0x33, 0xdd, 0x09, 0xc3, 0x31, 0x98, 0x24, 0x9e, 0x16, 0xf1, 0x8a, 0xd9, 0xf9, 0x93, 0x7c, 0x96, 0xe2, 0x61, 0x82, 0x9f, 0x74, 0xda, 0x9b, 0xde, 0x84, 0x52, 0x01, 0x68, 0x9f, 0x71, 0x92, 0x19, 0xe2, 0x2c, 0xa1, 0x24, 0x7b, 0xd5, 0x91, 0xde, 0x08, 0x40, 0xc7, 0x64, 0xaa, 0xa2, 0x32, 0x2a, 0xa0, 0x2a, 0x6d, 0x3a, 0x1a, 0x19, 0x15, 0xd0, 0x31, 0x99, 0xaa, 0xa8, 0x8c, 0x0a, 0xa8, 0x4a, 0x9b, 0x8e, 0x46, 0x6a, 0x2a, 0x70, 0x12, 0x6a, 0x92, 0x93, 0xf0, 0xfb, 0xfd, 0x5d, 0x5d, 0x5d, 0x43, 0x43, 0x43, 0x92, 0x48, 0x4d, 0x00, 0xfc, 0x16, 0x52, 0xd4, 0xaa, 0xaa, 0xaa, 0xd0, 0x9f, 0xc9, 0x64, 0x1a, 0x1d, 0x1d, 0x4d, 0x6c, 0x38, 0x37, 0x47, 0x9e, 0x8f, 0x72, 0x73, 0x73, 0x13, 0xc3, 0x34, 0x8e, 0x2a, 0xae, 0x40, 0x41, 0x41, 0x41, 0x4a, 0x4a, 0x0a, 0x7a, 0x3d, 0x38, 0x38, 0x48, 0x9c, 0x39, 0x9b, 0xcd, 0x96, 0x9a, 0x9a, 0x9a, 0x9d, 0x2d, 0xeb, 0x79, 0x27, 0x31, 0x55, 0xa2, 0x51, 0x15, 0x09, 0xc0, 0xa4, 0x22, 0xe3, 0xf0, 0xf0, 0xb0, 0xa4, 0xad, 0xcf, 0xe7, 0x93, 0xc4, 0x68, 0x04, 0x28, 0xae, 0x00, 0x4b, 0xc6, 0xc6, 0xc6, 0x46, 0x7b, 0x7b, 0x7b, 0x75, 0x75, 0x75, 0x6b, 0x6b, 0xeb, 0xd8, 0xd8, 0x18, 0xd3, 0x53, 0xa1, 0xb9, 0xb9, 0xb9, 0xbc, 0xbc, 0xbc, 0xa2, 0xa2, 0xa2, 0xb2, 0xb2, 0x72, 0x6f, 0x2f, 0xfc, 0x9c, 0x01, 0xb0, 0xbb, 0xbb, 0xdb, 0xd8, 0xd8, 0x88, 0x43, 0x6d, 0x6d, 0x6d, 0x83, 0x83, 0x83, 0xc5, 0xc5, 0xc5, 0xe9, 0xe9, 0xe9, 0x75, 0x75, 0x75, 0x9b, 0x9b, 0x9b, 0x51, 0x0c, 0x72, 0xbb, 0x2a, 0x12, 0x40, 0x2b, 0x80, 0xdb, 0x80, 0xf9, 0xb0, 0x58, 0x2c, 0x3d, 0x3d, 0x3d, 0x8c, 0xca, 0xed, 0x76, 0xe3, 0x32, 0x63, 0xa3, 0x4b, 0x4b, 0x4b, 0x6c, 0x68, 0x62, 0x82, 0x7b, 0x34, 0x77, 0x3a, 0x9d, 0x7c, 0x4c, 0x53, 0x53, 0x13, 0xc3, 0x28, 0x12, 0x40, 0x11, 0x9a, 0x82, 0x69, 0x00, 0x38, 0x69, 0x4c, 0x73, 0x77, 0x77, 0x77, 0x5e, 0x1e, 0x79, 0x42, 0x4d, 0x4b, 0x4b, 0x5b, 0x5e, 0x5e, 0x66, 0x6c, 0xd3, 0xd3, 0xd3, 0x03, 0x03, 0x03, 0x34, 0x06, 0x7e, 0x00, 0x08, 0xe8, 0xeb, 0xeb, 0xa3, 0xfa, 0xda, 0xda, 0x5a, 0x8c, 0xa7, 0xa5, 0xa5, 0x05, 0xbb, 0x58, 0x07, 0x66, 0xab, 0x48, 0x50, 0x1f, 0x00, 0xcb, 0xd9, 0xfc, 0x3c, 0xf7, 0x5e, 0xd4, 0xd9, 0xd9, 0xc9, 0xf7, 0x7d, 0x74, 0xc4, 0xbd, 0x68, 0x44, 0x05, 0x30, 0x35, 0x35, 0x45, 0x03, 0x70, 0xb9, 0x5c, 0x88, 0x9f, 0x9c, 0x0c, 0xfd, 0x1b, 0x06, 0x60, 0x7f, 0x7f, 0x9f, 0x6f, 0x2e, 0x53, 0x56, 0xbf, 0x07, 0x1a, 0x1a, 0x1a, 0xe8, 0x3c, 0xf2, 0xf3, 0xf3, 0x0b, 0x0b, 0x0b, 0x51, 0xa6, 0xe7, 0x26, 0x55, 0xca, 0xf9, 0x2d, 0x29, 0x29, 0x41, 0x58, 0x4e, 0x4e, 0x0e, 0x05, 0x7b, 0x3c, 0x1e, 0x39, 0x56, 0x51, 0x18, 0xf5, 0x01, 0x60, 0x5e, 0x29, 0x97, 0xd7, 0xeb, 0x5d, 0x5b, 0x5b, 0x43, 0xd9, 0x6e, 0x0f, 0xbf, 0xab, 0x46, 0x39, 0x89, 0xd3, 0xa5, 0xbb, 0x88, 0xbf, 0x97, 0xe2, 0x00, 0x13, 0xa9, 0xd5, 0x07, 0xd0, 0xdf, 0xdf, 0xbf, 0xba, 0xba, 0x8a, 0x85, 0xee, 0xed, 0xed, 0xc5, 0x5d, 0x8b, 0x4e, 0x4a, 0x4b, 0x23, 0x2f, 0x76, 0x78, 0x59, 0xe3, 0x4d, 0x4c, 0x3d, 0xf3, 0x65, 0xd4, 0xa0, 0x09, 0xd5, 0x53, 0x21, 0x10, 0x08, 0xf0, 0xbb, 0x54, 0x56, 0xf0, 0x2b, 0x73, 0xa9, 0x31, 0x58, 0x4d, 0x4d, 0x0d, 0x63, 0xc7, 0xab, 0x8a, 0x6e, 0x68, 0xd4, 0x14, 0x15, 0x15, 0x61, 0x29, 0x28, 0xac, 0xac, 0xac, 0x8c, 0x61, 0x98, 0x80, 0x2b, 0xed, 0xf8, 0xf8, 0x18, 0x37, 0x7a, 0x46, 0x46, 0x06, 0x55, 0xa2, 0x06, 0x4f, 0xd8, 0xac, 0xac, 0x2c, 0xda, 0xcd, 0xcc, 0xcc, 0xc4, 0xcb, 0x91, 0x39, 0x92, 0x29, 0x28, 0xae, 0x80, 0xd9, 0x4c, 0x4c, 0x1c, 0x0e, 0x47, 0x47, 0x47, 0x07, 0x26, 0x6f, 0x71, 0x71, 0x11, 0xd7, 0x40, 0x7d, 0x7d, 0xfd, 0xc8, 0xc8, 0x88, 0xd5, 0x6a, 0xa5, 0x53, 0xa1, 0x18, 0x2a, 0xb3, 0x5f, 0x54, 0xe2, 0x9c, 0xb0, 0x8b, 0x61, 0x53, 0x25, 0xde, 0xd3, 0xc8, 0xc0, 0xef, 0x52, 0x00, 0x33, 0x91, 0x23, 0x68, 0x7a, 0x56, 0xc1, 0x6d, 0xb7, 0xb0, 0xb0, 0x80, 0xbb, 0x10, 0x0f, 0x75, 0x39, 0xce, 0x92, 0x81, 0xd1, 0x14, 0x40, 0x32, 0x26, 0xa4, 0x94, 0x53, 0xf1, 0x12, 0x52, 0xea, 0x20, 0xd9, 0x78, 0x23, 0x80, 0x64, 0x67, 0x58, 0x8a, 0xdf, 0xa8, 0x80, 0x54, 0x86, 0x92, 0x3d, 0x6e, 0x54, 0x20, 0xd9, 0x19, 0x96, 0xe2, 0x37, 0x2a, 0x20, 0x95, 0xa1, 0x64, 0x8f, 0x1b, 0x15, 0x48, 0x76, 0x86, 0xa5, 0xf8, 0xff, 0x03, 0xf5, 0x1a, 0x5a, 0xe0, 0xcf, 0xeb, 0xd5, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};\n\n@implementation FLEXResources\n\n\n#pragma mark - Images\n\n#define FLEXImage(base) (([[UIScreen mainScreen] scale] > 1.5) ? \\\n    [self imageWithBytesNoCopy:(void *)base##2x length:sizeof(base##2x) scale:2.0] : \\\n    [self imageWithBytesNoCopy:(void *)base length:sizeof(base) scale:1.0])\n\n#define FLEXRetinaOnlyImage(base) ([self imageWithBytesNoCopy:(void *)(base) length:sizeof(base) scale:2.0])\n\n+ (UIImage *)closeIcon\n{\n    return FLEXImage(FLEXCloseIcon);\n}\n\n+ (UIImage *)dragHandle\n{\n    return FLEXImage(FLEXDragHandle);\n}\n\n+ (UIImage *)globeIcon\n{\n    return FLEXImage(FLEXGlobeIcon);\n}\n\n+ (UIImage *)hierarchyIndentPattern\n{\n    return FLEXImage(FLEXHierarchyIndentPattern);\n}\n\n+ (UIImage *)listIcon\n{\n    return FLEXImage(FLEXListIcon);\n}\n\n+ (UIImage *)moveIcon\n{\n    return FLEXImage(FLEXMoveIcon);\n}\n\n+ (UIImage *)selectIcon\n{\n    return FLEXImage(FLEXSelectIcon);\n}\n\n+ (UIImage *)jsonIcon\n{\n    return FLEXRetinaOnlyImage(FLEXJSONIcon2x);\n}\n\n+ (UIImage *)textPlainIcon\n{\n    return FLEXRetinaOnlyImage(FLEXTextPlainIcon2x);\n}\n\n+ (UIImage *)htmlIcon\n{\n    return FLEXRetinaOnlyImage(FLEXHTMLIcon2x);\n}\n\n+ (UIImage *)audioIcon\n{\n    return FLEXRetinaOnlyImage(FLEXAudioIcon2x);\n}\n\n+ (UIImage *)jsIcon\n{\n    return FLEXRetinaOnlyImage(FLEXJSIcon2x);\n}\n\n+ (UIImage *)plistIcon\n{\n    return FLEXRetinaOnlyImage(FLEXPlistIcon2x);\n}\n\n+ (UIImage *)textIcon\n{\n    return FLEXRetinaOnlyImage(FLEXTextIcon2x);\n}\n\n+ (UIImage *)videoIcon\n{\n    return FLEXRetinaOnlyImage(FLEXVideoIcon2x);\n}\n\n+ (UIImage *)xmlIcon\n{\n    return FLEXRetinaOnlyImage(FLEXXMLIcon2x);\n}\n\n+ (UIImage *)binaryIcon\n{\n    return FLEXRetinaOnlyImage(FLEXBinaryIcon2x);\n}\n\n#undef FLEXImage\n#undef FLEXRetinaOnlyImage\n\n\n#pragma mark - Helpers\n\n+ (UIImage *)imageWithBytesNoCopy:(void *)bytes length:(NSUInteger)length scale:(CGFloat)scale\n{\n    NSData *data = [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:NO];\n    return [UIImage imageWithData:data scale:scale];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXRuntimeUtility.h",
    "content": "//\n//  FLEXRuntimeUtility.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/8/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <objc/runtime.h>\n\nextern const unsigned int kFLEXNumberOfImplicitArgs;\n\n// See https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW6\nextern NSString *const kFLEXUtilityAttributeTypeEncoding;\nextern NSString *const kFLEXUtilityAttributeBackingIvar;\nextern NSString *const kFLEXUtilityAttributeReadOnly;\nextern NSString *const kFLEXUtilityAttributeCopy;\nextern NSString *const kFLEXUtilityAttributeRetain;\nextern NSString *const kFLEXUtilityAttributeNonAtomic;\nextern NSString *const kFLEXUtilityAttributeCustomGetter;\nextern NSString *const kFLEXUtilityAttributeCustomSetter;\nextern NSString *const kFLEXUtilityAttributeDynamic;\nextern NSString *const kFLEXUtilityAttributeWeak;\nextern NSString *const kFLEXUtilityAttributeGarbageCollectable;\nextern NSString *const kFLEXUtilityAttributeOldStyleTypeEncoding;\n\n#define FLEXEncodeClass(class) (\"@\\\"\" #class \"\\\"\")\n\n@interface FLEXRuntimeUtility : NSObject\n\n// Property Helpers\n+ (NSString *)prettyNameForProperty:(objc_property_t)property;\n+ (NSString *)typeEncodingForProperty:(objc_property_t)property;\n+ (BOOL)isReadonlyProperty:(objc_property_t)property;\n+ (SEL)setterSelectorForProperty:(objc_property_t)property;\n+ (NSString *)fullDescriptionForProperty:(objc_property_t)property;\n+ (id)valueForProperty:(objc_property_t)property onObject:(id)object;\n+ (NSString *)descriptionForIvarOrPropertyValue:(id)value;\n+ (void)tryAddPropertyWithName:(const char *)name attributes:(NSDictionary<NSString *, NSString *> *)attributePairs toClass:(__unsafe_unretained Class)theClass;\n\n// Ivar Helpers\n+ (NSString *)prettyNameForIvar:(Ivar)ivar;\n+ (id)valueForIvar:(Ivar)ivar onObject:(id)object;\n+ (void)setValue:(id)value forIvar:(Ivar)ivar onObject:(id)object;\n\n// Method Helpers\n+ (NSString *)prettyNameForMethod:(Method)method isClassMethod:(BOOL)isClassMethod;\n+ (NSArray *)prettyArgumentComponentsForMethod:(Method)method;\n\n// Method Calling/Field Editing\n+ (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray *)arguments error:(NSError * __autoreleasing *)error;\n+ (NSString *)editableJSONStringForObject:(id)object;\n+ (id)objectValueFromEditableJSONString:(NSString *)string;\n+ (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputString:(NSString *)inputString;\n+ (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:(void (^)(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset))typeBlock;\n+ (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)type;\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXRuntimeUtility.m",
    "content": "//\n//  FLEXRuntimeUtility.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/8/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FLEXRuntimeUtility.h\"\n\n// See https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW6\nNSString *const kFLEXUtilityAttributeTypeEncoding = @\"T\";\nNSString *const kFLEXUtilityAttributeBackingIvar = @\"V\";\nNSString *const kFLEXUtilityAttributeReadOnly = @\"R\";\nNSString *const kFLEXUtilityAttributeCopy = @\"C\";\nNSString *const kFLEXUtilityAttributeRetain = @\"&\";\nNSString *const kFLEXUtilityAttributeNonAtomic = @\"N\";\nNSString *const kFLEXUtilityAttributeCustomGetter = @\"G\";\nNSString *const kFLEXUtilityAttributeCustomSetter = @\"S\";\nNSString *const kFLEXUtilityAttributeDynamic = @\"D\";\nNSString *const kFLEXUtilityAttributeWeak = @\"W\";\nNSString *const kFLEXUtilityAttributeGarbageCollectable = @\"P\";\nNSString *const kFLEXUtilityAttributeOldStyleTypeEncoding = @\"t\";\n\nstatic NSString *const FLEXRuntimeUtilityErrorDomain = @\"FLEXRuntimeUtilityErrorDomain\";\ntypedef NS_ENUM(NSInteger, FLEXRuntimeUtilityErrorCode) {\n    FLEXRuntimeUtilityErrorCodeDoesNotRecognizeSelector = 0,\n    FLEXRuntimeUtilityErrorCodeInvocationFailed = 1,\n    FLEXRuntimeUtilityErrorCodeArgumentTypeMismatch = 2\n};\n\n// Arguments 0 and 1 are self and _cmd always\nconst unsigned int kFLEXNumberOfImplicitArgs = 2;\n\n@implementation FLEXRuntimeUtility\n\n\n#pragma mark - Property Helpers (Public)\n\n+ (NSString *)prettyNameForProperty:(objc_property_t)property\n{\n    NSString *name = @(property_getName(property));\n    NSString *encoding = [self typeEncodingForProperty:property];\n    NSString *readableType = [self readableTypeForEncoding:encoding];\n    return [self appendName:name toType:readableType];\n}\n\n+ (NSString *)typeEncodingForProperty:(objc_property_t)property\n{\n    NSDictionary<NSString *, NSString *> *attributesDictionary = [self attributesDictionaryForProperty:property];\n    return attributesDictionary[kFLEXUtilityAttributeTypeEncoding];\n}\n\n+ (BOOL)isReadonlyProperty:(objc_property_t)property\n{\n    return [[self attributesDictionaryForProperty:property] objectForKey:kFLEXUtilityAttributeReadOnly] != nil;\n}\n\n+ (SEL)setterSelectorForProperty:(objc_property_t)property\n{\n    SEL setterSelector = NULL;\n    NSString *setterSelectorString = [[self attributesDictionaryForProperty:property] objectForKey:kFLEXUtilityAttributeCustomSetter];\n    if (!setterSelectorString) {\n        NSString *propertyName = @(property_getName(property));\n        setterSelectorString = [NSString stringWithFormat:@\"set%@%@:\", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]];\n    }\n    if (setterSelectorString) {\n        setterSelector = NSSelectorFromString(setterSelectorString);\n    }\n    return setterSelector;\n}\n\n+ (NSString *)fullDescriptionForProperty:(objc_property_t)property\n{\n    NSDictionary<NSString *, NSString *> *attributesDictionary = [self attributesDictionaryForProperty:property];\n    NSMutableArray<NSString *> *attributesStrings = [NSMutableArray array];\n    \n    // Atomicity\n    if (attributesDictionary[kFLEXUtilityAttributeNonAtomic]) {\n        [attributesStrings addObject:@\"nonatomic\"];\n    } else {\n        [attributesStrings addObject:@\"atomic\"];\n    }\n    \n    // Storage\n    if (attributesDictionary[kFLEXUtilityAttributeRetain]) {\n        [attributesStrings addObject:@\"strong\"];\n    } else if (attributesDictionary[kFLEXUtilityAttributeCopy]) {\n        [attributesStrings addObject:@\"copy\"];\n    } else if (attributesDictionary[kFLEXUtilityAttributeWeak]) {\n        [attributesStrings addObject:@\"weak\"];\n    } else {\n        [attributesStrings addObject:@\"assign\"];\n    }\n    \n    // Mutability\n    if (attributesDictionary[kFLEXUtilityAttributeReadOnly]) {\n        [attributesStrings addObject:@\"readonly\"];\n    } else {\n        [attributesStrings addObject:@\"readwrite\"];\n    }\n    \n    // Custom getter/setter\n    NSString *customGetter = attributesDictionary[kFLEXUtilityAttributeCustomGetter];\n    NSString *customSetter = attributesDictionary[kFLEXUtilityAttributeCustomSetter];\n    if (customGetter) {\n        [attributesStrings addObject:[NSString stringWithFormat:@\"getter=%@\", customGetter]];\n    }\n    if (customSetter) {\n        [attributesStrings addObject:[NSString stringWithFormat:@\"setter=%@\", customSetter]];\n    }\n    \n    NSString *attributesString = [attributesStrings componentsJoinedByString:@\", \"];\n    NSString *shortName = [self prettyNameForProperty:property];\n    \n    return [NSString stringWithFormat:@\"@property (%@) %@\", attributesString, shortName];\n}\n\n+ (id)valueForProperty:(objc_property_t)property onObject:(id)object\n{\n    NSString *customGetterString = nil;\n    char *customGetterName = property_copyAttributeValue(property, \"G\");\n    if (customGetterName) {\n        customGetterString = @(customGetterName);\n        free(customGetterName);\n    }\n    \n    SEL getterSelector;\n    if ([customGetterString length] > 0) {\n        getterSelector = NSSelectorFromString(customGetterString);\n    } else {\n        NSString *propertyName = @(property_getName(property));\n        getterSelector = NSSelectorFromString(propertyName);\n    }\n    \n    return [self performSelector:getterSelector onObject:object withArguments:nil error:NULL];\n}\n\n+ (NSString *)descriptionForIvarOrPropertyValue:(id)value\n{\n    NSString *description = nil;\n    \n    // Special case BOOL for better readability.\n    if ([value isKindOfClass:[NSValue class]]) {\n        const char *type = [value objCType];\n        if (strcmp(type, @encode(BOOL)) == 0) {\n            BOOL boolValue = NO;\n            [value getValue:&boolValue];\n            description = boolValue ? @\"YES\" : @\"NO\";\n        } else if (strcmp(type, @encode(SEL)) == 0) {\n            SEL selector = NULL;\n            [value getValue:&selector];\n            description = NSStringFromSelector(selector);\n        }\n    }\n    \n    @try {\n        if (!description) {\n            // Single line display - replace newlines and tabs with spaces.\n            description = [[value description] stringByReplacingOccurrencesOfString:@\"\\n\" withString:@\" \"];\n            description = [description stringByReplacingOccurrencesOfString:@\"\\t\" withString:@\" \"];\n        }\n    } @catch (NSException *e) {\n        description = [@\"Thrown: \" stringByAppendingString:e.reason ?: @\"(nil exception reason)\"];\n    }\n    \n    if (!description) {\n        description = @\"nil\";\n    }\n    \n    return description;\n}\n\n+ (void)tryAddPropertyWithName:(const char *)name attributes:(NSDictionary<NSString *, NSString *> *)attributePairs toClass:(__unsafe_unretained Class)theClass\n{\n    objc_property_t property = class_getProperty(theClass, name);\n    if (!property) {\n        unsigned int totalAttributesCount = (unsigned int)[attributePairs count];\n        objc_property_attribute_t *attributes = malloc(sizeof(objc_property_attribute_t) * totalAttributesCount);\n        if (attributes) {\n            unsigned int attributeIndex = 0;\n            for (NSString *attributeName in [attributePairs allKeys]) {\n                objc_property_attribute_t attribute;\n                attribute.name = [attributeName UTF8String];\n                attribute.value = [attributePairs[attributeName] UTF8String];\n                attributes[attributeIndex++] = attribute;\n            }\n            \n            class_addProperty(theClass, name, attributes, totalAttributesCount);\n            free(attributes);\n        }\n    }\n}\n\n\n#pragma mark - Ivar Helpers (Public)\n\n+ (NSString *)prettyNameForIvar:(Ivar)ivar\n{\n    const char *nameCString = ivar_getName(ivar);\n    NSString *name = nameCString ? @(nameCString) : nil;\n    const char *encodingCString = ivar_getTypeEncoding(ivar);\n    NSString *encoding = encodingCString ? @(encodingCString) : nil;\n    NSString *readableType = [self readableTypeForEncoding:encoding];\n    return [self appendName:name toType:readableType];\n}\n\n+ (id)valueForIvar:(Ivar)ivar onObject:(id)object\n{\n    id value = nil;\n    const char *type = ivar_getTypeEncoding(ivar);\n#ifdef __arm64__\n    // See http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html\n    const char *name = ivar_getName(ivar);\n    if (type[0] == @encode(Class)[0] && strcmp(name, \"isa\") == 0) {\n        value = object_getClass(object);\n    } else\n#endif\n    if (type[0] == @encode(id)[0] || type[0] == @encode(Class)[0]) {\n        value = object_getIvar(object, ivar);\n    } else {\n        ptrdiff_t offset = ivar_getOffset(ivar);\n        void *pointer = (__bridge void *)object + offset;\n        value = [self valueForPrimitivePointer:pointer objCType:type];\n    }\n    return value;\n}\n\n+ (void)setValue:(id)value forIvar:(Ivar)ivar onObject:(id)object\n{\n    const char *typeEncodingCString = ivar_getTypeEncoding(ivar);\n    if (typeEncodingCString[0] == '@') {\n        object_setIvar(object, ivar, value);\n    } else if ([value isKindOfClass:[NSValue class]]) {\n        // Primitive - unbox the NSValue.\n        NSValue *valueValue = (NSValue *)value;\n        \n        // Make sure that the box contained the correct type.\n        NSAssert(strcmp([valueValue objCType], typeEncodingCString) == 0, @\"Type encoding mismatch (value: %s; ivar: %s) in setting ivar named: %s on object: %@\", [valueValue objCType], typeEncodingCString, ivar_getName(ivar), object);\n        \n        NSUInteger bufferSize = 0;\n        @try {\n            // NSGetSizeAndAlignment barfs on type encoding for bitfields.\n            NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);\n        } @catch (NSException *exception) { }\n        if (bufferSize > 0) {\n            void *buffer = calloc(bufferSize, 1);\n            [valueValue getValue:buffer];\n            ptrdiff_t offset = ivar_getOffset(ivar);\n            void *pointer = (__bridge void *)object + offset;\n            memcpy(pointer, buffer, bufferSize);\n            free(buffer);\n        }\n    }\n}\n\n\n#pragma mark - Method Helpers (Public)\n\n+ (NSString *)prettyNameForMethod:(Method)method isClassMethod:(BOOL)isClassMethod\n{\n    NSString *selectorName = NSStringFromSelector(method_getName(method));\n    NSString *methodTypeString = isClassMethod ? @\"+\" : @\"-\";\n    char *returnType = method_copyReturnType(method);\n    NSString *readableReturnType = [self readableTypeForEncoding:@(returnType)];\n    free(returnType);\n    NSString *prettyName = [NSString stringWithFormat:@\"%@ (%@)\", methodTypeString, readableReturnType];\n    NSArray<NSString *> *components = [self prettyArgumentComponentsForMethod:method];\n    if ([components count] > 0) {\n        prettyName = [prettyName stringByAppendingString:[components componentsJoinedByString:@\" \"]];\n    } else {\n        prettyName = [prettyName stringByAppendingString:selectorName];\n    }\n    \n    return prettyName;\n}\n\n+ (NSArray<NSString *> *)prettyArgumentComponentsForMethod:(Method)method\n{\n    NSMutableArray<NSString *> *components = [NSMutableArray array];\n    \n    NSString *selectorName = NSStringFromSelector(method_getName(method));\n    NSMutableArray<NSString *> *selectorComponents = [[selectorName componentsSeparatedByString:@\":\"] mutableCopy];\n    \n    // this is a workaround cause method_getNumberOfArguments() returns wrong number for some methods\n    if (selectorComponents.count == 1) {\n        return [selectorComponents copy];\n    }\n    \n    if ([selectorComponents.lastObject isEqualToString:@\"\"]) {\n        [selectorComponents removeLastObject];\n    }\n    \n    for (unsigned int argIndex = 0; argIndex < selectorComponents.count; argIndex++) {\n        char *argType = method_copyArgumentType(method, argIndex + kFLEXNumberOfImplicitArgs);\n        NSString *readableArgType = (argType != NULL) ? [self readableTypeForEncoding:@(argType)] : nil;\n        free(argType);\n        NSString *prettyComponent = [NSString stringWithFormat:@\"%@:(%@) \", [selectorComponents objectAtIndex:argIndex], readableArgType];\n        [components addObject:prettyComponent];\n    }\n    \n    return components;\n}\n\n\n#pragma mark - Method Calling/Field Editing (Public)\n\n+ (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray *)arguments error:(NSError * __autoreleasing *)error\n{\n    // Bail if the object won't respond to this selector.\n    if (![object respondsToSelector:selector]) {\n        if (error) {\n            NSDictionary<NSString *, id> *userInfo = @{ NSLocalizedDescriptionKey : [NSString stringWithFormat:@\"%@ does not respond to the selector %@\", object, NSStringFromSelector(selector)]};\n            *error = [NSError errorWithDomain:FLEXRuntimeUtilityErrorDomain code:FLEXRuntimeUtilityErrorCodeDoesNotRecognizeSelector userInfo:userInfo];\n        }\n        return nil;\n    }\n    \n    // Build the invocation\n    NSMethodSignature *methodSignature = [object methodSignatureForSelector:selector];\n    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];\n    [invocation setSelector:selector];\n    [invocation setTarget:object];\n    [invocation retainArguments];\n    \n    // Always self and _cmd\n    NSUInteger numberOfArguments = [methodSignature numberOfArguments];\n    for (NSUInteger argumentIndex = kFLEXNumberOfImplicitArgs; argumentIndex < numberOfArguments; argumentIndex++) {\n        NSUInteger argumentsArrayIndex = argumentIndex - kFLEXNumberOfImplicitArgs;\n        id argumentObject = [arguments count] > argumentsArrayIndex ? arguments[argumentsArrayIndex] : nil;\n        \n        // NSNull in the arguments array can be passed as a placeholder to indicate nil. We only need to set the argument if it will be non-nil.\n        if (argumentObject && ![argumentObject isKindOfClass:[NSNull class]]) {\n            const char *typeEncodingCString = [methodSignature getArgumentTypeAtIndex:argumentIndex];\n            if (typeEncodingCString[0] == @encode(id)[0] || typeEncodingCString[0] == @encode(Class)[0] || [self isTollFreeBridgedValue:argumentObject forCFType:typeEncodingCString]) {\n                // Object\n                [invocation setArgument:&argumentObject atIndex:argumentIndex];\n            } else if (strcmp(typeEncodingCString, @encode(CGColorRef)) == 0 && [argumentObject isKindOfClass:[UIColor class]]) {\n                // Bridging UIColor to CGColorRef\n                CGColorRef colorRef = [argumentObject CGColor];\n                [invocation setArgument:&colorRef atIndex:argumentIndex];\n            } else if ([argumentObject isKindOfClass:[NSValue class]]) {\n                // Primitive boxed in NSValue\n                NSValue *argumentValue = (NSValue *)argumentObject;\n                \n                // Ensure that the type encoding on the NSValue matches the type encoding of the argument in the method signature\n                if (strcmp([argumentValue objCType], typeEncodingCString) != 0) {\n                    if (error) {\n                        NSDictionary<NSString *, id> *userInfo = @{ NSLocalizedDescriptionKey : [NSString stringWithFormat:@\"Type encoding mismatch for agrument at index %lu. Value type: %s; Method argument type: %s.\", (unsigned long)argumentsArrayIndex, [argumentValue objCType], typeEncodingCString]};\n                        *error = [NSError errorWithDomain:FLEXRuntimeUtilityErrorDomain code:FLEXRuntimeUtilityErrorCodeArgumentTypeMismatch userInfo:userInfo];\n                    }\n                    return nil;\n                }\n                \n                NSUInteger bufferSize = 0;\n                @try {\n                    // NSGetSizeAndAlignment barfs on type encoding for bitfields.\n                    NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);\n                } @catch (NSException *exception) { }\n                \n                if (bufferSize > 0) {\n                    void *buffer = calloc(bufferSize, 1);\n                    [argumentValue getValue:buffer];\n                    [invocation setArgument:buffer atIndex:argumentIndex];\n                    free(buffer);\n                }\n            }\n        }\n    }\n    \n    // Try to invoke the invocation but guard against an exception being thrown.\n    BOOL successfullyInvoked = NO;\n    @try {\n        // Some methods are not fit to be called...\n        // Looking at you -[UIResponder(UITextInputAdditions) _caretRect]\n        [invocation invoke];\n        successfullyInvoked = YES;\n    } @catch (NSException *exception) {\n        // Bummer...\n        if (error) {\n            // \"… on <class>\" / \"… on instance of <class>\"\n            NSString *class = NSStringFromClass([object class]);\n            NSString *calledOn = object == [object class] ? class : [@\"an instance of \" stringByAppendingString:class];\n\n            NSString *message = [NSString stringWithFormat:@\"Exception '%@' thrown while performing selector '%@' on %@.\\nReason:\\n\\n%@\",\n                                 exception.name,\n                                 NSStringFromSelector(selector),\n                                 calledOn,\n                                 exception.reason];\n\n            *error = [NSError errorWithDomain:FLEXRuntimeUtilityErrorDomain\n                                         code:FLEXRuntimeUtilityErrorCodeInvocationFailed\n                                     userInfo:@{ NSLocalizedDescriptionKey : message }];\n        }\n    }\n    \n    // Retreive the return value and box if necessary.\n    id returnObject = nil;\n    if (successfullyInvoked) {\n        const char *returnType = [methodSignature methodReturnType];\n        if (returnType[0] == @encode(id)[0] || returnType[0] == @encode(Class)[0]) {\n            __unsafe_unretained id objectReturnedFromMethod = nil;\n            [invocation getReturnValue:&objectReturnedFromMethod];\n            returnObject = objectReturnedFromMethod;\n        } else if (returnType[0] != @encode(void)[0]) {\n            void *returnValue = malloc([methodSignature methodReturnLength]);\n            if (returnValue) {\n                [invocation getReturnValue:returnValue];\n                returnObject = [self valueForPrimitivePointer:returnValue objCType:returnType];\n                free(returnValue);\n            }\n        }\n    }\n    \n    return returnObject;\n}\n\n+ (BOOL)isTollFreeBridgedValue:(id)value forCFType:(const char *)typeEncoding\n{\n    // See https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/Toll-FreeBridgin/Toll-FreeBridgin.html\n#define CASE(cftype, foundationClass) \\\n    if(strcmp(typeEncoding, @encode(cftype)) == 0) { \\\n        return [value isKindOfClass:[foundationClass class]]; \\\n    }\n    \n    CASE(CFArrayRef, NSArray);\n    CASE(CFAttributedStringRef, NSAttributedString);\n    CASE(CFCalendarRef, NSCalendar);\n    CASE(CFCharacterSetRef, NSCharacterSet);\n    CASE(CFDataRef, NSData);\n    CASE(CFDateRef, NSDate);\n    CASE(CFDictionaryRef, NSDictionary);\n    CASE(CFErrorRef, NSError);\n    CASE(CFLocaleRef, NSLocale);\n    CASE(CFMutableArrayRef, NSMutableArray);\n    CASE(CFMutableAttributedStringRef, NSMutableAttributedString);\n    CASE(CFMutableCharacterSetRef, NSMutableCharacterSet);\n    CASE(CFMutableDataRef, NSMutableData);\n    CASE(CFMutableDictionaryRef, NSMutableDictionary);\n    CASE(CFMutableSetRef, NSMutableSet);\n    CASE(CFMutableStringRef, NSMutableString);\n    CASE(CFNumberRef, NSNumber);\n    CASE(CFReadStreamRef, NSInputStream);\n    CASE(CFRunLoopTimerRef, NSTimer);\n    CASE(CFSetRef, NSSet);\n    CASE(CFStringRef, NSString);\n    CASE(CFTimeZoneRef, NSTimeZone);\n    CASE(CFURLRef, NSURL);\n    CASE(CFWriteStreamRef, NSOutputStream);\n    \n#undef CASE\n    \n    return NO;\n}\n\n+ (NSString *)editableJSONStringForObject:(id)object\n{\n    NSString *editableDescription = nil;\n    \n    if (object) {\n        // This is a hack to use JSON serialization for our editable objects.\n        // NSJSONSerialization doesn't allow writing fragments - the top level object must be an array or dictionary.\n        // We always wrap the object inside an array and then strip the outer square braces off the final string.\n        NSArray *wrappedObject = @[object];\n        if ([NSJSONSerialization isValidJSONObject:wrappedObject]) {\n            NSString *wrappedDescription = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:wrappedObject options:0 error:NULL] encoding:NSUTF8StringEncoding];\n            editableDescription = [wrappedDescription substringWithRange:NSMakeRange(1, [wrappedDescription length] - 2)];\n        }\n    }\n    \n    return editableDescription;\n}\n\n+ (id)objectValueFromEditableJSONString:(NSString *)string\n{\n    id value = nil;\n    // nil for empty string/whitespace\n    if ([[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] > 0) {\n        value = [NSJSONSerialization JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:NULL];\n    }\n    return value;\n}\n\n+ (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputString:(NSString *)inputString\n{\n    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];\n    [formatter setNumberStyle:NSNumberFormatterDecimalStyle];\n    NSNumber *number = [formatter numberFromString:inputString];\n    \n    // Make sure we box the number with the correct type encoding so it can be propperly unboxed later via getValue:\n    NSValue *value = nil;\n    if (strcmp(typeEncoding, @encode(char)) == 0) {\n        char primitiveValue = [number charValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(int)) == 0) {\n        int primitiveValue = [number intValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(short)) == 0) {\n        short primitiveValue = [number shortValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(long)) == 0) {\n        long primitiveValue = [number longValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(long long)) == 0) {\n        long long primitiveValue = [number longLongValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(unsigned char)) == 0) {\n        unsigned char primitiveValue = [number unsignedCharValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(unsigned int)) == 0) {\n        unsigned int primitiveValue = [number unsignedIntValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(unsigned short)) == 0) {\n        unsigned short primitiveValue = [number unsignedShortValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(unsigned long)) == 0) {\n        unsigned long primitiveValue = [number unsignedLongValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(unsigned long long)) == 0) {\n        unsigned long long primitiveValue = [number unsignedLongValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(float)) == 0) {\n        float primitiveValue = [number floatValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    } else if (strcmp(typeEncoding, @encode(double)) == 0) {\n        double primitiveValue = [number doubleValue];\n        value = [NSValue value:&primitiveValue withObjCType:typeEncoding];\n    }\n    \n    return value;\n}\n\n+ (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:(void (^)(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset))typeBlock\n{\n    if (structEncoding && structEncoding[0] == '{') {\n        const char *equals = strchr(structEncoding, '=');\n        if (equals) {\n            const char *nameStart = structEncoding + 1;\n            NSString *structName = [@(structEncoding) substringWithRange:NSMakeRange(nameStart - structEncoding, equals - nameStart)];\n            \n            NSUInteger fieldAlignment = 0;\n            NSUInteger structSize = 0;\n            @try {\n                // NSGetSizeAndAlignment barfs on type encoding for bitfields.\n                NSGetSizeAndAlignment(structEncoding, &structSize, &fieldAlignment);\n            } @catch (NSException *exception) { }\n            \n            if (structSize > 0) {\n                NSUInteger runningFieldIndex = 0;\n                NSUInteger runningFieldOffset = 0;\n                const char *typeStart = equals + 1;\n                while (*typeStart != '}') {\n                    NSUInteger fieldSize = 0;\n                    // If the struct type encoding was successfully handled by NSGetSizeAndAlignment above, we *should* be ok with the field here.\n                    const char *nextTypeStart = NSGetSizeAndAlignment(typeStart, &fieldSize, NULL);\n                    NSString *typeEncoding = [@(structEncoding) substringWithRange:NSMakeRange(typeStart - structEncoding, nextTypeStart - typeStart)];\n                    typeBlock(structName, [typeEncoding UTF8String], [self readableTypeForEncoding:typeEncoding], runningFieldIndex, runningFieldOffset);\n                    runningFieldOffset += fieldSize;\n                    // Padding to keep propper alignment. __attribute((packed)) structs will break here.\n                    // The type encoding is no different for packed structs, so it's not clear there's anything we can do for those.\n                    if (runningFieldOffset % fieldAlignment != 0) {\n                        runningFieldOffset += fieldAlignment - runningFieldOffset % fieldAlignment;\n                    }\n                    runningFieldIndex++;\n                    typeStart = nextTypeStart;\n                }\n            }\n        }\n    }\n}\n\n\n#pragma mark - Internal Helpers\n\n+ (NSDictionary<NSString *, NSString *> *)attributesDictionaryForProperty:(objc_property_t)property\n{\n    NSString *attributes = @(property_getAttributes(property));\n    // Thanks to MAObjcRuntime for inspiration here.\n    NSArray<NSString *> *attributePairs = [attributes componentsSeparatedByString:@\",\"];\n    NSMutableDictionary<NSString *, NSString *> *attributesDictionary = [NSMutableDictionary dictionaryWithCapacity:[attributePairs count]];\n    for (NSString *attributePair in attributePairs) {\n        [attributesDictionary setObject:[attributePair substringFromIndex:1] forKey:[attributePair substringToIndex:1]];\n    }\n    return attributesDictionary;\n}\n\n+ (NSString *)appendName:(NSString *)name toType:(NSString *)type\n{\n    NSString *combined = nil;\n    if ([type characterAtIndex:[type length] - 1] == '*') {\n        combined = [type stringByAppendingString:name];\n    } else {\n        combined = [type stringByAppendingFormat:@\" %@\", name];\n    }\n    return combined;\n}\n\n+ (NSString *)readableTypeForEncoding:(NSString *)encodingString\n{\n    if (!encodingString) {\n        return nil;\n    }\n    \n    // See https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html\n    // class-dump has a much nicer and much more complete implementation for this task, but it is distributed under GPLv2 :/\n    // See https://github.com/nygard/class-dump/blob/master/Source/CDType.m\n    // Warning: this method uses multiple middle returns and macros to cut down on boilerplate.\n    // The use of macros here was inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html\n    const char *encodingCString = [encodingString UTF8String];\n    \n    // Objects\n    if (encodingCString[0] == '@') {\n        NSString *class = [encodingString substringFromIndex:1];\n        class = [class stringByReplacingOccurrencesOfString:@\"\\\"\" withString:@\"\"];\n        if ([class length] == 0 || [class isEqual:@\"?\"]) {\n            class = @\"id\";\n        } else {\n            class = [class stringByAppendingString:@\" *\"];\n        }\n        return class;\n    }\n    \n    // C Types\n#define TRANSLATE(ctype) \\\n    if (strcmp(encodingCString, @encode(ctype)) == 0) { \\\n        return (NSString *)CFSTR(#ctype); \\\n    }\n    \n    // Order matters here since some of the cocoa types are typedefed to c types.\n    // We can't recover the exact mapping, but we choose to prefer the cocoa types.\n    // This is not an exhaustive list, but it covers the most common types\n    TRANSLATE(CGRect);\n    TRANSLATE(CGPoint);\n    TRANSLATE(CGSize);\n    TRANSLATE(UIEdgeInsets);\n    TRANSLATE(UIOffset);\n    TRANSLATE(NSRange);\n    TRANSLATE(CGAffineTransform);\n    TRANSLATE(CATransform3D);\n    TRANSLATE(CGColorRef);\n    TRANSLATE(CGPathRef);\n    TRANSLATE(CGContextRef);\n    TRANSLATE(NSInteger);\n    TRANSLATE(NSUInteger);\n    TRANSLATE(CGFloat);\n    TRANSLATE(BOOL);\n    TRANSLATE(int);\n    TRANSLATE(short);\n    TRANSLATE(long);\n    TRANSLATE(long long);\n    TRANSLATE(unsigned char);\n    TRANSLATE(unsigned int);\n    TRANSLATE(unsigned short);\n    TRANSLATE(unsigned long);\n    TRANSLATE(unsigned long long);\n    TRANSLATE(float);\n    TRANSLATE(double);\n    TRANSLATE(long double);\n    TRANSLATE(char *);\n    TRANSLATE(Class);\n    TRANSLATE(objc_property_t);\n    TRANSLATE(Ivar);\n    TRANSLATE(Method);\n    TRANSLATE(Category);\n    TRANSLATE(NSZone *);\n    TRANSLATE(SEL);\n    TRANSLATE(void);\n    \n#undef TRANSLATE\n    \n    // Qualifier Prefixes\n    // Do this after the checks above since some of the direct translations (i.e. Method) contain a prefix.\n#define RECURSIVE_TRANSLATE(prefix, formatString) \\\n    if (encodingCString[0] == prefix) { \\\n        NSString *recursiveType = [self readableTypeForEncoding:[encodingString substringFromIndex:1]]; \\\n        return [NSString stringWithFormat:formatString, recursiveType]; \\\n    }\n    \n    // If there's a qualifier prefix on the encoding, translate it and then\n    // recursively call this method with the rest of the encoding string.\n    RECURSIVE_TRANSLATE('^', @\"%@ *\");\n    RECURSIVE_TRANSLATE('r', @\"const %@\");\n    RECURSIVE_TRANSLATE('n', @\"in %@\");\n    RECURSIVE_TRANSLATE('N', @\"inout %@\");\n    RECURSIVE_TRANSLATE('o', @\"out %@\");\n    RECURSIVE_TRANSLATE('O', @\"bycopy %@\");\n    RECURSIVE_TRANSLATE('R', @\"byref %@\");\n    RECURSIVE_TRANSLATE('V', @\"oneway %@\");\n    RECURSIVE_TRANSLATE('b', @\"bitfield(%@)\");\n    \n#undef RECURSIVE_TRANSLATE\n    \n    // If we couldn't translate, just return the original encoding string\n    return encodingString;\n}\n\n+ (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)type\n{\n    // CASE macro inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html\n#define CASE(ctype, selectorpart) \\\n    if(strcmp(type, @encode(ctype)) == 0) { \\\n        return [NSNumber numberWith ## selectorpart: *(ctype *)pointer]; \\\n    }\n    \n    CASE(BOOL, Bool);\n    CASE(unsigned char, UnsignedChar);\n    CASE(short, Short);\n    CASE(unsigned short, UnsignedShort);\n    CASE(int, Int);\n    CASE(unsigned int, UnsignedInt);\n    CASE(long, Long);\n    CASE(unsigned long, UnsignedLong);\n    CASE(long long, LongLong);\n    CASE(unsigned long long, UnsignedLongLong);\n    CASE(float, Float);\n    CASE(double, Double);\n    \n#undef CASE\n    \n    NSValue *value = nil;\n    @try {\n        value = [NSValue valueWithBytes:pointer objCType:type];\n    } @catch (NSException *exception) {\n        // Certain type encodings are not supported by valueWithBytes:objCType:. Just fail silently if an exception is thrown.\n    }\n    \n    return value;\n}\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXUtility.h",
    "content": "//\n//  FLEXUtility.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/18/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <Availability.h>\n#import <AvailabilityInternal.h>\n#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n#import <objc/runtime.h>\n\n#define FLEXFloor(x) (floor([[UIScreen mainScreen] scale] * (x)) / [[UIScreen mainScreen] scale])\n\n#if defined(__IPHONE_11_0)\n#define FLEX_AT_LEAST_IOS11_SDK (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0)\n#else\n#define FLEX_AT_LEAST_IOS11_SDK NO\n#endif\n\n@interface FLEXUtility : NSObject\n\n+ (UIColor *)consistentRandomColorForObject:(id)object;\n+ (NSString *)descriptionForView:(UIView *)view includingFrame:(BOOL)includeFrame;\n+ (NSString *)stringForCGRect:(CGRect)rect;\n+ (UIViewController *)viewControllerForView:(UIView *)view;\n+ (UIViewController *)viewControllerForAncestralView:(UIView *)view;\n+ (NSString *)detailDescriptionForView:(UIView *)view;\n+ (UIImage *)circularImageWithColor:(UIColor *)color radius:(CGFloat)radius;\n+ (UIColor *)scrollViewGrayColor;\n+ (UIColor *)hierarchyIndentPatternColor;\n+ (NSString *)applicationImageName;\n+ (NSString *)applicationName;\n+ (NSString *)safeDescriptionForObject:(id)object;\n+ (UIFont *)defaultFontOfSize:(CGFloat)size;\n+ (UIFont *)defaultTableViewCellLabelFont;\n+ (NSString *)stringByEscapingHTMLEntitiesInString:(NSString *)originalString;\n+ (UIInterfaceOrientationMask)infoPlistSupportedInterfaceOrientationsMask;\n+ (NSString *)searchBarPlaceholderText;\n+ (BOOL)isImagePathExtension:(NSString *)extension;\n+ (UIImage *)thumbnailedImageWithMaxPixelDimension:(NSInteger)dimension fromImageData:(NSData *)data;\n+ (NSString *)stringFromRequestDuration:(NSTimeInterval)duration;\n+ (NSString *)statusCodeStringFromURLResponse:(NSURLResponse *)response;\n+ (BOOL)isErrorStatusCodeFromURLResponse:(NSURLResponse *)response;\n+ (NSDictionary<NSString *, id> *)dictionaryFromQuery:(NSString *)query;\n+ (NSString *)prettyJSONStringFromData:(NSData *)data;\n+ (BOOL)isValidJSONData:(NSData *)data;\n+ (NSData *)inflatedDataFromCompressedData:(NSData *)compressedData;\n\n+ (NSArray<UIWindow *> *)allWindows;\n\n// Swizzling utilities\n\n+ (SEL)swizzledSelectorForSelector:(SEL)selector;\n+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls;\n+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)class withBlock:(id)block swizzledSelector:(SEL)swizzledSelector;\n+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock;\n\n@end\n"
  },
  {
    "path": "FLEX/Utility/FLEXUtility.m",
    "content": "//\n//  FLEXUtility.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 4/18/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXUtility.h\"\n#import \"FLEXResources.h\"\n#import <ImageIO/ImageIO.h>\n#import <zlib.h>\n#import <objc/runtime.h>\n\n@implementation FLEXUtility\n\n+ (UIColor *)consistentRandomColorForObject:(id)object\n{\n    CGFloat hue = (((NSUInteger)object >> 4) % 256) / 255.0;\n    return [UIColor colorWithHue:hue saturation:1.0 brightness:1.0 alpha:1.0];\n}\n\n+ (NSString *)descriptionForView:(UIView *)view includingFrame:(BOOL)includeFrame\n{\n    NSString *description = [[view class] description];\n    \n    NSString *viewControllerDescription = [[[self viewControllerForView:view] class] description];\n    if ([viewControllerDescription length] > 0) {\n        description = [description stringByAppendingFormat:@\" (%@)\", viewControllerDescription];\n    }\n    \n    if (includeFrame) {\n        description = [description stringByAppendingFormat:@\" %@\", [self stringForCGRect:view.frame]];\n    }\n    \n    if ([view.accessibilityLabel length] > 0) {\n        description = [description stringByAppendingFormat:@\" · %@\", view.accessibilityLabel];\n    }\n    \n    return description;\n}\n\n+ (NSString *)stringForCGRect:(CGRect)rect\n{\n    return [NSString stringWithFormat:@\"{(%g, %g), (%g, %g)}\", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height];\n}\n\n+ (UIViewController *)viewControllerForView:(UIView *)view\n{\n    UIViewController *viewController = nil;\n    SEL viewDelSel = NSSelectorFromString([NSString stringWithFormat:@\"%@ewDelegate\", @\"_vi\"]);\n    if ([view respondsToSelector:viewDelSel]) {\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Warc-performSelector-leaks\"\n        viewController = [view performSelector:viewDelSel];\n#pragma clang diagnostic pop\n    }\n    return viewController;\n}\n\n+ (UIViewController *)viewControllerForAncestralView:(UIView *)view{\n    UIViewController *viewController = nil;\n    SEL viewDelSel = NSSelectorFromString([NSString stringWithFormat:@\"%@ewControllerForAncestor\", @\"_vi\"]);\n    if ([view respondsToSelector:viewDelSel]) {\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Warc-performSelector-leaks\"\n        viewController = [view performSelector:viewDelSel];\n#pragma clang diagnostic pop\n    }\n    return viewController;\n}\n\n+ (NSString *)detailDescriptionForView:(UIView *)view\n{\n    return [NSString stringWithFormat:@\"frame %@\", [self stringForCGRect:view.frame]];\n}\n\n+ (UIImage *)circularImageWithColor:(UIColor *)color radius:(CGFloat)radius\n{\n    CGFloat diameter = radius * 2.0;\n    UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), NO, 0.0);\n    CGContextRef imageContext = UIGraphicsGetCurrentContext();\n    CGContextSetFillColorWithColor(imageContext, [color CGColor]);\n    CGContextFillEllipseInRect(imageContext, CGRectMake(0, 0, diameter, diameter));\n    UIImage *circularImage = UIGraphicsGetImageFromCurrentImageContext();\n    UIGraphicsEndImageContext();\n    return circularImage;\n}\n\n+ (UIColor *)scrollViewGrayColor\n{\n    return [UIColor colorWithRed:239.0/255.0 green:239.0/255.0 blue:244.0/255.0 alpha:1.0];\n}\n\n+ (UIColor *)hierarchyIndentPatternColor\n{\n    static UIColor *patternColor = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        UIImage *indentationPatternImage = [FLEXResources hierarchyIndentPattern];\n        patternColor = [UIColor colorWithPatternImage:indentationPatternImage];\n    });\n    return patternColor;\n}\n\n+ (NSString *)applicationImageName\n{\n    return [NSBundle mainBundle].executablePath;\n}\n\n+ (NSString *)applicationName\n{\n    return [FLEXUtility applicationImageName].lastPathComponent;\n}\n\n+ (NSString *)safeDescriptionForObject:(id)object\n{\n    // Don't assume that we have an NSObject subclass.\n    // Check to make sure the object responds to the description methods.\n    NSString *description = nil;\n    if ([object respondsToSelector:@selector(debugDescription)]) {\n        description = [object debugDescription];\n    } else if ([object respondsToSelector:@selector(description)]) {\n        description = [object description];\n    }\n    return description;\n}\n\n+ (UIFont *)defaultFontOfSize:(CGFloat)size\n{\n    return [UIFont fontWithName:@\"HelveticaNeue\" size:size];\n}\n\n+ (UIFont *)defaultTableViewCellLabelFont\n{\n    return [self defaultFontOfSize:12.0];\n}\n\n+ (NSString *)stringByEscapingHTMLEntitiesInString:(NSString *)originalString\n{\n    static NSDictionary<NSString *, NSString *> *escapingDictionary = nil;\n    static NSRegularExpression *regex = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        escapingDictionary = @{ @\" \" : @\"&nbsp;\",\n                                @\">\" : @\"&gt;\",\n                                @\"<\" : @\"&lt;\",\n                                @\"&\" : @\"&amp;\",\n                                @\"'\" : @\"&apos;\",\n                                @\"\\\"\" : @\"&quot;\",\n                                @\"«\" : @\"&laquo;\",\n                                @\"»\" : @\"&raquo;\"\n                                };\n        regex = [NSRegularExpression regularExpressionWithPattern:@\"(&|>|<|'|\\\"|«|»)\" options:0 error:NULL];\n    });\n    \n    NSMutableString *mutableString = [originalString mutableCopy];\n    \n    NSArray<NSTextCheckingResult *> *matches = [regex matchesInString:mutableString options:0 range:NSMakeRange(0, [mutableString length])];\n    for (NSTextCheckingResult *result in [matches reverseObjectEnumerator]) {\n        NSString *foundString = [mutableString substringWithRange:result.range];\n        NSString *replacementString = escapingDictionary[foundString];\n        if (replacementString) {\n            [mutableString replaceCharactersInRange:result.range withString:replacementString];\n        }\n    }\n    \n    return [mutableString copy];\n}\n\n+ (UIInterfaceOrientationMask)infoPlistSupportedInterfaceOrientationsMask\n{\n    NSArray<NSString *> *supportedOrientations = [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"UISupportedInterfaceOrientations\"];\n    UIInterfaceOrientationMask supportedOrientationsMask = 0;\n    if ([supportedOrientations containsObject:@\"UIInterfaceOrientationPortrait\"]) {\n        supportedOrientationsMask |= UIInterfaceOrientationMaskPortrait;\n    }\n    if ([supportedOrientations containsObject:@\"UIInterfaceOrientationMaskLandscapeRight\"]) {\n        supportedOrientationsMask |= UIInterfaceOrientationMaskLandscapeRight;\n    }\n    if ([supportedOrientations containsObject:@\"UIInterfaceOrientationMaskPortraitUpsideDown\"]) {\n        supportedOrientationsMask |= UIInterfaceOrientationMaskPortraitUpsideDown;\n    }\n    if ([supportedOrientations containsObject:@\"UIInterfaceOrientationLandscapeLeft\"]) {\n        supportedOrientationsMask |= UIInterfaceOrientationMaskLandscapeLeft;\n    }\n    return supportedOrientationsMask;\n}\n\n+ (NSString *)searchBarPlaceholderText\n{\n    return @\"Filter\";\n}\n\n+ (BOOL)isImagePathExtension:(NSString *)extension\n{\n    // https://developer.apple.com/library/ios/documentation/uikit/reference/UIImage_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006890-CH3-SW3\n    return [@[@\"jpg\", @\"jpeg\", @\"png\", @\"gif\", @\"tiff\", @\"tif\"] containsObject:extension];\n}\n\n+ (UIImage *)thumbnailedImageWithMaxPixelDimension:(NSInteger)dimension fromImageData:(NSData *)data\n{\n    UIImage *thumbnail = nil;\n    CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, 0);\n    if (imageSource) {\n        NSDictionary<NSString *, id> *options = @{ (__bridge id)kCGImageSourceCreateThumbnailWithTransform : @YES,\n                                                   (__bridge id)kCGImageSourceCreateThumbnailFromImageAlways : @YES,\n                                                   (__bridge id)kCGImageSourceThumbnailMaxPixelSize : @(dimension) };\n\n        CGImageRef scaledImageRef = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, (__bridge CFDictionaryRef)options);\n        if (scaledImageRef) {\n            thumbnail = [UIImage imageWithCGImage:scaledImageRef];\n            CFRelease(scaledImageRef);\n        }\n        CFRelease(imageSource);\n    }\n    return thumbnail;\n}\n\n+ (NSString *)stringFromRequestDuration:(NSTimeInterval)duration\n{\n    NSString *string = @\"0s\";\n    if (duration > 0.0) {\n        if (duration < 1.0) {\n            string = [NSString stringWithFormat:@\"%dms\", (int)(duration * 1000)];\n        } else if (duration < 10.0) {\n            string = [NSString stringWithFormat:@\"%.2fs\", duration];\n        } else {\n            string = [NSString stringWithFormat:@\"%.1fs\", duration];\n        }\n    }\n    return string;\n}\n\n+ (NSString *)statusCodeStringFromURLResponse:(NSURLResponse *)response\n{\n    NSString *httpResponseString = nil;\n    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {\n        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;\n        NSString *statusCodeDescription = nil;\n        if (httpResponse.statusCode == 200) {\n            // Prefer OK to the default \"no error\"\n            statusCodeDescription = @\"OK\";\n        } else {\n            statusCodeDescription = [NSHTTPURLResponse localizedStringForStatusCode:httpResponse.statusCode];\n        }\n        httpResponseString = [NSString stringWithFormat:@\"%ld %@\", (long)httpResponse.statusCode, statusCodeDescription];\n    }\n    return httpResponseString;\n}\n\n+ (BOOL)isErrorStatusCodeFromURLResponse:(NSURLResponse *)response {\n    NSIndexSet *errorStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(400, 200)];\n    \n    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {\n        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;\n        return [errorStatusCodes containsIndex:httpResponse.statusCode];\n    }\n    \n    return NO;\n}\n\n\n+ (NSDictionary<NSString *, id> *)dictionaryFromQuery:(NSString *)query\n{\n    NSMutableDictionary<NSString *, id> *queryDictionary = [NSMutableDictionary dictionary];\n\n    // [a=1, b=2, c=3]\n    NSArray<NSString *> *queryComponents = [query componentsSeparatedByString:@\"&\"];\n    for (NSString *keyValueString in queryComponents) {\n        // [a, 1]\n        NSArray<NSString *> *components = [keyValueString componentsSeparatedByString:@\"=\"];\n        if ([components count] == 2) {\n            NSString *key = [[components firstObject] stringByRemovingPercentEncoding];\n            id value = [[components lastObject] stringByRemovingPercentEncoding];\n\n            // Handle multiple entries under the same key as an array\n            id existingEntry = queryDictionary[key];\n            if (existingEntry) {\n                if ([existingEntry isKindOfClass:[NSArray class]]) {\n                    value = [existingEntry arrayByAddingObject:value];\n                } else {\n                    value = @[existingEntry, value];\n                }\n            }\n            \n            [queryDictionary setObject:value forKey:key];\n        }\n    }\n\n    return queryDictionary;\n}\n\n+ (NSString *)prettyJSONStringFromData:(NSData *)data\n{\n    NSString *prettyString = nil;\n    \n    id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];\n    if ([NSJSONSerialization isValidJSONObject:jsonObject]) {\n        prettyString = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:jsonObject options:NSJSONWritingPrettyPrinted error:NULL] encoding:NSUTF8StringEncoding];\n        // NSJSONSerialization escapes forward slashes. We want pretty json, so run through and unescape the slashes.\n        prettyString = [prettyString stringByReplacingOccurrencesOfString:@\"\\\\/\" withString:@\"/\"];\n    } else {\n        prettyString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];\n    }\n    \n    return prettyString;\n}\n\n+ (BOOL)isValidJSONData:(NSData *)data\n{\n    return [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL] ? YES : NO;\n}\n\n// Thanks to the following links for help with this method\n// http://www.cocoanetics.com/2012/02/decompressing-files-into-memory/\n// https://github.com/nicklockwood/GZIP\n+ (NSData *)inflatedDataFromCompressedData:(NSData *)compressedData\n{\n    NSData *inflatedData = nil;\n    NSUInteger compressedDataLength = [compressedData length];\n    if (compressedDataLength > 0) {\n        z_stream stream;\n        stream.zalloc = Z_NULL;\n        stream.zfree = Z_NULL;\n        stream.avail_in = (uInt)compressedDataLength;\n        stream.next_in = (void *)[compressedData bytes];\n        stream.total_out = 0;\n        stream.avail_out = 0;\n\n        NSMutableData *mutableData = [NSMutableData dataWithLength:compressedDataLength * 1.5];\n        if (inflateInit2(&stream, 15 + 32) == Z_OK) {\n            int status = Z_OK;\n            while (status == Z_OK) {\n                if (stream.total_out >= [mutableData length]) {\n                    mutableData.length += compressedDataLength / 2;\n                }\n                stream.next_out = (uint8_t *)[mutableData mutableBytes] + stream.total_out;\n                stream.avail_out = (uInt)([mutableData length] - stream.total_out);\n                status = inflate(&stream, Z_SYNC_FLUSH);\n            }\n            if (inflateEnd(&stream) == Z_OK) {\n                if (status == Z_STREAM_END) {\n                    mutableData.length = stream.total_out;\n                    inflatedData = [mutableData copy];\n                }\n            }\n        }\n    }\n    return inflatedData;\n}\n\n+ (NSArray<UIWindow *> *)allWindows\n{\n    BOOL includeInternalWindows = YES;\n    BOOL onlyVisibleWindows = NO;\n\n    NSArray<NSString *> *allWindowsComponents = @[@\"al\", @\"lWindo\", @\"wsIncl\", @\"udingInt\", @\"ernalWin\", @\"dows:o\", @\"nlyVisi\", @\"bleWin\", @\"dows:\"];\n    SEL allWindowsSelector = NSSelectorFromString([allWindowsComponents componentsJoinedByString:@\"\"]);\n\n    NSMethodSignature *methodSignature = [[UIWindow class] methodSignatureForSelector:allWindowsSelector];\n    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];\n\n    invocation.target = [UIWindow class];\n    invocation.selector = allWindowsSelector;\n    [invocation setArgument:&includeInternalWindows atIndex:2];\n    [invocation setArgument:&onlyVisibleWindows atIndex:3];\n    [invocation invoke];\n\n    __unsafe_unretained NSArray<UIWindow *> *windows = nil;\n    [invocation getReturnValue:&windows];\n    return windows;\n}\n\n+ (SEL)swizzledSelectorForSelector:(SEL)selector\n{\n    return NSSelectorFromString([NSString stringWithFormat:@\"_flex_swizzle_%x_%@\", arc4random(), NSStringFromSelector(selector)]);\n}\n\n+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls\n{\n    if ([cls instancesRespondToSelector:selector]) {\n        unsigned int numMethods = 0;\n        Method *methods = class_copyMethodList(cls, &numMethods);\n        \n        BOOL implementsSelector = NO;\n        for (int index = 0; index < numMethods; index++) {\n            SEL methodSelector = method_getName(methods[index]);\n            if (selector == methodSelector) {\n                implementsSelector = YES;\n                break;\n            }\n        }\n        \n        free(methods);\n        \n        if (!implementsSelector) {\n            return YES;\n        }\n    }\n    \n    return NO;\n}\n\n+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)class withBlock:(id)block swizzledSelector:(SEL)swizzledSelector\n{\n    // This method is only intended for swizzling methods that are know to exist on the class.\n    // Bail if that isn't the case.\n    Method originalMethod = class_getInstanceMethod(class, originalSelector);\n    if (!originalMethod) {\n        return;\n    }\n    \n    IMP implementation = imp_implementationWithBlock(block);\n    class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalMethod));\n    Method newMethod = class_getInstanceMethod(class, swizzledSelector);\n    method_exchangeImplementations(originalMethod, newMethod);\n}\n\n+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock\n{\n    if ([self instanceRespondsButDoesNotImplementSelector:selector class:cls]) {\n        return;\n    }\n    \n    IMP implementation = imp_implementationWithBlock((id)([cls instancesRespondToSelector:selector] ? implementationBlock : undefinedBlock));\n    \n    Method oldMethod = class_getInstanceMethod(cls, selector);\n    if (oldMethod) {\n        class_addMethod(cls, swizzledSelector, implementation, methodDescription.types);\n        \n        Method newMethod = class_getInstanceMethod(cls, swizzledSelector);\n        \n        method_exchangeImplementations(oldMethod, newMethod);\n    } else {\n        class_addMethod(cls, selector, implementation, methodDescription.types);\n    }\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ViewHierarchy/FLEXHierarchyTableViewCell.h",
    "content": "//\n//  FLEXHierarchyTableViewCell.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-02.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXHierarchyTableViewCell : UITableViewCell\n\n- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier;\n\n@property (nonatomic, assign) NSInteger viewDepth;\n@property (nonatomic, strong) UIColor *viewColor;\n\n@end\n"
  },
  {
    "path": "FLEX/ViewHierarchy/FLEXHierarchyTableViewCell.m",
    "content": "//\n//  FLEXHierarchyTableViewCell.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-02.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXHierarchyTableViewCell.h\"\n#import \"FLEXUtility.h\"\n\n@interface FLEXHierarchyTableViewCell ()\n\n@property (nonatomic, strong) UIView *depthIndicatorView;\n@property (nonatomic, strong) UIImageView *colorCircleImageView;\n\n@end\n\n@implementation FLEXHierarchyTableViewCell\n\n- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier\n{\n    return [self initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];\n}\n\n- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier\n{\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.depthIndicatorView = [[UIView alloc] init];\n        self.depthIndicatorView.backgroundColor = [FLEXUtility hierarchyIndentPatternColor];\n        [self.contentView addSubview:self.depthIndicatorView];\n        \n        UIImage *defaultCircleImage = [FLEXUtility circularImageWithColor:[UIColor blackColor] radius:5.0];\n        self.colorCircleImageView = [[UIImageView alloc] initWithImage:defaultCircleImage];\n        [self.contentView addSubview:self.colorCircleImageView];\n        \n        self.textLabel.font = [UIFont fontWithName:@\"HelveticaNeue-Medium\" size:14.0];\n        self.detailTextLabel.font = [FLEXUtility defaultTableViewCellLabelFont];\n        self.accessoryType = UITableViewCellAccessoryDetailButton;\n    }\n    return self;\n}\n\n- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated\n{\n    [super setHighlighted:highlighted animated:animated];\n    \n    // UITableViewCell changes all subviews in the contentView to backgroundColor = clearColor.\n    // We want to preserve the hierarchy background color when highlighted.\n    self.depthIndicatorView.backgroundColor = [FLEXUtility hierarchyIndentPatternColor];\n}\n\n- (void)setSelected:(BOOL)selected animated:(BOOL)animated\n{\n    [super setSelected:selected animated:animated];\n    \n    // See setHighlighted above.\n    self.depthIndicatorView.backgroundColor = [FLEXUtility hierarchyIndentPatternColor];\n}\n\n- (void)layoutSubviews\n{\n    [super layoutSubviews];\n    \n    const CGFloat kContentPadding = 10.0;\n    const CGFloat kDepthIndicatorWidthMultiplier = 4.0;\n    \n    CGRect depthIndicatorFrame = CGRectMake(kContentPadding, 0, self.viewDepth * kDepthIndicatorWidthMultiplier, self.contentView.bounds.size.height);\n    self.depthIndicatorView.frame = depthIndicatorFrame;\n    \n    CGRect circleFrame = self.colorCircleImageView.frame;\n    circleFrame.origin.x = CGRectGetMaxX(depthIndicatorFrame);\n    circleFrame.origin.y = self.textLabel.frame.origin.y + FLEXFloor((self.textLabel.frame.size.height - circleFrame.size.height) / 2.0);\n    self.colorCircleImageView.frame = circleFrame;\n    \n    CGRect textLabelFrame = self.textLabel.frame;\n    CGFloat textOriginX = CGRectGetMaxX(circleFrame) + 4.0;\n    textLabelFrame.origin.x = textOriginX;\n    textLabelFrame.size.width = CGRectGetMaxX(self.contentView.bounds) - kContentPadding - textOriginX;\n    self.textLabel.frame = textLabelFrame;\n    \n    CGRect detailTextLabelFrame = self.detailTextLabel.frame;\n    CGFloat detailOriginX = CGRectGetMaxX(depthIndicatorFrame);\n    detailTextLabelFrame.origin.x = detailOriginX;\n    detailTextLabelFrame.size.width = CGRectGetMaxX(self.contentView.bounds) - kContentPadding - detailOriginX;\n    self.detailTextLabel.frame = detailTextLabelFrame;\n}\n\n- (void)setViewColor:(UIColor *)viewColor\n{\n    if (![_viewColor isEqual:viewColor]) {\n        _viewColor = viewColor;\n        self.colorCircleImageView.image = [FLEXUtility circularImageWithColor:viewColor radius:6.0];\n    }\n}\n\n- (void)setViewDepth:(NSInteger)viewDepth\n{\n    if (_viewDepth != viewDepth) {\n        _viewDepth = viewDepth;\n        [self setNeedsLayout];\n    }\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ViewHierarchy/FLEXHierarchyTableViewController.h",
    "content": "//\n//  FLEXHierarchyTableViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-01.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@protocol FLEXHierarchyTableViewControllerDelegate;\n\n@interface FLEXHierarchyTableViewController : UITableViewController\n\n- (instancetype)initWithViews:(NSArray<UIView *> *)allViews viewsAtTap:(NSArray<UIView *> *)viewsAtTap selectedView:(UIView *)selectedView depths:(NSDictionary<NSValue *, NSNumber *> *)depthsForViews;\n\n@property (nonatomic, weak) id <FLEXHierarchyTableViewControllerDelegate> delegate;\n\n@end\n\n@protocol FLEXHierarchyTableViewControllerDelegate <NSObject>\n\n- (void)hierarchyViewController:(FLEXHierarchyTableViewController *)hierarchyViewController didFinishWithSelectedView:(UIView *)selectedView;\n\n@end\n"
  },
  {
    "path": "FLEX/ViewHierarchy/FLEXHierarchyTableViewController.m",
    "content": "//\n//  FLEXHierarchyTableViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 2014-05-01.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXHierarchyTableViewController.h\"\n#import \"FLEXUtility.h\"\n#import \"FLEXHierarchyTableViewCell.h\"\n#import \"FLEXObjectExplorerViewController.h\"\n#import \"FLEXObjectExplorerFactory.h\"\n\nstatic const NSInteger kFLEXHierarchyScopeViewsAtTapIndex = 0;\nstatic const NSInteger kFLEXHierarchyScopeFullHierarchyIndex = 1;\n\n@interface FLEXHierarchyTableViewController () <UISearchBarDelegate>\n\n@property (nonatomic, strong) NSArray<UIView *> *allViews;\n@property (nonatomic, strong) NSDictionary<NSValue *, NSNumber *> *depthsForViews;\n@property (nonatomic, strong) NSArray<UIView *> *viewsAtTap;\n@property (nonatomic, strong) UIView *selectedView;\n@property (nonatomic, strong) NSArray<UIView *> *displayedViews;\n\n@property (nonatomic, strong) UISearchBar *searchBar;\n\n@end\n\n@implementation FLEXHierarchyTableViewController\n\n- (instancetype)initWithViews:(NSArray<UIView *> *)allViews viewsAtTap:(NSArray<UIView *> *)viewsAtTap selectedView:(UIView *)selectedView depths:(NSDictionary<NSValue *, NSNumber *> *)depthsForViews\n{\n    self = [super initWithStyle:UITableViewStylePlain];\n    if (self) {\n        self.allViews = allViews;\n        self.depthsForViews = depthsForViews;\n        self.viewsAtTap = viewsAtTap;\n        self.selectedView = selectedView;\n        \n        self.title = @\"View Hierarchy\";\n    }\n    return self;\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n\n    // Preserve selection between presentations.\n    self.clearsSelectionOnViewWillAppear = NO;\n    // Done button.\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(donePressed:)];\n    \n    // A little more breathing room.\n    self.tableView.rowHeight = 50.0;\n    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    // Separator inset clashes with persistent cell selection.\n    [self.tableView setSeparatorInset:UIEdgeInsetsZero];\n    \n    self.searchBar = [[UISearchBar alloc] init];\n    self.searchBar.placeholder = [FLEXUtility searchBarPlaceholderText];\n    self.searchBar.delegate = self;\n    if ([self showScopeBar]) {\n        self.searchBar.showsScopeBar = YES;\n        self.searchBar.scopeButtonTitles = @[@\"Views at Tap\", @\"Full Hierarchy\"];\n    }\n    [self.searchBar sizeToFit];\n    self.tableView.tableHeaderView = self.searchBar;\n    \n    [self updateDisplayedViews];\n}\n\n- (void)viewDidAppear:(BOOL)animated\n{\n    [super viewDidAppear:animated];\n    \n    [self trySelectCellForSelectedViewWithScrollPosition:UITableViewScrollPositionMiddle];\n}\n\n\n#pragma mark Selection and Filtering Helpers\n\n- (void)trySelectCellForSelectedViewWithScrollPosition:(UITableViewScrollPosition)scrollPosition\n{\n    NSUInteger selectedViewIndex = [self.displayedViews indexOfObject:self.selectedView];\n    if (selectedViewIndex != NSNotFound) {\n        NSIndexPath *selectedViewIndexPath = [NSIndexPath indexPathForRow:selectedViewIndex inSection:0];\n        [self.tableView selectRowAtIndexPath:selectedViewIndexPath animated:YES scrollPosition:scrollPosition];\n    }\n}\n\n- (void)updateDisplayedViews\n{\n    NSArray<UIView *> *candidateViews = nil;\n    if ([self showScopeBar]) {\n        if (self.searchBar.selectedScopeButtonIndex == kFLEXHierarchyScopeViewsAtTapIndex) {\n            candidateViews = self.viewsAtTap;\n        } else if (self.searchBar.selectedScopeButtonIndex == kFLEXHierarchyScopeFullHierarchyIndex) {\n            candidateViews = self.allViews;\n        }\n    } else {\n        candidateViews = self.allViews;\n    }\n    \n    if ([self.searchBar.text length] > 0) {\n        self.displayedViews = [candidateViews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UIView *candidateView, NSDictionary<NSString *, id> *bindings) {\n            NSString *title = [FLEXUtility descriptionForView:candidateView includingFrame:NO];\n            NSString *candidateViewPointerAddress = [NSString stringWithFormat:@\"%p\", candidateView];\n            BOOL matchedViewPointerAddress = [candidateViewPointerAddress rangeOfString:self.searchBar.text options:NSCaseInsensitiveSearch].location != NSNotFound;\n            BOOL matchedViewTitle = [title rangeOfString:self.searchBar.text options:NSCaseInsensitiveSearch].location != NSNotFound;\n            return matchedViewPointerAddress || matchedViewTitle;\n        }]];\n    } else {\n        self.displayedViews = candidateViews;\n    }\n    \n    [self.tableView reloadData];\n}\n\n- (BOOL)showScopeBar\n{\n    return [self.viewsAtTap count] > 0;\n}\n\n- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope\n{\n    [self updateDisplayedViews];\n    \n    // If the search bar text field is active, don't scroll on selection because we may want to continue typing.\n    // Otherwise, scroll so that the selected cell is visible.\n    UITableViewScrollPosition scrollPosition = self.searchBar.isFirstResponder ? UITableViewScrollPositionNone : UITableViewScrollPositionMiddle;\n    [self trySelectCellForSelectedViewWithScrollPosition:scrollPosition];\n}\n\n- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText\n{\n    [self updateDisplayedViews];\n    [self trySelectCellForSelectedViewWithScrollPosition:UITableViewScrollPositionNone];\n}\n\n- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar\n{\n    [searchBar resignFirstResponder];\n}\n\n\n#pragma mark - Table View Data Source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\n{\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\n{\n    return [self.displayedViews count];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    static NSString *CellIdentifier = @\"Cell\";\n    FLEXHierarchyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];\n    if (!cell) {\n        cell = [[FLEXHierarchyTableViewCell alloc] initWithReuseIdentifier:CellIdentifier];\n    }\n    \n    UIView *view = self.displayedViews[indexPath.row];\n    NSNumber *depth = [self.depthsForViews objectForKey:[NSValue valueWithNonretainedObject:view]];\n    UIColor *viewColor = [FLEXUtility consistentRandomColorForObject:view];\n    cell.textLabel.text = [FLEXUtility descriptionForView:view includingFrame:NO];\n    cell.detailTextLabel.text = [FLEXUtility detailDescriptionForView:view];\n    cell.viewColor = viewColor;\n    cell.viewDepth = [depth integerValue];\n    if (view.isHidden || view.alpha < 0.01) {\n        cell.textLabel.textColor = [UIColor lightGrayColor];\n        cell.detailTextLabel.textColor = [UIColor lightGrayColor];\n    } else {\n        cell.textLabel.textColor = [UIColor blackColor];\n        cell.detailTextLabel.textColor = [UIColor blackColor];\n    }\n    \n    return cell;\n}\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    self.selectedView = self.displayedViews[indexPath.row];\n    [self.delegate hierarchyViewController:self didFinishWithSelectedView:self.selectedView];\n}\n\n- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath\n{\n    UIView *drillInView = self.displayedViews[indexPath.row];\n    FLEXObjectExplorerViewController *viewExplorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:drillInView];\n    [self.navigationController pushViewController:viewExplorer animated:YES];\n}\n\n\n#pragma mark - Button Actions\n\n- (void)donePressed:(id)sender\n{\n    [self.delegate hierarchyViewController:self didFinishWithSelectedView:self.selectedView];\n}\n\n@end\n"
  },
  {
    "path": "FLEX/ViewHierarchy/FLEXImagePreviewViewController.h",
    "content": "//\n//  FLEXImagePreviewViewController.h\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/12/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface FLEXImagePreviewViewController : UIViewController\n\n- (id)initWithImage:(UIImage *)image;\n\n@end\n"
  },
  {
    "path": "FLEX/ViewHierarchy/FLEXImagePreviewViewController.m",
    "content": "//\n//  FLEXImagePreviewViewController.m\n//  Flipboard\n//\n//  Created by Ryan Olson on 6/12/14.\n//  Copyright (c) 2014 Flipboard. All rights reserved.\n//\n\n#import \"FLEXImagePreviewViewController.h\"\n#import \"FLEXUtility.h\"\n\n@interface FLEXImagePreviewViewController () <UIScrollViewDelegate>\n\n@property (nonatomic, strong) UIImage *image;\n\n@property (nonatomic, strong) UIScrollView *scrollView;\n@property (nonatomic, strong) UIImageView *imageView;\n\n@end\n\n@implementation FLEXImagePreviewViewController\n\n- (id)initWithImage:(UIImage *)image\n{\n    self = [super initWithNibName:nil bundle:nil];\n    if (self) {\n        self.title = @\"Preview\";\n        self.image = image;\n    }\n    return self;\n}\n\n- (void)viewDidLoad\n{\n    [super viewDidLoad];\n    \n    self.view.backgroundColor = [FLEXUtility scrollViewGrayColor];\n    \n    self.imageView = [[UIImageView alloc] initWithImage:self.image];\n    self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];\n    self.scrollView.delegate = self;\n    self.scrollView.backgroundColor = self.view.backgroundColor;\n    self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    [self.scrollView addSubview:self.imageView];\n    self.scrollView.contentSize = self.imageView.frame.size;\n    self.scrollView.minimumZoomScale = 1.0;\n    self.scrollView.maximumZoomScale = 2.0;\n    [self.view addSubview:self.scrollView];\n    \n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(actionButtonPressed:)];\n}\n\n- (void)viewDidLayoutSubviews\n{\n    [self centerContentInScrollViewIfNeeded];\n}\n\n- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView\n{\n    return self.imageView;\n}\n\n- (void)scrollViewDidZoom:(UIScrollView *)scrollView\n{\n    [self centerContentInScrollViewIfNeeded];\n}\n\n- (void)centerContentInScrollViewIfNeeded\n{\n    CGFloat horizontalInset = 0.0;\n    CGFloat verticalInset = 0.0;\n    if (self.scrollView.contentSize.width < self.scrollView.bounds.size.width) {\n        horizontalInset = (self.scrollView.bounds.size.width - self.scrollView.contentSize.width) / 2.0;\n    }\n    if (self.scrollView.contentSize.height < self.scrollView.bounds.size.height) {\n        verticalInset = (self.scrollView.bounds.size.height - self.scrollView.contentSize.height) / 2.0;\n    }\n    self.scrollView.contentInset = UIEdgeInsetsMake(verticalInset, horizontalInset, verticalInset, horizontalInset);\n}\n\n- (void)actionButtonPressed:(id)sender\n{\n    static BOOL CanSaveToCameraRoll = NO;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        if ([UIDevice currentDevice].systemVersion.floatValue < 10) {\n            CanSaveToCameraRoll = YES;\n            return;\n        }\n        \n        NSBundle *mainBundle = [NSBundle mainBundle];\n        if ([mainBundle.infoDictionary.allKeys containsObject:@\"NSPhotoLibraryUsageDescription\"]) {\n            CanSaveToCameraRoll = YES;\n        } else {\n            NSLog(@\"Add NSPhotoLibraryUsageDescription in app's Info.plist for saving captured image into camera roll.\");\n        }\n    });\n    \n    UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:@[self.image] applicationActivities:@[]];\n    \n    if (!CanSaveToCameraRoll) {\n        activityVC.excludedActivityTypes = @[UIActivityTypeSaveToCameraRoll];\n    }\n    \n    [self presentViewController:activityVC animated:YES completion:nil];\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/1Password.xcassets/onepassword-button-light.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"onepassword-button-light.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"onepassword-button-light@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"onepassword-button-light@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/1Password.xcassets/onepassword-button.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"onepassword-button.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"onepassword-button@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"onepassword-button@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/1Password.xcassets/onepassword-extension-light.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"onepassword-extension-light~compact.png\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"onepassword-extension-light@2x~compact.png\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"onepassword-extension-light@3x~compact.png\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"onepassword-extension-light~regular.png\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"onepassword-extension-light@2x~regular.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/1Password.xcassets/onepassword-extension.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"onepassword-extension~compact.png\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"onepassword-extension@2x~compact.png\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"onepassword-extension@3x~compact.png\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"onepassword-extension~regular.png\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"onepassword-extension@2x~regular.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/1Password.xcassets/onepassword-navbar-light.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"onepassword-navbar-light.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"onepassword-navbar-light@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"onepassword-navbar-light@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/1Password.xcassets/onepassword-navbar.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"onepassword-navbar.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"onepassword-navbar@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"onepassword-navbar@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/1Password.xcassets/onepassword-toolbar-light.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"onepassword-toolbar-light.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"onepassword-toolbar-light@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"onepassword-toolbar-light@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/1Password.xcassets/onepassword-toolbar.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"onepassword-toolbar.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"onepassword-toolbar@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"onepassword-toolbar@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Classes/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n#import <UserNotifications/UserNotifications.h>\n#import <Intents/Intents.h>\n#import \"LoginSplashViewController.h\"\n#import \"MainViewController.h\"\n#import \"ECSlidingViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"URLHandler.h\"\n#import \"SplashViewController.h\"\n\n@class ViewController;\n\n@protocol IRCCloudSystemMenu<NSObject>\n-(void)chooseFGColor;\n-(void)chooseBGColor;\n-(void)resetColors;\n-(void)chooseFile;\n-(void)startPastebin;\n-(void)showUploads;\n-(void)showPastebins;\n-(void)logout;\n-(void)markAsRead;\n-(void)markAllAsRead;\n-(void)showSettings;\n-(void)downloadLogs;\n-(void)addNetwork;\n-(void)editConnection;\n-(void)selectNext;\n-(void)selectPrevious;\n-(void)selectNextUnread;\n-(void)selectPreviousUnread;\n-(void)setAllowsAutomaticWindowTabbing:(BOOL)allow;\n-(void)sendFeedback;\n-(void)joinFeedback;\n-(void)joinBeta;\n-(void)FAQ;\n-(void)versionHistory;\n-(void)openSourceLicenses;\n-(void)jumpToChannel;\n@end\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate, NSURLSessionDataDelegate, UNUserNotificationCenterDelegate> {\n    NetworkConnection *_conn;\n    URLHandler *_urlHandler;\n    id _backlogCompletedObserver;\n    id _backlogFailedObserver;\n    id _IRCEventObserver;\n    void (^imageUploadCompletionHandler)(void);\n    BOOL _movedToBackground;\n    void (^_fetchHandler)(UIBackgroundFetchResult);\n    void (^_refreshHandler)(UIBackgroundFetchResult);\n    NSMutableSet *_activeScenes;\n}\n\n@property (strong) UIWindow *window;\n\n@property (strong) LoginSplashViewController *loginSplashViewController;\n@property (strong) MainViewController *mainViewController;\n@property (strong) ECSlidingViewController *slideViewController;\n@property (strong) SplashViewController *splashViewController;\n\n@property BOOL movedToBackground;\n\n-(void)showLoginView;\n-(void)showMainView:(BOOL)animated;\n-(void)showConnectionView;\n-(void)launchURL:(NSURL *)url;\n-(void)addScene:(id)scene;\n-(void)removeScene:(id)scene;\n-(void)setActiveScene:(UIWindow *)window;\n-(UIScene *)sceneForWindow:(UIWindow *)window API_AVAILABLE(ios(13.0));\n-(void)closeWindow:(UIWindow *)window;\n-(BOOL)isOnVisionOS;\n@end\n\nAPI_AVAILABLE(ios(13.0))\n@interface SceneDelegate : NSObject <UIWindowSceneDelegate, UIGestureRecognizerDelegate> {\n    AppDelegate *_appDelegate;\n    UIScene *_scene;\n}\n@property (strong) UIWindow *window;\n@property (strong) UIScene *scene;\n\n@property (strong) LoginSplashViewController *loginSplashViewController;\n@property (strong) MainViewController *mainViewController;\n@property (strong) ECSlidingViewController *slideViewController;\n@property (strong) SplashViewController *splashViewController;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <SafariServices/SafariServices.h>\n#import <AdSupport/AdSupport.h>\n#import <IntentsUI/IntentsUI.h>\n#import \"AppDelegate.h\"\n#import \"NetworkConnection.h\"\n#import \"EditConnectionViewController.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"ColorFormatter.h\"\n#import \"config.h\"\n#import \"URLHandler.h\"\n#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n#import \"AvatarsDataSource.h\"\n#import \"ImageCache.h\"\n#import \"LogExportsTableViewController.h\"\n#import \"ImageViewController.h\"\n#import \"SettingsViewController.h\"\n#import \"ColorFormatter.h\"\n#import \"EventsDataSource.h\"\n#import \"AvatarsDataSource.h\"\n#import \"SendMessageIntentHandler.h\"\n#if DEBUG\n#import \"FLEXManager.h\"\n#endif\n@import Firebase;\n@import FirebaseMessaging;\n\nextern NSURL *__logfile;\n\n#ifdef DEBUG\n@implementation NSURLRequest(CertificateHack)\n+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host {\n    return YES;\n}\n@end\n#endif\n\n//From: http://stackoverflow.com/a/19313559\n@interface NavBarHax : UINavigationBar\n\n@property (assign) BOOL changingUserInteraction;\n@property (assign) BOOL userInteractionChangedBySystem;\n\n@end\n\n@implementation NavBarHax\n\n- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {\n    if (self.userInteractionChangedBySystem && self.userInteractionEnabled == NO) {\n        return [super hitTest:point withEvent:event];\n    }\n    \n    if ([self pointInside:point withEvent:event]) {\n        self.changingUserInteraction = YES;\n        self.userInteractionEnabled = YES;\n        self.changingUserInteraction = NO;\n    } else {\n        self.changingUserInteraction = YES;\n        self.userInteractionEnabled = NO;\n        self.changingUserInteraction = NO;\n    }\n    \n    return [super hitTest:point withEvent:event];\n}\n\n- (void)setUserInteractionEnabled:(BOOL)userInteractionEnabled\n{\n    if (!self.changingUserInteraction) {\n        self.userInteractionChangedBySystem = YES;\n    } else {\n        self.userInteractionChangedBySystem = NO;\n    }\n    \n    [super setUserInteractionEnabled:userInteractionEnabled];\n}\n\n@end\n\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n#if TARGET_OS_MACCATALYST\n    Class _nswindow = NSClassFromString(@\"NSWindow\");\n    [_nswindow setAllowsAutomaticWindowTabbing:NO];\n#endif\n    \n#ifdef ENTERPRISE\n    NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.enterprise.share\"];\n#else\n    NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.share\"];\n#endif\n    if(sharedcontainer) {\n        __logfile = [[[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] objectAtIndex:0] URLByAppendingPathComponent:@\"log.txt\"];\n        [[NSFileManager defaultManager] removeItemAtURL:__logfile error:nil];\n    }\n#ifdef CRASHLYTICS_TOKEN\n    if([FIROptions defaultOptions]) {\n        [FIRApp configure];\n    }\n#endif\n    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];\n    center.delegate = self;\n    UNTextInputNotificationAction *replyAction = [UNTextInputNotificationAction actionWithIdentifier:@\"reply\" title:@\"Reply\" options:UNNotificationActionOptionAuthenticationRequired textInputButtonTitle:@\"Send\" textInputPlaceholder:@\"\"];\n    \n    UNNotificationAction *joinAction = [UNNotificationAction actionWithIdentifier:@\"join\" title:@\"Join\" options:UNNotificationActionOptionForeground];\n    UNNotificationAction *acceptAction = [UNNotificationAction actionWithIdentifier:@\"accept\" title:@\"Accept\" options:UNNotificationActionOptionNone];\n    UNNotificationAction *retryAction = [UNNotificationAction actionWithIdentifier:@\"retry\" title:@\"Retry\" options:UNNotificationActionOptionNone];\n    //UNNotificationAction *readAction = [UNNotificationAction actionWithIdentifier:@\"read\" title:@\"Mark As Read\" options:UNNotificationActionOptionNone];\n\n    [center setNotificationCategories:[NSSet setWithObjects:\n                                       [UNNotificationCategory categoryWithIdentifier:@\"buffer_msg\" actions:@[replyAction/*,readAction*/] intentIdentifiers:@[INSendMessageIntentIdentifier] hiddenPreviewsBodyPlaceholder:@\"New message\" categorySummaryFormat:@\"%u more messages\" options:UNNotificationCategoryOptionNone],\n                                       [UNNotificationCategory categoryWithIdentifier:@\"buffer_me_msg\" actions:@[replyAction/*,readAction*/] intentIdentifiers:@[INSendMessageIntentIdentifier] hiddenPreviewsBodyPlaceholder:@\"New message\" categorySummaryFormat:@\"%u more messages\" options:UNNotificationCategoryOptionNone],\n                                       [UNNotificationCategory categoryWithIdentifier:@\"channel_invite\" actions:@[joinAction] intentIdentifiers:@[] hiddenPreviewsBodyPlaceholder:@\"Channel invite\" categorySummaryFormat:@\"%u more channel invites\" options:UNNotificationCategoryOptionNone],\n                                       [UNNotificationCategory categoryWithIdentifier:@\"callerid\" actions:@[acceptAction] intentIdentifiers:@[] hiddenPreviewsBodyPlaceholder:@\"Caller ID\" categorySummaryFormat:@\"%u more notifications\" options:UNNotificationCategoryOptionNone],\n                                       [UNNotificationCategory categoryWithIdentifier:@\"retry\" actions:@[retryAction] intentIdentifiers:@[] options:UNNotificationCategoryOptionNone],\n                                       nil]];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n    NSURL *caches = [[[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] objectAtIndex:0] URLByAppendingPathComponent:[[NSBundle mainBundle] bundleIdentifier]];\n    [[NSFileManager defaultManager] removeItemAtURL:caches error:nil];\n    \n    sharedcontainer = [sharedcontainer URLByAppendingPathComponent:@\"attachments/\"];\n    [[NSFileManager defaultManager] removeItemAtURL:sharedcontainer error:nil];\n    \n    [[NSUserDefaults standardUserDefaults] registerDefaults:@{@\"bgTimeout\":@(30), @\"autoCaps\":@(YES), @\"host\":IRCCLOUD_HOST, @\"saveToCameraRoll\":@(YES), @\"photoSize\":@(1024), @\"notificationSound\":@(YES), @\"tabletMode\":@(YES), @\"uploadsAvailable\":@(NO), @\"browser\":([SFSafariViewController class] && !((AppDelegate *)([UIApplication sharedApplication].delegate)).isOnVisionOS)?@\"IRCCloud\":@\"Safari\", @\"warnBeforeLaunchingBrowser\":@(NO), @\"imageViewer\":@(YES), @\"videoViewer\":@(YES), @\"inlineWifiOnly\":@(NO), @\"iCloudLogs\":@(NO), @\"clearFormattingAfterSending\":@(YES)}];\n    if (@available(iOS 14, *)) {\n        [[NSUserDefaults standardUserDefaults] registerDefaults:@{@\"fontSize\":@([UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody].pointSize * ([NSProcessInfo processInfo].macCatalystApp ? 1.0 : 0.8))}];\n    } else {\n        [[NSUserDefaults standardUserDefaults] registerDefaults:@{@\"fontSize\":@([UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody].pointSize * 0.8)}];\n    }\n\n    if (@available(iOS 13, *)) {\n        if([UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark)\n            [[NSUserDefaults standardUserDefaults] registerDefaults:@{@\"theme\":@\"automatic\"}];\n    }\n    \n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"path\"]) {\n        IRCCLOUD_HOST = [[NSUserDefaults standardUserDefaults] objectForKey:@\"host\"];\n        IRCCLOUD_PATH = [[NSUserDefaults standardUserDefaults] objectForKey:@\"path\"];\n    } else if([NetworkConnection sharedInstance].session.length) {\n        CLS_LOG(@\"Session cookie found without websocket path\");\n        [NetworkConnection sharedInstance].session = nil;\n    }\n\n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"useChrome\"]) {\n        CLS_LOG(@\"Migrating browser setting\");\n        if([[NSUserDefaults standardUserDefaults] boolForKey:@\"useChrome\"])\n            [[NSUserDefaults standardUserDefaults] setObject:@\"Chrome\" forKey:@\"browser\"];\n        [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"useChrome\"];\n    }\n    \n    if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"imgur_account_username\"] length])\n        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@\"imgur_removed\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"imgur_access_token\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"imgur_refresh_token\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"imgur_account_username\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"imgur_token_type\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"imgur_expires_in\"];\n    \n    self->_conn = [NetworkConnection sharedInstance];\n#ifdef DEBUG\n    if([[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"]) {\n        [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];\n        \n        IRCCLOUD_HOST = @\"MOCK.HOST\";\n        IRCCLOUD_PATH = @\"/\";\n        [NetworkConnection sharedInstance].mock = YES;\n        if([[NSProcessInfo processInfo].arguments containsObject:@\"-mono\"])\n            [NetworkConnection sharedInstance].userInfo = @{@\"last_selected_bid\":@(5), @\"prefs\":@\"{\\\"font\\\":\\\"mono\\\"}\"};\n        else\n            [NetworkConnection sharedInstance].userInfo = @{@\"last_selected_bid\":@(5)};\n        \n        [[ServersDataSource sharedInstance] clear];\n        [[BuffersDataSource sharedInstance] clear];\n        [[ChannelsDataSource sharedInstance] clear];\n        [[UsersDataSource sharedInstance] clear];\n        [[EventsDataSource sharedInstance] clear];\n\n        [[NetworkConnection sharedInstance] fetchOOB:@\"https://irccloud.com/test/bufferview.json\"];\n    }\n#endif\n    [[NSUserDefaults standardUserDefaults] synchronize];\n    \n    [ColorFormatter loadFonts];\n    [UIColor setTheme];\n    [self.mainViewController applyTheme];\n    [[EventsDataSource sharedInstance] reformat];\n    \n    if(IRCCLOUD_HOST.length < 1)\n    [NetworkConnection sharedInstance].session = nil;\n#ifdef ENTERPRISE\n    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n    [d setObject:IRCCLOUD_HOST forKey:@\"host\"];\n    [d setObject:IRCCLOUD_PATH forKey:@\"path\"];\n    [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"photoSize\"] forKey:@\"photoSize\"];\n    [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"cacheVersion\"] forKey:@\"cacheVersion\"];\n    [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"uploadsAvailable\"] forKey:@\"uploadsAvailable\"];\n    [d synchronize];\n    \n    self.splashViewController = [[UIStoryboard storyboardWithName:@\"MainStoryboard\" bundle:nil] instantiateViewControllerWithIdentifier:@\"SplashViewController\"];\n    self.splashViewController.view.accessibilityIgnoresInvertColors = YES;\n    self.window.rootViewController = self.splashViewController;\n    self.loginSplashViewController = [[UIStoryboard storyboardWithName:@\"MainStoryboard\" bundle:nil] instantiateViewControllerWithIdentifier:@\"LoginSplashViewController\"];\n    self.mainViewController = [[UIStoryboard storyboardWithName:@\"MainStoryboard\" bundle:nil] instantiateViewControllerWithIdentifier:@\"MainViewController\"];\n    self.slideViewController = [[ECSlidingViewController alloc] init];\n    self.slideViewController.view.backgroundColor = [UIColor blackColor];\n    self.slideViewController.topViewController = [[UINavigationController alloc] initWithNavigationBarClass:[NavBarHax class] toolbarClass:nil];\n    [((UINavigationController *)self.slideViewController.topViewController) setViewControllers:@[self.mainViewController]];\n    self.slideViewController.topViewController.view.backgroundColor = [UIColor blackColor];\n    self.slideViewController.view.accessibilityIgnoresInvertColors = YES;\n    if(launchOptions && [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]) {\n        self.mainViewController.bidToOpen = [[[[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey] objectForKey:@\"d\"] objectAtIndex:1] intValue];\n        self.mainViewController.eidToOpen = [[[[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey] objectForKey:@\"d\"] objectAtIndex:2] doubleValue];\n    }\n\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        NSString *session = [NetworkConnection sharedInstance].session;\n        if(session != nil && [session length] > 0 && IRCCLOUD_HOST.length > 0) {\n            self.window.backgroundColor = [UIColor textareaBackgroundColor];\n            self.window.rootViewController = self.slideViewController;\n        } else {\n            self.window.rootViewController = self.loginSplashViewController;\n        }\n        \n#ifdef DEBUG\n        if(![[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"]) {\n#endif\n            [self.window addSubview:self.splashViewController.view];\n            \n            if([NetworkConnection sharedInstance].session.length) {\n                [self.splashViewController animate:nil];\n            } else {\n                self.loginSplashViewController.logo.hidden = YES;\n                [self.splashViewController animate:self.loginSplashViewController.logo];\n            }\n            \n            [UIView animateWithDuration:0.25 delay:0.25 options:0 animations:^{\n                self.splashViewController.view.backgroundColor = [UIColor clearColor];\n            } completion:^(BOOL finished) {\n                self.loginSplashViewController.logo.hidden = NO;\n                [self.splashViewController.view removeFromSuperview];\n            }];\n#ifdef DEBUG\n        }\n#endif\n    }];\n    \n    [[ImageCache sharedInstance] performSelectorInBackground:@selector(prune) withObject:nil];\n    if (@available(iOS 14.0, *)) {\n        [UIMenuSystem.mainSystem setNeedsRebuild];\n    }\n\n#if TARGET_IPHONE_SIMULATOR\n#ifdef FLEX\n    [FLEXManager sharedManager].simulatorShortcutsEnabled = YES;\n#endif\n#endif\n    return YES;\n}\n\n-(BOOL)continueActivity:(NSUserActivity *)userActivity {\n    CLS_LOG(@\"Continuing activity type: %@\", userActivity.activityType);\n#ifdef ENTERPRISE\n    if([userActivity.activityType isEqualToString:@\"com.irccloud.enterprise.buffer\"])\n#else\n    if([userActivity.activityType isEqualToString:@\"com.irccloud.buffer\"])\n#endif\n    {\n        if([userActivity.userInfo objectForKey:@\"bid\"]) {\n            self.mainViewController.bidToOpen = [[userActivity.userInfo objectForKey:@\"bid\"] intValue];\n            self.mainViewController.eidToOpen = 0;\n            self.mainViewController.incomingDraft = [userActivity.userInfo objectForKey:@\"draft\"];\n            CLS_LOG(@\"Opening BID from handoff: %i\", self.mainViewController.bidToOpen);\n            [self.mainViewController bufferSelected:[[userActivity.userInfo objectForKey:@\"bid\"] intValue]];\n            [self showMainView:YES];\n            return YES;\n        }\n    } else if([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {\n        [self launchURL:userActivity.webpageURL];\n    }\n    \n    return NO;\n}\n\n-(id)application:(UIApplication *)application handlerForIntent:(INIntent *)intent {\n    if([intent isKindOfClass:INSendMessageIntent.class]) {\n        return [[SendMessageIntentHandler alloc] init];\n    }\n    return nil;\n}\n\n-(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {\n    return [self continueActivity:userActivity];\n}\n\n- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n\n    if([url.scheme hasPrefix:@\"irccloud\"]) {\n        if([url.host isEqualToString:@\"chat\"] && [url.path isEqualToString:@\"/access-link\"]) {\n            [[NetworkConnection sharedInstance] logout];\n            self.loginSplashViewController.accessLink = url;\n            self.window.backgroundColor = [UIColor colorWithRed:11.0/255.0 green:46.0/255.0 blue:96.0/255.0 alpha:1];\n            self.loginSplashViewController.view.alpha = 1;\n            if(self.window.rootViewController == self.loginSplashViewController)\n                [self.loginSplashViewController viewWillAppear:YES];\n            else\n                self.window.rootViewController = self.loginSplashViewController;\n        } else {\n            return NO;\n        }\n    } else {\n        [self launchURL:url];\n    }\n    return YES;\n}\n\n- (void)launchURL:(NSURL *)url {\n    if (!_urlHandler) {\n        self->_urlHandler = [[URLHandler alloc] init];\n#ifdef ENTERPRISE\n        self->_urlHandler.appCallbackURL = [NSURL URLWithString:@\"irccloud-enterprise://\"];\n#else\n        self->_urlHandler.appCallbackURL = [NSURL URLWithString:@\"irccloud://\"];\n#endif\n        \n    }\n    [self->_urlHandler launchURL:url];\n}\n\n-(void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {\n    \n}\n\n- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {\n    NSData *oldToken = [[NSUserDefaults standardUserDefaults] objectForKey:@\"APNs\"];\n    NSString *oldFcmToken = [[NSUserDefaults standardUserDefaults] objectForKey:@\"FCM\"];\n\n    [[FIRMessaging messaging] tokenWithCompletion:^(NSString *token, NSError *error) {\n        if (error != nil || !token) {\n            CLS_LOG(@\"Error fetching FIRMessaging token: %@\", error);\n        } else {\n            //CLS_LOG(@\"FCM Token: %@\", result.token);\n            if(self->_conn.session && oldToken && oldFcmToken &&(![devToken isEqualToData:oldToken] || ![oldFcmToken isEqualToString:token])) {\n              CLS_LOG(@\"Unregistering old APNs token\");\n                [self->_conn unregisterAPNs:oldToken fcm:oldFcmToken session:self->_conn.session handler:^(IRCCloudJSONObject *result) {\n                  CLS_LOG(@\"Unregistration result: %@\", result);\n              }];\n            }\n            [[NSUserDefaults standardUserDefaults] setObject:devToken forKey:@\"APNs\"];\n            [[NSUserDefaults standardUserDefaults] setObject:token forKey:@\"FCM\"];\n            [self->_conn registerAPNs:devToken fcm:token handler:^(IRCCloudJSONObject *result) {\n              CLS_LOG(@\"Registration result: %@\", result);\n            }];\n        }\n    }];\n}\n\n- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {\n    CLS_LOG(@\"Error in APNs registration. Error: %@\", err);\n}\n\n- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {\n    if([userInfo objectForKey:@\"d\"]) {\n        int cid = [[[userInfo objectForKey:@\"d\"] objectAtIndex:0] intValue];\n        int bid = [[[userInfo objectForKey:@\"d\"] objectAtIndex:1] intValue];\n        NSTimeInterval eid = [[[userInfo objectForKey:@\"d\"] objectAtIndex:2] doubleValue];\n        \n        if(application.applicationState == UIApplicationStateBackground && (!_conn || (self->_conn.state != kIRCCloudStateConnected && _conn.state != kIRCCloudStateConnecting))) {\n            [[NotificationsDataSource sharedInstance] notify:nil category:nil cid:cid bid:bid eid:eid];\n        }\n        \n        if(self->_movedToBackground && application.applicationState == UIApplicationStateInactive) {\n            self.mainViewController.bidToOpen = bid;\n            self.mainViewController.eidToOpen = eid;\n            CLS_LOG(@\"Opening BID from notification: %i\", self.mainViewController.bidToOpen);\n            [UIColor setTheme];\n            [self.mainViewController applyTheme];\n            [self.mainViewController bufferSelected:bid];\n            [self showMainView:YES];\n        } else if(application.applicationState == UIApplicationStateBackground && (!_conn || (self->_conn.state != kIRCCloudStateConnected && _conn.state != kIRCCloudStateConnecting))) {\n            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{\n                CLS_LOG(@\"Preloading backlog for bid%i from notification\", bid);\n                [[NetworkConnection sharedInstance] requestBacklogForBuffer:bid server:cid completion:^(BOOL success) {\n                    [self.mainViewController refresh];\n                    [[NotificationsDataSource sharedInstance] updateBadgeCount];\n                    if(success) {\n                        CLS_LOG(@\"Backlog download completed for bid%i\", bid);\n                        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n                            [[NetworkConnection sharedInstance] serialize];\n                            handler(UIBackgroundFetchResultNewData);\n                        });\n                    } else {\n                        CLS_LOG(@\"Backlog download failed for bid%i\", bid);\n                        handler(UIBackgroundFetchResultFailed);\n                    }\n                }];\n            });\n        } else {\n            handler(UIBackgroundFetchResultNoData);\n        }\n    } else if ([userInfo objectForKey:@\"hb\"] && application.applicationState == UIApplicationStateBackground) {\n        //CLS_LOG(@\"APNS Heartbeat: %@\", userInfo);\n        for(NSString *key in [userInfo objectForKey:@\"hb\"]) {\n            NSDictionary *bids = [[userInfo objectForKey:@\"hb\"] objectForKey:key];\n            for(NSString *bid in bids.allKeys) {\n                NSTimeInterval eid = [[bids objectForKey:bid] doubleValue];\n                //CLS_LOG(@\"Setting bid %i last_seen_eid to %f\", bid.intValue, eid);\n                [[BuffersDataSource sharedInstance] updateLastSeenEID:eid buffer:bid.intValue];\n                [[NotificationsDataSource sharedInstance] removeNotificationsForBID:bid.intValue olderThan:eid];\n            }\n        }\n        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n            [[NetworkConnection sharedInstance] serialize];\n            handler(UIBackgroundFetchResultNoData);\n        });\n    } else {\n        handler(UIBackgroundFetchResultNoData);\n    }\n    [[NotificationsDataSource sharedInstance] updateBadgeCount];\n}\n\n-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {\n    if([notification.request.content.userInfo objectForKey:@\"d\"]) {\n        int bid = [[[notification.request.content.userInfo objectForKey:@\"d\"] objectAtIndex:1] intValue];\n        NSTimeInterval eid = [[[notification.request.content.userInfo objectForKey:@\"d\"] objectAtIndex:2] doubleValue];\n        Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:bid];\n        if(self->_mainViewController.buffer.bid != bid && eid > b.last_seen_eid) {\n            completionHandler(UNNotificationPresentationOptionAlert + UNNotificationPresentationOptionSound);\n            return;\n        }\n    } else if([notification.request.content.userInfo objectForKey:@\"view_logs\"]) {\n        if([UIApplication sharedApplication].applicationState == UIApplicationStateActive && [self->_mainViewController.presentedViewController isKindOfClass:[UINavigationController class]] && [((UINavigationController *)_mainViewController.presentedViewController).topViewController isKindOfClass:[LogExportsTableViewController class]])\n            completionHandler(UNNotificationPresentationOptionNone);\n        else\n            completionHandler(UNNotificationPresentationOptionAlert + UNNotificationPresentationOptionSound);\n    }\n    completionHandler(UNNotificationPresentationOptionNone);\n}\n\n-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {\n    [UIColor setTheme];\n    [self.mainViewController applyTheme];\n    if([response isKindOfClass:[UNTextInputNotificationResponse class]]) {\n        [self handleAction:response.actionIdentifier userInfo:response.notification.request.content.userInfo response:((UNTextInputNotificationResponse *)response).userText completionHandler:completionHandler];\n    } else if([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {\n        if([response.notification.request.content.userInfo objectForKey:@\"view_logs\"]) {\n            LogExportsTableViewController *lvc = [[LogExportsTableViewController alloc] initWithStyle:UITableViewStyleGrouped];\n            lvc.buffer = self->_mainViewController.buffer;\n            lvc.server = [[ServersDataSource sharedInstance] getServer:self->_mainViewController.buffer.cid];\n            UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:lvc];\n            [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n            if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                nc.modalPresentationStyle = UIModalPresentationFormSheet;\n            else\n                nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n            [self showMainView:YES];\n            [self->_mainViewController presentViewController:nc animated:YES completion:nil];\n        } else {\n            if([response.notification.request.content.userInfo objectForKey:@\"d\"]) {\n                self.mainViewController.bidToOpen = [[[response.notification.request.content.userInfo objectForKey:@\"d\"] objectAtIndex:1] intValue];\n                self.mainViewController.eidToOpen = [[[response.notification.request.content.userInfo objectForKey:@\"d\"] objectAtIndex:2] doubleValue];\n                CLS_LOG(@\"Opening BID from notification: %i\", self.mainViewController.bidToOpen);\n                [UIColor setTheme];\n                [self.mainViewController applyTheme];\n                [self.mainViewController bufferSelected:[[[response.notification.request.content.userInfo objectForKey:@\"d\"] objectAtIndex:1] intValue]];\n                [self showMainView:YES];\n            }\n        }\n        completionHandler();\n    } else {\n        [self handleAction:response.actionIdentifier userInfo:response.notification.request.content.userInfo response:nil completionHandler:completionHandler];\n    }\n}\n\n-(void)userNotificationCenter:(UNUserNotificationCenter *)center openSettingsForNotification:(UNNotification *)notification {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        [UIColor setTheme];\n        [self.mainViewController applyTheme];\n        [self showMainView:NO];\n        SettingsViewController *svc = [[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];\n        svc.scrollToNotifications = YES;\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:svc];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationPageSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        [self.mainViewController presentViewController:nc animated:NO completion:nil];\n    }];\n}\n\n-(void)handleAction:(NSString *)identifier userInfo:(NSDictionary *)userInfo response:(NSString *)response completionHandler:(void (^)())completionHandler {\n    IRCCloudAPIResultHandler handler = ^(IRCCloudJSONObject *result) {\n        if([[result objectForKey:@\"success\"] intValue] == 1) {\n            if([identifier isEqualToString:@\"reply\"]) {\n                AudioServicesPlaySystemSound(1001);\n            } else if([identifier isEqualToString:@\"read\"]) {\n                Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:[[[userInfo objectForKey:@\"d\"] objectAtIndex:1] intValue]];\n                if(b && b.last_seen_eid < [[[userInfo objectForKey:@\"d\"] objectAtIndex:2] doubleValue])\n                    b.last_seen_eid = [[[userInfo objectForKey:@\"d\"] objectAtIndex:2] doubleValue];\n                [[NotificationsDataSource sharedInstance] removeNotificationsForBID:[[[userInfo objectForKey:@\"d\"] objectAtIndex:1] intValue] olderThan:[[[userInfo objectForKey:@\"d\"] objectAtIndex:2] doubleValue]];\n                [[NotificationsDataSource sharedInstance] updateBadgeCount];\n            } else if([identifier isEqualToString:@\"join\"]) {\n                Buffer *b = [[BuffersDataSource sharedInstance] getBufferWithName:[[[[userInfo objectForKey:@\"aps\"] objectForKey:@\"alert\"] objectForKey:@\"loc-args\"] objectAtIndex:1] server:[[[userInfo objectForKey:@\"d\"] objectAtIndex:0] intValue]];\n                if(b) {\n                    [self.mainViewController bufferSelected:b.bid];\n                } else {\n                    self.mainViewController.cidToOpen = [[[userInfo objectForKey:@\"d\"] objectAtIndex:0] intValue];\n                    self.mainViewController.bufferToOpen = [[[[userInfo objectForKey:@\"aps\"] objectForKey:@\"alert\"] objectForKey:@\"loc-args\"] objectAtIndex:1];\n                }\n                [self showMainView:YES];\n            }\n        } else {\n            CLS_LOG(@\"Failed: %@ %@\", identifier, result);\n            NSString *alertBody = @\"\";\n            if([identifier isEqualToString:@\"reply\"]) {\n                Buffer *b = [[BuffersDataSource sharedInstance] getBufferWithName:[[[[userInfo objectForKey:@\"aps\"] objectForKey:@\"alert\"] objectForKey:@\"loc-args\"] objectAtIndex:0] server:[[[userInfo objectForKey:@\"d\"] objectAtIndex:0] intValue]];\n                if(b)\n                    b.draft = response;\n                alertBody = [NSString stringWithFormat:@\"Failed to send message to %@\", [[[[userInfo objectForKey:@\"aps\"] objectForKey:@\"alert\"] objectForKey:@\"loc-args\"] objectAtIndex:0]];\n            } else if([identifier isEqualToString:@\"join\"]) {\n                alertBody = [NSString stringWithFormat:@\"Failed to join %@\", [[[[userInfo objectForKey:@\"aps\"] objectForKey:@\"alert\"] objectForKey:@\"loc-args\"] objectAtIndex:1]];\n            } else if([identifier isEqualToString:@\"accept\"]) {\n                alertBody = [NSString stringWithFormat:@\"Failed to add %@ to accept list\", [[[[userInfo objectForKey:@\"aps\"] objectForKey:@\"alert\"] objectForKey:@\"loc-args\"] objectAtIndex:0]];\n            }\n            NSDictionary *ui;\n            if(response)\n                ui = @{@\"identifier\":identifier, @\"userInfo\":userInfo, @\"responseInfo\":@{UIUserNotificationActionResponseTypedTextKey:response}, @\"d\":[userInfo objectForKey:@\"d\"]};\n            else\n                ui = @{@\"identifier\":identifier, @\"userInfo\":userInfo, @\"d\":[userInfo objectForKey:@\"d\"]};\n            [[NotificationsDataSource sharedInstance] alert:alertBody title:nil category:@\"retry\" userInfo:ui];\n        }\n        \n        completionHandler();\n    };\n    \n    if([identifier isEqualToString:@\"reply\"]) {\n        [[NetworkConnection sharedInstance] POSTsay:response\n                                                 to:[[[[userInfo objectForKey:@\"aps\"] objectForKey:@\"alert\"] objectForKey:@\"loc-args\"] objectAtIndex:[[[[userInfo objectForKey:@\"aps\"] objectForKey:@\"alert\"] objectForKey:@\"loc-key\"] hasSuffix:@\"CH\"]?2:0]\n                                                cid:[[[userInfo objectForKey:@\"d\"] objectAtIndex:0] intValue]\n                                            handler:handler];\n    } else if([identifier isEqualToString:@\"join\"]) {\n        [[NetworkConnection sharedInstance] POSTsay:[NSString stringWithFormat:@\"/join %@\", [[[[userInfo objectForKey:@\"aps\"] objectForKey:@\"alert\"] objectForKey:@\"loc-args\"] objectAtIndex:1]]\n                                                 to:@\"\"\n                                                cid:[[[userInfo objectForKey:@\"d\"] objectAtIndex:0] intValue]\n                                            handler:handler];\n    } else if([identifier isEqualToString:@\"accept\"]) {\n        [[NetworkConnection sharedInstance] POSTsay:[NSString stringWithFormat:@\"/accept %@\", [[[[userInfo objectForKey:@\"aps\"] objectForKey:@\"alert\"] objectForKey:@\"loc-args\"] objectAtIndex:0]]\n                                                 to:@\"\"\n                                                cid:[[[userInfo objectForKey:@\"d\"] objectAtIndex:0] intValue]\n                                            handler:handler];\n    } else if([identifier isEqualToString:@\"read\"]) {\n        [[NetworkConnection sharedInstance] POSTheartbeat:[[[userInfo objectForKey:@\"d\"] objectAtIndex:1] intValue] cid:[[[userInfo objectForKey:@\"d\"] objectAtIndex:0] intValue] bid:[[[userInfo objectForKey:@\"d\"] objectAtIndex:1] intValue] lastSeenEid:[[[userInfo objectForKey:@\"d\"] objectAtIndex:2] doubleValue] handler:handler];\n    }\n}\n\n-(void)showLoginView {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        self.window.backgroundColor = [UIColor colorWithRed:11.0/255.0 green:46.0/255.0 blue:96.0/255.0 alpha:1];\n        self.loginSplashViewController.view.alpha = 1;\n        self.window.rootViewController = self.loginSplashViewController;\n#ifndef ENTERPRISE\n        [self.loginSplashViewController loginHintPressed:nil];\n#endif\n    }];\n}\n\n-(void)showMainView {\n    [self showMainView:YES];\n}\n\n-(void)showMainView:(BOOL)animated {\n    if([NetworkConnection sharedInstance].session.length) {\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        [UIColor setTheme];\n        [self.mainViewController applyTheme];\n        if(animated) {\n            if([NetworkConnection sharedInstance].state != kIRCCloudStateConnected)\n                [[NetworkConnection sharedInstance] connect:NO];\n\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [UIApplication sharedApplication].statusBarHidden = self.mainViewController.prefersStatusBarHidden;\n                self.slideViewController.view.alpha = 1;\n                if(self.window.rootViewController != self.slideViewController) {\n                    if([self.window.rootViewController isKindOfClass:ImageViewController.class])\n                        self.mainViewController.ignoreVisibilityChanges = YES;\n                    BOOL fromLoginView = (self.window.rootViewController == self.loginSplashViewController);\n                    UIView *v = self.window.rootViewController.view;\n                    self.window.rootViewController = self.slideViewController;\n                    [self.window insertSubview:v aboveSubview:self.window.rootViewController.view];\n                    self.mainViewController.ignoreVisibilityChanges = NO;\n                    if(fromLoginView)\n                        [self.loginSplashViewController hideLoginView];\n                    [UIView animateWithDuration:0.5f animations:^{\n                        v.alpha = 0;\n                    } completion:^(BOOL finished){\n                        [v removeFromSuperview];\n                        self.window.backgroundColor = [UIColor textareaBackgroundColor];\n                        self.mainViewController.ignoreVisibilityChanges = YES;\n                        self.window.rootViewController = nil;\n                        self.window.rootViewController = self.slideViewController;\n                        self.mainViewController.ignoreVisibilityChanges = NO;\n                    }];\n                }\n            }];\n        } else if(self.window.rootViewController != self.slideViewController) {\n            if([self.window.rootViewController isKindOfClass:ImageViewController.class])\n                self.mainViewController.ignoreVisibilityChanges = YES;\n            [UIApplication sharedApplication].statusBarHidden = self.mainViewController.prefersStatusBarHidden;\n            self.slideViewController.view.alpha = 1;\n            [self.window.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];\n            self.window.rootViewController = self.slideViewController;\n            self.window.backgroundColor = [UIColor textareaBackgroundColor];\n            self.mainViewController.ignoreVisibilityChanges = NO;\n        }\n        }];\n        if(self.slideViewController.presentedViewController)\n            [self.slideViewController dismissViewControllerAnimated:animated completion:nil];\n    }\n}\n\n-(void)showConnectionView {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[EditConnectionViewController alloc] initWithStyle:UITableViewStyleGrouped]];\n    }];\n}\n\n- (void)applicationDidEnterBackground:(UIApplication *)application {\n    CLS_LOG(@\"App entering background\");\n#ifndef DEBUG\n#ifdef ENTERPRISE\n    NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.enterprise.share\"];\n#else\n    NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.share\"];\n#endif\n    if(sharedcontainer) {\n        NSURL *logfile = [[[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] objectAtIndex:0] URLByAppendingPathComponent:@\"log.txt\"];\n        \n        NSDate *yesterday = [NSDate dateWithTimeIntervalSinceNow:(-60*60*24)];\n        NSDate *modificationDate = nil;\n        [logfile getResourceValue:&modificationDate forKey:NSURLContentModificationDateKey error:nil];\n\n        if([yesterday compare:modificationDate] == NSOrderedDescending) {\n            [[NSFileManager defaultManager] removeItemAtURL:logfile error:nil];\n        }\n    }\n#endif\n    [self performSelectorInBackground:@selector(_pruneAndSync) withObject:nil];\n    [[ImageCache sharedInstance] clearFailedURLs];\n    [[ImageCache sharedInstance] performSelectorInBackground:@selector(prune) withObject:nil];\n    self->_conn = [NetworkConnection sharedInstance];\n    self->_movedToBackground = YES;\n    self->_conn.failCount = 0;\n    self->_conn.reconnectTimestamp = 0;\n    [self->_conn cancelIdleTimer];\n    if([self.window.rootViewController isKindOfClass:[ECSlidingViewController class]]) {\n        ECSlidingViewController *evc = (ECSlidingViewController *)self.window.rootViewController;\n        [evc.topViewController viewWillDisappear:NO];\n    } else {\n        [self.window.rootViewController viewWillDisappear:NO];\n    }\n    \n    /*__block UIBackgroundTaskIdentifier background_task = [application beginBackgroundTaskWithExpirationHandler: ^ {\n        if(background_task == self->_background_task) {\n            if([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {\n                CLS_LOG(@\"Background task expired, disconnecting websocket\");\n                [self->_conn performSelectorOnMainThread:@selector(disconnect) withObject:nil waitUntilDone:YES];\n                [self->_conn serialize];\n                [NetworkConnection sync];\n            }\n            self->_background_task = UIBackgroundTaskInvalid;\n        }\n    }];\n    self->_background_task = background_task;\n    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n        for(Buffer *b in [[BuffersDataSource sharedInstance] getBuffers]) {\n            if(!b.scrolledUp && [[EventsDataSource sharedInstance] highlightStateForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type] == 0)\n                [[EventsDataSource sharedInstance] pruneEventsForBuffer:b.bid maxSize:100];\n        }\n        [self->_conn serialize];\n        [NSThread sleepForTimeInterval:[UIApplication sharedApplication].backgroundTimeRemaining - 5];\n        if(background_task == self->_background_task) {\n            dispatch_async(dispatch_get_main_queue(), ^{\n                self->_background_task = UIBackgroundTaskInvalid;\n                if([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {\n                    CLS_LOG(@\"Background task timed out, disconnecting websocket\");\n                    [[NetworkConnection sharedInstance] disconnect];\n                    [[NetworkConnection sharedInstance] serialize];\n                    [NetworkConnection sync];\n                }\n                [application endBackgroundTask: background_task];\n            });\n        }\n    });*/\n    if(self.window.rootViewController != self->_slideViewController && [ServersDataSource sharedInstance].count) {\n        [self showMainView:NO];\n        self.window.backgroundColor = [UIColor blackColor];\n    }\n    [[NotificationsDataSource sharedInstance] updateBadgeCount];\n}\n\n- (void)_pruneAndSync {\n    __block BOOL __interrupt = NO;\n#ifndef EXTENSION\n    UIBackgroundTaskIdentifier background_task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^ {\n        CLS_LOG(@\"AppDelegate pruneAndSync task expired\");\n        __interrupt = YES;\n    }];\n#endif\n    for(Buffer *b in [[BuffersDataSource sharedInstance] getBuffers]) {\n        if(!b.scrolledUp && [[EventsDataSource sharedInstance] highlightStateForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type] == 0)\n            [[EventsDataSource sharedInstance] pruneEventsForBuffer:b.bid maxSize:100];\n        if(__interrupt)\n            break;\n    }\n    if(!__interrupt)\n        [[NetworkConnection sharedInstance] serialize];\n    if(!__interrupt)\n        [NetworkConnection sync];\n#ifndef EXTENSION\n    [[UIApplication sharedApplication] endBackgroundTask: background_task];\n#endif\n}\n\n- (void)applicationDidBecomeActive:(UIApplication *)application {\n    self->_conn = [NetworkConnection sharedInstance];\n    CLS_LOG(@\"App became active, state: %i notifier: %i movedToBackground: %i reconnectTimestamp: %f\", _conn.state, _conn.notifier, _movedToBackground, _conn.reconnectTimestamp);\n    \n    if(self->_backlogCompletedObserver) {\n        CLS_LOG(@\"Backlog completed observer was registered, removing\");\n        [[NSNotificationCenter defaultCenter] removeObserver:self->_backlogCompletedObserver];\n        self->_backlogCompletedObserver = nil;\n    }\n    if(self->_backlogFailedObserver) {\n        CLS_LOG(@\"Backlog failed observer was registered, removing\");\n        [[NSNotificationCenter defaultCenter] removeObserver:self->_backlogFailedObserver];\n        self->_backlogFailedObserver = nil;\n    }\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n    if(self->_conn.reconnectTimestamp == 0)\n        self->_conn.reconnectTimestamp = -1;\n    self->_conn.failCount = 0;\n    self->_conn.reachabilityValid = NO;\n    if(self->_conn.session.length && self->_conn.state != kIRCCloudStateConnected && self->_conn.state != kIRCCloudStateConnecting) {\n        CLS_LOG(@\"Attempting to reconnect on app resume\");\n        [self->_conn connect:NO];\n    } else if(self->_conn.notifier) {\n        CLS_LOG(@\"Clearing notifier flag\");\n        self->_conn.notifier = NO;\n    } else {\n        CLS_LOG(@\"Not attempting to reconnect, session length: %i state: %i\", self->_conn.session.length, self->_conn.state);\n    }\n    \n    if(self->_movedToBackground) {\n        self->_movedToBackground = NO;\n        if([ColorFormatter shouldClearFontCache]) {\n            [ColorFormatter clearFontCache];\n            [[EventsDataSource sharedInstance] clearFormattingCache];\n            [[AvatarsDataSource sharedInstance] invalidate];\n            [ColorFormatter loadFonts];\n        }\n        self->_conn.reconnectTimestamp = -1;\n        if(_conn.state == kIRCCloudStateConnected)\n            [self->_conn scheduleIdleTimer];\n        if([self.window.rootViewController isKindOfClass:[ECSlidingViewController class]]) {\n            ECSlidingViewController *evc = (ECSlidingViewController *)self.window.rootViewController;\n            [evc.topViewController viewWillAppear:NO];\n        } else {\n            [self.window.rootViewController viewWillAppear:NO];\n        }\n    }\n    \n    [[NotificationsDataSource sharedInstance] updateBadgeCount];\n}\n\n- (void)applicationWillTerminate:(UIApplication *)application {\n    CLS_LOG(@\"Application terminating, disconnecting websocket\");\n    [self->_conn disconnect];\n    [self->_conn serialize];\n}\n\n- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler {\n    NSURLSessionConfiguration *config;\n    config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];\n#ifdef ENTERPRISE\n    config.sharedContainerIdentifier = @\"group.com.irccloud.enterprise.share\";\n#else\n    config.sharedContainerIdentifier = @\"group.com.irccloud.share\";\n#endif\n    config.HTTPCookieStorage = nil;\n    config.URLCache = nil;\n    config.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;\n    config.discretionary = NO;\n    if([identifier hasPrefix:@\"com.irccloud.logs.\"]) {\n        LogExportsTableViewController *lvc;\n        \n        if([self->_mainViewController.presentedViewController isKindOfClass:[UINavigationController class]] && [((UINavigationController *)_mainViewController.presentedViewController).topViewController isKindOfClass:[LogExportsTableViewController class]])\n            lvc = (LogExportsTableViewController *)(((UINavigationController *)_mainViewController.presentedViewController).topViewController);\n        else\n            lvc = [[LogExportsTableViewController alloc] initWithStyle:UITableViewStyleGrouped];\n        \n        lvc.completionHandler = completionHandler;\n        [[NSURLSession sessionWithConfiguration:config delegate:lvc delegateQueue:[NSOperationQueue mainQueue]] finishTasksAndInvalidate];\n    } else if([identifier hasPrefix:@\"com.irccloud.share.\"]) {\n        [[NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]] finishTasksAndInvalidate];\n        imageUploadCompletionHandler = completionHandler;\n    } else {\n        CLS_LOG(@\"Unrecognized background task: %@\", identifier);\n        completionHandler();\n    }\n}\n\n- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {\n    self->_conn = [NetworkConnection sharedInstance];\n    NSData *response = [NSData dataWithContentsOfURL:location];\n    if(session.configuration.identifier) {\n#ifdef ENTERPRISE\n        NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n        NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n        NSMutableDictionary *uploadtasks = [[d dictionaryForKey:@\"uploadtasks\"] mutableCopy];\n        NSDictionary *dict = [uploadtasks objectForKey:session.configuration.identifier];\n        [uploadtasks removeObjectForKey:session.configuration.identifier];\n        [d setObject:uploadtasks forKey:@\"uploadtasks\"];\n        [d synchronize];\n        \n        FileUploader *u = [[FileUploader alloc] initWithTask:dict response:response completion:self->imageUploadCompletionHandler];\n        u.delegate = self.mainViewController;\n        [u connectionDidFinishLoading];\n    }\n}\n\n- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {\n    if(error) {\n        CLS_LOG(@\"Download error: %@\", error);\n        [[NotificationsDataSource sharedInstance] alert:@\"Unable to share image. Please try again shortly.\" title:nil category:nil userInfo:nil];\n    }\n    [session finishTasksAndInvalidate];\n}\n\n-(void)addScene:(id)scene {\n    if(!_activeScenes)\n        _activeScenes = [[NSMutableSet alloc] init];\n    \n    [_activeScenes addObject:scene];\n    \n    if(_activeScenes.count == 1)\n        [self applicationDidBecomeActive:[UIApplication sharedApplication]];\n    \n    [self setActiveScene:[scene window]];\n    \n    CLS_LOG(@\"Active scene count: %i\", _activeScenes.count);\n}\n\n-(void)removeScene:(id)scene {\n    [_activeScenes removeObject:scene];\n\n    if(_activeScenes.count == 0)\n        [self applicationDidEnterBackground:[UIApplication sharedApplication]];\n\n    CLS_LOG(@\"Active scene count: %i\", _activeScenes.count);\n}\n\n-(void)setActiveScene:(UIWindow *)window {\n    if (@available(iOS 13.0, *)) {\n        for(SceneDelegate *d in _activeScenes) {\n            if(d.window == window) {\n                self.window = d.window;\n                self.splashViewController = d.splashViewController;\n                self.loginSplashViewController = d.loginSplashViewController;\n                self.mainViewController = d.mainViewController;\n                self.slideViewController = d.slideViewController;\n                break;\n            }\n        }\n    }\n}\n\n-(UIScene *)sceneForWindow:(UIWindow *)window API_AVAILABLE(ios(13.0)){\n    for(SceneDelegate *d in _activeScenes) {\n        if(d.window == window) {\n            return d.scene;\n        }\n    }\n    return nil;\n}\n\n-(void)closeWindow:(UIWindow *)window {\n    if (@available(iOS 13.0, *)) {\n        for(UISceneSession *session in [UIApplication sharedApplication].openSessions) {\n            if([session.scene.delegate isKindOfClass:SceneDelegate.class] && ((SceneDelegate *)session.scene.delegate).window == window) {\n                [UIApplication.sharedApplication requestSceneSessionDestruction:session options:nil errorHandler:nil];\n                break;\n            }\n        }\n    }\n}\n\n- (void)buildMenuWithBuilder:(id<UIMenuBuilder>)builder {\n    [super buildMenuWithBuilder:builder];\n    \n    if(!builder || ![builder menuForIdentifier:UIMenuFont])\n        return;\n    \n    if (@available(iOS 14.0, *)) {\n        NSMutableArray *formatting = [[NSMutableArray alloc] init];\n        UICommand *toggleBoldface = [builder commandForAction:@selector(toggleBoldface:) propertyList:nil];\n        UICommand *toggleItalics = [builder commandForAction:@selector(toggleItalics:) propertyList:nil];\n        UICommand *toggleUnderline = [builder commandForAction:@selector(toggleUnderline:) propertyList:nil];\n        \n        if (toggleBoldface)\n            [formatting addObject:toggleBoldface];\n        \n        if (toggleItalics)\n            [formatting addObject:toggleItalics];\n        \n        if (toggleUnderline)\n            [formatting addObject:toggleUnderline];\n        \n        [formatting addObject:[UICommand commandWithTitle:@\"Text Color\" image:nil action:@selector(chooseFGColor) propertyList:nil]];\n        \n        [formatting addObject:[UICommand commandWithTitle:@\"Background Color\" image:nil action:@selector(chooseBGColor) propertyList:nil]];\n        \n        [formatting addObject:[UICommand commandWithTitle:@\"Reset Colors\" image:nil action:@selector(resetColors) propertyList:nil]];\n        \n        [builder replaceMenuForIdentifier:UIMenuFont withMenu:[[builder menuForIdentifier:UIMenuFont] menuByReplacingChildren:formatting]];\n        \n        if(builder.system == UIMenuSystem.mainSystem && [builder menuForIdentifier:UIMenuPreferences]) {\n            [builder removeMenuForIdentifier:UIMenuServices];\n            [builder removeMenuForIdentifier:UIMenuToolbar];\n            \n            [builder replaceMenuForIdentifier:UIMenuPreferences withMenu:[[builder menuForIdentifier:UIMenuPreferences] menuByReplacingChildren:@[\n                [UIKeyCommand commandWithTitle:@\"Preferences…\" image:nil action:@selector(showSettings) input:@\",\" modifierFlags:UIKeyModifierCommand propertyList:nil],\n            ]]];\n\n            [builder replaceMenuForIdentifier:UIMenuView withMenu:[[builder menuForIdentifier:UIMenuView] menuByReplacingChildren:@[\n                [builder menuForIdentifier:UIMenuFullscreen],\n            ]]];\n\n            [builder replaceMenuForIdentifier:UIMenuFormat withMenu:[[builder menuForIdentifier:UIMenuFormat] menuByReplacingChildren:formatting]];\n\n            [builder replaceMenuForIdentifier:UIMenuFile withMenu:[[builder menuForIdentifier:UIMenuFile] menuByReplacingChildren:@[\n                [builder menuForIdentifier:UIMenuNewScene],\n                [UIMenu menuWithTitle:@\"\" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[\n                    [UICommand commandWithTitle:@\"Upload a File…\" image:nil action:@selector(chooseFile) propertyList:nil],\n                    [UICommand commandWithTitle:@\"New Text Snippet…\" image:nil action:@selector(startPastebin) propertyList:nil]\n                ]],\n                [UIMenu menuWithTitle:@\"\" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[\n                    [UICommand commandWithTitle:@\"Add a Network…\" image:nil action:@selector(addNetwork) propertyList:nil],\n                    [UICommand commandWithTitle:@\"Edit Connection…\" image:nil action:@selector(editConnection) propertyList:nil]\n                ]],\n                [UIMenu menuWithTitle:@\"\" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[\n                    [UIKeyCommand commandWithTitle:@\"Select Next in List\" image:nil action:@selector(selectNext) input:UIKeyInputDownArrow modifierFlags:UIKeyModifierCommand propertyList:nil],\n                    [UIKeyCommand commandWithTitle:@\"Select Previous in List\" image:nil action:@selector(selectPrevious) input:UIKeyInputUpArrow modifierFlags:UIKeyModifierCommand propertyList:nil],\n                    [UIKeyCommand commandWithTitle:@\"Select Next Unread in List\" image:nil action:@selector(selectNextUnread) input:UIKeyInputDownArrow modifierFlags:UIKeyModifierCommand|UIKeyModifierShift propertyList:nil],\n                    [UIKeyCommand commandWithTitle:@\"Select Previous Unread in List\" image:nil action:@selector(selectPreviousUnread) input:UIKeyInputUpArrow modifierFlags:UIKeyModifierCommand|UIKeyModifierShift propertyList:nil],\n                ]],\n                [UIMenu menuWithTitle:@\"\" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[\n                    [UIKeyCommand commandWithTitle:@\"Mark Current As Read\" image:nil action:@selector(markAsRead) input:@\"r\" modifierFlags:UIKeyModifierCommand propertyList:nil],\n                    [UIKeyCommand commandWithTitle:@\"Mark All As Read\" image:nil action:@selector(markAllAsRead) input:@\"r\" modifierFlags:UIKeyModifierCommand|UIKeyModifierShift propertyList:nil],\n                ]],\n                [UIMenu menuWithTitle:@\"\" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[\n                    [UICommand commandWithTitle:@\"Download Logs…\" image:nil action:@selector(downloadLogs) propertyList:nil],\n                ]],\n                [builder menuForIdentifier:UIMenuClose],\n                [UIMenu menuWithTitle:@\"\" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[\n                    [UICommand commandWithTitle:@\"Logout\" image:nil action:@selector(logout) propertyList:nil]\n                ]],\n            ]]];\n\n            [builder insertSiblingMenu:[UIMenu menuWithTitle:@\"Go\" children:@[\n                [UIKeyCommand commandWithTitle:@\"Jump To Channel\" image:nil action:@selector(jumpToChannel) input:@\"k\" modifierFlags:UIKeyModifierCommand propertyList:nil],\n                [UICommand commandWithTitle:@\"File Uploads\" image:nil action:@selector(showUploads) propertyList:nil],\n                [UICommand commandWithTitle:@\"Text Snippets\" image:nil action:@selector(showPastebins) propertyList:nil]\n            ]] afterMenuForIdentifier:UIMenuView];\n            \n            [builder insertChildMenu:[UIMenu menuWithTitle:@\"\" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[\n                [UICommand commandWithTitle:@\"Send Feedback\" image:nil action:@selector(sendFeedback) propertyList:nil],\n                [UICommand commandWithTitle:@\"Join #feedback Channel\" image:nil action:@selector(joinFeedback) propertyList:nil],\n                [UICommand commandWithTitle:@\"Become A Beta Tester\" image:nil action:@selector(joinBeta) propertyList:nil],\n                [UICommand commandWithTitle:@\"FAQ\" image:nil action:@selector(FAQ) propertyList:nil],\n                [UICommand commandWithTitle:@\"Version History\" image:nil action:@selector(versionHistory) propertyList:nil],\n                [UICommand commandWithTitle:@\"Open-Source Licenses\" image:nil action:@selector(openSourceLicenses) propertyList:nil],\n            ]] atStartOfMenuForIdentifier:UIMenuHelp];\n        }\n    }\n}\n\n-(BOOL)isOnVisionOS { //From: https://medium.com/@timonus/low-hanging-fruit-for-ios-apps-running-on-visionos-08a85db0fb31\n    static BOOL isOnVisionOSDevice = NO;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        isOnVisionOSDevice = (NSClassFromString(@\"UIWindowSceneGeometryPreferencesVision\") != nil);\n    });\n    return isOnVisionOSDevice;\n}\n@end\n\n@implementation SceneDelegate\n-(void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions API_AVAILABLE(ios(13.0)) {\n    _appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;\n    self.scene = scene;\n\n    for(NSUserActivity *a in connectionOptions.userActivities) {\n        if([a.activityType isEqualToString:@\"com.IRCCloud.settings\"]) {\n            SettingsViewController *svc = [[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];\n            UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:svc];\n            [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n            self.window.rootViewController = nc;\n            ((UIWindowScene *)scene).sizeRestrictions.maximumSize = ((UIWindowScene *)scene).sizeRestrictions.minimumSize;\n            return;\n        }\n    }\n    \n    self.splashViewController = [[UIStoryboard storyboardWithName:@\"MainStoryboard\" bundle:nil] instantiateViewControllerWithIdentifier:@\"SplashViewController\"];\n    self.splashViewController.view.accessibilityIgnoresInvertColors = YES;\n    self.window.rootViewController = self.splashViewController;\n    self.loginSplashViewController = [[UIStoryboard storyboardWithName:@\"MainStoryboard\" bundle:nil] instantiateViewControllerWithIdentifier:@\"LoginSplashViewController\"];\n    self.mainViewController = [[UIStoryboard storyboardWithName:@\"MainStoryboard\" bundle:nil] instantiateViewControllerWithIdentifier:@\"MainViewController\"];\n    self.slideViewController = [[ECSlidingViewController alloc] init];\n    self.slideViewController.view.backgroundColor = [UIColor blackColor];\n    self.slideViewController.topViewController = [[UINavigationController alloc] initWithNavigationBarClass:[NavBarHax class] toolbarClass:nil];\n    [((UINavigationController *)self.slideViewController.topViewController) setViewControllers:@[self.mainViewController]];\n    self.slideViewController.topViewController.view.backgroundColor = [UIColor blackColor];\n    self.slideViewController.view.accessibilityIgnoresInvertColors = YES;\n    \n    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sceneTapped:)];\n    tap.delegate = self;\n    [self.window addGestureRecognizer: tap];\n}\n\n- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveEvent:(UIEvent *)event {\n    [_appDelegate setActiveScene:self.window];\n    return NO;\n}\n\n-(void)sceneTapped:(id)sender {\n}\n\n-(void)sceneDidEnterBackground:(UIScene *)scene API_AVAILABLE(ios(13.0)) {\n    [_appDelegate removeScene:self];\n}\n\n-(void)sceneDidBecomeActive:(UIScene *)scene API_AVAILABLE(ios(13.0)) {\n    [_appDelegate addScene:self];\n}\n\n-(void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts API_AVAILABLE(ios(13.0)) {\n    [_appDelegate setActiveScene:self.window];\n    for(UIOpenURLContext *c in URLContexts) {\n        [_appDelegate application:[UIApplication sharedApplication] handleOpenURL:c.URL options:nil];\n    }\n}\n\n-(void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity API_AVAILABLE(ios(13.0)) {\n    [_appDelegate setActiveScene:self.window];\n    [_appDelegate continueActivity:userActivity];\n}\n\n-(void)sceneWillEnterForeground:(UIScene *)scene API_AVAILABLE(ios(13.0)) {\n    [_appDelegate setActiveScene:self.window];\n    self.window.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;\n\n    if(self.window.rootViewController == self.splashViewController) {\n        NSString *session = [NetworkConnection sharedInstance].session;\n        if(session != nil && [session length] > 0 && IRCCLOUD_HOST.length > 0) {\n            self.window.backgroundColor = [UIColor textareaBackgroundColor];\n            self.window.rootViewController = self.slideViewController;\n            self.window.overrideUserInterfaceStyle = self.mainViewController.view.overrideUserInterfaceStyle;\n        } else {\n            self.window.rootViewController = self.loginSplashViewController;\n        }\n        \n#ifdef DEBUG\n        if(![[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"]) {\n#endif\n            [self.window addSubview:self.splashViewController.view];\n            \n            if([NetworkConnection sharedInstance].session.length) {\n                [self.splashViewController animate:nil];\n            } else {\n                self.loginSplashViewController.logo.hidden = YES;\n                [self.splashViewController animate:self.loginSplashViewController.logo];\n            }\n            \n            [UIView animateWithDuration:0.25 delay:0.25 options:0 animations:^{\n                self.splashViewController.view.backgroundColor = [UIColor clearColor];\n            } completion:^(BOOL finished) {\n                self.loginSplashViewController.logo.hidden = NO;\n                [self.splashViewController.view removeFromSuperview];\n            }];\n#ifdef DEBUG\n        }\n#endif\n    }\n    \n    [self.window becomeKeyWindow];\n    [self.window becomeFirstResponder];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/AvatarsDataSource.h",
    "content": "//\n//  AvatarsDataSource.h\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import <Foundation/Foundation.h>\n\n@interface Avatar : NSObject {\n    int _bid;\n    NSString *_nick;\n    NSString *_displayName;\n    NSMutableDictionary *_images;\n    NSMutableDictionary *_selfImages;\n    NSTimeInterval _lastAccessTime;\n}\n@property (assign) int bid;\n@property (copy) NSString *nick, *displayName;\n@property (readonly) NSTimeInterval lastAccessTime;\n-(UIImage *)getImage:(int)size isSelf:(BOOL)isSelf;\n-(UIImage *)getImage:(int)size isSelf:(BOOL)isSelf isChannel:(BOOL)isChannel;\n@end\n\n@interface AvatarsDataSource : NSObject {\n    NSMutableDictionary *_avatars;\n    NSMutableDictionary *_avatarURLs;\n}\n+(AvatarsDataSource *)sharedInstance;\n-(void)invalidate;\n-(void)serialize;\n-(Avatar *)getAvatar:(NSString *)displayName nick:(NSString *)nick bid:(int)bid;\n-(void)setAvatarURL:(NSURL *)url bid:(int)bid eid:(NSTimeInterval)eid;\n-(NSURL *)URLforBid:(int)bid;\n-(void)removeAllURLs;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/AvatarsDataSource.m",
    "content": "//\n//  AvatarsDataSource.m\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import \"AvatarsDataSource.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@implementation Avatar\n-(id)init {\n    self = [super init];\n    if(self) {\n        self->_images = [[NSMutableDictionary alloc] init];\n        self->_selfImages = [[NSMutableDictionary alloc] init];\n    }\n    return self;\n}\n\n-(UIImage *)getImage:(int)size isSelf:(BOOL)isSelf {\n    return [self getImage:size isSelf:isSelf isChannel:NO];\n}\n\n-(UIImage *)getImage:(int)size isSelf:(BOOL)isSelf isChannel:(BOOL)isChannel {\n    self->_lastAccessTime = [[NSDate date] timeIntervalSince1970];\n    NSMutableDictionary *images = isSelf?_selfImages:self->_images;\n    if(![images objectForKey:@(size)]) {\n        UIFont *font = [UIFont boldSystemFontOfSize:(size * (isChannel ? 0.5 : 0.65))];\n        UIGraphicsBeginImageContextWithOptions(CGSizeMake(size, size), NO, 0);\n        CGContextRef ctx = UIGraphicsGetCurrentContext();\n        if(isChannel) {\n            UIColor *color = [UIColor lightGrayColor];\n            CGContextSetFillColorWithColor(ctx, color.CGColor);\n            CGContextFillEllipseInRect(ctx,CGRectMake(1,1,size-2,size-2));\n        } else {\n            UIColor *color = isSelf?[UIColor selfNickColor]:[UIColor colorFromHexString:[UIColor colorForNick:self->_nick]];\n            if([UIColor isDarkTheme]) {\n                CGContextSetFillColorWithColor(ctx, color.CGColor);\n                CGContextFillEllipseInRect(ctx,CGRectMake(1,1,size-2,size-2));\n            } else {\n                CGFloat h, s, b, a;\n                [color getHue:&h saturation:&s brightness:&b alpha:&a];\n                \n                CGContextSetFillColorWithColor(ctx, [UIColor colorWithHue:h saturation:s brightness:b * 0.8 alpha:a].CGColor);\n                CGContextFillEllipseInRect(ctx,CGRectMake(1,1,size-2,size-2));\n                CGContextSetFillColorWithColor(ctx, color.CGColor);\n                CGContextFillEllipseInRect(ctx,CGRectMake(1,1,size-2,size-3));\n            }\n        }\n        \n        NSRegularExpression *r = [NSRegularExpression regularExpressionWithPattern:@\"[_\\\\W]+\" options:NSRegularExpressionCaseInsensitive error:nil];\n        NSString *text = [r stringByReplacingMatchesInString:[self->_displayName uppercaseString] options:0 range:NSMakeRange(0, _displayName.length) withTemplate:@\"\"];\n        if(!text.length)\n            text = [self->_displayName uppercaseString];\n        text = isChannel ? [NSString stringWithFormat:@\"#%@\", [text substringToIndex:1]] : [text substringToIndex:1];\n        CGSize textSize = [text sizeWithAttributes:@{NSFontAttributeName:font, NSForegroundColorAttributeName:isChannel?[UIColor whiteColor]:[UIColor contentBackgroundColor]}];\n        CGPoint p = CGPointMake((size / 2) - (textSize.width / 2),(size / 2) - (textSize.height / 2) - 0.5);\n        [text drawAtPoint:p withAttributes:@{NSFontAttributeName:font, NSForegroundColorAttributeName:isChannel?[UIColor whiteColor]:[UIColor contentBackgroundColor]}];\n        \n        [images setObject:UIGraphicsGetImageFromCurrentImageContext() forKey:@(size)];\n        UIGraphicsEndImageContext();\n    }\n    return [images objectForKey:@(size)];\n}\n@end\n\n@implementation AvatarsDataSource\n+(AvatarsDataSource *)sharedInstance {\n    static AvatarsDataSource *sharedInstance;\n    \n    @synchronized(self) {\n        if(!sharedInstance)\n            sharedInstance = [[AvatarsDataSource alloc] init];\n        \n        return sharedInstance;\n    }\n    return nil;\n}\n\n-(id)init {\n    self = [super init];\n    if(self) {\n        self->_avatars = [[NSMutableDictionary alloc] init];\n\n        if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"cacheVersion\"] isEqualToString:[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleVersion\"]]) {\n            NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"avatarURLs\"];\n            \n            @try {\n                NSError* error = nil;\n                self->_avatarURLs = [[NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:NSDictionary.class, NSURL.class, NSString.class, NSNumber.class, nil] fromData:[NSData dataWithContentsOfFile:cacheFile] error:&error] mutableCopy];\n                if(error)\n                    @throw [NSException exceptionWithName:@\"NSError\" reason:error.debugDescription userInfo:@{ @\"NSError\" : error }];\n            } @catch(NSException *e) {\n                CLS_LOG(@\"Exception: %@\", e);\n                [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n                [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"cacheVersion\"];\n            }\n        }\n        \n        if(!_avatarURLs)\n            self->_avatarURLs = [[NSMutableDictionary alloc] init];\n    }\n    return self;\n}\n\n-(void)serialize {\n    NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"avatarURLs\"];\n\n    NSDictionary *avatarURLs;\n    @synchronized(self->_avatarURLs) {\n        avatarURLs = [self->_avatarURLs copy];\n    }\n    \n    @synchronized(self) {\n        @try {\n            NSError* error = nil;\n            [[NSKeyedArchiver archivedDataWithRootObject:avatarURLs requiringSecureCoding:YES error:&error] writeToFile:cacheFile atomically:YES];\n            if(error)\n                CLS_LOG(@\"Error archiving: %@\", error);\n            [[NSURL fileURLWithPath:cacheFile] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL];\n        }\n        @catch (NSException *e) {\n            CLS_LOG(@\"Exception: %@\", e);\n            [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n        }\n    }\n}\n\n-(void)setAvatarURL:(NSURL *)url bid:(int)bid eid:(NSTimeInterval)eid {\n    if(url && [[[_avatarURLs objectForKey:@(bid)] objectForKey:@\"eid\"] longValue] < eid) {\n        [_avatarURLs setObject:@{@\"eid\":@(eid), @\"url\":url} forKey:@(bid)];\n    }\n}\n\n-(NSURL *)URLforBid:(int)bid {\n    return [[_avatarURLs objectForKey:@(bid)] objectForKey:@\"url\"];\n}\n\n-(Avatar *)getAvatar:(NSString *)displayName nick:(NSString *)nick bid:(int)bid {\n    if(!displayName.length)\n        return nil;\n    \n    if(!nick.length)\n        nick = displayName;\n    \n    if(![self->_avatars objectForKey:@(bid)]) {\n        [self->_avatars setObject:[[NSMutableDictionary alloc] init] forKey:@(bid)];\n    }\n    \n    if(![[self->_avatars objectForKey:@(bid)] objectForKey:nick]) {\n        Avatar *a = [[Avatar alloc] init];\n        a.bid = bid;\n        a.nick = nick;\n        a.displayName = displayName;\n        [[self->_avatars objectForKey:@(bid)] setObject:a forKey:displayName];\n    }\n    \n    return [[self->_avatars objectForKey:@(bid)] objectForKey:displayName];\n}\n\n-(void)invalidate {\n    [self->_avatars removeAllObjects];\n}\n\n-(void)removeAllURLs {\n    [self->_avatarURLs removeAllObjects];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/AvatarsTableViewController.h",
    "content": "//\n//  AvatarsTableViewController.h\n//\n//  Copyright (C) 2018 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n#import \"NetworkConnection.h\"\n#import \"FileUploader.h\"\n\n@interface AvatarsTableViewController : UITableViewController<UIImagePickerControllerDelegate,FileUploaderDelegate> {\n    NSArray *_avatars;\n    Server *_server;\n    FileUploader *_uploader;\n    BOOL _failed;\n}\n-(id)initWithServer:(int)cid;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/AvatarsTableViewController.m",
    "content": "//\n//  AvatarsTableViewController.m\n//\n//  Copyright (C) 2018 IRCCloud, Ltd.\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#if !TARGET_OS_MACCATALYST\n#import <AssetsLibrary/AssetsLibrary.h>\n#endif\n#import \"AvatarsTableViewController.h\"\n#import \"YYAnimatedImageView.h\"\n#import \"ImageCache.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@interface AvatarTableCell : UITableViewCell {\n    YYAnimatedImageView *_avatar;\n}\n@property (readonly) YYAnimatedImageView *avatar;\n@end\n\n@implementation AvatarTableCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        \n        self->_avatar = [[YYAnimatedImageView alloc] initWithFrame:CGRectZero];\n        self->_avatar.layer.cornerRadius = 5.0;\n        self->_avatar.layer.masksToBounds = YES;\n        \n        [self.contentView addSubview:self->_avatar];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n    [super layoutSubviews];\n    \n    CGRect frame = [self.contentView bounds];\n    frame.origin.x = frame.origin.y = 6;\n    frame.size.width -= 12;\n    frame.size.height -= 12;\n    \n    self->_avatar.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.height, frame.size.height);\n    self.textLabel.frame = CGRectMake(frame.origin.x + frame.size.height + 6, frame.origin.y, frame.size.width - frame.size.height, frame.size.height);\n}\n\n-(void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n@end\n\n\n@implementation AvatarsTableViewController\n\n-(id)initWithServer:(int)cid {\n    self = [super initWithStyle:UITableViewStylePlain];\n    if(self) {\n        self->_server = [[ServersDataSource sharedInstance] getServer:cid];\n    }\n    return self;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationItem.title = @\"Choose An Avatar\";\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    if(self.navigationController.viewControllers.count == 1)\n        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed)];\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(addButtonPressed)];\n    self.tableView.backgroundColor = [[UITableViewCell appearance] backgroundColor];\n}\n\n-(void)cancelButtonPressed {\n    [self->_uploader cancel];\n    if(self.navigationController.viewControllers.count == 1)\n        [self.parentViewController dismissViewControllerAnimated:YES completion:nil];\n    else\n        [self.navigationController popViewControllerAnimated:YES];\n}\n\n-(void)addButtonPressed {\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];\n    \n    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Take a Photo\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n            [self _choosePhoto:UIImagePickerControllerSourceTypeCamera];\n        }]];\n    }\n    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Choose Photo\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n            [self _choosePhoto:UIImagePickerControllerSourceTypePhotoLibrary];\n        }]];\n    }\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    alert.popoverPresentationController.barButtonItem = self.navigationItem.rightBarButtonItem;\n    alert.popoverPresentationController.sourceView = self.view;\n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)_choosePhoto:(UIImagePickerControllerSourceType)sourceType {\n    [self->_uploader cancel];\n    self->_uploader = nil;\n    UIImagePickerController *picker = [[UIImagePickerController alloc] init];\n    picker.sourceType = sourceType;\n    picker.allowsEditing = YES;\n    picker.delegate = (id)self;\n    [UIColor clearTheme];\n    if(sourceType == UIImagePickerControllerSourceTypeCamera) {\n        picker.modalPresentationStyle = UIModalPresentationFullScreen;\n        [self presentViewController:picker animated:YES completion:nil];\n    } else {\n        picker.modalPresentationStyle = UIModalPresentationPopover;\n        picker.popoverPresentationController.barButtonItem = self.navigationItem.rightBarButtonItem;\n        [self presentViewController:picker animated:YES completion:nil];\n    }\n}\n\n-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {\n    [picker dismissViewControllerAnimated:YES completion:^{\n        [UIColor setTheme];\n        [picker dismissViewControllerAnimated:YES completion:nil];\n        \n        NSURL *refURL = [info valueForKey:UIImagePickerControllerReferenceURL];\n        NSURL *mediaURL = [info valueForKey:UIImagePickerControllerMediaURL];\n        UIImage *img = [info objectForKey:UIImagePickerControllerEditedImage];\n        if(!img)\n            img = [info objectForKey:UIImagePickerControllerOriginalImage];\n        \n        CLS_LOG(@\"Image file chosen: %@ %@\", refURL, mediaURL);\n        if(img || refURL || mediaURL) {\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n                [activity startAnimating];\n                self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:activity];\n            }];\n            if(picker.sourceType == UIImagePickerControllerSourceTypeCamera && [[NSUserDefaults standardUserDefaults] boolForKey:@\"saveToCameraRoll\"]) {\n                if(img)\n                    UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);\n                else if(UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(mediaURL.path))\n                    UISaveVideoAtPathToSavedPhotosAlbum(mediaURL.path, nil, nil, nil);\n            }\n            self->_failed = NO;\n            FileUploader *u = [[FileUploader alloc] init];\n            u.delegate = self;\n            u.avatar = YES;\n            if(self->_server) {\n                if(self->_server.orgId) {\n                    u.orgId = self->_server.orgId;\n                } else {\n                    u.cid = self->_server.cid;\n                }\n            } else {\n                u.orgId = -1;\n            }\n            \n            if(refURL) {\n#if !TARGET_OS_MACCATALYST\n                CLS_LOG(@\"Loading metadata from asset library\");\n                ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset) {\n                    ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];\n                    CLS_LOG(@\"Got filename: %@\", imageRep.filename);\n                    u.originalFilename = imageRep.filename;\n                    if([imageRep.filename.lowercaseString hasSuffix:@\".gif\"] || [imageRep.filename.lowercaseString hasSuffix:@\".png\"]) {\n                        CLS_LOG(@\"Uploading file data\");\n                        NSMutableData *data = [[NSMutableData alloc] initWithCapacity:(NSUInteger)imageRep.size];\n                        uint8_t buffer[4096];\n                        long long len = 0;\n                        while(len < imageRep.size) {\n                            long long i = [imageRep getBytes:buffer fromOffset:len length:4096 error:nil];\n                            [data appendBytes:buffer length:(NSUInteger)i];\n                            len += i;\n                        }\n                        [u uploadFile:imageRep.filename UTI:imageRep.UTI data:data];\n                    } else {\n                        CLS_LOG(@\"Uploading UIImage\");\n                        [u uploadImage:img];\n                    }\n                };\n                \n                ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];\n                [assetslibrary assetForURL:refURL resultBlock:resultblock failureBlock:^(NSError *e) {\n                    CLS_LOG(@\"Error getting asset: %@\", e);\n                    if(img) {\n                        [u uploadImage:img];\n                    } else {\n                        [u uploadFile:mediaURL];\n                    }\n                }];\n#endif\n            } else {\n                CLS_LOG(@\"no asset library URL, uploading image data instead\");\n                if(img) {\n                    [u uploadImage:img];\n                } else {\n                    [u uploadFile:mediaURL];\n                }\n            }\n        }\n    }];\n}\n\n-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {\n    [UIColor setTheme];\n    [picker dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)fileUploadProgress:(float)progress {\n    CLS_LOG(@\"Avatar upload progress: %f\", progress);\n}\n\n-(void)fileUploadDidFail:(NSString *)reason {\n    self->_failed = YES;\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        CLS_LOG(@\"File upload failed: %@\", reason);\n        NSString *msg;\n        if([reason isEqualToString:@\"upload_limit_reached\"]) {\n            msg = @\"Sorry, you can’t upload more than 100 MB of files.  Delete some uploads and try again.\";\n        } else if([reason isEqualToString:@\"upload_already_exists\"]) {\n            msg = @\"You’ve already uploaded this file\";\n        } else if([reason isEqualToString:@\"banned_content\"]) {\n            msg = @\"Banned content\";\n        } else {\n            msg = @\"Failed to upload avatar. Please try again shortly.\";\n        }\n        [self dismissViewControllerAnimated:YES completion:^{\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Upload Failed\" message:msg preferredStyle:UIAlertControllerStyleAlert];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n            [self presentViewController:alert animated:YES completion:nil];\n        }];\n    }];\n}\n\n-(void)fileUploadDidFinish {\n    if(!_failed)\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            CLS_LOG(@\"Avatar upload finished\");\n            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(addButtonPressed)];\n            [self cancelButtonPressed];\n        }];\n}\n\n-(void)fileUploadWasCancelled {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        CLS_LOG(@\"Avatar upload cancelled\");\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(addButtonPressed)];\n    }];\n}\n\n-(void)fileUploadTooLarge {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        CLS_LOG(@\"File upload too large\");\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Upload Failed\" message:@\"Sorry, you can’t upload files larger than 15 MB\" preferredStyle:UIAlertControllerStyleAlert];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n        [self presentViewController:alert animated:YES completion:nil];\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(addButtonPressed)];\n    }];\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    \n    switch(event) {\n        case kIRCEventMakeServer:\n        case kIRCEventUserInfo:\n        case kIRCEventAvatarChange:\n        {\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [self viewWillAppear:NO];\n            }];\n            break;\n        }\n        default:\n            break;\n    }\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)viewDidAppear:(BOOL)animated {\n    [super viewDidAppear:animated];\n    \n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"avatars-off\"] || ![[NSUserDefaults standardUserDefaults] boolForKey:@\"avatarImages\"]) {\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Enable Avatars\" message:@\"Viewing avatars in messages requires both the User Icons and Avatars settings to be enabled.  Would you like to enable them now?\" preferredStyle:UIAlertControllerStyleAlert];\n        \n        [alert addAction:[UIAlertAction actionWithTitle:@\"Enable\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n            [[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:@\"avatars-off\"];\n            [[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@\"avatarImages\"];\n            [[NSUserDefaults standardUserDefaults] synchronize];\n        }]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n        alert.popoverPresentationController.barButtonItem = self.navigationItem.rightBarButtonItem;\n        alert.popoverPresentationController.sourceView = self.view;\n        [self presentViewController:alert animated:YES completion:nil];\n\n    }\n}\n\n- (void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n\n    if(animated)\n        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n\n    NSMutableArray *data = [[NSMutableArray alloc] init];\n    for(Server *s in [ServersDataSource sharedInstance].getServers) {\n        if([s.avatar isKindOfClass:NSString.class] && s.avatar.length && ![s.avatar isEqualToString:[[NetworkConnection sharedInstance].userInfo objectForKey:@\"avatar\"]]) {\n            NSURL *url = [NSURL URLWithString:[[NetworkConnection sharedInstance].avatarURITemplate relativeStringWithVariables:@{@\"id\":s.avatar, @\"modifiers\":[NSString stringWithFormat:@\"w%i\", (int)(64 * [UIScreen mainScreen].scale)]} error:nil]];\n            if(url) {\n                if(![[ImageCache sharedInstance] imageForURL:url]) {\n                    [[ImageCache sharedInstance] fetchURL:url completionHandler:^(BOOL success) {\n                        if(success) {\n                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                                [self.tableView reloadData];\n                            }];\n                        }\n                    }];\n                }\n                [data addObject:@{@\"label\":[NSString stringWithFormat:@\"%@ on %@\", s.nick, s.name.length?s.name:s.hostname],\n                                  @\"id\":s.avatar,\n                                  @\"url\":url,\n                                  @\"orgId\":@(s.orgId),\n                                  @\"cid\":@(s.cid)\n                                  }];\n            }\n        }\n    }\n    if([[[NetworkConnection sharedInstance].userInfo objectForKey:@\"avatar\"] isKindOfClass:NSString.class] && [[[NetworkConnection sharedInstance].userInfo objectForKey:@\"avatar\"] length]) {\n        NSURL *url = [NSURL URLWithString:[[NetworkConnection sharedInstance].avatarURITemplate relativeStringWithVariables:@{@\"id\":[[NetworkConnection sharedInstance].userInfo objectForKey:@\"avatar\"], @\"modifiers\":[NSString stringWithFormat:@\"w%i\", (int)(64 * [UIScreen mainScreen].scale)]} error:nil]];\n        if(url) {\n            if(![[ImageCache sharedInstance] imageForURL:url]) {\n                [[ImageCache sharedInstance] fetchURL:url completionHandler:^(BOOL success) {\n                    if(success) {\n                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                            [self.tableView reloadData];\n                        }];\n                    }\n                }];\n            }\n            [data addObject:@{@\"label\":@\"Public avatar\",\n                              @\"id\":[[NetworkConnection sharedInstance].userInfo objectForKey:@\"avatar\"],\n                              @\"url\":url,\n                              @\"orgId\":@(-1),\n                              }];\n        }\n    }\n\n    self->_avatars = data;\n    [self.tableView reloadData];\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return _avatars.count;\n}\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    return 64;\n}\n\n-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized(self->_avatars) {\n        AvatarTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"avatarcell\"];\n        if(!cell)\n            cell = [[AvatarTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"avatarcell\"];\n        NSDictionary *row = [self->_avatars objectAtIndex:[indexPath row]];\n        cell.textLabel.text = [row objectForKey:@\"label\"];\n        cell.avatar.image = [[ImageCache sharedInstance] imageForURL:[row objectForKey:@\"url\"]];\n        return cell;\n    }\n}\n\n- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {\n    return YES;\n}\n\n- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {\n    if (editingStyle == UITableViewCellEditingStyleDelete) {\n        IRCCloudAPIResultHandler handler = ^(IRCCloudJSONObject *result) {\n            if(![[result objectForKey:@\"success\"] intValue]) {\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:[NSString stringWithFormat:@\"Unable to clear avatar: %@\", [result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n            }\n        };\n        if([[[self->_avatars objectAtIndex:indexPath.row] objectForKey:@\"orgId\"] intValue] == 0) {\n            [[NetworkConnection sharedInstance] setAvatar:nil cid:[[[self->_avatars objectAtIndex:indexPath.row] objectForKey:@\"cid\"] intValue] handler:handler];\n        } else {\n            [[NetworkConnection sharedInstance] setAvatar:nil orgId:[[[self->_avatars objectAtIndex:indexPath.row] objectForKey:@\"orgId\"] intValue] handler:handler];\n        }\n    }\n}\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized(self->_avatars) {\n        NSDictionary *row = [self->_avatars objectAtIndex:[indexPath row]];\n        IRCCloudAPIResultHandler handler = ^(IRCCloudJSONObject *result) {\n            if([[result objectForKey:@\"success\"] intValue]) {\n                [self cancelButtonPressed];\n            } else {\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:[NSString stringWithFormat:@\"Unable to set avatar: %@\", [result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n            }\n        };\n        int orgId = -1;\n        if(self->_server) {\n            if(_server.orgId)\n                orgId = self->_server.orgId;\n            else if(_server.avatars_supported)\n                orgId = 0;\n        }\n        if(orgId == 0) {\n            [[NetworkConnection sharedInstance] setAvatar:[row objectForKey:@\"id\"] cid:_server.cid handler:handler];\n        } else {\n            [[NetworkConnection sharedInstance] setAvatar:[row objectForKey:@\"id\"] orgId:orgId handler:handler];\n        }\n        [self.tableView deselectRowAtIndexPath:indexPath animated:YES];\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/BuffersDataSource.h",
    "content": "//\n//  BuffersDataSource.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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@interface Buffer : NSObject<NSSecureCoding> {\n    int _bid;\n    int _cid;\n    NSTimeInterval _min_eid;\n    NSTimeInterval _last_seen_eid;\n    NSTimeInterval _created;\n    NSString *_name;\n    NSString *_type;\n    int _archived;\n    int _deferred;\n    int _timeout;\n    NSString *_away_msg;\n    BOOL _valid;\n    NSString *_draft;\n    NSString *_chantypes;\n    BOOL _scrolledUp;\n    NSTimeInterval _scrolledUpFrom;\n    CGFloat _savedScrollOffset;\n    Buffer *_lastBuffer;\n    Buffer *_nextBuffer;\n    int _extraHighlights;\n    BOOL _serverIsSlack;\n    NSString *_displayName;\n    NSMutableDictionary *_typingIndicators;\n}\n@property (assign) int bid, cid, archived, deferred, timeout, extraHighlights;\n@property (assign) NSTimeInterval min_eid, last_seen_eid, scrolledUpFrom, created;\n@property (assign) CGFloat savedScrollOffset;\n@property (copy) NSString *name, *type, *away_msg, *chantypes;\n@property (assign) BOOL valid, scrolledUp, serverIsSlack;\n@property (copy) NSString *draft;\n@property (strong) Buffer *lastBuffer, *nextBuffer;\n@property (strong) NSMutableDictionary *typingIndicators;\n@property (readonly) NSString *accessibilityValue, *normalizedName, *displayName;\n@property (readonly) BOOL isMPDM;\n-(NSComparisonResult)compare:(Buffer *)aBuffer;\n-(void)purgeExpiredTypingIndicators;\n-(void)addTyping:(NSString *)nick;\n@end\n\n@interface BuffersDataSource : NSObject {\n    NSMutableDictionary *_buffers;\n}\n+(BuffersDataSource *)sharedInstance;\n-(void)serialize;\n-(void)clear;\n-(void)invalidate;\n-(NSUInteger)count;\n-(int)mostRecentBid;\n-(void)addBuffer:(Buffer *)buffer;\n-(Buffer *)getBuffer:(int)bid;\n-(Buffer *)getBufferWithName:(NSString *)name server:(int)cid;\n-(NSArray *)getBuffersForServer:(int)cid;\n-(NSArray *)getBuffers;\n-(void)updateLastSeenEID:(NSTimeInterval)eid buffer:(int)bid;\n-(void)updateArchived:(int)archived buffer:(int)bid;\n-(void)updateTimeout:(int)timeout buffer:(int)bid;\n-(void)updateName:(NSString *)name buffer:(int)bid;\n-(void)updateAway:(NSString *)away nick:(NSString *)nick server:(int)cid;\n-(void)removeBuffer:(int)bid;\n-(void)removeAllDataForBuffer:(int)bid;\n-(void)purgeInvalidBIDs;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/BuffersDataSource.m",
    "content": "//\n//  BuffersDataSource.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"BuffersDataSource.h\"\n#import \"ChannelsDataSource.h\"\n#import \"EventsDataSource.h\"\n#import \"UsersDataSource.h\"\n#import \"ServersDataSource.h\"\n\nNSString *__DEFAULT_CHANTYPES__;\n\n@implementation Buffer\n\n+ (BOOL)supportsSecureCoding {\n    return YES;\n}\n\n-(void)purgeExpiredTypingIndicators {\n    NSTimeInterval now = [NSDate date].timeIntervalSince1970;\n    \n    for (NSString *from in _typingIndicators.allKeys) {\n        if (from != nil) {\n            if (now - [[_typingIndicators objectForKey:from] doubleValue] > 6.5)\n                [_typingIndicators removeObjectForKey:from];\n        }\n    }\n}\n\n-(void)addTyping:(NSString *)nick {\n    if(!_typingIndicators)\n        _typingIndicators = [[NSMutableDictionary alloc] init];\n    \n    [_typingIndicators setObject:@([NSDate date].timeIntervalSince1970) forKey:nick];\n    \n    [self purgeExpiredTypingIndicators];\n}\n\n-(NSComparisonResult)compare:(Buffer *)aBuffer {\n    @synchronized (self) {\n        int joinedLeft = 1, joinedRight = 1;\n        if(self->_cid < aBuffer.cid)\n            return NSOrderedAscending;\n        if(self->_cid > aBuffer.cid)\n            return NSOrderedDescending;\n        if([self->_type isEqualToString:@\"console\"])\n            return NSOrderedAscending;\n        if([aBuffer.type isEqualToString:@\"console\"])\n            return NSOrderedDescending;\n        if(self->_bid == aBuffer.bid)\n            return NSOrderedSame;\n        if([self->_type isEqualToString:@\"channel\"] || self.isMPDM)\n            joinedLeft = [[ChannelsDataSource sharedInstance] channelForBuffer:self->_bid] != nil;\n        if([[aBuffer type] isEqualToString:@\"channel\"] || aBuffer.isMPDM)\n            joinedRight = [[ChannelsDataSource sharedInstance] channelForBuffer:aBuffer.bid] != nil;\n        \n        NSString *typeLeft = self.isMPDM ? @\"conversation\" : _type;\n        NSString *typeRight = aBuffer.isMPDM ? @\"conversation\" : aBuffer.type;\n        if([typeLeft isEqualToString:@\"conversation\"] && [typeRight isEqualToString:@\"channel\"])\n            return NSOrderedDescending;\n        else if([typeLeft isEqualToString:@\"channel\"] && [typeRight isEqualToString:@\"conversation\"])\n            return NSOrderedAscending;\n        else if(joinedLeft > joinedRight)\n            return NSOrderedAscending;\n        else if(joinedLeft < joinedRight)\n            return NSOrderedDescending;\n        else {\n            NSString *nameLeft = self.normalizedName;\n            NSString *nameRight = aBuffer.normalizedName;\n            \n            if([nameLeft compare:nameRight] == NSOrderedSame)\n                return (self->_bid < aBuffer.bid)?NSOrderedAscending:NSOrderedDescending;\n            else\n                return [nameLeft localizedStandardCompare:nameRight];\n        }\n    }\n}\n-(NSString *)normalizedName {\n    if(self->_serverIsSlack)\n        return self.displayName.lowercaseString;\n    \n    if(self->_chantypes == nil || _chantypes == __DEFAULT_CHANTYPES__) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_cid];\n        if(s) {\n            self->_chantypes = s.CHANTYPES;\n            if(self->_chantypes == nil || _chantypes.length == 0)\n                self->_chantypes = __DEFAULT_CHANTYPES__;\n        }\n    }\n    NSRegularExpression *r = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@\"^[%@]+\", _chantypes] options:NSRegularExpressionCaseInsensitive error:nil];\n    return [r stringByReplacingMatchesInString:[self->_name lowercaseString] options:0 range:NSMakeRange(0, _name.length) withTemplate:@\"\"];\n}\n-(BOOL)isMPDM {\n    if(!_serverIsSlack)\n        return NO;\n    \n    static NSPredicate *p;\n    if(!p)\n        p = [NSPredicate predicateWithFormat:@\"SELF MATCHES %@\", @\"#mpdm-(.*)-\\\\d\"];\n\n    return [p evaluateWithObject:self->_name];\n}\n-(NSString *)name {\n    return _name;\n}\n-(void)setName:(NSString *)name {\n    self->_name = name;\n    self->_displayName = nil;\n}\n-(NSString *)displayName {\n    if(self.isMPDM) {\n        if(!_displayName) {\n            NSString *selfNick = [[ServersDataSource sharedInstance] getServer:self->_cid].nick.lowercaseString;\n            NSMutableArray *names = [self->_name componentsSeparatedByString:@\"-\"].mutableCopy;\n            [names removeObjectAtIndex:0];\n            [names removeObjectAtIndex:names.count - 1];\n            for(int i = 0; i < names.count; i++) {\n                NSString *name = [[names objectAtIndex:i] lowercaseString];\n                if([name length] == 0 || [selfNick isEqualToString:name]) {\n                    [names removeObjectAtIndex:i];\n                    i--;\n                }\n            }\n            [names sortUsingComparator:^NSComparisonResult(NSString *left, NSString *right) {\n                return [left.lowercaseString localizedStandardCompare:right.lowercaseString];\n            }];\n            self->_displayName = [names componentsJoinedByString:@\", \"];\n        }\n        return _displayName;\n    } else {\n        return _name;\n    }\n}\n-(NSString *)description {\n    return [NSString stringWithFormat:@\"{cid: %i, bid: %i, name: %@, type: %@}\", _cid, _bid, _name, _type];\n}\n-(NSString *)accessibilityValue {\n    if(self.isMPDM)\n        return self.displayName;\n    \n    if(self->_chantypes == nil || _chantypes == __DEFAULT_CHANTYPES__) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_cid];\n        if(s) {\n            self->_chantypes = s.CHANTYPES;\n            if(self->_chantypes == nil || _chantypes.length == 0)\n                self->_chantypes = __DEFAULT_CHANTYPES__;\n        }\n    }\n    NSRegularExpression *r = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@\"^[%@]+\", _chantypes] options:NSRegularExpressionCaseInsensitive error:nil];\n    return [r stringByReplacingMatchesInString:self->_name options:0 range:NSMakeRange(0, _name.length) withTemplate:@\"\"];\n}\n-(id)initWithCoder:(NSCoder *)aDecoder {\n    self = [super init];\n    if(self) {\n        decodeInt(self->_bid);\n        decodeInt(self->_cid);\n        decodeDouble(self->_min_eid);\n        decodeDouble(self->_last_seen_eid);\n        decodeObjectOfClass(NSString.class, self->_name);\n        decodeObjectOfClass(NSString.class, self->_type);\n        decodeInt(self->_archived);\n        decodeInt(self->_deferred);\n        decodeObjectOfClass(NSString.class, self->_away_msg);\n        decodeBool(self->_valid);\n        decodeObjectOfClass(NSString.class, self->_draft);\n        decodeObjectOfClass(NSString.class, self->_chantypes);\n        decodeBool(self->_scrolledUp);\n        decodeDouble(self->_scrolledUpFrom);\n        decodeFloat(self->_savedScrollOffset);\n        decodeObjectOfClass(Buffer.class, self->_lastBuffer);\n        decodeObjectOfClass(Buffer.class, self->_nextBuffer);\n    }\n    return self;\n}\n-(void)encodeWithCoder:(NSCoder *)aCoder {\n    encodeInt(self->_bid);\n    encodeInt(self->_cid);\n    encodeDouble(self->_min_eid);\n    encodeDouble(self->_last_seen_eid);\n    encodeObject(self->_name);\n    encodeObject(self->_type);\n    encodeInt(self->_archived);\n    encodeInt(self->_deferred);\n    encodeObject(self->_away_msg);\n    encodeBool(self->_valid);\n    encodeObject(self->_draft);\n    encodeObject(self->_chantypes);\n    encodeBool(self->_scrolledUp);\n    encodeDouble(self->_scrolledUpFrom);\n    encodeFloat(self->_savedScrollOffset);\n    encodeObject(self->_lastBuffer);\n    encodeObject(self->_nextBuffer);\n}\n@end\n\n@implementation BuffersDataSource\n+(BuffersDataSource *)sharedInstance {\n    static BuffersDataSource *sharedInstance;\n\t\n    @synchronized(self) {\n        if(!sharedInstance)\n            sharedInstance = [[BuffersDataSource alloc] init];\n\t\t\n        return sharedInstance;\n    }\n\treturn nil;\n}\n\n-(id)init {\n    self = [super init];\n    if(self) {\n        __DEFAULT_CHANTYPES__ = @\"#&!+\";\n        [NSKeyedArchiver setClassName:@\"IRCCloud.Buffer\" forClass:Buffer.class];\n        [NSKeyedUnarchiver setClass:Buffer.class forClassName:@\"IRCCloud.Buffer\"];\n\n        if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"cacheVersion\"] isEqualToString:[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleVersion\"]]) {\n            NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"buffers\"];\n            \n            @try {\n                NSError* error = nil;\n                self->_buffers = [[NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:NSDictionary.class, NSArray.class, Buffer.class,NSString.class,NSNumber.class,nil] fromData:[NSData dataWithContentsOfFile:cacheFile] error:&error] mutableCopy];\n                if(error)\n                    @throw [NSException exceptionWithName:@\"NSError\" reason:error.debugDescription userInfo:@{ @\"NSError\" : error }];\n            } @catch(NSException *e) {\n                CLS_LOG(@\"Exception: %@\", e);\n                [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n                [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"cacheVersion\"];\n                [[ServersDataSource sharedInstance] clear];\n                [[ChannelsDataSource sharedInstance] clear];\n                [[EventsDataSource sharedInstance] clear];\n                [[UsersDataSource sharedInstance] clear];\n            }\n        }\n        \n        if(!_buffers)\n            self->_buffers = [[NSMutableDictionary alloc] init];\n    }\n    return self;\n}\n\n-(void)serialize {\n    NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"buffers\"];\n\n    NSArray *buffers;\n    @synchronized(self->_buffers) {\n        buffers = [self->_buffers copy];\n    }\n    \n    @synchronized(self) {\n        @try {\n            NSError* error = nil;\n            [[NSKeyedArchiver archivedDataWithRootObject:buffers requiringSecureCoding:YES error:&error] writeToFile:cacheFile atomically:YES];\n            if(error)\n                CLS_LOG(@\"Error archiving: %@\", error);\n            [[NSURL fileURLWithPath:cacheFile] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL];\n        }\n        @catch (NSException *exception) {\n            [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n        }\n    }\n}\n\n-(void)clear {\n    @synchronized(self->_buffers) {\n        [self->_buffers removeAllObjects];\n    }\n}\n\n-(NSUInteger)count {\n    @synchronized(self->_buffers) {\n        return _buffers.count;\n    }\n}\n\n-(int)mostRecentBid {\n    @synchronized(self->_buffers) {\n        Buffer *buffer;\n        for(Buffer *b in self->_buffers.allValues) {\n            if(!buffer || b.last_seen_eid > buffer.last_seen_eid)\n                buffer = b;\n        }\n        if(buffer)\n            return buffer.bid;\n        else\n            return -1;\n    }\n}\n\n-(void)addBuffer:(Buffer *)buffer {\n    @synchronized(self->_buffers) {\n        [self->_buffers setObject:buffer forKey:@(buffer.bid)];\n    }\n}\n\n-(Buffer *)getBuffer:(int)bid {\n    return [self->_buffers objectForKey:@(bid)];\n}\n\n-(Buffer *)getBufferWithName:(NSString *)name server:(int)cid {\n    NSArray *copy;\n    @synchronized(self->_buffers) {\n        copy = self->_buffers.allValues;\n    }\n    for(Buffer *buffer in copy) {\n        if(buffer.cid == cid && [[buffer.name lowercaseString] isEqualToString:[name lowercaseString]])\n            return buffer;\n    }\n    return nil;\n}\n\n-(NSArray *)getBuffersForServer:(int)cid {\n    @synchronized (self) {\n        NSMutableArray *buffers = [[NSMutableArray alloc] init];\n        NSArray *copy;\n        @synchronized(self->_buffers) {\n            copy = self->_buffers.allValues;\n        }\n        for(Buffer *buffer in copy) {\n            if(buffer.cid == cid)\n                [buffers addObject:buffer];\n        }\n        return [buffers sortedArrayUsingSelector:@selector(compare:)];\n    }\n}\n\n-(NSArray *)getBuffers {\n    @synchronized(self->_buffers) {\n        return _buffers.allValues;\n    }\n}\n\n-(void)updateLastSeenEID:(NSTimeInterval)eid buffer:(int)bid {\n    Buffer *buffer = [self getBuffer:bid];\n    if(buffer)\n        buffer.last_seen_eid = eid;\n}\n\n-(void)updateArchived:(int)archived buffer:(int)bid {\n    Buffer *buffer = [self getBuffer:bid];\n    if(buffer) {\n        buffer.archived = archived;\n        if(!archived) {\n            Server *s = [[ServersDataSource sharedInstance] getServer:buffer.cid];\n            if(s.deferred_archives)\n                s.deferred_archives--;\n        }\n    }\n}\n\n-(void)updateTimeout:(int)timeout buffer:(int)bid {\n    Buffer *buffer = [self getBuffer:bid];\n    if(buffer)\n        buffer.timeout = timeout;\n}\n\n-(void)updateName:(NSString *)name buffer:(int)bid {\n    Buffer *buffer = [self getBuffer:bid];\n    if(buffer)\n        buffer.name = name;\n}\n\n-(void)updateAway:(NSString *)away nick:(NSString *)nick server:(int)cid {\n    Buffer *buffer = [self getBufferWithName:nick server:cid];\n    if(buffer)\n        buffer.away_msg = away;\n}\n\n-(void)removeBuffer:(int)bid {\n    @synchronized(self->_buffers) {\n        NSArray *copy;\n        @synchronized(self->_buffers) {\n            copy = self->_buffers.allValues;\n        }\n        for(Buffer *buffer in copy) {\n            if(buffer.lastBuffer.bid == bid)\n                buffer.lastBuffer = buffer.lastBuffer.lastBuffer;\n            if(buffer.nextBuffer.bid == bid)\n                buffer.nextBuffer = buffer.nextBuffer.nextBuffer;\n        }\n        [self->_buffers removeObjectForKey:@(bid)];\n    }\n}\n\n-(void)removeAllDataForBuffer:(int)bid {\n    Buffer *buffer = [self getBuffer:bid];\n    if(buffer) {\n        [self removeBuffer:bid];\n        [[ChannelsDataSource sharedInstance] removeChannelForBuffer:bid];\n        [[EventsDataSource sharedInstance] removeEventsForBuffer:bid];\n        [[UsersDataSource sharedInstance] removeUsersForBuffer:bid];\n    }\n}\n\n-(void)invalidate {\n    NSArray *copy;\n    @synchronized(self->_buffers) {\n        copy = self->_buffers.allValues;\n    }\n    for(Buffer *buffer in copy) {\n        buffer.valid = NO;\n    }\n}\n\n-(void)purgeInvalidBIDs {\n    CLS_LOG(@\"Cleaning up invalid BIDs\");\n    NSArray *copy;\n    @synchronized(self->_buffers) {\n        copy = self->_buffers.allValues;\n    }\n    for(Buffer *buffer in copy) {\n        if(!buffer.valid) {\n            CLS_LOG(@\"Removing buffer: bid%i\", buffer.bid);\n            [[ChannelsDataSource sharedInstance] removeChannelForBuffer:buffer.bid];\n            [[EventsDataSource sharedInstance] removeEventsForBuffer:buffer.bid];\n            [[UsersDataSource sharedInstance] removeUsersForBuffer:buffer.bid];\n            if([buffer.type isEqualToString:@\"console\"]) {\n                CLS_LOG(@\"Removing CID: cid%i\", buffer.cid);\n                [[ServersDataSource sharedInstance] removeServer:buffer.cid];\n            }\n            [self removeBuffer:buffer.bid];\n        }\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/BuffersTableView.h",
    "content": "//\n//  BuffersTableView.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"ServersDataSource.h\"\n#import \"BuffersDataSource.h\"\n\n@protocol BuffersTableViewDelegate<NSObject>\n-(void)spamSelected:(int)cid;\n-(void)bufferSelected:(int)bid;\n-(void)bufferLongPressed:(int)bid rect:(CGRect)rect;\n-(void)dismissKeyboard;\n-(void)addNetwork;\n@end\n\n@interface BuffersTableView : UITableViewController<UITextFieldDelegate, UIGestureRecognizerDelegate,UIViewControllerPreviewingDelegate, UIContextMenuInteractionDelegate,UISearchTextFieldDelegate> {\n    NSMutableArray *_data;\n    NSMutableDictionary *_expandedCids;\n    NSInteger _selectedRow;\n    UIViewController<BuffersTableViewDelegate> *_delegate;\n    NSMutableDictionary *_expandedArchives;\n    Buffer *_selectedBuffer;\n    \n    API_AVAILABLE(ios(13.0)) UITextField *_searchText;\n    NSString *_filter;\n\n    UIControl *topUnreadIndicator;\n    UIView *topUnreadIndicatorColor;\n    UIView *topUnreadIndicatorBorder;\n    UIControl *bottomUnreadIndicator;\n    UIView *bottomUnreadIndicatorColor;\n    UIView *bottomUnreadIndicatorBorder;\n\n    NSInteger _firstUnreadPosition;\n\tNSInteger _lastUnreadPosition;\n\tNSInteger _firstHighlightPosition;\n\tNSInteger _lastHighlightPosition;\n    NSInteger _firstFailurePosition;\n    NSInteger _lastFailurePosition;\n    \n    ServersDataSource *_servers;\n    BuffersDataSource *_buffers;\n    \n    UIFont *_boldFont;\n    UIFont *_normalFont;\n    UIFont *_awesomeFont;\n    UIFont *_smallFont;\n    id<UIViewControllerPreviewing> __previewer;\n    UILongPressGestureRecognizer *lp;\n    \n    BOOL _requestingArchives;\n}\n@property UIViewController<BuffersTableViewDelegate> *delegate;\n-(void)setBuffer:(Buffer *)buffer;\n-(IBAction)topUnreadIndicatorClicked:(id)sender;\n-(IBAction)bottomUnreadIndicatorClicked:(id)sender;\n-(void)refresh;\n-(void)next;\n-(void)prev;\n-(void)nextUnread;\n-(void)prevUnread;\n-(void)focusSearchText;\n-(void)scrollToSelectedBuffer;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/BuffersTableView.m",
    "content": "//\n//  BuffersTableView.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"BuffersTableView.h\"\n#import \"NetworkConnection.h\"\n#import \"ServersDataSource.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"HighlightsCountView.h\"\n#import \"ECSlidingViewController.h\"\n#import \"EditConnectionViewController.h\"\n#import \"ServerReorderViewController.h\"\n#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n#import \"ColorFormatter.h\"\n#import \"FontAwesome.h\"\n#import \"EventsTableView.h\"\n#import \"MainViewController.h\"\n#import \"NSString+Score.h\"\n@import Firebase;\n\n#define TYPE_SERVER 0\n#define TYPE_CHANNEL 1\n#define TYPE_CONVERSATION 2\n#define TYPE_ARCHIVES_HEADER 3\n#define TYPE_JOIN_CHANNEL 4\n#define TYPE_SPAM 5\n#define TYPE_COLLAPSED 6\n#define TYPE_PINNED 7\n#define TYPE_ADD_NETWORK 8\n#define TYPE_FILTER 9\n#define TYPE_LOADING 10\n\n@interface BuffersTableCell : UITableViewCell {\n    UILabel *_label;\n    UILabel *_icon;\n    UILabel *_spamHint;\n    int _type;\n    UIView *_unreadIndicator;\n    UIView *_bg;\n    UIView *_border;\n    HighlightsCountView *_highlights;\n    UIActivityIndicatorView *_activity;\n    UIColor *_bgColor;\n    UIColor *_highlightColor;\n    CGFloat _borderInset;\n    UITextField *_searchText;\n}\n@property int type;\n@property UIColor *bgColor, *highlightColor;\n@property CGFloat borderInset;\n@property (readonly) UILabel *label, *icon;\n@property (readonly) UIView *unreadIndicator, *bg, *border;\n@property (readonly) HighlightsCountView *highlights;\n@property (readonly) UIActivityIndicatorView *activity;\n@property (strong) UITextField *searchText;\n@end\n\n@implementation BuffersTableCell\n\n- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self->_type = 0;\n        \n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        \n        self->_bg = [[UIView alloc] init];\n        [self.contentView addSubview:self->_bg];\n        \n        self->_border = [[UIView alloc] init];\n        [self.contentView addSubview:self->_border];\n        \n        self->_unreadIndicator = [[UIView alloc] init];\n        self->_unreadIndicator.backgroundColor = [UIColor unreadBlueColor];\n        [self.contentView addSubview:self->_unreadIndicator];\n        \n        self->_icon = [[UILabel alloc] init];\n        self->_icon.backgroundColor = [UIColor clearColor];\n        self->_icon.textColor = [UIColor bufferTextColor];\n        self->_icon.textAlignment = NSTextAlignmentCenter;\n        [self.contentView addSubview:self->_icon];\n\n        self->_label = [[UILabel alloc] init];\n        self->_label.backgroundColor = [UIColor clearColor];\n        self->_label.textColor = [UIColor bufferTextColor];\n        [self.contentView addSubview:self->_label];\n        \n        self->_highlights = [[HighlightsCountView alloc] initWithFrame:CGRectZero];\n        [self.contentView addSubview:self->_highlights];\n        \n        self->_activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n        self->_activity.hidden = YES;\n        [self.contentView addSubview:self->_activity];\n        \n        self->_spamHint = [[UILabel alloc] init];\n        self->_spamHint.text = @\"Tap here to choose conversations to delete\";\n        self->_spamHint.numberOfLines = 0;\n        [self.contentView addSubview:self->_spamHint];\n    }\n    return self;\n}\n\n- (void)layoutSubviews {\n    [super layoutSubviews];\n    \n    CGRect frame = [self.contentView bounds];\n    frame.origin.x += self->_borderInset;\n    frame.size.width -= self->_borderInset;\n    self->_border.frame = CGRectMake(frame.origin.x - _borderInset, frame.origin.y, 6 + _borderInset, frame.size.height);\n    frame.size.width -= 8;\n    if(self->_type == TYPE_SERVER || self->_type == TYPE_ADD_NETWORK) {\n        frame.origin.y += 6;\n        frame.size.height -= 6;\n    }\n    self->_bg.frame = CGRectMake(frame.origin.x + 6, frame.origin.y, frame.size.width - 6, frame.size.height);\n    self->_unreadIndicator.frame = CGRectMake(frame.origin.x, frame.origin.y, 6, frame.size.height);\n    self->_icon.frame = CGRectMake(frame.origin.x + 12, frame.origin.y + ((self->_type == TYPE_COLLAPSED)?8:10), 16, 18);\n    if(!_activity.hidden) {\n        frame.size.width -= self->_activity.frame.size.width + 12;\n        self->_activity.frame = CGRectMake(frame.origin.x + 6 + frame.size.width, frame.origin.y + 10, _activity.frame.size.width, _activity.frame.size.height);\n    }\n    if(!_highlights.hidden) {\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n        CGSize size = [self->_highlights.count sizeWithFont:self->_highlights.font];\n#pragma GCC diagnostic pop\n        size.width += 0;\n        size.height = frame.size.height - 16;\n        if(size.width < size.height)\n            size.width = size.height;\n        frame.size.width -= size.width + 12;\n        self->_highlights.frame = CGRectMake(frame.origin.x + 6 + frame.size.width, frame.origin.y + 6, size.width, size.height);\n    }\n    self->_label.frame = CGRectMake(frame.origin.x + 12 + _icon.frame.size.width + 6, (self->_type == TYPE_SPAM)?_icon.frame.origin.y-1:frame.origin.y, frame.size.width - 6 - _icon.frame.size.width - 16, (self->_type == TYPE_SPAM)?_icon.frame.size.width:frame.size.height);\n    \n    if(self->_type == TYPE_SPAM) {\n        self->_spamHint.textColor = self->_label.textColor;\n        self->_spamHint.font = [self->_label.font fontWithSize:self->_label.font.pointSize - 2];\n        self->_spamHint.frame = CGRectMake(self->_label.frame.origin.x, _label.frame.origin.y + _label.frame.size.height, _label.frame.size.width, frame.size.height - _label.frame.size.height - _label.frame.origin.y);\n        self->_spamHint.hidden = NO;\n    } else {\n        self->_spamHint.hidden = YES;\n    }\n    \n    self->_searchText.frame = CGRectMake(frame.origin.x + 12 + _icon.frame.size.width + 6, frame.origin.y, frame.size.width - 6 - _icon.frame.size.width - 16, frame.size.height);\n}\n\n-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {\n    [super setHighlighted:highlighted animated:animated];\n    if(!self.selected)\n        self->_bg.backgroundColor = highlighted?_highlightColor:self->_bgColor;\n}\n\n@end\n\n@implementation BuffersTableView\n\n- (id)initWithStyle:(UITableViewStyle)style {\n    self = [super initWithStyle:style];\n    if (self) {\n        self->_data = nil;\n        self->_expandedCids = [[NSMutableDictionary alloc] init];\n        self->_selectedRow = -1;\n        self->_expandedArchives = [[NSMutableDictionary alloc] init];\n        self->_firstHighlightPosition = -1;\n        self->_firstUnreadPosition = -1;\n        self->_lastHighlightPosition = -1;\n        self->_lastUnreadPosition = -1;\n        self->_servers = [ServersDataSource sharedInstance];\n        self->_buffers = [BuffersDataSource sharedInstance];\n    }\n    return self;\n}\n\n- (id)initWithCoder:(NSCoder *)aDecoder {\n    self = [super initWithCoder:aDecoder];\n    if (self) {\n        self->_data = nil;\n        self->_expandedCids = [[NSMutableDictionary alloc] init];\n        self->_selectedRow = -1;\n        self->_expandedArchives = [[NSMutableDictionary alloc] init];\n        self->_firstHighlightPosition = -1;\n        self->_firstUnreadPosition = -1;\n        self->_lastHighlightPosition = -1;\n        self->_lastUnreadPosition = -1;\n        self->_servers = [ServersDataSource sharedInstance];\n        self->_buffers = [BuffersDataSource sharedInstance];\n    }\n    return self;\n}\n\n-(void)dealloc {\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {\n    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];\n    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n        [self reloadData];\n        [self _updateUnreadIndicators];\n    }\n     ];\n}\n\n- (void)didMoveToParentViewController:(UIViewController *)parent {\n    [self performSelectorInBackground:@selector(refresh) withObject:nil];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    UIView *v = self->_searchText.superview;\n    [self->_searchText removeFromSuperview];\n    \n    self->_searchText.keyboardAppearance = [UITextField appearance].keyboardAppearance;\n    self->_searchText.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@\"Jump to channel\" attributes:@{NSForegroundColorAttributeName: [UIColor inactiveBufferTextColor]}];\n\n    [v addSubview:self->_searchText];\n    [self scrollToSelectedBuffer];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [self->_searchText resignFirstResponder];\n}\n\n- (NSMutableDictionary *)_addBuffer:(Buffer *)buffer data:(NSMutableArray *)data prefs:(NSDictionary *)prefs server:(Server *)server collapsed:(NSDictionary *)collapsed unread:(int)unread highlights:(int)highlights firstUnreadPosition:(NSInteger *)firstUnreadPosition lastUnreadPosition:(NSInteger *)lastUnreadPosition firstHighlightPosition:(NSInteger *)firstHighlightPosition lastHighlightPosition:(NSInteger *)lastHighlightPosition {\n    NSMutableDictionary *entry = nil;\n    int type = -1;\n    int key = 0;\n    int joined = 1;\n    if([buffer.type isEqualToString:@\"channel\"] || buffer.isMPDM) {\n        type = buffer.isMPDM ? TYPE_CONVERSATION : TYPE_CHANNEL;\n        Channel *channel = [[ChannelsDataSource sharedInstance] channelForBuffer:buffer.bid];\n        if(channel) {\n            if(channel.key || (buffer.serverIsSlack && !buffer.isMPDM && [channel hasMode:@\"s\"]))\n                key = 1;\n        } else {\n            joined = 0;\n        }\n    } else if([buffer.type isEqualToString:@\"conversation\"]) {\n        type = TYPE_CONVERSATION;\n    }\n    if(type > 0 && buffer.archived == 0) {\n        if(type == TYPE_CHANNEL) {\n            if([[[prefs objectForKey:@\"channel-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] == 1)\n                unread = 0;\n        } else {\n            if([[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] == 1)\n                unread = 0;\n            if(type == TYPE_CONVERSATION && [[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] == 1)\n                highlights = 0;\n        }\n        if([[prefs objectForKey:@\"disableTrackUnread\"] intValue] == 1) {\n            if(type == TYPE_CHANNEL) {\n                if([[[prefs objectForKey:@\"channel-enableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] != 1)\n                    unread = 0;\n            }\n        }\n        \n        if(buffer.bid == self->_selectedBuffer.bid || !collapsed || [self->_expandedCids objectForKey:@(buffer.cid)]) {\n            NSString *serverName = server.name;\n            if(!serverName || serverName.length == 0)\n                serverName = server.hostname;\n\n            entry = @{\n            @\"type\":@(type),\n            @\"cid\":@(buffer.cid),\n            @\"bid\":@(buffer.bid),\n            @\"name\":buffer.displayName?buffer.displayName:buffer.name,\n            @\"unread\":@(unread),\n            @\"highlights\":@(highlights),\n            @\"archived\":@0,\n            @\"joined\":@(joined),\n            @\"key\":@(key),\n            @\"timeout\":@(buffer.timeout),\n            @\"hint\":buffer.accessibilityValue?buffer.accessibilityValue:@\"\",\n            @\"status\":server.status,\n            @\"server\":serverName\n            }.mutableCopy;\n            [data addObject:entry];\n        }\n        if(unread > 0 && *firstUnreadPosition == -1)\n            *firstUnreadPosition = data.count - 1;\n        if(unread > 0 && (*lastUnreadPosition == -1 || *lastUnreadPosition < data.count - 1))\n            *lastUnreadPosition = data.count - 1;\n        if(highlights > 0 && *firstHighlightPosition == -1)\n            *firstHighlightPosition = data.count - 1;\n        if(highlights > 0 && (*lastHighlightPosition == -1 || *lastHighlightPosition < data.count - 1))\n            *lastHighlightPosition = data.count - 1;\n    }\n    return entry;\n}\n\n- (void)refresh {\n    @synchronized(self->_data) {\n        NSMutableArray *data = [[NSMutableArray alloc] init];\n        NSInteger archiveCount = 0;\n        NSInteger firstHighlightPosition = -1;\n        NSInteger firstUnreadPosition = -1;\n        NSInteger firstFailurePosition = -1;\n        NSInteger lastHighlightPosition = -1;\n        NSInteger lastUnreadPosition = -1;\n        NSInteger lastFailurePosition = -1;\n        NSInteger selectedRow = -1;\n        \n        NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n        NSMutableSet *pinnedBIDs = [[NSMutableSet alloc] init];\n        NSMutableDictionary *pinnedNames = [[NSMutableDictionary alloc] init];\n        \n#ifndef EXTENSION\n        if (@available(iOS 13, *)) {\n            [data addObject:@{@\"type\":@TYPE_FILTER}];\n        }\n#endif\n\n        if(self->_filter.length) {\n            NSMutableDictionary *current_buffer = nil;\n            NSMutableArray *results_active = [[NSMutableArray alloc] init];\n            NSMutableArray *results_inactive = [[NSMutableArray alloc] init];\n            NSMutableArray *results_archived = [[NSMutableArray alloc] init];\n            for(Server *server in [self->_servers getServers]) {\n                if(server.deferred_archives) {\n                    _requestingArchives = YES;\n                    [[NetworkConnection sharedInstance] requestArchives:server.cid];\n                }\n\n                NSArray *buffers = [self->_buffers getBuffersForServer:server.cid];\n                for(Buffer *buffer in buffers) {\n                    if(![buffer.type isEqualToString:@\"console\"]) {\n                        CGFloat score = [buffer.name scoreAgainst:self->_filter fuzziness:nil options:NSStringScoreOptionReducedLongStringPenalty];\n                        if(score) {\n                            int type = -1;\n                            int key = 0;\n                            int joined = !buffer.archived;\n                            if([buffer.type isEqualToString:@\"channel\"] || buffer.isMPDM) {\n                                type = buffer.isMPDM ? TYPE_CONVERSATION : TYPE_CHANNEL;\n                                Channel *channel = [[ChannelsDataSource sharedInstance] channelForBuffer:buffer.bid];\n                                if(channel) {\n                                    if(channel.key || (buffer.serverIsSlack && !buffer.isMPDM && [channel hasMode:@\"s\"]))\n                                        key = 1;\n                                } else {\n                                    joined = 0;\n                                }\n                            } else if([buffer.type isEqualToString:@\"conversation\"]) {\n                                type = TYPE_CONVERSATION;\n                            }\n                            NSString *serverName = server.name;\n                            if(!serverName || serverName.length == 0)\n                                serverName = server.hostname;\n                            NSString *name = buffer.displayName?buffer.displayName:buffer.name;\n\n                            NSMutableDictionary *entry = @{\n                            @\"type\":@(type),\n                            @\"cid\":@(buffer.cid),\n                            @\"bid\":@(buffer.bid),\n                            @\"name\":[NSString stringWithFormat:@\"%@ (%@)\", name, serverName],\n                            @\"joined\":@(joined),\n                            @\"key\":@(key),\n                            @\"status\":server.status,\n                            @\"server\":serverName,\n                            @\"score\":@(score),\n                            }.mutableCopy;\n                            \n                            if(self->_selectedBuffer.bid == buffer.bid)\n                                current_buffer = entry;\n                            else if(buffer.archived)\n                                [results_archived addObject:entry];\n                            else if(joined == 0)\n                                [results_inactive addObject:entry];\n                            else\n                                [results_active addObject:entry];\n                        }\n                    }\n                }\n            }\n            \n            if(results_active.count) {\n                [data addObjectsFromArray:[results_active sortedArrayUsingDescriptors:@[[[NSSortDescriptor alloc] initWithKey:@\"score\" ascending:NO]]]];\n            }\n            if(current_buffer) {\n                [data addObject:current_buffer];\n            }\n            if(results_inactive.count) {\n                [data addObjectsFromArray:[results_inactive sortedArrayUsingDescriptors:@[[[NSSortDescriptor alloc] initWithKey:@\"score\" ascending:NO]]]];\n            }\n            if(results_archived.count) {\n                [data addObjectsFromArray:[results_archived sortedArrayUsingDescriptors:@[[[NSSortDescriptor alloc] initWithKey:@\"score\" ascending:NO]]]];\n            }\n\n            if(_requestingArchives) {\n                NSMutableDictionary *entry = @{\n                @\"type\":@TYPE_LOADING,\n                @\"name\":@\"Loading Archives\",\n                }.mutableCopy;\n                [data addObject:entry];\n\n            }\n            \n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                NSUInteger oldCount = self->_data.count;\n                self->_data = data;\n                self->_selectedRow = selectedRow;\n                self->_firstUnreadPosition = firstUnreadPosition;\n                self->_firstHighlightPosition = firstHighlightPosition;\n                self->_firstFailurePosition = firstFailurePosition;\n                self->_lastUnreadPosition = lastUnreadPosition;\n                self->_lastHighlightPosition = lastHighlightPosition;\n                self->_lastFailurePosition = lastFailurePosition;\n\n                NSMutableArray *paths = [[NSMutableArray alloc] init];\n                if(oldCount > self->_data.count) {\n                    for(NSUInteger row = self->_data.count; row < oldCount; row++) {\n                        [paths addObject:[NSIndexPath indexPathForRow:row inSection:0]];\n                    }\n                    [self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationNone];\n                } else if(oldCount < self->_data.count) {\n                    [paths removeAllObjects];\n                    for(NSUInteger row = oldCount; row < self->_data.count; row++) {\n                        [paths addObject:[NSIndexPath indexPathForRow:row inSection:0]];\n                    }\n                    [self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationNone];\n                }\n                \n                [paths removeAllObjects];\n                for(NSUInteger row = 0; row < self->_data.count; row++) {\n                    if (row >= 1)\n                        [paths addObject:[NSIndexPath indexPathForRow:row inSection:0]];\n                }\n                [self.tableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationNone];\n                \n                [self _updateUnreadIndicators];\n            }];\n            return;\n        }\n        \n        if([[prefs objectForKey:@\"pinnedBuffers\"] isKindOfClass:NSArray.class] && [(NSArray *)[prefs objectForKey:@\"pinnedBuffers\"] count] > 0) {\n            for(NSNumber *n in [prefs objectForKey:@\"pinnedBuffers\"]) {\n                Buffer *buffer = [[BuffersDataSource sharedInstance] getBuffer:n.intValue];\n                if(buffer && buffer.archived == 0) {\n                    if(pinnedBIDs.count == 0) {\n                        [data addObject:@{\n                         @\"type\":@TYPE_PINNED,\n                         @\"name\":@\"Pinned\"\n                         }];\n                    }\n                    Server *server = [[ServersDataSource sharedInstance] getServer:buffer.cid];\n                    int type = -1;\n                    if([buffer.type isEqualToString:@\"channel\"] || buffer.isMPDM) {\n                        type = buffer.isMPDM ? TYPE_CONVERSATION : TYPE_CHANNEL;\n                    } else if([buffer.type isEqualToString:@\"conversation\"]) {\n                        type = TYPE_CONVERSATION;\n                    }\n                    if(type > 0 && buffer.archived == 0) {\n                        int unread = 0;\n                        int highlights = 0;\n                        unread = [[EventsDataSource sharedInstance] unreadStateForBuffer:buffer.bid lastSeenEid:buffer.last_seen_eid type:buffer.type];\n                        highlights = [[EventsDataSource sharedInstance] highlightCountForBuffer:buffer.bid lastSeenEid:buffer.last_seen_eid type:buffer.type];\n                        \n                        NSMutableDictionary *d = [self _addBuffer:buffer data:data prefs:prefs server:server collapsed:nil unread:unread highlights:highlights firstUnreadPosition:&firstUnreadPosition lastUnreadPosition:&lastUnreadPosition firstHighlightPosition:&firstHighlightPosition lastHighlightPosition:&lastHighlightPosition];\n                        \n                        NSMutableDictionary *last = [pinnedNames objectForKey:[d objectForKey:@\"name\"]];\n                        [pinnedNames setObject:d forKey:[d objectForKey:@\"name\"]];\n                        if(last) {\n                            if(![[last objectForKey:@\"name\"] hasSuffix:@\")\"]) {\n                                [last setObject:[NSString stringWithFormat:@\"%@ (%@)\", [last objectForKey:@\"name\"], [last objectForKey:@\"server\"]] forKey:@\"name\"];\n                            }\n                            [d setObject:[NSString stringWithFormat:@\"%@ (%@)\", [d objectForKey:@\"name\"], [d objectForKey:@\"server\"]] forKey:@\"name\"];\n                        }\n                        [pinnedBIDs addObject:n];\n\n                        if(buffer.bid == self->_selectedBuffer.bid)\n                            selectedRow = data.count - 1;\n                    }\n                }\n            }\n        }\n        \n        for(Server *server in [self->_servers getServers]) {\n            NSMutableDictionary *collapsed;\n            int collapsed_unread = 0;\n            int collapsed_highlights = 0;\n#ifndef EXTENSION\n            NSUInteger collapsed_row = data.count;\n            int spamCount = 0;\n#endif\n            archiveCount = server.deferred_archives;\n            NSArray *buffers = [self->_buffers getBuffersForServer:server.cid];\n            for(Buffer *buffer in buffers) {\n                if([buffer.type isEqualToString:@\"console\"]) {\n                    int unread = 0;\n                    int highlights = 0;\n                    NSString *name = server.name;\n                    NSString *status = server.status;\n                    NSDictionary *fail_info = server.fail_info;\n                    if(!name || name.length == 0)\n                        name = server.hostname;\n                    unread = [[EventsDataSource sharedInstance] unreadStateForBuffer:buffer.bid lastSeenEid:buffer.last_seen_eid type:buffer.type];\n                    highlights = [[EventsDataSource sharedInstance] highlightCountForBuffer:buffer.bid lastSeenEid:buffer.last_seen_eid type:buffer.type];\n                    if([[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] == 1)\n                        unread = 0;\n                    [data addObject:@{\n                     @\"type\":@TYPE_SERVER,\n                     @\"cid\":@(buffer.cid),\n                     @\"bid\":@(buffer.bid),\n                     @\"name\":name,\n                     @\"hint\":name,\n                     @\"unread\":@(unread),\n                     @\"highlights\":@(highlights),\n                     @\"archived\":@0,\n                     @\"status\":status ? status : @\"\",\n                     @\"fail_info\":fail_info ? fail_info : @{},\n                     @\"ssl\":@(server.ssl),\n                     @\"slack\":@(server.isSlack),\n                     @\"count\":@(buffers.count)\n                     }];\n                    \n                    if(unread > 0 && firstUnreadPosition == -1)\n                        firstUnreadPosition = data.count - 1;\n                    if(unread > 0 && (lastUnreadPosition == -1 || lastUnreadPosition < data.count - 1))\n                        lastUnreadPosition = data.count - 1;\n                    if(highlights > 0 && firstHighlightPosition == -1)\n                        firstHighlightPosition = data.count - 1;\n                    if(highlights > 0 && (lastHighlightPosition == -1 || lastHighlightPosition < data.count - 1))\n                        lastHighlightPosition = data.count - 1;\n                    if(server.fail_info.count > 0 && firstFailurePosition == -1)\n                        firstFailurePosition = data.count - 1;\n                    if(server.fail_info.count > 0 && (lastFailurePosition == -1 || lastFailurePosition < data.count - 1))\n                        lastFailurePosition = data.count - 1;\n\n                    if(buffer.bid == self->_selectedBuffer.bid)\n                        selectedRow = data.count - 1;\n                    \n#ifndef ENTERPRISE\n#ifndef EXTENSION\n                    if(buffer.archived || [self->_expandedCids objectForKey:@(buffer.cid)]) {\n                        collapsed = [[NSMutableDictionary alloc] init];\n                        [collapsed setObject:@TYPE_COLLAPSED forKey:@\"type\"];\n                        [collapsed setObject:@(buffer.cid) forKey:@\"cid\"];\n                        [collapsed setObject:@(buffer.bid) forKey:@\"bid\"];\n                        [collapsed setObject:@(buffer.archived) forKey:@\"archived\"];\n                        [collapsed setObject:@(collapsed_row) forKey:@\"row\"];\n                        server.collapsed = collapsed;\n                    }\n#endif\n#endif\n                    break;\n                }\n            }\n            if(collapsed)\n                [data addObject:collapsed];\n            for(Buffer *buffer in buffers) {\n                if([pinnedBIDs containsObject:@(buffer.bid)])\n                    continue;\n                int type = -1;\n                if([buffer.type isEqualToString:@\"channel\"] || buffer.isMPDM) {\n                    type = buffer.isMPDM ? TYPE_CONVERSATION : TYPE_CHANNEL;\n                } else if([buffer.type isEqualToString:@\"conversation\"]) {\n                    type = TYPE_CONVERSATION;\n                }\n                if(type > 0 && buffer.archived == 0) {\n                    int unread = 0;\n                    int highlights = 0;\n                    unread = [[EventsDataSource sharedInstance] unreadStateForBuffer:buffer.bid lastSeenEid:buffer.last_seen_eid type:buffer.type];\n                    highlights = [[EventsDataSource sharedInstance] highlightCountForBuffer:buffer.bid lastSeenEid:buffer.last_seen_eid type:buffer.type];\n                    \n                    [self _addBuffer:buffer data:data prefs:prefs server:server collapsed:collapsed unread:unread highlights:highlights firstUnreadPosition:&firstUnreadPosition lastUnreadPosition:&lastUnreadPosition firstHighlightPosition:&firstHighlightPosition lastHighlightPosition:&lastHighlightPosition];\n#ifndef EXTENSION\n                    if(type == TYPE_CONVERSATION && unread == 1 && [[EventsDataSource sharedInstance] sizeOfBuffer:buffer.bid] == 1)\n                        spamCount++;\n#endif\n                    collapsed_unread += unread;\n                    collapsed_highlights += highlights;\n\n                    if(buffer.bid == self->_selectedBuffer.bid)\n                        selectedRow = data.count - 1;\n                    \n                }\n                if(type > 0 && buffer.archived > 0)\n                    archiveCount++;\n            }\n#ifndef EXTENSION\n            if(spamCount > 3 && (!collapsed || [self->_expandedCids objectForKey:@(server.cid)])) {\n                for(int i = 0; i < data.count; i++) {\n                    NSDictionary *d = [data objectAtIndex:i];\n                    if([[d objectForKey:@\"cid\"] intValue] == server.cid && [[d objectForKey:@\"type\"] intValue] == TYPE_CONVERSATION) {\n                        [data insertObject:@{@\"type\":@(TYPE_SPAM), @\"name\":@\"Spam Detected\", @\"cid\":@(server.cid)} atIndex:i];\n                        break;\n                    }\n                }\n            }\n            \n            if(collapsed) {\n                if([self->_expandedCids objectForKey:@(server.cid)]) {\n                    [collapsed setObject:@\"Collapse\" forKey:@\"name\"];\n                    [collapsed setObject:FA_MINUS_SQUARE_O forKey:@\"icon\"];\n                } else {\n                    [collapsed setObject:@\"Expand\" forKey:@\"name\"];\n                    [collapsed setObject:FA_PLUS_SQUARE_O forKey:@\"icon\"];\n                    [collapsed setObject:@(collapsed_unread) forKey:@\"unread\"];\n                    [collapsed setObject:@(collapsed_highlights) forKey:@\"highlights\"];\n                }\n\n                if(collapsed_unread > 0 && firstUnreadPosition == -1)\n                    firstUnreadPosition = collapsed_row;\n                if(collapsed_unread > 0 && (lastUnreadPosition == -1 || lastUnreadPosition < collapsed_row))\n                    lastUnreadPosition = collapsed_row;\n                if(collapsed_highlights > 0 && firstHighlightPosition == -1)\n                    firstHighlightPosition = collapsed_row;\n                if(collapsed_highlights > 0 && (lastHighlightPosition == -1 || lastHighlightPosition < collapsed_row))\n                    lastHighlightPosition = collapsed_row;\n\n            }\n            collapsed_unread = collapsed_highlights = 0;\n#endif\n            if((!collapsed || [self->_expandedCids objectForKey:@(server.cid)]) && archiveCount > 0) {\n                [data addObject:@{@\"type\":@(TYPE_ARCHIVES_HEADER), @\"name\":@\"Archives\", @\"cid\":@(server.cid)}];\n                if([self->_expandedArchives objectForKey:@(server.cid)]) {\n                    for(Buffer *buffer in buffers) {\n                        int type = -1;\n                        if(buffer.archived && ![buffer.type isEqualToString:@\"console\"]) {\n                            if([buffer.type isEqualToString:@\"channel\"]) {\n                                type = TYPE_CHANNEL;\n                            } else if([buffer.type isEqualToString:@\"conversation\"]) {\n                                type = TYPE_CONVERSATION;\n                            }\n                            [data addObject:@{\n                             @\"type\":@(type),\n                             @\"cid\":@(buffer.cid),\n                             @\"bid\":@(buffer.bid),\n                             @\"name\":buffer.displayName?buffer.displayName:buffer.name,\n                             @\"unread\":@0,\n                             @\"highlights\":@0,\n                             @\"archived\":@1,\n                             @\"hint\":buffer.accessibilityValue?buffer.accessibilityValue:@\"\",\n                             @\"key\":@0,\n                             }];\n                            if(buffer.bid == self->_selectedBuffer.bid)\n                                selectedRow = data.count - 1;\n                        }\n                    }\n                }\n            }\n            if(buffers.count == 1 && [server.status isEqualToString:@\"connected_ready\"] && archiveCount == 0) {\n                [data addObject:@{\n                 @\"type\":@TYPE_JOIN_CHANNEL,\n                 @\"cid\":@(server.cid),\n                 @\"bid\":@-1,\n                 @\"name\":@\"Join a channel\",\n                 @\"unread\":@0,\n                 @\"highlights\":@0,\n                 @\"archived\":@0,\n                 }];\n            }\n        }\n#ifndef EXTENSION\n        if([NetworkConnection sharedInstance].state == kIRCCloudStateConnected && [NetworkConnection sharedInstance].ready) {\n            [data addObject:@{\n             @\"type\":@TYPE_ADD_NETWORK,\n             @\"cid\":@-1,\n             @\"bid\":@-1,\n             @\"name\":@\"Add a network\",\n             @\"unread\":@0,\n             @\"highlights\":@0,\n             @\"archived\":@0,\n             }];\n        }\n#endif\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            self->_boldFont = [UIFont boldSystemFontOfSize:FONT_SIZE];\n            self->_normalFont = [UIFont systemFontOfSize:FONT_SIZE];\n            self->_smallFont = [UIFont systemFontOfSize:FONT_SIZE - 2];\n\n            if(data.count <= 1) {\n                CLS_LOG(@\"The buffer list doesn't have any buffers: %@\", data);\n                CLS_LOG(@\"I should have %lu servers with %lu buffers\", (unsigned long)[self->_servers count], (unsigned long)[self->_buffers count]);\n            }\n            self->_data = data;\n            self->_selectedRow = selectedRow;\n            self->_firstUnreadPosition = firstUnreadPosition;\n            self->_firstHighlightPosition = firstHighlightPosition;\n            self->_firstFailurePosition = firstFailurePosition;\n            self->_lastUnreadPosition = lastUnreadPosition;\n            self->_lastHighlightPosition = lastHighlightPosition;\n            self->_lastFailurePosition = lastFailurePosition;\n            self.view.backgroundColor = [UIColor buffersDrawerBackgroundColor];\n            [self.tableView reloadData];\n            [self _updateUnreadIndicators];\n        }];\n    }\n}\n\n-(void)reloadData {\n    NSMutableArray *paths = [[NSMutableArray alloc] init];\n    \n    for(NSUInteger row = 0; row < self->_data.count; row++) {\n        if (row >= 1)\n            [paths addObject:[NSIndexPath indexPathForRow:row inSection:0]];\n    }\n    [self.tableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationNone];\n}\n\n-(void)_updateUnreadIndicators {\n#ifndef EXTENSION\n    [self.tableView visibleCells];\n    CGRect bounds = UIEdgeInsetsInsetRect(self.tableView.bounds, UIEdgeInsetsMake(0, 0, self.safeAreaInsets.bottom, 0));\n    NSArray *rows = [self.tableView indexPathsForRowsInRect:bounds];\n    if(rows.count) {\n        NSInteger first = [[rows objectAtIndex:0] row];\n        NSInteger last = rows.count > 1 ? [[rows objectAtIndex:rows.count - 2] row] : [[rows lastObject] row];\n        \n        if(self->_firstFailurePosition != -1 && first > _firstFailurePosition) {\n            topUnreadIndicator.hidden = NO;\n            topUnreadIndicator.alpha = 1;\n            topUnreadIndicatorColor.backgroundColor = [UIColor networkErrorBackgroundColor];\n            topUnreadIndicatorBorder.backgroundColor = [UIColor networkErrorBorderColor];\n        } else {\n            topUnreadIndicator.hidden = YES;\n            topUnreadIndicator.alpha = 0;\n        }\n        if(self->_firstUnreadPosition != -1 && first > _firstUnreadPosition) {\n            topUnreadIndicator.hidden = NO;\n            topUnreadIndicator.alpha = 1;\n            topUnreadIndicatorColor.backgroundColor = [UIColor unreadBlueColor];\n            topUnreadIndicatorBorder.backgroundColor = [UIColor unreadBorderColor];\n        }\n        if((self->_lastHighlightPosition != -1 && first > _lastHighlightPosition) ||\n           (self->_firstHighlightPosition != -1 && first > _firstHighlightPosition)) {\n            topUnreadIndicator.hidden = NO;\n            topUnreadIndicator.alpha = 1;\n            topUnreadIndicatorColor.backgroundColor = [UIColor redColor];\n            topUnreadIndicatorBorder.backgroundColor = [UIColor highlightBorderColor];\n        }\n        \n        if(last < _data.count) {\n            if(self->_lastFailurePosition != -1 && last < _lastFailurePosition) {\n                bottomUnreadIndicator.hidden = NO;\n                bottomUnreadIndicator.alpha = 1;\n                bottomUnreadIndicatorColor.backgroundColor = [UIColor networkErrorBackgroundColor];\n                bottomUnreadIndicatorBorder.backgroundColor = [UIColor networkErrorBorderColor];\n            } else {\n                bottomUnreadIndicator.hidden = YES;\n                bottomUnreadIndicator.alpha = 0;\n            }\n            if(self->_lastUnreadPosition != -1 && last < _lastUnreadPosition) {\n                bottomUnreadIndicator.hidden = NO;\n                bottomUnreadIndicator.alpha = 1;\n                bottomUnreadIndicatorColor.backgroundColor = [UIColor unreadBlueColor];\n                bottomUnreadIndicatorBorder.backgroundColor = [UIColor unreadBorderColor];\n            }\n            if((self->_firstHighlightPosition != -1 && last < _firstHighlightPosition) ||\n               (self->_lastHighlightPosition != -1 && last < _lastHighlightPosition)) {\n                bottomUnreadIndicator.hidden = NO;\n                bottomUnreadIndicator.alpha = 1;\n                bottomUnreadIndicatorColor.backgroundColor = [UIColor redColor];\n                bottomUnreadIndicatorBorder.backgroundColor = [UIColor highlightBorderColor];\n            }\n        } else {\n            bottomUnreadIndicator.hidden = YES;\n            bottomUnreadIndicator.alpha = 0;\n        }\n    } else {\n        topUnreadIndicator.hidden = YES;\n        topUnreadIndicator.alpha = 0;\n        bottomUnreadIndicator.hidden = YES;\n        bottomUnreadIndicator.alpha = 0;\n    }\n    topUnreadIndicator.frame = CGRectMake(0,self.tableView.contentOffset.y + self.tableView.contentInset.top,self.view.frame.size.width, 40);\n    bottomUnreadIndicator.frame = CGRectMake(0,self.view.frame.size.height - 40 + self.tableView.contentOffset.y - self.tableView.contentInset.bottom,self.view.frame.size.width, 40 + self.tableView.contentInset.bottom);\n#endif\n}\n\n- (void)searchTextDidChange {\n    self->_filter = self->_searchText.text.lowercaseString;\n    for(UIView *v in self->_searchText.superview.subviews) {\n        if([v isKindOfClass:UILabel.class] && [((UILabel *)v).text isEqualToString:FA_SEARCH])\n            ((UILabel *)v).textColor = self->_searchText.text.length ? [UIColor bufferTextColor] : [UIColor inactiveBufferTextColor];\n    }\n    [self performSelectorInBackground:@selector(refresh) withObject:nil];\n}\n\n-(BOOL)textFieldShouldReturn:(UITextField *)textField {\n    if(self->_data.count > 1)\n        [self tableView:self.tableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]];\n    return NO;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.tableView.scrollsToTop = NO;\n    self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;\n    self.tableView.insetsLayoutMarginsFromSafeArea = NO;\n    self.tableView.insetsContentViewsToSafeArea = NO;\n    \n#ifndef EXTENSION\n    self->_searchText = [[UITextField alloc] initWithFrame:CGRectZero];\n    self->_searchText.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    self->_searchText.spellCheckingType = UITextSpellCheckingTypeNo;\n    self->_searchText.returnKeyType = UIReturnKeyGo;\n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(searchTextDidChange)\n                                                 name:UITextFieldTextDidChangeNotification\n                                               object:self->_searchText];\n#endif\n\n    UIFontDescriptor *d = [[UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody] fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold];\n    self->_boldFont = [UIFont fontWithDescriptor:d size:d.pointSize];\n    \n    d = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody];\n    self->_normalFont = [UIFont fontWithDescriptor:d size:d.pointSize - 2];\n    self->_awesomeFont = [UIFont fontWithName:@\"FontAwesome\" size:18];\n\n    lp = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(_longPress:)];\n    lp.minimumPressDuration = 1.0;\n    lp.delegate = self;\n    [self.tableView addGestureRecognizer:lp];\n    \n    UISwipeGestureRecognizer *swipe =[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(focusSearchText)];\n    swipe.direction = UISwipeGestureRecognizerDirectionRight;\n    [self.tableView addGestureRecognizer:swipe];\n    \n    if (@available(iOS 13.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp)\n            [self.tableView addInteraction:[[UIContextMenuInteraction alloc] initWithDelegate:self]];\n    }\n    \n#ifndef EXTENSION\n    if(!_delegate) {\n        self->_delegate = (UIViewController<BuffersTableViewDelegate> *)[(UINavigationController *)(self.slidingViewController.topViewController) topViewController];\n    }\n    \n    if(!topUnreadIndicatorColor) {\n        topUnreadIndicatorColor = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,15)];\n        topUnreadIndicatorColor.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n        topUnreadIndicatorColor.userInteractionEnabled = NO;\n        topUnreadIndicatorColor.backgroundColor = [UIColor unreadBlueColor];\n    }\n\n    if(!topUnreadIndicatorBorder) {\n        topUnreadIndicatorBorder = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,16)];\n        topUnreadIndicatorBorder.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n        topUnreadIndicatorBorder.userInteractionEnabled = NO;\n        topUnreadIndicatorBorder.backgroundColor = [UIColor unreadBorderColor];\n        [topUnreadIndicatorBorder addSubview:topUnreadIndicatorColor];\n    }\n    \n    if(!topUnreadIndicator) {\n        topUnreadIndicator = [[UIControl alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,40)];\n        topUnreadIndicator.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n        topUnreadIndicator.autoresizesSubviews = YES;\n        topUnreadIndicator.userInteractionEnabled = YES;\n        topUnreadIndicator.backgroundColor = [UIColor clearColor];\n        [topUnreadIndicator addSubview: topUnreadIndicatorBorder];\n        [topUnreadIndicator addTarget:self action:@selector(topUnreadIndicatorClicked:) forControlEvents:UIControlEventTouchUpInside];\n        [self.view addSubview: topUnreadIndicator];\n    }\n\n    if(!bottomUnreadIndicatorColor) {\n        bottomUnreadIndicatorColor = [[UIView alloc] initWithFrame:CGRectMake(0,1,self.view.frame.size.width,79)];\n        bottomUnreadIndicatorColor.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n        bottomUnreadIndicatorColor.userInteractionEnabled = NO;\n        bottomUnreadIndicatorColor.backgroundColor = [UIColor unreadBlueColor];\n    }\n\n    if(!bottomUnreadIndicatorBorder) {\n        bottomUnreadIndicatorBorder = [[UIView alloc] initWithFrame:CGRectMake(0,24,self.view.frame.size.width,56)];\n        bottomUnreadIndicatorBorder.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n        bottomUnreadIndicatorBorder.userInteractionEnabled = NO;\n        bottomUnreadIndicatorBorder.backgroundColor = [UIColor unreadBorderColor];\n        [bottomUnreadIndicatorBorder addSubview:bottomUnreadIndicatorColor];\n    }\n    \n    if(!bottomUnreadIndicator) {\n        bottomUnreadIndicator = [[UIControl alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,80)];\n        bottomUnreadIndicator.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n        bottomUnreadIndicator.autoresizesSubviews = YES;\n        bottomUnreadIndicator.userInteractionEnabled = YES;\n        bottomUnreadIndicator.backgroundColor = [UIColor clearColor];\n        [bottomUnreadIndicator addSubview: bottomUnreadIndicatorBorder];\n        [bottomUnreadIndicator addTarget:self action:@selector(bottomUnreadIndicatorClicked:) forControlEvents:UIControlEventTouchUpInside];\n        [self.view addSubview: bottomUnreadIndicator];\n    }\n#endif\n\n    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    self.view.backgroundColor = [UIColor buffersDrawerBackgroundColor];\n\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backlogCompleted:) name:kIRCCloudBacklogCompletedNotification object:nil];\n\n#ifndef EXTENSION\n    if([self respondsToSelector:@selector(registerForPreviewingWithDelegate:sourceView:)]) {\n        __previewer = [self registerForPreviewingWithDelegate:self sourceView:self.tableView];\n    }\n#endif\n    \n    [self viewWillAppear:NO];\n}\n\n- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location {\n#ifndef EXTENSION\n    if ([self.tableView indexPathForRowAtPoint:location].row < self->_data.count) {\n        NSDictionary *d = [self->_data objectAtIndex:[self.tableView indexPathForRowAtPoint:location].row];\n\n        if(d) {\n            Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:[[d objectForKey:@\"bid\"] intValue]];\n            if(b) {\n                previewingContext.sourceRect = [self.tableView cellForRowAtIndexPath:[self.tableView indexPathForRowAtPoint:location]].frame;\n                EventsTableView *e = [[EventsTableView alloc] init];\n                e.navigationItem.title = [d objectForKey:@\"name\"];\n                [e setBuffer:b];\n                e.modalPresentationStyle = UIModalPresentationCurrentContext;\n                e.preferredContentSize = ((MainViewController *)((UINavigationController *)self.slidingViewController.topViewController).topViewController).eventsView.view.bounds.size;\n                lp.enabled = NO;\n                [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                    self->lp.enabled = YES;\n                }];\n                return e;\n            }\n        }\n    }\n#endif\n    return nil;\n}\n\n- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit {\n    [viewControllerToCommit viewWillDisappear:NO];\n    [self->_delegate bufferSelected:((EventsTableView *)viewControllerToCommit).buffer.bid];\n}\n\n- (void)backlogCompleted:(NSNotification *)notification {\n    if(notification.object == nil || [notification.object bid] < 1) {\n        if(!_requestingArchives)\n            [_expandedArchives removeAllObjects];\n        if(_filter.length) {\n            for(Server *s in [[ServersDataSource sharedInstance] getServers]) {\n                if(s.deferred_archives) {\n                    return;\n                }\n            }\n        }\n        _requestingArchives = NO;\n        [self performSelectorInBackground:@selector(refresh) withObject:nil];\n    } else {\n        [self performSelectorInBackground:@selector(refreshBuffer:) withObject:[self->_buffers getBuffer:[notification.object bid]]];\n    }\n}\n\n- (void)scrollToSelectedBuffer {\n    if(self->_selectedRow != -1) {\n        NSArray *a = [self.tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self.tableView.bounds, self.tableView.scrollIndicatorInsets)];\n        if(a.count) {\n            if([[a objectAtIndex:0] row] > self->_selectedRow || [[a lastObject] row] < self->_selectedRow)\n                [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self->_selectedRow inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:NO];\n        }\n    }\n}\n\n- (void)refreshBuffer:(Buffer *)b {\n    @synchronized(self->_data) {\n        if(self->_filter.length)\n            return;\n        \n        NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n        NSMutableArray *data = self->_data;\n        int pos = -1;\n        for(int i = 1; i < data.count; i++) {\n            NSDictionary *d = [data objectAtIndex:i];\n            if(b.bid == [[d objectForKey:@\"bid\"] intValue]) {\n                pos = i;\n                NSMutableDictionary *m = [d mutableCopy];\n                int unread = [[EventsDataSource sharedInstance] unreadStateForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type];\n                int highlights = [[EventsDataSource sharedInstance] highlightCountForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type];\n                if([b.type isEqualToString:@\"channel\"]) {\n                    if([[[prefs objectForKey:@\"channel-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] == 1)\n                        unread = 0;\n                } else {\n                    if([[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] == 1)\n                        unread = 0;\n                    if([b.type isEqualToString:@\"conversation\"] && [[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] == 1)\n                        highlights = 0;\n                }\n                if([[prefs objectForKey:@\"disableTrackUnread\"] intValue] == 1) {\n                    if([b.type isEqualToString:@\"channel\"]) {\n                        if([[[prefs objectForKey:@\"channel-enableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] != 1)\n                            unread = 0;\n                    }\n                }\n                if([b.type isEqualToString:@\"channel\"]) {\n                    Channel *channel = [[ChannelsDataSource sharedInstance] channelForBuffer:b.bid];\n                    if(channel) {\n                        if(channel.key || (b.serverIsSlack && !b.isMPDM && [channel hasMode:@\"s\"]))\n                            [m setObject:@1 forKey:@\"key\"];\n                        else\n                            [m setObject:@0 forKey:@\"key\"];\n                        [m setObject:@1 forKey:@\"joined\"];\n                    } else {\n                        [m setObject:@0 forKey:@\"joined\"];\n                    }\n                }\n                [m setObject:@(b.timeout) forKey:@\"timeout\"];\n                Server *s = [[ServersDataSource sharedInstance] getServer:[[m objectForKey:@\"cid\"] intValue]];\n                [m setObject:@(unread) forKey:@\"unread\"];\n                [m setObject:@(highlights) forKey:@\"highlights\"];\n                if(s.status)\n                    [m setObject:s.status forKey:@\"status\"];\n                if(s.fail_info)\n                    [m setObject:s.fail_info forKey:@\"fail_info\"];\n                [data setObject:[NSDictionary dictionaryWithDictionary:m] atIndexedSubscript:i];\n                if(unread) {\n                    if(self->_firstUnreadPosition == -1 || _firstUnreadPosition > i)\n                        self->_firstUnreadPosition = i;\n                    if(self->_lastUnreadPosition == -1 || _lastUnreadPosition < i)\n                        self->_lastUnreadPosition = i;\n                } else {\n                    if(self->_firstUnreadPosition == i) {\n                        self->_firstUnreadPosition = -1;\n                        for(int j = i; j < _data.count; j++) {\n                            if([[[self->_data objectAtIndex:j] objectForKey:@\"unread\"] intValue]) {\n                                self->_firstUnreadPosition = j;\n                                break;\n                            }\n                        }\n                    }\n                    if(self->_lastUnreadPosition == i) {\n                        self->_lastUnreadPosition = -1;\n                        for(int j = i; j >= 0; j--) {\n                            if([[[self->_data objectAtIndex:j] objectForKey:@\"unread\"] intValue]) {\n                                self->_lastUnreadPosition = j;\n                                break;\n                            }\n                        }\n                    }\n                }\n                if(highlights) {\n                    if(self->_firstHighlightPosition == -1 || _firstHighlightPosition > i)\n                        self->_firstHighlightPosition = i;\n                    if(self->_lastHighlightPosition == -1 || _lastHighlightPosition < i)\n                        self->_lastHighlightPosition = i;\n                } else {\n                    if(self->_firstHighlightPosition == i) {\n                        self->_firstHighlightPosition = -1;\n                        for(int j = i; j < _data.count; j++) {\n                            if([[[self->_data objectAtIndex:j] objectForKey:@\"highlights\"] intValue]) {\n                                self->_firstHighlightPosition = j;\n                                break;\n                            }\n                        }\n                    }\n                    if(self->_lastHighlightPosition == i) {\n                        self->_lastHighlightPosition = -1;\n                        for(int j = i; j >= 0; j--) {\n                            if([[[self->_data objectAtIndex:j] objectForKey:@\"highlights\"] intValue]) {\n                                self->_lastHighlightPosition = j;\n                                break;\n                            }\n                        }\n                    }\n                }\n                if([[m objectForKey:@\"type\"] intValue] == TYPE_SERVER) {\n                    if(s.fail_info.count) {\n                        if(self->_firstFailurePosition == -1 || _firstFailurePosition > i)\n                            self->_firstFailurePosition = i;\n                        if(self->_lastFailurePosition == -1 || _lastFailurePosition < i)\n                            self->_lastFailurePosition = i;\n                    } else {\n                        if(self->_firstFailurePosition == i) {\n                            self->_firstFailurePosition = -1;\n                            for(int j = i; j < _data.count; j++) {\n                                if([[[self->_data objectAtIndex:j] objectForKey:@\"type\"] intValue] == TYPE_SERVER && [(NSDictionary *)[[self->_data objectAtIndex:j] objectForKey:@\"fail_info\"] count]) {\n                                    self->_firstFailurePosition = j;\n                                    break;\n                                }\n                            }\n                        }\n                        if(self->_lastFailurePosition == i) {\n                            self->_lastFailurePosition = -1;\n                            for(int j = i; j >= 0; j--) {\n                                if([[[self->_data objectAtIndex:j] objectForKey:@\"type\"] intValue] == TYPE_SERVER && [(NSDictionary *)[[self->_data objectAtIndex:j] objectForKey:@\"fail_info\"] count]) {\n                                    self->_lastFailurePosition = j;\n                                    break;\n                                }\n                            }\n                        }\n                        \n                    }\n                }\n                [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                    [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:pos inSection:0]] withRowAnimation:UITableViewRowAnimationNone];\n                    [self _updateUnreadIndicators];\n                }];\n            }\n        }\n    }\n}\n\n- (void)refreshCollapsed:(Server *)s {\n    @synchronized(self->_data) {\n        if(self->_filter.length)\n            return;\n        \n        NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n        \n        int unread = 0, highlights = 0;\n        for(Buffer *b in [self->_buffers getBuffersForServer:s.cid]) {\n            int u = [[EventsDataSource sharedInstance] unreadStateForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type];\n            int h = [[EventsDataSource sharedInstance] highlightCountForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type];\n            if([b.type isEqualToString:@\"channel\"]) {\n                if([[[prefs objectForKey:@\"channel-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] == 1)\n                    u = 0;\n            } else {\n                if([[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] == 1)\n                    u = 0;\n                if([b.type isEqualToString:@\"conversation\"] && [[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] == 1)\n                    h = 0;\n            }\n            if([[prefs objectForKey:@\"disableTrackUnread\"] intValue] == 1) {\n                if([b.type isEqualToString:@\"channel\"]) {\n                    if([[[prefs objectForKey:@\"channel-enableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] != 1)\n                        u = 0;\n                }\n            }\n            unread += u;\n            highlights += h;\n        }\n        \n        [s.collapsed setObject:@(unread) forKey:@\"unread\"];\n        [s.collapsed setObject:@(highlights) forKey:@\"highlights\"];\n        \n        int row = [[s.collapsed objectForKey:@\"row\"] intValue];\n        if(unread) {\n            if(self->_firstUnreadPosition == -1 || _firstUnreadPosition > row)\n                self->_firstUnreadPosition = row;\n            if(self->_lastUnreadPosition == -1 || _lastUnreadPosition < row)\n                self->_lastUnreadPosition = row;\n        } else {\n            if(self->_firstUnreadPosition == row) {\n                self->_firstUnreadPosition = -1;\n                for(int j = row; j < _data.count; j++) {\n                    if([[[self->_data objectAtIndex:j] objectForKey:@\"unread\"] intValue]) {\n                        self->_firstUnreadPosition = j;\n                        break;\n                    }\n                }\n            }\n            if(self->_lastUnreadPosition == row) {\n                self->_lastUnreadPosition = -1;\n                for(int j = row; j >= 0; j--) {\n                    if([[[self->_data objectAtIndex:j] objectForKey:@\"unread\"] intValue]) {\n                        self->_lastUnreadPosition = j;\n                        break;\n                    }\n                }\n            }\n        }\n        if(highlights) {\n            if(self->_firstHighlightPosition == -1 || _firstHighlightPosition > row)\n                self->_firstHighlightPosition = row;\n            if(self->_lastHighlightPosition == -1 || _lastHighlightPosition < row)\n                self->_lastHighlightPosition = row;\n        } else {\n            if(self->_firstHighlightPosition == row) {\n                self->_firstHighlightPosition = -1;\n                for(int j = row; j < _data.count; j++) {\n                    if([[[self->_data objectAtIndex:j] objectForKey:@\"highlights\"] intValue]) {\n                        self->_firstHighlightPosition = j;\n                        break;\n                    }\n                }\n            }\n            if(self->_lastHighlightPosition == row) {\n                self->_lastHighlightPosition = -1;\n                for(int j = row; j >= 0; j--) {\n                    if([[[self->_data objectAtIndex:j] objectForKey:@\"highlights\"] intValue]) {\n                        self->_lastHighlightPosition = j;\n                        break;\n                    }\n                }\n            }\n        }\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self reloadData];\n            [self _updateUnreadIndicators];\n        }];\n    }\n}\n\n- (void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    IRCCloudJSONObject *o = notification.object;\n    Event *e = notification.object;\n    switch(event) {\n        case kIRCEventChannelTopic:\n        case kIRCEventNickChange:\n        case kIRCEventMemberUpdates:\n        case kIRCEventUserChannelMode:\n        case kIRCEventAway:\n        case kIRCEventSelfBack:\n        case kIRCEventChannelTimestamp:\n        case kIRCEventSelfDetails:\n        case kIRCEventUserMode:\n        case kIRCEventSetIgnores:\n        case kIRCEventBadChannelKey:\n        case kIRCEventOpenBuffer:\n        case kIRCEventBanList:\n        case kIRCEventWhoList:\n        case kIRCEventWhois:\n        case kIRCEventNamesList:\n        case kIRCEventLinkChannel:\n        case kIRCEventListResponseFetching:\n        case kIRCEventListResponse:\n        case kIRCEventListResponseTooManyChannels:\n        case kIRCEventConnectionLag:\n        case kIRCEventGlobalMsg:\n        case kIRCEventAcceptList:\n        case kIRCEventChannelTopicIs:\n        case kIRCEventServerMap:\n        case kIRCEventSessionDeleted:\n        case kIRCEventQuietList:\n        case kIRCEventBanExceptionList:\n        case kIRCEventInviteList:\n        case kIRCEventWhoSpecialResponse:\n        case kIRCEventModulesList:\n        case kIRCEventChannelQuery:\n        case kIRCEventLinksResponse:\n        case kIRCEventWhoWas:\n        case kIRCEventAuthFailure:\n        case kIRCEventAlert:\n        case kIRCEventAvatarChange:\n        case kIRCEventMessageChanged:\n        case kIRCEventUserTyping:\n            break;\n        case kIRCEventJoin:\n        case kIRCEventPart:\n        case kIRCEventKick:\n        case kIRCEventQuit:\n            if([o.type hasPrefix:@\"you_\"])\n                [self performSelectorInBackground:@selector(refresh) withObject:nil];\n            break;\n        case kIRCEventHeartbeatEcho:\n        {\n            NSDictionary *seenEids = [o objectForKey:@\"seenEids\"];\n            for(NSNumber *cid in seenEids.allKeys) {\n#ifndef ENTERPRISE\n                Buffer *b = [self->_buffers getBufferWithName:@\"*\" server:cid.intValue];\n                if(b.archived) {\n                    [self performSelectorInBackground:@selector(refreshCollapsed:) withObject:[self->_servers getServer:[cid intValue]]];\n                    break;\n                } else {\n#endif\n                    NSDictionary *eids = [seenEids objectForKey:cid];\n                    for(NSNumber *bid in eids.allKeys) {\n                        [self performSelectorInBackground:@selector(refreshBuffer:) withObject:[self->_buffers getBuffer:[bid intValue]]];\n                    }\n#ifndef ENTERPRISE\n                }\n#endif\n            }\n        }\n            break;\n        case kIRCEventBufferMsg:\n            if(e) {\n                Buffer *b = [self->_buffers getBuffer:e.bid];\n                if([e isImportant:b.type]) {\n#ifndef ENTERPRISE\n                    Buffer *c = [self->_buffers getBufferWithName:@\"*\" server:e.cid];\n                    if(c.archived) {\n                        [self performSelectorInBackground:@selector(refreshCollapsed:) withObject:[self->_servers getServer:e.cid]];\n                    } else {\n#endif\n                        [self refreshBuffer:b];\n#ifndef ENTERPRISE\n                    }\n#endif\n                }\n            }\n            break;\n        case kIRCEventStatusChanged:\n            if(o) {\n                NSArray *buffers = [self->_buffers getBuffersForServer:o.cid];\n                for(Buffer *b in buffers) {\n                    [self refreshBuffer:b];\n                }\n            }\n            break;\n        case kIRCEventChannelMode:\n            if(o) {\n                Buffer *b = [self->_buffers getBuffer:o.bid];\n                if(b)\n                    [self refreshBuffer:b];\n            }\n            break;\n        case kIRCEventRefresh:\n            if([notification.object isKindOfClass:NSSet.class]) {\n                for(Buffer *b in notification.object) {\n                    [self refreshBuffer:b];\n                }\n                break;\n            }\n        case kIRCEventBufferArchived:\n            [self->_expandedCids removeObjectForKey:@(o.cid)];\n            [self performSelectorInBackground:@selector(refresh) withObject:nil];\n            break;\n        case kIRCEventUserInfo:\n        case kIRCEventMakeServer:\n        case kIRCEventMakeBuffer:\n        case kIRCEventDeleteBuffer:\n        case kIRCEventChannelInit:\n        case kIRCEventBufferUnarchived:\n        case kIRCEventRenameConversation:\n        case kIRCEventConnectionDeleted:\n        case kIRCEventReorderConnections:\n            [self performSelectorInBackground:@selector(refresh) withObject:nil];\n            break;\n        default:\n            CLS_LOG(@\"Slow event: %i\", event);\n            [self performSelectorInBackground:@selector(refresh) withObject:nil];\n            break;\n    }\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    @synchronized(self->_data) {\n        return _data.count;\n    }\n}\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized(self->_data) {\n       if([[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_SERVER || [[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_ADD_NETWORK) {\n           return 46;\n       } else if([[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_SPAM) {\n           return 64;\n       } else if([[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_COLLAPSED) {\n           return 32;\n       } else {\n           return 40;\n       }\n    }\n}\n\n- (UIEdgeInsets)safeAreaInsets {\n    return self.slidingViewController ? self.slidingViewController.view.window.safeAreaInsets : _delegate.view.window.safeAreaInsets;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized(self->_data) {\n        BOOL selected = (indexPath.row == self->_selectedRow);\n        BuffersTableCell *cell = [tableView dequeueReusableCellWithIdentifier:indexPath.row > 0 ? @\"bufferscell\" : @\"searchcell\"];\n        if(!cell) {\n            cell = [[BuffersTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:indexPath.row > 0 ? @\"bufferscell\" : @\"searchcell\"];\n        }\n        NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n        NSString *status = [row objectForKey:@\"status\"];\n        cell.type = [[row objectForKey:@\"type\"] intValue];\n        cell.label.text = [row objectForKey:@\"name\"];\n        cell.activity.hidden = YES;\n        cell.activity.activityIndicatorViewStyle = [UIColor isDarkTheme]?UIActivityIndicatorViewStyleWhite:[UIColor activityIndicatorViewStyle];\n        cell.accessibilityValue = [row objectForKey:@\"hint\"];\n        cell.highlightColor = [UIColor bufferHighlightColor];\n        cell.border.backgroundColor = [UIColor bufferBorderColor];\n        cell.contentView.backgroundColor = [UIColor bufferBackgroundColor];\n        cell.icon.font = self->_awesomeFont;\n#ifndef EXTENSION\n        cell.borderInset = self.safeAreaInsets.left;\n#endif\n        if([[row objectForKey:@\"unread\"] intValue] || (selected && cell.type != TYPE_ARCHIVES_HEADER)) {\n            if([[row objectForKey:@\"archived\"] intValue])\n                cell.unreadIndicator.backgroundColor = [UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:1];\n            else\n                cell.unreadIndicator.backgroundColor = selected?[UIColor selectedBufferBorderColor]:[UIColor unreadBlueColor];\n            cell.unreadIndicator.hidden = NO;\n            cell.label.font = self->_boldFont;\n            cell.accessibilityValue = [cell.accessibilityValue stringByAppendingString:@\", unread\"];\n        } else {\n            if(cell.type == TYPE_SERVER) {\n                if([status isEqualToString:@\"waiting_to_retry\"] || [status isEqualToString:@\"pool_unavailable\"] || [(NSDictionary *)[row objectForKey:@\"fail_info\"] count])\n                    cell.unreadIndicator.backgroundColor = [UIColor failedServerBorderColor];\n                else\n                    cell.unreadIndicator.backgroundColor = [UIColor serverBorderColor];\n                cell.unreadIndicator.hidden = NO;\n            } else {\n                cell.unreadIndicator.hidden = YES;\n            }\n            cell.label.font = self->_normalFont;\n        }\n        if([[row objectForKey:@\"highlights\"] intValue]) {\n            cell.highlights.hidden = NO;\n            cell.highlights.count = [NSString stringWithFormat:@\"%@\",[row objectForKey:@\"highlights\"]];\n            cell.accessibilityValue = [cell.accessibilityValue stringByAppendingFormat:@\", %@ highlights\", [row objectForKey:@\"highlights\"]];\n        } else {\n            cell.highlights.hidden = YES;\n        }\n        \n        switch(cell.type) {\n            case TYPE_FILTER:\n                cell.icon.text = FA_SEARCH;\n                cell.icon.hidden = NO;\n                cell.label.text = nil;\n                if(!cell.searchText) {\n                    cell.searchText = self->_searchText;\n                    [cell.contentView addSubview:self->_searchText];\n                }\n                cell.searchText.delegate = self;\n                cell.border.backgroundColor = [UIColor serverBorderColor];\n                cell.bgColor = cell.highlightColor = [UIColor serverBackgroundColor];\n                cell.icon.textColor = self->_filter.length ? [UIColor bufferTextColor] : [UIColor inactiveBufferTextColor];\n                cell.label.textColor = cell.searchText.textColor = [UIColor bufferTextColor];\n                cell.accessibilityLabel = @\"\";\n                break;\n            case TYPE_SERVER:\n                cell.accessibilityLabel = @\"Network\";\n                if([[row objectForKey:@\"slack\"] intValue]) {\n                    cell.icon.text = FA_SLACK;\n                } else {\n                    if([[row objectForKey:@\"ssl\"] intValue])\n                        cell.icon.text = FA_SHIELD;\n                    else\n                        cell.icon.text = FA_GLOBE;\n                }\n\n                cell.icon.hidden = NO;\n                if(selected) {\n                    cell.highlightColor = [UIColor selectedBufferHighlightColor];\n                    cell.icon.textColor = cell.label.textColor = [UIColor selectedBufferTextColor];\n                    if([status isEqualToString:@\"waiting_to_retry\"] || [status isEqualToString:@\"pool_unavailable\"] || [(NSDictionary *)[row objectForKey:@\"fail_info\"] count]) {\n                        cell.icon.tintColor = cell.label.textColor = [UIColor networkErrorColor];\n                        cell.unreadIndicator.backgroundColor = cell.bgColor = cell.highlightColor = [UIColor networkErrorBackgroundColor];\n                    } else {\n                        cell.bgColor = [UIColor selectedBufferBackgroundColor];\n                    }\n                } else {\n                    if([status isEqualToString:@\"waiting_to_retry\"] || [status isEqualToString:@\"pool_unavailable\"] || [(NSDictionary *)[row objectForKey:@\"fail_info\"] count])\n                        cell.icon.textColor = cell.label.textColor = [UIColor ownersBorderColor];\n                    else if(![status isEqualToString:@\"connected_ready\"])\n                        cell.icon.textColor = cell.label.textColor = [UIColor inactiveBufferTextColor];\n                    else if([[row objectForKey:@\"unread\"] intValue])\n                        cell.icon.textColor = cell.label.textColor = [UIColor unreadBufferTextColor];\n                    else\n                        cell.icon.textColor = cell.label.textColor = [UIColor bufferTextColor];\n                    if([status isEqualToString:@\"waiting_to_retry\"] || [status isEqualToString:@\"pool_unavailable\"] || [(NSDictionary *)[row objectForKey:@\"fail_info\"] count])\n                        cell.bgColor = cell.highlightColor = [UIColor colorWithRed:1 green:0.933 blue:0.592 alpha:1];\n                    else\n                        cell.bgColor = [UIColor serverBackgroundColor];\n                }\n                if(![status isEqualToString:@\"connected_ready\"] && ![status isEqualToString:@\"quitting\"] && ![status isEqualToString:@\"disconnected\"]) {\n                    if(!cell.activity.isAnimating)\n                        [cell.activity startAnimating];\n                    cell.activity.hidden = NO;\n                    cell.activity.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;\n                } else {\n                    [cell.activity stopAnimating];\n                    cell.activity.hidden = YES;\n                }\n                break;\n            case TYPE_CHANNEL:\n            case TYPE_CONVERSATION:\n                if(cell.type == TYPE_CONVERSATION)\n                    cell.accessibilityLabel = @\"Conversation with\";\n                else\n                    cell.accessibilityLabel = @\"Channel\";\n                if([[row objectForKey:@\"key\"] intValue]) {\n                    cell.icon.text = FA_LOCK;\n                    cell.icon.hidden = NO;\n                } else {\n                    cell.icon.text = nil;\n                    cell.icon.hidden = YES;\n                }\n                if(selected) {\n                    cell.label.textColor = [UIColor selectedBufferTextColor];\n                    if([[row objectForKey:@\"archived\"] intValue]) {\n                        cell.bgColor = [UIColor selectedArchivedBufferBackgroundColor];\n                        cell.highlightColor = [UIColor selectedArchivedBufferHighlightColor];\n                        cell.accessibilityValue = [cell.accessibilityValue stringByAppendingString:@\", archived\"];\n                    } else {\n                        cell.icon.textColor = cell.label.textColor = [UIColor selectedBufferTextColor];\n                        cell.bgColor = [UIColor selectedBufferBackgroundColor];\n                        cell.highlightColor = [UIColor selectedBufferHighlightColor];\n                    }\n                } else {\n                    if([[row objectForKey:@\"archived\"] intValue]) {\n                        cell.label.textColor = (cell.type == TYPE_CHANNEL)?[UIColor archivedChannelTextColor]:[UIColor archivedBufferTextColor];\n                        cell.bgColor = [UIColor bufferBackgroundColor];\n                        cell.highlightColor = [UIColor archivedBufferHighlightColor];\n                        cell.accessibilityValue = [cell.accessibilityValue stringByAppendingString:@\", archived\"];\n                    } else {\n                        if([[row objectForKey:@\"joined\"] intValue] == 0 || ![status isEqualToString:@\"connected_ready\"])\n                            cell.icon.textColor = cell.label.textColor = [UIColor inactiveBufferTextColor];\n                        else if([[row objectForKey:@\"unread\"] intValue])\n                            cell.icon.textColor = cell.label.textColor = [UIColor unreadBufferTextColor];\n                        else\n                            cell.icon.textColor = cell.label.textColor = [UIColor bufferTextColor];\n                        cell.bgColor = [UIColor bufferBackgroundColor];\n                    }\n                }\n                if([[row objectForKey:@\"timeout\"] intValue]) {\n                    if(!cell.activity.isAnimating)\n                        [cell.activity startAnimating];\n                    cell.activity.hidden = NO;\n                    cell.activity.activityIndicatorViewStyle = selected?UIActivityIndicatorViewStyleWhite:[UIColor activityIndicatorViewStyle];\n                } else {\n                    [cell.activity stopAnimating];\n                    cell.activity.hidden = YES;\n                }\n                break;\n            case TYPE_ARCHIVES_HEADER:\n                cell.icon.text = nil;\n                cell.icon.hidden = YES;\n                if([self->_expandedArchives objectForKey:[row objectForKey:@\"cid\"]]) {\n                    cell.label.textColor = [UIColor blackColor];\n                    cell.bgColor = [UIColor timestampColor];\n                    cell.accessibilityHint = @\"Hides archive list\";\n                    if(_requestingArchives && [[ServersDataSource sharedInstance] getServer:[[row objectForKey:@\"cid\"] intValue]].deferred_archives) {\n                        if(!cell.activity.isAnimating)\n                            [cell.activity startAnimating];\n                        cell.activity.hidden = NO;\n                        cell.activity.activityIndicatorViewStyle = selected?UIActivityIndicatorViewStyleWhite:[UIColor activityIndicatorViewStyle];\n                    } else {\n                        [cell.activity stopAnimating];\n                        cell.activity.hidden = YES;\n                    }\n                } else {\n                    cell.label.textColor = [UIColor archivesHeadingTextColor];\n                    cell.bgColor = [UIColor bufferBackgroundColor];\n                    cell.accessibilityHint = @\"Shows archive list\";\n                }\n                break;\n            case TYPE_JOIN_CHANNEL:\n                cell.label.textColor = [UIColor colorWithRed:0.361 green:0.69 blue:0 alpha:1];\n                cell.bgColor = [UIColor bufferBackgroundColor];\n                cell.icon.text = nil;\n                cell.icon.hidden = YES;\n                break;\n            case TYPE_SPAM:\n                cell.icon.textColor = cell.label.textColor = [UIColor ownersBorderColor];\n                cell.bgColor = cell.highlightColor = [UIColor colorWithRed:1 green:0.933 blue:0.592 alpha:1];\n                cell.icon.text = FA_EXCLAMATION_TRIANGLE;\n                cell.icon.hidden = NO;\n                cell.accessibilityLabel = @\"Spam detected. Double tap to choose conversations to delete\";\n                break;\n            case TYPE_COLLAPSED:\n                cell.bgColor = cell.highlightColor = [UIColor bufferBackgroundColor];\n                cell.icon.textColor = cell.label.textColor = [UIColor archivesHeadingTextColor];\n                cell.icon.text = [row objectForKey:@\"icon\"];\n                cell.icon.hidden = NO;\n                cell.label.font = self->_smallFont;\n                cell.accessibilityLabel = [row objectForKey:@\"name\"];\n                cell.unreadIndicator.backgroundColor = [UIColor unreadCollapsedColor];\n                cell.unreadIndicator.hidden = ([[row objectForKey:@\"unread\"] intValue] == 0);\n                break;\n            case TYPE_PINNED:\n                cell.icon.textColor = cell.label.textColor = [UIColor bufferTextColor];\n                cell.icon.hidden = NO;\n                cell.icon.text = FA_THUMB_TACK;\n                cell.bgColor = [UIColor bufferBackgroundColor];\n                cell.accessibilityLabel = @\"Pinned Channels\";\n                break;\n            case TYPE_ADD_NETWORK:\n                cell.icon.textColor = cell.label.textColor = [UIColor bufferTextColor];\n                cell.icon.hidden = NO;\n                cell.icon.text = FA_PLUS_CIRCLE;\n                cell.bgColor = [UIColor bufferBackgroundColor];\n                cell.accessibilityLabel = @\"Add a network\";\n                break;\n            case TYPE_LOADING:\n                cell.icon.textColor = cell.label.textColor = [UIColor bufferTextColor];\n                cell.icon.hidden = YES;\n                cell.bgColor = [UIColor bufferBackgroundColor];\n                cell.accessibilityLabel = @\"Loading\";\n                if(!cell.activity.isAnimating)\n                    [cell.activity startAnimating];\n                cell.activity.hidden = NO;\n                cell.activity.activityIndicatorViewStyle = selected?UIActivityIndicatorViewStyleWhite:[UIColor activityIndicatorViewStyle];\n                break;\n        }\n        return cell;\n    }\n}\n\n/*\n// Override to support conditional editing of the table view.\n- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    // Return NO if you do not want the specified item to be editable.\n    return YES;\n}\n*/\n\n/*\n// Override to support editing the table view.\n- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    if (editingStyle == UITableViewCellEditingStyleDelete) {\n        // Delete the row from the data source\n        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];\n    }   \n    else if (editingStyle == UITableViewCellEditingStyleInsert) {\n        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view\n    }   \n}\n*/\n\n/*\n// Override to support rearranging the table view.\n- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath\n{\n}\n*/\n\n/*\n// Override to support conditional rearranging of the table view.\n- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    // Return NO if you do not want the item to be re-orderable.\n    return YES;\n}\n*/\n\n#pragma mark - Table view delegate\n\n-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {\n    if([UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPad)\n        [self->_delegate dismissKeyboard];\n}\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized(self->_data) {\n        [tableView deselectRowAtIndexPath:indexPath animated:NO];\n        if(indexPath.row >= self->_data.count)\n            return;\n        \n        if([[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_ARCHIVES_HEADER) {\n            int cid = [[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"cid\"] intValue];\n            if([self->_expandedArchives objectForKey:@(cid)])\n                [self->_expandedArchives removeObjectForKey:@(cid)];\n            else\n                [self->_expandedArchives setObject:@YES forKey:@(cid)];\n            if([[ServersDataSource sharedInstance] getServer:cid].deferred_archives) {\n                [[NetworkConnection sharedInstance] requestArchives:cid];\n                _requestingArchives = YES;\n            }\n            [self performSelectorInBackground:@selector(refresh) withObject:nil];\n    #ifndef EXTENSION\n        } else if([[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_SPAM) {\n            if(self->_delegate)\n                [self->_delegate spamSelected:[[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"cid\"] intValue]];\n        } else if([[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_JOIN_CHANNEL) {\n            [self->_delegate dismissKeyboard];\n            Server *s = [self->_servers getServer:[[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"cid\"] intValue]];\n            \n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"What channel do you want to join?\" preferredStyle:UIAlertControllerStyleAlert];\n            \n            [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Join\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n                    NSString *channel = ((UITextField *)[alert.textFields objectAtIndex:0]).text;\n                    NSString *key = nil;\n                    NSUInteger pos = [channel rangeOfString:@\" \"].location;\n                    if(pos != NSNotFound) {\n                        key = [channel substringFromIndex:pos + 1];\n                        channel = [channel substringToIndex:pos];\n                    }\n                    [[NetworkConnection sharedInstance] join:channel key:key cid:s.cid handler:^(IRCCloudJSONObject *result) {\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:[NSString stringWithFormat:@\"Unable to join channel: %@. Please try again shortly.\", [result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n                        [self presentViewController:alert animated:YES completion:nil];\n                    }];\n                }\n            }]];\n            \n            [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n                textField.placeholder = @\"#example\";\n                textField.text = @\"#\";\n                textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n                textField.delegate = self;\n            }];\n            \n            [self presentViewController:alert animated:YES completion:nil];\n        } else if([[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_COLLAPSED) {\n            NSDictionary *d = [self->_data objectAtIndex:indexPath.row];\n            if([[d objectForKey:@\"archived\"] intValue]) {\n                [[NetworkConnection sharedInstance] unarchiveBuffer:[[d objectForKey:@\"bid\"] intValue] cid:[[d objectForKey:@\"cid\"] intValue] handler:nil];\n                [self->_expandedCids setObject:@(1) forKey:[d objectForKey:@\"cid\"]];\n            } else {\n                [[NetworkConnection sharedInstance] archiveBuffer:[[d objectForKey:@\"bid\"] intValue] cid:[[d objectForKey:@\"cid\"] intValue] handler:nil];\n                [self->_expandedCids removeObjectForKey:[d objectForKey:@\"cid\"]];\n            }\n            return;\n    #endif\n        } else if([[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_FILTER) {\n        } else if([[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_PINNED) {\n        } else if([[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue] == TYPE_ADD_NETWORK) {\n            [(MainViewController *)_delegate addNetwork];\n        } else {\n            [self->_searchText resignFirstResponder];\n    #ifndef EXTENSION\n            self->_selectedRow = indexPath.row;\n            if([self->_delegate isKindOfClass:MainViewController.class])\n                [(MainViewController *)_delegate clearMsgId];\n    #endif\n            [self.tableView reloadData];\n            [self _updateUnreadIndicators];\n            if(self->_delegate)\n                [self->_delegate bufferSelected:[[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"bid\"] intValue]];\n#ifndef EXTENSION\n            if(self->_searchText.text.length) {\n                self->_searchText.text = nil;\n                self->_filter = nil;\n                [self refresh];\n            }\n#endif\n        }\n    }\n}\n\n-(void)setBuffer:(Buffer *)buffer {\n    if(self->_selectedBuffer.bid != buffer.bid)\n        self->_selectedRow = -1;\n    self->_selectedBuffer = buffer;\n#ifndef ENTERPRISE\n    if(self->_selectedBuffer.archived && ![self->_selectedBuffer.type isEqualToString:@\"console\"]) {\n        if(![self->_expandedArchives objectForKey:@(self->_selectedBuffer.cid)]) {\n            [self->_expandedArchives setObject:@YES forKey:@(self->_selectedBuffer.cid)];\n            [self performSelectorInBackground:@selector(refresh) withObject:nil];\n            return;\n        }\n    }\n#endif\n    @synchronized(self->_data) {\n        if(self->_data.count > 1) {\n            for(int i = 0; i < _data.count; i++) {\n                if([[[self->_data objectAtIndex:i] objectForKey:@\"bid\"] intValue] == self->_selectedBuffer.bid) {\n                    self->_selectedRow = i;\n                    break;\n                }\n            }\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [self reloadData];\n                [self _updateUnreadIndicators];\n                [self scrollToSelectedBuffer];\n            }];\n        } else {\n            [self performSelectorInBackground:@selector(refresh) withObject:nil];\n        }\n    }\n}\n\n-(void)scrollViewDidScroll:(UIScrollView *)scrollView {\n    [self _updateUnreadIndicators];\n}\n\n-(IBAction)topUnreadIndicatorClicked:(id)sender {\n    @synchronized(self->_data) {\n        NSArray *rows = [self.tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self.tableView.bounds, self.tableView.contentInset)];\n        if(rows.count) {\n            NSInteger first = [[rows objectAtIndex:0] row] - 1;\n            NSInteger pos = 0;\n            \n            for(NSInteger i = first; i >= 0; i--) {\n                NSDictionary *d = [self->_data objectAtIndex:i];\n                if([[d objectForKey:@\"unread\"] intValue] || [[d objectForKey:@\"highlights\"] intValue] || ([[d objectForKey:@\"type\"] intValue] == TYPE_SERVER && [(NSDictionary *)[d objectForKey:@\"fail_info\"] count])) {\n                    pos = i - 1;\n                    break;\n                }\n            }\n\n            if(pos < 0)\n                pos = 0;\n            \n            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:pos inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];\n        }\n    }\n}\n\n-(IBAction)bottomUnreadIndicatorClicked:(id)sender {\n    @synchronized(self->_data) {\n        NSArray *rows = [self.tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self.tableView.bounds, self.tableView.contentInset)];\n        if(rows.count) {\n            NSInteger last = [[rows lastObject] row] + 1;\n            NSInteger pos = self->_data.count - 1;\n            \n            for(NSInteger i = last; i  < _data.count; i++) {\n                NSDictionary *d = [self->_data objectAtIndex:i];\n                if([[d objectForKey:@\"unread\"] intValue] || [[d objectForKey:@\"highlights\"] intValue] || ([[d objectForKey:@\"type\"] intValue] == TYPE_SERVER && [(NSDictionary *)[d objectForKey:@\"fail_info\"] count])) {\n                    pos = i + 1;\n                    break;\n                }\n            }\n\n            if(pos > _data.count - 1)\n                pos = self->_data.count - 1;\n            \n            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:pos inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];\n        }\n    }\n}\n\n-(void)_showLongPressMenu:(CGPoint)location {\n    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];\n    if(indexPath) {\n        if(indexPath.row < _data.count) {\n            int type = [[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"type\"] intValue];\n            if(type == TYPE_SERVER || type == TYPE_CHANNEL || type == TYPE_CONVERSATION)\n                [self->_delegate bufferLongPressed:[[[self->_data objectAtIndex:indexPath.row] objectForKey:@\"bid\"] intValue] rect:[self.tableView rectForRowAtIndexPath:indexPath]];\n        }\n    }\n}\n\n-(void)_longPress:(UILongPressGestureRecognizer *)gestureRecognizer {\n    @synchronized(self->_data) {\n        if(gestureRecognizer.state == UIGestureRecognizerStateBegan) {\n            [self _showLongPressMenu:[gestureRecognizer locationInView:self.tableView]];\n        }\n    }\n}\n\n- (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction\n                        configurationForMenuAtLocation:(CGPoint)location API_AVAILABLE(ios(13.0)) {\n    [self _showLongPressMenu:location];\n    return nil;\n}\n\n-(void)next {\n    @synchronized(self->_data) {\n        NSDictionary *d;\n        NSInteger row = self->_selectedRow + 1;\n        \n        do {\n            if(row < _data.count)\n                d = [self->_data objectAtIndex:row];\n            else\n                d = nil;\n            row++;\n        } while(d && ([[d objectForKey:@\"type\"] intValue] > TYPE_CONVERSATION));\n        \n        if(d) {\n            [self->_delegate bufferSelected:[[d objectForKey:@\"bid\"] intValue]];\n        }\n    }\n}\n\n-(void)prev {\n    @synchronized(self->_data) {\n        NSDictionary *d;\n        NSInteger row = self->_selectedRow - 1;\n        \n        do {\n            if(row >= 0)\n                d = [self->_data objectAtIndex:row];\n            else\n                d = nil;\n            row--;\n        } while(d && ([[d objectForKey:@\"type\"] intValue] > TYPE_CONVERSATION));\n        \n        if(d) {\n            [self->_delegate bufferSelected:[[d objectForKey:@\"bid\"] intValue]];\n        }\n    }\n}\n\n-(void)nextUnread {\n    @synchronized(self->_data) {\n        NSDictionary *d;\n        NSInteger row = self->_selectedRow + 1;\n        \n        do {\n            if(row < _data.count)\n                d = [self->_data objectAtIndex:row];\n            else\n                d = nil;\n            row++;\n        } while(d && ([[d objectForKey:@\"unread\"] intValue] == 0 || [[d objectForKey:@\"type\"] intValue] > TYPE_CONVERSATION));\n        \n        if(d) {\n            [self->_delegate bufferSelected:[[d objectForKey:@\"bid\"] intValue]];\n        }\n    }\n}\n\n-(void)prevUnread {\n    @synchronized(self->_data) {\n        NSDictionary *d;\n        NSInteger row = self->_selectedRow - 1;\n        \n        do {\n            if(row >= 0)\n                d = [self->_data objectAtIndex:row];\n            else\n                d = nil;\n            row--;\n        } while(d && ([[d objectForKey:@\"unread\"] intValue] == 0 || [[d objectForKey:@\"type\"] intValue] > TYPE_CONVERSATION));\n        \n        if(d) {\n            [self->_delegate bufferSelected:[[d objectForKey:@\"bid\"] intValue]];\n        }\n    }\n}\n\n-(void)focusSearchText {\n    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];\n    [self->_searchText becomeFirstResponder];\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/CallerIDTableViewController.h",
    "content": "//\n//  CallerIDTableViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"IRCCloudJSONObject.h\"\n\n@interface CallerIDTableViewController : UITableViewController {\n    NSArray *_nicks;\n    IRCCloudJSONObject *_event;\n    UIBarButtonItem *_addButton;\n    UILabel *_placeholder;\n}\n@property (strong) NSArray *nicks;\n@property (strong) IRCCloudJSONObject *event;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/CallerIDTableViewController.m",
    "content": "//\n//  CallerIDTableViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"CallerIDTableViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"ColorFormatter.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@implementation CallerIDTableViewController\n\n-(id)initWithStyle:(UITableViewStyle)style {\n    self = [super initWithStyle:style];\n    if (self) {\n        self->_addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonPressed)];\n        self->_placeholder = [[UILabel alloc] initWithFrame:CGRectZero];\n        self->_placeholder.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n        self->_placeholder.numberOfLines = 0;\n        self->_placeholder.text = @\"No accepted nicks.\\n\\nYou can accept someone by tapping their message request or by using `/accept`.\\n\";\n        self->_placeholder.attributedText = [ColorFormatter format:[self->_placeholder.text insertCodeSpans] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil];\n        self->_placeholder.textAlignment = NSTextAlignmentCenter;\n    }\n    return self;\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.navigationItem.leftBarButtonItem = self->_addButton;\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed)];\n    self.tableView.backgroundColor = [[UITableViewCell appearance] backgroundColor];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    self->_placeholder.frame = CGRectInset(self.tableView.frame, 12, 0);\n    if(self->_nicks.count)\n        [self->_placeholder removeFromSuperview];\n    else\n        [self.tableView.superview addSubview:self->_placeholder];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    IRCCloudJSONObject *o = nil;\n    \n    switch(event) {\n        case kIRCEventAcceptList:\n            o = notification.object;\n            if(o.cid == self->_event.cid) {\n                self->_event = o;\n                self->_nicks = [o objectForKey:@\"nicks\"];\n                if(self->_nicks.count)\n                    [self->_placeholder removeFromSuperview];\n                else\n                    [self.tableView.superview addSubview:self->_placeholder];\n                [self.tableView reloadData];\n            }\n            break;\n        default:\n            break;\n    }\n}\n\n-(void)doneButtonPressed {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)addButtonPressed {\n    [self.view endEditing:YES];\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_event.cid];\n    \n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Allow messages from this user\" preferredStyle:UIAlertControllerStyleAlert];\n    \n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Allow\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n        if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n            [[NetworkConnection sharedInstance] say:[NSString stringWithFormat:@\"/accept %@\", ((UITextField *)[alert.textFields objectAtIndex:0]).text] to:nil cid:self->_event.cid handler:nil];\n            [[NetworkConnection sharedInstance] say:@\"/accept *\" to:nil cid:self->_event.cid handler:nil];\n        }\n    }]];\n    \n    [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n        textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n    }];\n    \n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n#pragma mark - Table view data source\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    return [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody].pointSize + 32;\n}\n\n-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return [self->_nicks count];\n}\n\n-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"calleridcell\"];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"calleridcell\"];\n    id nick = [self->_nicks objectAtIndex:[indexPath row]];\n    if([nick isKindOfClass:[NSArray class]])\n        cell.textLabel.text = [nick objectAtIndex:0];\n    else\n        cell.textLabel.text = nick;\n    return cell;\n}\n\n-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {\n    return YES;\n}\n\n-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {\n    if (editingStyle == UITableViewCellEditingStyleDelete) {\n        NSString *nick = [[self->_nicks objectAtIndex:indexPath.row] objectAtIndex:0];\n        [[NetworkConnection sharedInstance] say:[NSString stringWithFormat:@\"/accept -%@\", nick] to:nil cid:self->_event.cid handler:nil];\n        [[NetworkConnection sharedInstance] say:@\"/accept *\" to:nil cid:self->_event.cid handler:nil];\n    }\n}\n\n#pragma mark - Table view delegate\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [tableView deselectRowAtIndexPath:indexPath animated:NO];\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ChannelInfoViewController.h",
    "content": "//\n//  ChannelInfoViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"ChannelsDataSource.h\"\n#import \"LinkTextView.h\"\n#import \"IRCColorPickerView.h\"\n\n@interface ChannelInfoViewController : UITableViewController<UITextViewDelegate,LinkTextViewDelegate,NSTextStorageDelegate,IRCColorPickerViewDelegate> {\n    Channel *_channel;\n    long _topiclen;\n    UITextView *_topicEdit;\n    NSAttributedString *_topic;\n    LinkTextView *_topicLabel;\n    LinkTextView *_url;\n    NSMutableArray *_modeHints;\n    NSString *_topicSetBy;\n    BOOL _topicChanged;\n    int offset;\n    IRCColorPickerView *_colorPickerView;\n    NSDictionary *_currentMessageAttributes;\n}\n-(id)initWithChannel:(Channel *)channel;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ChannelInfoViewController.m",
    "content": "//\n//  ChannelInfoViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <MobileCoreServices/UTCoreTypes.h>\n#import <MobileCoreServices/UTType.h>\n#import \"ChannelInfoViewController.h\"\n#import \"ColorFormatter.h\"\n#import \"NetworkConnection.h\"\n#import \"AppDelegate.h\"\n#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@implementation ChannelInfoViewController\n\n-(id)initWithChannel:(Channel *)channel {\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        self->_channel = channel;\n        self->_modeHints = [[NSMutableArray alloc] init];\n        self->_topicChanged = NO;\n        Server *s = [[ServersDataSource sharedInstance] getServer:channel.cid];\n        self->_topiclen = [[s.isupport objectForKey:@\"TOPICLEN\"] longValue];\n    }\n    return self;\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.navigationItem.rightBarButtonItem = self.editButtonItem;\n    if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {\n        offset = 40;\n    } else {\n        offset = 80;\n    }\n    self.navigationItem.title = [NSString stringWithFormat:@\"%@ Info\", _channel.name];\n    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];\n    self->_topicLabel = [[LinkTextView alloc] initWithFrame:CGRectZero];\n    self->_topicLabel.editable = NO;\n    self->_topicLabel.scrollEnabled = NO;\n    self->_topicLabel.textContainerInset = UIEdgeInsetsZero;\n    self->_topicLabel.dataDetectorTypes = UIDataDetectorTypeNone;\n    self->_topicLabel.linkDelegate = self;\n    self->_topicLabel.backgroundColor = [UIColor clearColor];\n    self->_topicLabel.textColor = [UIColor messageTextColor];\n    self->_topicLabel.textContainer.lineFragmentPadding = 0;\n\n    self->_url = [[LinkTextView alloc] initWithFrame:CGRectZero];\n    self->_url.editable = NO;\n    self->_url.scrollEnabled = NO;\n    self->_url.textContainerInset = UIEdgeInsetsZero;\n    self->_url.dataDetectorTypes = UIDataDetectorTypeNone;\n    self->_url.linkDelegate = self;\n    self->_url.backgroundColor = [UIColor clearColor];\n    self->_url.textColor = [UIColor messageTextColor];\n    self->_url.textContainer.lineFragmentPadding = 0;\n    \n    self->_topicEdit = [[UITextView alloc] initWithFrame:CGRectZero];\n    self->_topicEdit.font = [UIFont systemFontOfSize:14];\n    self->_topicEdit.returnKeyType = UIReturnKeyDone;\n    self->_topicEdit.delegate = self;\n    self->_topicEdit.textStorage.delegate = self;\n    self->_topicEdit.backgroundColor = [UIColor clearColor];\n    self->_topicEdit.textColor = [UIColor textareaTextColor];\n    self->_topicEdit.keyboardAppearance = [UITextField appearance].keyboardAppearance;\n    self->_topicEdit.allowsEditingTextAttributes = YES;\n    \n    self->_colorPickerView = [[IRCColorPickerView alloc] initWithFrame:CGRectZero];\n    self->_colorPickerView.frame = CGRectMake(self.view.bounds.size.width / 2 - _colorPickerView.intrinsicContentSize.width / 2,20,_colorPickerView.intrinsicContentSize.width,_colorPickerView.intrinsicContentSize.height);\n    self->_colorPickerView.delegate = self;\n    self->_colorPickerView.alpha = 0;\n    [self->_colorPickerView updateButtonColors:YES];\n    [self.navigationController.view addSubview:self->_colorPickerView];\n\n    [self refresh];\n}\n\n-(void)cancelButtonPressed:(id)sender {\n    [self.tableView endEditing:YES];\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n- (void)LinkTextView:(LinkTextView *)label didSelectLinkWithTextCheckingResult:(NSTextCheckingResult *)result {\n    [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:result.URL];\n    if([result.URL.scheme hasPrefix:@\"irc\"])\n        [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    IRCCloudJSONObject *o = nil;\n    \n    switch(event) {\n        case kIRCEventChannelInit:\n        case kIRCEventChannelTopic:\n        case kIRCEventChannelMode:\n        case kIRCEventUserChannelMode:\n            o = notification.object;\n            if(o.bid == self->_channel.bid && !self.tableView.editing)\n                [self refresh];\n            break;\n        default:\n            break;\n    }\n}\n\n-(void)textStorage:(NSTextStorage *)textStorage didProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta {\n    self->_topicChanged = YES;\n}\n\n-(BOOL)canPerformAction:(SEL)action withSender:(id)sender {\n    if(action == @selector(chooseFGColor:) || action == @selector(chooseBGColor:) || action == @selector(resetColors:)) {\n        return YES;\n    }\n    \n    return [super canPerformAction:action withSender:sender];\n}\n\n-(void)resetColors:(id)sender {\n    if(self->_topicEdit.selectedRange.length) {\n        NSRange selection = self->_topicEdit.selectedRange;\n        NSMutableAttributedString *msg = self->_topicEdit.attributedText.mutableCopy;\n        [msg removeAttribute:NSForegroundColorAttributeName range:self->_topicEdit.selectedRange];\n        [msg removeAttribute:NSBackgroundColorAttributeName range:self->_topicEdit.selectedRange];\n        self->_topicEdit.attributedText = msg;\n        self->_topicEdit.selectedRange = selection;\n    } else {\n        self->_currentMessageAttributes = self->_topicEdit.typingAttributes = @{NSForegroundColorAttributeName:[UIColor textareaTextColor], NSFontAttributeName:self->_topicEdit.font };\n    }\n}\n\n-(void)chooseFGColor:(id)sender {\n    [self->_colorPickerView updateButtonColors:NO];\n    [UIView animateWithDuration:0.25 animations:^{ self->_colorPickerView.alpha = 1; } completion:nil];\n}\n\n-(void)chooseBGColor:(id)sender {\n    [self->_colorPickerView updateButtonColors:YES];\n    [UIView animateWithDuration:0.25 animations:^{ self->_colorPickerView.alpha = 1; } completion:nil];\n}\n\n-(void)foregroundColorPicked:(UIColor *)color {\n    if(self->_topicEdit.selectedRange.length) {\n        NSRange selection = self->_topicEdit.selectedRange;\n        NSMutableAttributedString *msg = self->_topicEdit.attributedText.mutableCopy;\n        [msg addAttribute:NSForegroundColorAttributeName value:color range:self->_topicEdit.selectedRange];\n        self->_topicEdit.attributedText = msg;\n        self->_topicEdit.selectedRange = selection;\n    } else {\n        NSMutableDictionary *d = [[NSMutableDictionary alloc] initWithDictionary:self->_topicEdit.typingAttributes];\n        [d setObject:color forKey:NSForegroundColorAttributeName];\n        self->_topicEdit.typingAttributes = d;\n    }\n    [self closeColorPicker];\n}\n\n-(void)backgroundColorPicked:(UIColor *)color {\n    if(self->_topicEdit.selectedRange.length) {\n        NSRange selection = self->_topicEdit.selectedRange;\n        NSMutableAttributedString *msg = self->_topicEdit.attributedText.mutableCopy;\n        [msg addAttribute:NSBackgroundColorAttributeName value:color range:self->_topicEdit.selectedRange];\n        self->_topicEdit.attributedText = msg;\n        self->_topicEdit.selectedRange = selection;\n    } else {\n        NSMutableDictionary *d = [[NSMutableDictionary alloc] initWithDictionary:self->_topicEdit.typingAttributes];\n        [d setObject:color forKey:NSBackgroundColorAttributeName];\n        self->_topicEdit.typingAttributes = d;\n    }\n    [self closeColorPicker];\n}\n\n-(void)closeColorPicker {\n    [UIView animateWithDuration:0.25 animations:^{ self->_colorPickerView.alpha = 0; } completion:nil];\n}\n\n-(void)textViewDidChangeSelection:(UITextView *)textView {\n    [self closeColorPicker];\n}\n\n-(void)textViewDidChange:(UITextView *)textView {\n    if(self->_currentMessageAttributes)\n        textView.typingAttributes = self->_currentMessageAttributes;\n    else\n        self->_currentMessageAttributes = textView.typingAttributes;\n    [self.tableView headerViewForSection:0].textLabel.text = [self tableView:self.tableView titleForHeaderInSection:0];\n}\n\n- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {\n    if(range.location == textView.text.length)\n        self->_currentMessageAttributes = textView.typingAttributes;\n    else\n        self->_currentMessageAttributes = nil;\n\n    if(text.length && [text isEqualToString:[UIPasteboard generalPasteboard].string]) {\n        if([[UIPasteboard generalPasteboard] valueForPasteboardType:@\"IRC formatting type\"]) {\n            NSMutableAttributedString *msg = self->_topicEdit.attributedText.mutableCopy;\n            if(self->_topicEdit.selectedRange.length > 0)\n                [msg deleteCharactersInRange:self->_topicEdit.selectedRange];\n            [msg insertAttributedString:[ColorFormatter format:[[NSString alloc] initWithData:[[UIPasteboard generalPasteboard] valueForPasteboardType:@\"IRC formatting type\"] encoding:NSUTF8StringEncoding] defaultColor:self->_topicEdit.textColor mono:NO linkify:NO server:nil links:nil] atIndex:self->_topicEdit.selectedRange.location];\n            \n            [self->_topicEdit setAttributedText:msg];\n        } else if([[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString *)kUTTypeRTF]) {\n            NSMutableAttributedString *msg = self->_topicEdit.attributedText.mutableCopy;\n            if(self->_topicEdit.selectedRange.length > 0)\n                [msg deleteCharactersInRange:self->_topicEdit.selectedRange];\n            [msg insertAttributedString:[ColorFormatter stripUnsupportedAttributes:[[NSAttributedString alloc] initWithData:[[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString *)kUTTypeRTF] options:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType} documentAttributes:nil error:nil] fontSize:self->_topicEdit.font.pointSize] atIndex:self->_topicEdit.selectedRange.location];\n            \n            [self->_topicEdit setAttributedText:msg];\n        } else if([[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString *)kUTTypeFlatRTFD]) {\n            NSMutableAttributedString *msg = self->_topicEdit.attributedText.mutableCopy;\n            if(self->_topicEdit.selectedRange.length > 0)\n                [msg deleteCharactersInRange:self->_topicEdit.selectedRange];\n            [msg insertAttributedString:[ColorFormatter stripUnsupportedAttributes:[[NSAttributedString alloc] initWithData:[[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString *)kUTTypeFlatRTFD] options:@{NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType} documentAttributes:nil error:nil] fontSize:self->_topicEdit.font.pointSize] atIndex:self->_topicEdit.selectedRange.location];\n            \n            [self->_topicEdit setAttributedText:msg];\n        } else if([[UIPasteboard generalPasteboard] valueForPasteboardType:@\"Apple Web Archive pasteboard type\"]) {\n            NSDictionary *d = [NSPropertyListSerialization propertyListWithData:[[UIPasteboard generalPasteboard] valueForPasteboardType:@\"Apple Web Archive pasteboard type\"] options:NSPropertyListImmutable format:NULL error:NULL];\n            NSMutableAttributedString *msg = self->_topicEdit.attributedText.mutableCopy;\n            if(self->_topicEdit.selectedRange.length > 0)\n                [msg deleteCharactersInRange:self->_topicEdit.selectedRange];\n            [msg insertAttributedString:[ColorFormatter stripUnsupportedAttributes:[[NSAttributedString alloc] initWithData:[[d objectForKey:@\"WebMainResource\"] objectForKey:@\"WebResourceData\"] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} documentAttributes:nil error:nil] fontSize:self->_topicEdit.font.pointSize] atIndex:self->_topicEdit.selectedRange.location];\n            \n            [self->_topicEdit setAttributedText:msg];\n        } else if([UIPasteboard generalPasteboard].string) {\n            NSMutableAttributedString *msg = self->_topicEdit.attributedText.mutableCopy;\n            if(self->_topicEdit.selectedRange.length > 0)\n                [msg deleteCharactersInRange:self->_topicEdit.selectedRange];\n            \n            [msg insertAttributedString:[[NSAttributedString alloc] initWithString:[UIPasteboard generalPasteboard].string attributes:@{NSFontAttributeName:self->_topicEdit.font,NSForegroundColorAttributeName:self->_topicEdit.textColor}] atIndex:self->_topicEdit.selectedRange.location];\n            \n            [self->_topicEdit setAttributedText:msg];\n        }\n        return NO;\n    } else if([text isEqualToString:@\"\\n\"]) {\n        [self setEditing:NO animated:YES];\n        return NO;\n    }\n    self->_topicChanged = YES;\n    return YES;\n}\n\n-(void)refresh {\n    self.navigationItem.rightBarButtonItem = self.editButtonItem;\n    [self->_modeHints removeAllObjects];\n    self->_topicChanged = NO;\n    Server *server = [[ServersDataSource sharedInstance] getServer:self->_channel.cid];\n    if([self->_channel.topic_text isKindOfClass:[NSString class]] && _channel.topic_text.length) {\n        NSArray *links;\n        self->_topic = [ColorFormatter format:self->_channel.topic_text defaultColor:[UIColor textareaTextColor] mono:NO linkify:YES server:[[ServersDataSource sharedInstance] getServer:self->_channel.cid] links:&links];\n        self->_topicLabel.attributedText = self->_topic;\n        self->_topicLabel.linkAttributes = [UIColor linkAttributes];\n        \n        for(NSTextCheckingResult *result in links) {\n            if(result.resultType == NSTextCheckingTypeLink) {\n                [self->_topicLabel addLinkWithTextCheckingResult:result];\n            } else {\n                NSString *url = [[self->_topic attributedSubstringFromRange:result.range] string];\n                if(![url hasPrefix:@\"irc\"]) {\n                    url = [NSString stringWithFormat:@\"irc://%i/%@\", server.cid, [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]];\n                }\n                [self->_topicLabel addLinkToURL:[NSURL URLWithString:[url stringByReplacingOccurrencesOfString:@\"#\" withString:@\"%23\"]] withRange:result.range];\n            }\n        }\n        self->_topicEdit.attributedText = self->_topic;\n        \n        if(self->_channel.topic_author) {\n            self->_topicSetBy = [NSString stringWithFormat:@\"Set by %@\", _channel.topic_author];\n            if(self->_channel.topic_time > 0) {\n                NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];\n                [dateFormatter setDateStyle:NSDateFormatterMediumStyle];\n                [dateFormatter setTimeStyle:NSDateFormatterShortStyle];\n                \n                self->_topicSetBy = [self->_topicSetBy stringByAppendingFormat:@\" on %@\", [dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:self->_channel.topic_time]]];\n            }\n        } else {\n            self->_topicSetBy = nil;\n        }\n    } else {\n        self->_topic = [ColorFormatter format:@\"(No topic set)\" defaultColor:[UIColor textareaTextColor] mono:NO linkify:NO server:nil links:nil];\n        self->_topicLabel.attributedText = self->_topic;\n        self->_topicEdit.text = @\"\";\n        self->_topicSetBy = nil;\n    }\n    if(([self->_channel.url isKindOfClass:[NSString class]] && _channel.url.length) || server.isSlack) {\n        NSString *url = server.isSlack ? [NSString stringWithFormat:@\"%@/messages/%@/details\", server.slackBaseURL, [[BuffersDataSource sharedInstance] getBuffer:self->_channel.bid].normalizedName] : _channel.url;\n        NSArray *links;\n        self->_url.attributedText = [ColorFormatter format:url defaultColor:[UIColor textareaTextColor] mono:NO linkify:YES server:[[ServersDataSource sharedInstance] getServer:self->_channel.cid] links:&links];\n        self->_url.linkAttributes = [UIColor linkAttributes];\n        \n        for(NSTextCheckingResult *result in links) {\n            if(result.resultType == NSTextCheckingTypeLink) {\n                [self->_url addLinkWithTextCheckingResult:result];\n            } else {\n                NSString *url = [[self->_topic attributedSubstringFromRange:result.range] string];\n                if(![url hasPrefix:@\"irc\"]) {\n                    url = [NSString stringWithFormat:@\"irc://%i/%@\", server.cid, [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]];\n                }\n                [self->_url addLinkToURL:[NSURL URLWithString:[url stringByReplacingOccurrencesOfString:@\"#\" withString:@\"%23\"]] withRange:result.range];\n            }\n        }\n    } else {\n        self->_url.attributedText = nil;\n    }\n    if(self->_channel.mode.length) {\n        for(NSDictionary *mode in _channel.modes) {\n            unichar m = [[mode objectForKey:@\"mode\"] characterAtIndex:0];\n            switch(m) {\n                case 'i':\n                    [self->_modeHints addObject:@{@\"mode\":@\"Invite Only (+i)\", @\"hint\":@\"Members must be invited to join this channel.\"}];\n                    break;\n                case 'k':\n                    [self->_modeHints addObject:@{@\"mode\":@\"Password (+k)\", @\"hint\":[mode objectForKey:@\"param\"]}];\n                    break;\n                case 'm':\n                    [self->_modeHints addObject:@{@\"mode\":@\"Moderated (+m)\", @\"hint\":@\"Only ops and voiced members may talk.\"}];\n                    break;\n                case 'n':\n                    [self->_modeHints addObject:@{@\"mode\":@\"No External Messages (+n)\", @\"hint\":@\"No messages allowed from outside the channel.\"}];\n                    break;\n                case 'p':\n                    [self->_modeHints addObject:@{@\"mode\":@\"Private (+p)\", @\"hint\":@\"Membership is only visible to other members.\"}];\n                    break;\n                case 's':\n                    [self->_modeHints addObject:@{@\"mode\":@\"Secret (+s)\", @\"hint\":@\"This channel is unlisted and membership is only visible to other members.\"}];\n                    break;\n                case 't':\n                    [self->_modeHints addObject:@{@\"mode\":@\"Topic Control (+t)\", @\"hint\":@\"Only ops can set the topic.\"}];\n                    User *u = [[UsersDataSource sharedInstance] getUser:server.nick cid:self->_channel.cid bid:self->_channel.bid];\n                    if(u && [u.mode rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:server?[NSString stringWithFormat:@\"%@%@%@%@%@\",server.MODE_OPER, server.MODE_OWNER, server.MODE_ADMIN, server.MODE_OP, server.MODE_HALFOP]:@\"Yqaoh\"]].location == NSNotFound)\n                        self.navigationItem.rightBarButtonItem = nil;\n                    break;\n            }\n        }\n    }\n    if(self->_channel.bid == -1)\n        self.navigationItem.rightBarButtonItem = nil;\n    [self.tableView reloadData];\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n#pragma mark - Table view data source\n\n-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    if([self->_channel.mode isKindOfClass:[NSString class]] && _channel.mode.length)\n        return 2 + (self->_url.attributedText.length ? 1 : 0);\n    else\n        return 1 + (self->_url.attributedText.length ? 1 : 0);\n}\n\n-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    if(section == 1 && !_url.attributedText.length)\n        section++;\n\n    switch(section) {\n        case 2:\n            if(self->_modeHints.count)\n                return _modeHints.count;\n        default:\n            return 1;\n    }\n}\n\n- (void)setEditing:(BOOL)editing animated:(BOOL)animated {\n    if(self.tableView.editing && !editing && _topicChanged) {\n        [[NetworkConnection sharedInstance] topic:[ColorFormatter toIRC:self->_topicEdit.attributedText] chan:self->_channel.name cid:self->_channel.cid handler:nil];\n    }\n    [super setEditing:editing animated:animated];\n    [self.tableView reloadData];\n    if(editing) {\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self->_topicEdit becomeFirstResponder];\n        }];\n        self->_topicChanged = NO;\n    }\n}\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    if(indexPath.section == 0) {\n        if(tableView.isEditing)\n            return 148;\n        CGFloat height = [LinkTextView heightOfString:self->_topic constrainedToWidth:self.tableView.bounds.size.width - offset];\n        self->_topicLabel.frame = CGRectMake(8,8,self.tableView.bounds.size.width - offset,height + 20);\n        self->_topicEdit.frame = CGRectMake(4,4,self.tableView.bounds.size.width - offset,140);\n        return height + 20;\n    } else if(indexPath.section == 1 && _url.attributedText.length) {\n        CGFloat height = [LinkTextView heightOfString:self->_url.attributedText constrainedToWidth:self.tableView.bounds.size.width - offset];\n        self->_url.frame = CGRectMake(8,8,self.tableView.bounds.size.width - offset,height);\n        return height + 20;\n    } else {\n        return UITableViewAutomaticDimension;\n    }\n}\n\n-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {\n    if(section == 0 && _topicSetBy.length)\n        return _topicSetBy;\n    return nil;\n}\n\n-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {\n    if(section == 1 && !_url.attributedText.length)\n        section++;\n    switch(section) {\n        case 0:\n            if(tableView.isEditing && _topiclen) {\n                return [NSString stringWithFormat:@\"TOPIC (%li CHARS)\", (self->_topiclen - [ColorFormatter toIRC:self->_topicEdit.attributedText].length)];\n            } else {\n                return @\"TOPIC\";\n            }\n        case 1:\n            return @\"CHANNEL URL\";\n        case 2:\n            if(self->_modeHints.count)\n                return [NSString stringWithFormat:@\"MODE: +%@\", _channel.mode];\n            else\n                return @\"MODE\";\n    }\n    return nil;\n}\n\n- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section {\n    if([view isKindOfClass:[UITableViewHeaderFooterView class]]) {\n        ((UITableViewHeaderFooterView *)view).textLabel.text = [self tableView:tableView titleForHeaderInSection:section];\n    }\n}\n\n-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSUInteger section = indexPath.section;\n    if(section == 1 && !_url.attributedText.length)\n        section++;\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"infocell\"];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@\"infocell\"];\n    \n    [cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];\n    cell.textLabel.text = cell.detailTextLabel.text = nil;\n    switch(section) {\n        case 0:\n            if(tableView.isEditing) {\n                [cell.contentView addSubview:self->_topicEdit];\n            } else {\n                [cell.contentView addSubview:self->_topicLabel];\n            }\n            break;\n        case 1:\n            [cell.contentView addSubview:self->_url];\n            break;\n        case 2:\n            if(self->_modeHints.count) {\n                cell.textLabel.text = [[self->_modeHints objectAtIndex:indexPath.row] objectForKey:@\"mode\"];\n                cell.detailTextLabel.text = [[self->_modeHints objectAtIndex:indexPath.row] objectForKey:@\"hint\"];\n                cell.detailTextLabel.numberOfLines = 0;\n            } else {\n                cell.textLabel.text = [NSString stringWithFormat:@\"+%@\", _channel.mode];\n            }\n    }\n\n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    \n    return cell;\n}\n\n-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {\n    return NO;\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ChannelListTableViewController.h",
    "content": "//\n//  ChannelListTableViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"IRCCloudJSONObject.h\"\n\n@interface ChannelListTableViewController : UITableViewController {\n    NSArray *_channels;\n    NSArray *_data;\n    IRCCloudJSONObject *_event;\n    UILabel *_placeholder;\n    UIActivityIndicatorView *_activity;\n}\n@property (strong) NSArray *channels;\n@property (strong) IRCCloudJSONObject *event;\n-(void)refresh;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ChannelListTableViewController.m",
    "content": "//\n//  ChannelListTableViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import \"ChannelListTableViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"LinkTextView.h\"\n#import \"ColorFormatter.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@interface ChannelTableCell : UITableViewCell {\n    LinkTextView *_channel;\n    LinkTextView *_topic;\n}\n@property (readonly) LinkTextView *channel,*topic;\n@end\n\n@implementation ChannelTableCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        \n        self->_channel = [[LinkTextView alloc] init];\n        self->_channel.font = [UIFont boldSystemFontOfSize:FONT_SIZE];\n        self->_channel.editable = NO;\n        self->_channel.scrollEnabled = NO;\n        self->_channel.selectable = NO;\n        self->_channel.textContainerInset = UIEdgeInsetsZero;\n        self->_channel.textContainer.lineFragmentPadding = 0;\n        self->_channel.backgroundColor = [UIColor clearColor];\n        self->_channel.textColor = [UIColor messageTextColor];\n        [self.contentView addSubview:self->_channel];\n        \n        self->_topic = [[LinkTextView alloc] init];\n        self->_topic.font = [UIFont systemFontOfSize:FONT_SIZE];\n        self->_topic.editable = NO;\n        self->_topic.scrollEnabled = NO;\n        self->_topic.textContainerInset = UIEdgeInsetsZero;\n        self->_topic.textContainer.lineFragmentPadding = 0;\n        self->_topic.backgroundColor = [UIColor clearColor];\n        self->_topic.textColor = [UIColor messageTextColor];\n        [self.contentView addSubview:self->_topic];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n\t[super layoutSubviews];\n\t\n\tCGRect frame = [self.contentView bounds];\n    frame.origin.x = 6;\n    frame.origin.y = 6;\n    frame.size.width -= 12;\n    frame.size.height -= 8;\n    \n    self->_channel.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, FONT_SIZE + 2);\n    self->_topic.frame = CGRectMake(frame.origin.x, frame.origin.y + FONT_SIZE + 2, frame.size.width, frame.size.height - FONT_SIZE - 2);\n}\n\n-(void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n@end\n\n@implementation ChannelListTableViewController\n\n-(id)initWithStyle:(UITableViewStyle)style {\n    self = [super initWithStyle:style];\n    if (self) {\n        self->_placeholder = [[UILabel alloc] initWithFrame:CGRectZero];\n        self->_placeholder.font = [UIFont systemFontOfSize:FONT_SIZE];\n        self->_placeholder.numberOfLines = 0;\n        self->_placeholder.textAlignment = NSTextAlignmentCenter;\n        self->_placeholder.textColor = [UIColor messageTextColor];\n        self->_activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n        self->_activity.hidesWhenStopped = YES;\n        [self->_placeholder addSubview:self->_activity];\n    }\n    return self;\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed)];\n    self.tableView.backgroundColor = [[UITableViewCell appearance] backgroundColor];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    self->_placeholder.frame = CGRectInset(self.tableView.frame, 12, 0);;\n    if(self->_channels.count) {\n        [self refresh];\n        [self->_activity stopAnimating];\n        [self->_placeholder removeFromSuperview];\n    } else {\n        self->_placeholder.text = [NSString stringWithFormat:@\"\\nLoading channel list for %@\", [self->_event objectForKey:@\"server\"]];\n        self->_activity.frame = CGRectMake((self->_placeholder.frame.size.width - _activity.frame.size.width)/2,6,_activity.frame.size.width,_activity.frame.size.height);\n        [self->_activity startAnimating];\n        [self.tableView.superview addSubview:self->_placeholder];\n    }\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)refresh {\n    NSMutableArray *data = [[NSMutableArray alloc] init];\n    \n    for(NSDictionary *channel in _channels) {\n        NSMutableDictionary *c = [[NSMutableDictionary alloc] initWithDictionary:channel];\n        NSAttributedString *topic = [ColorFormatter format:[c objectForKey:@\"topic\"] defaultColor:[UITableViewCell appearance].detailTextLabelColor mono:NO linkify:NO server:nil links:nil];\n        [c setObject:topic forKey:@\"formatted_topic\"];\n        [c setObject:@([LinkTextView heightOfString:topic constrainedToWidth:self.tableView.bounds.size.width - 6 - 12] + 16 + FONT_SIZE + 2) forKey:@\"height\"];\n        [data addObject:c];\n    }\n    \n    self->_data = data;\n    [self.tableView reloadData];\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    IRCCloudJSONObject *o = nil;\n    \n    switch(event) {\n        case kIRCEventListResponse:\n            o = notification.object;\n            if(o.cid == self->_event.cid) {\n                self->_event = o;\n                self->_channels = [o objectForKey:@\"channels\"];\n                [self refresh];\n                [self->_activity stopAnimating];\n                [self->_placeholder removeFromSuperview];\n            }\n            break;\n        case kIRCEventListResponseTooManyChannels:\n            o = notification.object;\n            if(o.cid == self->_event.cid) {\n                self->_event = o;\n                self->_placeholder.text = [NSString stringWithFormat:@\"Too many channels to list for %@\\n\\nTry limiting the list to only respond with channels that have more than e.g. 50 members: `/LIST >50`\\n\", [o objectForKey:@\"server\"]];\n                self->_placeholder.attributedText = [ColorFormatter format:[self->_placeholder.text insertCodeSpans] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil];\n                self->_placeholder.textAlignment = NSTextAlignmentCenter;\n                [self->_activity stopAnimating];\n            }\n            break;\n        default:\n            break;\n    }\n}\n\n-(void)doneButtonPressed {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n#pragma mark - Table view data source\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    return [[row objectForKey:@\"height\"] floatValue];\n}\n\n-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    if([self->_data count])\n        self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;\n    else\n        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    return [self->_data count];\n}\n\n-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    ChannelTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"channelcell\"];\n    if(!cell)\n        cell = [[ChannelTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"channelcell\"];\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    cell.channel.attributedText = [ColorFormatter format:[NSString stringWithFormat:@\"%c%@%c (%i member%@)\",BOLD,[row objectForKey:@\"name\"],CLEAR, [[row objectForKey:@\"num_members\"] intValue],[[row objectForKey:@\"num_members\"] intValue]==1?@\"\":@\"s\"] defaultColor:[UITableViewCell appearance].textLabelColor mono:NO linkify:NO server:nil links:nil];\n    cell.topic.attributedText = [row objectForKey:@\"formatted_topic\"];\n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [tableView deselectRowAtIndexPath:indexPath animated:NO];\n    NSDictionary *row = [self->_data objectAtIndex:indexPath.row];\n    [[NetworkConnection sharedInstance] join:[row objectForKey:@\"name\"] key:nil cid:self->_event.cid handler:nil];\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ChannelModeListTableViewController.h",
    "content": "//\n//  ChannelModeListTableViewController.h\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"IRCCloudJSONObject.h\"\n\n@interface ChannelModeListTableViewController : UITableViewController {\n    NSArray *_data;\n    IRCCloudJSONObject *_event;\n    UIBarButtonItem *_addButton;\n    int _cid;\n    int _bid;\n    int _list;\n    UILabel *_placeholder;\n    NSString *_mode;\n    NSString *_param;\n    NSString *_mask;\n    BOOL _canChangeMode;\n}\n@property (strong) NSArray *data;\n@property (strong) IRCCloudJSONObject *event;\n@property NSString *mask;\n\n-(id)initWithList:(int)list mode:(NSString *)mode param:(NSString *)param placeholder:(NSString *)placeholder cid:(int)cid bid:(int)bid;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ChannelModeListTableViewController.m",
    "content": "//\n//  ChannelModeListTableViewController.m\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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 \"ChannelModeListTableViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"ColorFormatter.h\"\n\n@interface MaskTableCell : UITableViewCell {\n    UILabel *_mask;\n    UILabel *_setBy;\n}\n@property (readonly) UILabel *mask,*setBy;\n@end\n\n@implementation MaskTableCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        \n        self->_mask = [[UILabel alloc] init];\n        self->_mask.font = [UIFont boldSystemFontOfSize:16];\n        self->_mask.textColor = [UITableViewCell appearance].textLabelColor;\n        self->_mask.lineBreakMode = NSLineBreakByCharWrapping;\n        self->_mask.numberOfLines = 0;\n        [self.contentView addSubview:self->_mask];\n        \n        self->_setBy = [[UILabel alloc] init];\n        self->_setBy.font = [UIFont systemFontOfSize:14];\n        self->_setBy.textColor = [UITableViewCell appearance].detailTextLabelColor;\n        self->_setBy.lineBreakMode = NSLineBreakByCharWrapping;\n        self->_setBy.numberOfLines = 0;\n        [self.contentView addSubview:self->_setBy];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n\t[super layoutSubviews];\n\t\n\tCGRect frame = [self.contentView bounds];\n    frame.origin.x = frame.origin.y = 6;\n    frame.size.width -= 12;\n    \n    float maskHeight = ceil([self->_mask.text boundingRectWithSize:CGSizeMake(frame.size.width, INT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:self->_mask.font} context:nil].size.height) + 2;\n    self->_mask.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, maskHeight);\n    self->_setBy.frame = CGRectMake(frame.origin.x, frame.origin.y + maskHeight - 2, frame.size.width, frame.size.height - maskHeight - 8);\n}\n\n-(void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n@end\n\n@implementation ChannelModeListTableViewController\n\n-(id)initWithList:(int)list mode:(NSString *)mode param:(NSString *)param placeholder:(NSString *)placeholder cid:(int)cid bid:(int)bid {\n    self = [super initWithStyle:UITableViewStylePlain];\n    if (self) {\n        self->_addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonPressed)];\n        self->_placeholder = [[UILabel alloc] initWithFrame:CGRectZero];\n        self->_placeholder.text = placeholder;\n        self->_placeholder.numberOfLines = 0;\n        self->_placeholder.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n        self->_placeholder.attributedText = [ColorFormatter format:[self->_placeholder.text insertCodeSpans] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil];\n        self->_placeholder.textAlignment = NSTextAlignmentCenter;\n\n        self->_list = list;\n        self->_cid = cid;\n        self->_bid = bid;\n        self->_mode = mode;\n        self->_param = param;\n        self->_mask = @\"mask\";\n        \n        Server *s = [[ServersDataSource sharedInstance] getServer:cid];\n        if(s) {\n            User *u = [[UsersDataSource sharedInstance] getUser:s.nick cid:cid bid:bid];\n            if(u && ([u.mode containsString:s.MODE_OWNER] || [u.mode containsString:s.MODE_ADMIN] || [u.mode containsString:s.MODE_OP] || [u.mode containsString:s.MODE_HALFOP]))\n                self->_canChangeMode = YES;\n        }\n    }\n    return self;\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    if(self->_canChangeMode)\n        self.navigationItem.leftBarButtonItem = self->_addButton;\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed)];\n    self.tableView.backgroundColor = [[UITableViewCell appearance] backgroundColor];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    self->_placeholder.frame = CGRectInset(self.tableView.frame, 12, 0);\n    if(self->_data.count)\n        [self->_placeholder removeFromSuperview];\n    else\n        [self.tableView.superview addSubview:self->_placeholder];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    IRCCloudJSONObject *o = nil;\n    Event *e = nil;\n\n    if(event == self->_list) {\n        o = notification.object;\n        if(o.cid == self->_event.cid && [[o objectForKey:@\"channel\"] isEqualToString:[self->_event objectForKey:@\"channel\"]]) {\n            self->_event = o;\n            self->_data = [o objectForKey:self->_param];\n            if(self->_data.count)\n                [self->_placeholder removeFromSuperview];\n            else\n                [self.tableView.superview addSubview:self->_placeholder];\n            [self.tableView reloadData];\n        }\n    } else if(event == kIRCEventBufferMsg) {\n        e = notification.object;\n        if(e.cid == self->_event.cid && e.bid == self->_bid && [e.type isEqualToString:@\"channel_mode_list_change\"]) {\n            [[NetworkConnection sharedInstance] mode:self->_mode chan:[self->_event objectForKey:@\"channel\"] cid:self->_event.cid handler:nil];\n        }\n    }\n}\n\n-(void)doneButtonPressed {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)addButtonPressed {\n    [self.view endEditing:YES];\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_event.cid];\n    \n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:[_event.type isEqualToString:@\"chanfilter_list\"]?@\"Add this pattern\":@\"Add this hostmask\" preferredStyle:UIAlertControllerStyleAlert];\n    \n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Add\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n        if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n            [[NetworkConnection sharedInstance] mode:[NSString stringWithFormat:@\"+%@ %@\", self->_mode, ((UITextField *)[alert.textFields objectAtIndex:0]).text] chan:[self->_event objectForKey:@\"channel\"] cid:self->_event.cid handler:nil];\n        }\n    }]];\n    \n    [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n        textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n    }];\n    \n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n-(NSString *)setByTextForRow:(NSDictionary *)row {\n    NSString *msg = @\"Set \";\n    double seconds = [[NSDate date] timeIntervalSince1970] - [[row objectForKey:@\"time\"] doubleValue];\n    double minutes = seconds / 60.0;\n    double hours = minutes / 60.0;\n    double days = hours / 24.0;\n    if(days >= 1) {\n        if(days - (int)days > 0.5)\n            days++;\n        \n        if(days == 1)\n            msg = [msg stringByAppendingFormat:@\"%i day ago\", (int)days];\n        else\n            msg = [msg stringByAppendingFormat:@\"%i days ago\", (int)days];\n    } else if(hours >= 1) {\n        if(hours - (int)hours > 0.5)\n            hours++;\n        \n        if(hours < 2)\n            msg = [msg stringByAppendingFormat:@\"%i hour ago\", (int)hours];\n        else\n            msg = [msg stringByAppendingFormat:@\"%i hours ago\", (int)hours];\n    } else if(minutes >= 1) {\n        if(minutes - (int)minutes > 0.5)\n            minutes++;\n        \n        if(minutes == 1)\n            msg = [msg stringByAppendingFormat:@\"%i minute ago\", (int)minutes];\n        else\n            msg = [msg stringByAppendingFormat:@\"%i minutes ago\", (int)minutes];\n    } else {\n        msg = [msg stringByAppendingString:@\"less than a minute ago\"];\n    }\n    if([row objectForKey:@\"author\"])\n        return [msg stringByAppendingFormat:@\" by %@\", [row objectForKey:@\"author\"]];\n    else\n        return [msg stringByAppendingFormat:@\" by %@\", [row objectForKey:@\"usermask\"]];\n}\n\n#pragma mark - Table view data source\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    return ceil([[row objectForKey:self->_mask] boundingRectWithSize:CGSizeMake(self.tableView.frame.size.width - 12, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName: [UIFont boldSystemFontOfSize:16]} context:nil].size.height + [[self setByTextForRow:row] boundingRectWithSize:CGSizeMake(self.tableView.frame.size.width - 12, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14]} context:nil].size.height) + 12;\n}\n\n-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    if([self->_data count])\n        self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;\n    else\n        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    @synchronized(self->_data) {\n        return [self->_data count];\n    }\n}\n\n-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized(self->_data) {\n        MaskTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"maskcell\"];\n        if(!cell)\n            cell = [[MaskTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"maskcell\"];\n        NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n        cell.mask.text = [row objectForKey:self->_mask];\n        cell.setBy.text = [self setByTextForRow:row];\n        return cell;\n    }\n}\n\n-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {\n    return _canChangeMode;\n}\n\n-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {\n    if (editingStyle == UITableViewCellEditingStyleDelete && indexPath.row < _data.count) {\n        NSDictionary *row = [self->_data objectAtIndex:indexPath.row];\n        [[NetworkConnection sharedInstance] mode:[NSString stringWithFormat:@\"-%@ %@\", _mode, [row objectForKey:self->_mask]] chan:[self->_event objectForKey:@\"channel\"] cid:self->_event.cid handler:nil];\n    }\n}\n\n#pragma mark - Table view delegate\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [tableView deselectRowAtIndexPath:indexPath animated:NO];\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ChannelsDataSource.h",
    "content": "//\n//  ChannelsDataSource.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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@interface Channel : NSObject<NSSecureCoding> {\n    int _cid;\n    int _bid;\n    NSString *_name;\n    NSString *_topic_text;\n    NSTimeInterval _topic_time;\n    NSString *_topic_author;\n    NSString *_type;\n    NSMutableArray *_modes;\n    NSString *_mode;\n    NSTimeInterval _timestamp;\n    NSString *_url;\n    BOOL _valid;\n    BOOL _key;\n}\n@property (assign) int cid, bid;\n@property (assign) BOOL valid, key;\n@property (copy) NSString *name, *topic_text, *topic_author, *type, *mode, *url;\n@property (assign) NSTimeInterval topic_time, timestamp;\n@property (strong) NSArray *modes;\n-(void)addMode:(NSString *)mode param:(NSString *)param;\n-(void)removeMode:(NSString *)mode;\n-(BOOL)hasMode:(NSString *)mode;\n@end\n\n@interface ChannelsDataSource : NSObject {\n    NSMutableArray *_channels;\n}\n+(ChannelsDataSource *)sharedInstance;\n-(void)serialize;\n-(void)clear;\n-(void)invalidate;\n-(void)addChannel:(Channel *)channel;\n-(void)removeChannelForBuffer:(int)bid;\n-(void)updateTopic:(NSString *)text time:(NSTimeInterval)time author:(NSString *)author buffer:(int)bid;\n-(void)updateMode:(NSString *)mode buffer:(int)bid ops:(NSDictionary *)ops;\n-(void)updateURL:(NSString *)url buffer:(int)bid;\n-(void)updateTimestamp:(NSTimeInterval)timestamp buffer:(int)bid;\n-(Channel *)channelForBuffer:(int)bid;\n-(NSArray *)channelsForServer:(int)cid;\n-(NSArray *)channels;\n-(void)purgeInvalidChannels;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ChannelsDataSource.m",
    "content": "//\n//  ChannelsDataSource.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"ChannelsDataSource.h\"\n#import \"UsersDataSource.h\"\n#import \"BuffersDataSource.h\"\n#import \"ServersDataSource.h\"\n#import \"EventsDataSource.h\"\n\n@implementation Channel\n\n+ (BOOL)supportsSecureCoding {\n    return YES;\n}\n\n-(void)addMode:(NSString *)mode param:(NSString *)param {\n    [self removeMode:mode];\n    if([mode isEqualToString:@\"k\"])\n        self->_key = YES;\n    @synchronized(self->_modes) {\n        [self->_modes addObject:@{@\"mode\":mode,@\"param\":param}];\n    }\n}\n\n-(void)removeMode:(NSString *)mode {\n    @synchronized(self->_modes) {\n        if([mode isEqualToString:@\"k\"])\n            self->_key = NO;\n        for(NSDictionary *m in _modes) {\n            if([[[m objectForKey:@\"mode\"] lowercaseString] isEqualToString:mode]) {\n                [self->_modes removeObject:m];\n                return;\n            }\n        }\n    }\n}\n-(BOOL)hasMode:(NSString *)mode {\n    @synchronized(self->_modes) {\n        for(NSDictionary *m in _modes) {\n            if([[[m objectForKey:@\"mode\"] lowercaseString] isEqualToString:mode])\n                return YES;\n        }\n    }\n    return NO;\n}\n-(NSComparisonResult)compare:(Channel *)aChannel {\n    return [[self->_name lowercaseString] compare:[aChannel.name lowercaseString]];\n}\n-(NSString *)description {\n    return [NSString stringWithFormat:@\"{cid: %i, bid: %i, name: %@, type: %@}\", _cid, _bid, _name, _type];\n}\n-(id)initWithCoder:(NSCoder *)aDecoder {\n    self = [super init];\n    if(self) {\n        decodeInt(self->_cid);\n        decodeInt(self->_bid);\n        decodeObjectOfClass(NSString.class, self->_name);\n        decodeObjectOfClass(NSString.class, self->_topic_text);\n        decodeDouble(self->_topic_time);\n        decodeObjectOfClass(NSString.class, self->_topic_author);\n        decodeObjectOfClass(NSString.class, self->_type);\n        NSSet *set = [NSSet setWithObjects:NSMutableArray.class, NSDictionary.class, NSString.class, NSNumber.class, nil];\n        decodeObjectOfClasses(set, self->_modes);\n        decodeObjectOfClass(NSString.class, self->_mode);\n        decodeDouble(self->_timestamp);\n        decodeObjectOfClass(NSString.class, self->_url);\n        decodeBool(self->_valid);\n        decodeBool(self->_key);\n    }\n    return self;\n}\n-(void)encodeWithCoder:(NSCoder *)aCoder {\n    encodeInt(self->_cid);\n    encodeInt(self->_bid);\n    encodeObject(self->_name);\n    encodeObject(self->_topic_text);\n    encodeDouble(self->_topic_time);\n    encodeObject(self->_topic_author);\n    encodeObject(self->_type);\n    encodeObject(self->_modes);\n    encodeObject(self->_mode);\n    encodeDouble(self->_timestamp);\n    encodeObject(self->_url);\n    encodeBool(self->_valid);\n    encodeBool(self->_key);\n}\n@end\n\n@implementation ChannelsDataSource\n+(ChannelsDataSource *)sharedInstance {\n    static ChannelsDataSource *sharedInstance;\n\t\n    @synchronized(self) {\n        if(!sharedInstance)\n            sharedInstance = [[ChannelsDataSource alloc] init];\n\t\t\n        return sharedInstance;\n    }\n\treturn nil;\n}\n\n-(id)init {\n    self = [super init];\n    if(self) {\n        [NSKeyedArchiver setClassName:@\"IRCCloud.Channel\" forClass:Channel.class];\n        [NSKeyedUnarchiver setClass:Channel.class forClassName:@\"IRCCloud.Channel\"];\n\n        if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"cacheVersion\"] isEqualToString:[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleVersion\"]]) {\n            NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"channels\"];\n            \n            @try {\n                NSError* error = nil;\n                self->_channels = [[NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:NSDictionary.class, NSArray.class, Channel.class,NSString.class,NSNumber.class, nil] fromData:[NSData dataWithContentsOfFile:cacheFile] error:&error] mutableCopy];\n                if(error)\n                    @throw [NSException exceptionWithName:@\"NSError\" reason:error.debugDescription userInfo:@{ @\"NSError\" : error }];\n            } @catch(NSException *e) {\n                CLS_LOG(@\"Exception: %@\", e);\n                [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n                [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"cacheVersion\"];\n                [[ServersDataSource sharedInstance] clear];\n                [[BuffersDataSource sharedInstance] clear];\n                [[EventsDataSource sharedInstance] clear];\n                [[UsersDataSource sharedInstance] clear];\n            }\n        }\n        if(!_channels)\n            self->_channels = [[NSMutableArray alloc] init];\n    }\n    return self;\n}\n\n-(void)serialize {\n    NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"channels\"];\n    \n    NSArray *channels;\n    @synchronized(self->_channels) {\n        channels = [self->_channels copy];\n    }\n    \n    @synchronized(self) {\n        @try {\n            NSError* error = nil;\n            [[NSKeyedArchiver archivedDataWithRootObject:channels requiringSecureCoding:YES error:&error] writeToFile:cacheFile atomically:YES];\n            if(error)\n                CLS_LOG(@\"Error archiving: %@\", error);\n            [[NSURL fileURLWithPath:cacheFile] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL];\n        }\n        @catch (NSException *exception) {\n            [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n        }\n    }\n}\n\n-(void)clear {\n    @synchronized(self->_channels) {\n        [self->_channels removeAllObjects];\n    }\n}\n\n-(void)invalidate {\n    @synchronized(self->_channels) {\n        for(Channel *channel in _channels) {\n            channel.valid = NO;\n        }\n    }\n}\n\n-(void)addChannel:(Channel *)channel {\n    @synchronized(self->_channels) {\n        [self->_channels addObject:channel];\n    }\n}\n\n-(void)removeChannelForBuffer:(int)bid {\n    @synchronized(self->_channels) {\n        Channel *channel = [self channelForBuffer:bid];\n        if(channel)\n            [self->_channels removeObject:channel];\n    }\n}\n\n-(void)updateTopic:(NSString *)text time:(NSTimeInterval)time author:(NSString *)author buffer:(int)bid {\n    @synchronized(self->_channels) {\n        Channel *channel = [self channelForBuffer:bid];\n        if(channel) {\n            channel.topic_text = text;\n            channel.topic_time = time;\n            channel.topic_author = author;\n        }\n    }\n}\n\n-(void)updateMode:(NSString *)mode buffer:(int)bid ops:(NSDictionary *)ops {\n    @synchronized(self->_channels) {\n        Channel *channel = [self channelForBuffer:bid];\n        if(channel) {\n            NSArray *add = [ops objectForKey:@\"add\"];\n            for(NSDictionary *m in add) {\n                [channel addMode:[m objectForKey:@\"mode\"] param:[m objectForKey:@\"param\"]];\n            }\n            NSArray *remove = [ops objectForKey:@\"remove\"];\n            for(NSDictionary *m in remove) {\n                [channel removeMode:[m objectForKey:@\"mode\"]];\n            }\n            channel.mode = mode;\n        }\n    }\n}\n\n-(void)updateURL:(NSString *)url buffer:(int)bid {\n    @synchronized(self->_channels) {\n        Channel *channel = [self channelForBuffer:bid];\n        if(channel)\n            channel.url = url;\n    }\n}\n\n-(void)updateTimestamp:(NSTimeInterval)timestamp buffer:(int)bid {\n    @synchronized(self->_channels) {\n        Channel *channel = [self channelForBuffer:bid];\n        if(channel)\n            channel.timestamp = timestamp;\n    }\n}\n\n-(Channel *)channelForBuffer:(int)bid {\n    @synchronized(self->_channels) {\n        for(int i = 0; i < _channels.count; i++) {\n            Channel *channel = [self->_channels objectAtIndex:i];\n            if(channel.bid == bid)\n                return channel;\n        }\n        return nil;\n    }\n}\n\n-(NSArray *)channelsForServer:(int)cid {\n    NSMutableArray *channels = [[NSMutableArray alloc] init];\n    @synchronized(self->_channels) {\n        for(int i = 0; i < _channels.count; i++) {\n            Channel *channel = [self->_channels objectAtIndex:i];\n            if(channel.cid == cid)\n                [channels addObject:channel];\n        }\n    }\n    return channels;\n}\n\n-(NSArray *)channels {\n    return _channels;\n}\n\n-(void)purgeInvalidChannels {\n    CLS_LOG(@\"Cleaning up invalid channels\");\n    NSArray *copy;\n    @synchronized(self->_channels) {\n        copy = self->_channels.copy;\n    }\n    for(Channel *channel in copy) {\n        if(!channel.valid) {\n            CLS_LOG(@\"Removing invalid channel: %@\", channel.name);\n            [self->_channels removeObject:channel];\n            [[UsersDataSource sharedInstance] removeUsersForBuffer:channel.bid];\n        }\n    }\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/CollapsedEvents.h",
    "content": "//\n//  CollapsedEvents.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import \"EventsDataSource.h\"\n#import \"ServersDataSource.h\"\n\ntypedef enum {\n    kCollapsedEventNetSplit,\n    kCollapsedEventJoin,\n    kCollapsedEventPart,\n    kCollapsedEventQuit,\n    kCollapsedEventMode,\n    kCollapsedEventPopIn,\n    kCollapsedEventPopOut,\n    kCollapsedEventNickChange,\n    kCollapsedEventConnectionStatus\n} kCollapsedEvent;\n\ntypedef enum {\n    kCollapsedModeOper,\n    kCollapsedModeOwner,\n    kCollapsedModeAdmin,\n    kCollapsedModeOp,\n    kCollapsedModeHalfOp,\n    kCollapsedModeVoice,\n    \n    kCollapsedModeDeOper,\n    kCollapsedModeDeOwner,\n    kCollapsedModeDeAdmin,\n    kCollapsedModeDeOp,\n    kCollapsedModeDeHalfOp,\n    kCollapsedModeDeVoice,\n} kCollapsedMode;\n\n@interface CollapsedEvent : NSObject {\n    kCollapsedEvent _type;\n    BOOL _modes[12];\n    BOOL _operIsLower;\n    NSTimeInterval _eid;\n    NSString *_nick;\n    NSString *_oldNick;\n    NSString *_hostname;\n    NSString *_msg;\n    NSString *_fromMode;\n    NSString *_fromNick;\n    NSString *_targetMode;\n    NSString *_chan;\n    int _count;\n}\n@property NSTimeInterval eid;\n@property kCollapsedEvent type;\n@property NSString *nick, *oldNick, *hostname, *msg, *fromMode, *fromNick, *targetMode, *chan;\n@property BOOL operIsLower;\n@property int count;\n-(NSComparisonResult)compare:(CollapsedEvent *)aEvent;\n-(BOOL)addMode:(NSString *)mode server:(Server *)server;\n-(BOOL)removeMode:(NSString *)mode server:(Server *)server;\n-(NSString *)modes:(BOOL)showSymbol mode_modes:(NSArray *)mode_modes;\n-(void)copyModes:(CollapsedEvent *)from;\n-(int)modeCount;\n@end\n\n@interface CollapsedEvents : NSObject {\n    NSMutableArray *_data;\n    Server *_server;\n    NSArray *_mode_modes;\n    BOOL _showChan;\n    BOOL _noColor;\n}\n@property BOOL showChan, noColor;\n-(void)clear;\n-(BOOL)addEvent:(Event *)event;\n-(NSString *)collapse;\n-(NSUInteger)count;\n-(NSString *)formatNick:(NSString *)nick mode:(NSString *)mode colorize:(BOOL)colorize displayName:(NSString *)displayName;\n-(NSString *)formatNick:(NSString *)nick mode:(NSString *)mode colorize:(BOOL)colorize defaultColor:(NSString *)color displayName:(NSString *)displayName;\n-(NSString *)formatNick:(NSString *)nick mode:(NSString *)mode colorize:(BOOL)colorize defaultColor:(NSString *)color bold:(BOOL)bold displayName:(NSString *)displayName;\n-(void)setServer:(Server *)server;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/CollapsedEvents.m",
    "content": "//\n//  CollapsedEvents.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"CollapsedEvents.h\"\n#import \"ColorFormatter.h\"\n#import \"NetworkConnection.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@implementation CollapsedEvent\n-(NSComparisonResult)compare:(CollapsedEvent *)aEvent {\n    if(self->_type == aEvent.type) {\n        if(self->_eid < aEvent.eid)\n            return NSOrderedAscending;\n        else\n            return NSOrderedDescending;\n    } else if(self->_type < aEvent.type) {\n        return NSOrderedAscending;\n    } else {\n        return NSOrderedDescending;\n    }\n}\n-(NSString *)description {\n    return [NSString stringWithFormat:@\"{type: %i, chan: %@, nick: %@, oldNick: %@, hostmask: %@, fromMode: %@, targetMode: %@, modes: %@, msg: %@}\", _type, _chan, _nick, _oldNick, _hostname, _fromMode, _targetMode, [self modes:YES mode_modes:nil], _msg];\n}\n-(BOOL)addMode:(NSString *)mode server:(Server *)server {\n    if([mode rangeOfString:server?server.MODE_OPER.lowercaseString:@\"y\"].location != NSNotFound)\n        self->_operIsLower = YES;\n    mode = mode.lowercaseString;\n    \n    if([mode rangeOfString:server?server.MODE_OPER.lowercaseString:@\"y\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeDeOper])\n            self->_modes[kCollapsedModeDeOper] = false;\n        else\n            self->_modes[kCollapsedModeOper] = true;\n    } else if([mode rangeOfString:server?server.MODE_OWNER.lowercaseString:@\"q\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeDeOwner])\n            self->_modes[kCollapsedModeDeOwner] = false;\n        else\n            self->_modes[kCollapsedModeOwner] = true;\n    } else if([mode rangeOfString:server?server.MODE_ADMIN.lowercaseString:@\"a\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeDeAdmin])\n            self->_modes[kCollapsedModeDeAdmin] = false;\n        else\n            self->_modes[kCollapsedModeAdmin] = true;\n    } else if([mode rangeOfString:server?server.MODE_OP.lowercaseString:@\"o\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeDeOp])\n            self->_modes[kCollapsedModeDeOp] = false;\n        else\n            self->_modes[kCollapsedModeOp] = true;\n    } else if([mode rangeOfString:server?server.MODE_HALFOP.lowercaseString:@\"h\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeDeHalfOp])\n            self->_modes[kCollapsedModeDeHalfOp] = false;\n        else\n            self->_modes[kCollapsedModeHalfOp] = true;\n    } else if([mode rangeOfString:server?server.MODE_VOICED.lowercaseString:@\"v\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeDeVoice])\n            self->_modes[kCollapsedModeDeVoice] = false;\n        else\n            self->_modes[kCollapsedModeVoice] = true;\n    } else {\n        return NO;\n    }\n\n    if([self modeCount] == 0)\n        return [self addMode:mode server:server];\n    return YES;\n}\n-(BOOL)removeMode:(NSString *)mode server:(Server *)server {\n    mode = mode.lowercaseString;\n    \n    if([mode rangeOfString:server?server.MODE_OPER.lowercaseString:@\"y\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeOper])\n            self->_modes[kCollapsedModeOper] = false;\n        else\n            self->_modes[kCollapsedModeDeOper] = true;\n    } else if([mode rangeOfString:server?server.MODE_OWNER.lowercaseString:@\"q\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeOwner])\n            self->_modes[kCollapsedModeOwner] = false;\n        else\n            self->_modes[kCollapsedModeDeOwner] = true;\n    } else if([mode rangeOfString:server?server.MODE_ADMIN.lowercaseString:@\"a\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeAdmin])\n            self->_modes[kCollapsedModeAdmin] = false;\n        else\n            self->_modes[kCollapsedModeDeAdmin] = true;\n    } else if([mode rangeOfString:server?server.MODE_OP.lowercaseString:@\"o\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeOp])\n            self->_modes[kCollapsedModeOp] = false;\n        else\n            self->_modes[kCollapsedModeDeOp] = true;\n    } else if([mode rangeOfString:server?server.MODE_HALFOP.lowercaseString:@\"h\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeHalfOp])\n            self->_modes[kCollapsedModeHalfOp] = false;\n        else\n            self->_modes[kCollapsedModeDeHalfOp] = true;\n    } else if([mode rangeOfString:server?server.MODE_VOICED.lowercaseString:@\"v\"].location != NSNotFound) {\n        if(self->_modes[kCollapsedModeVoice])\n            self->_modes[kCollapsedModeVoice] = false;\n        else\n            self->_modes[kCollapsedModeDeVoice] = true;\n    } else {\n        return NO;\n    }\n    if([self modeCount] == 0)\n        return [self removeMode:mode server:server];\n    return YES;\n}\n-(void)_copyModes:(BOOL *)to {\n    for(int i = 0; i < sizeof(self->_modes); i++) {\n        to[i] = self->_modes[i];\n    }\n}\n-(void)copyModes:(CollapsedEvent *)from {\n    [from _copyModes:self->_modes];\n    self->_operIsLower = from.operIsLower;\n}\n-(NSString *)modes:(BOOL)showSymbol mode_modes:(NSArray *)mode_modes {\n    static NSString *mode_msgs[] = {\n        @\"promoted to oper\",\n        @\"promoted to owner\",\n        @\"promoted to admin\",\n        @\"opped\",\n        @\"halfopped\",\n        @\"voiced\",\n        @\"demoted from oper\",\n        @\"demoted from owner\",\n        @\"demoted from admin\",\n        @\"de-opped\",\n        @\"de-halfopped\",\n        @\"de-voiced\"\n    };\n    static NSString *mode_colors[] = {\n        @\"E02305\",\n        @\"E7AA00\",\n        @\"6500A5\",\n        @\"BA1719\",\n        @\"B55900\",\n        @\"25B100\"\n    };\n    NSString *output = nil;\n    if(!mode_modes) {\n        mode_modes = @[\n            self->_operIsLower?@\"+y\":@\"+Y\",\n            @\"+q\",\n            @\"+a\",\n            @\"+o\",\n            @\"+h\",\n            @\"+v\",\n            self->_operIsLower?@\"-y\":@\"-Y\",\n            @\"-q\",\n            @\"-a\",\n            @\"-o\",\n            @\"-h\",\n            @\"-v\"\n        ];\n    }\n    \n    if([self modeCount]) {\n        output = @\"\";\n        for(int i = 0; i < sizeof(self->_modes); i++) {\n            if(self->_modes[i]) {\n                if(output.length)\n                    output = [output stringByAppendingString:@\", \"];\n                output = [output stringByAppendingString:mode_msgs[i]];\n                if(showSymbol) {\n                    output = [output stringByAppendingFormat:@\" (%c%@%@%c%@)\", COLOR_RGB, mode_colors[i%6], mode_modes[i], COLOR_RGB, [UIColor messageTextColor].toHexString];\n                }\n            }\n        }\n    }\n    \n    return output;\n}\n-(int)modeCount {\n    int count = 0;\n    for(int i = 0; i < sizeof(self->_modes); i++) {\n        if(self->_modes[i])\n            count++;\n    }\n    return count;\n}\n@end\n\n@implementation CollapsedEvents\n-(id)init {\n    self = [super init];\n    if(self) {\n        self->_data = [[NSMutableArray alloc] init];\n        [self setServer:nil];\n    }\n    return self;\n}\n-(void)clear {\n    @synchronized(self->_data) {\n        [self->_data removeAllObjects];\n    }\n}\n-(void)setServer:(Server *)server {\n    self->_server = server;\n    if(server) {\n        self->_mode_modes = @[\n            [NSString stringWithFormat:@\"+%@\", server.MODE_OPER],\n            [NSString stringWithFormat:@\"+%@\", server.MODE_OWNER],\n            [NSString stringWithFormat:@\"+%@\", server.MODE_ADMIN],\n            [NSString stringWithFormat:@\"+%@\", server.MODE_OP],\n            [NSString stringWithFormat:@\"+%@\", server.MODE_HALFOP],\n            [NSString stringWithFormat:@\"+%@\", server.MODE_VOICED],\n            [NSString stringWithFormat:@\"-%@\", server.MODE_OPER],\n            [NSString stringWithFormat:@\"-%@\", server.MODE_OWNER],\n            [NSString stringWithFormat:@\"-%@\", server.MODE_ADMIN],\n            [NSString stringWithFormat:@\"-%@\", server.MODE_OP],\n            [NSString stringWithFormat:@\"-%@\", server.MODE_HALFOP],\n            [NSString stringWithFormat:@\"-%@\", server.MODE_VOICED],\n        ];\n    } else {\n        self->_mode_modes = nil;\n    }\n}\n-(CollapsedEvent *)findEvent:(NSString *)nick chan:(NSString *)chan {\n    @synchronized(self->_data) {\n        for(CollapsedEvent *event in _data) {\n            if([[event.nick lowercaseString] isEqualToString:[nick lowercaseString]] && (chan == nil || event.chan == nil || [[event.chan lowercaseString] isEqualToString:[chan lowercaseString]]))\n                return event;\n        }\n        return nil;\n    }\n}\n-(void)addCollapsedEvent:(CollapsedEvent *)event {\n    @synchronized(self->_data) {\n        CollapsedEvent *e = nil;\n        \n        if(event.type < kCollapsedEventNickChange) {\n            if(self->_showChan) {\n                if(event.type == kCollapsedEventQuit) {\n                    BOOL found = NO;\n                    for(e in _data) {\n                        if(e.type == kCollapsedEventJoin) {\n                            e.type = kCollapsedEventPopIn;\n                            found = YES;\n                        }\n                    }\n                    if(found)\n                        return;\n                } else if(event.type == kCollapsedEventJoin) {\n                    for(e in _data) {\n                        if(e.type == kCollapsedEventQuit) {\n                            [self->_data removeObject:e];\n                            event.type = kCollapsedEventPopOut;\n                            break;\n                        } else if(e.type == kCollapsedEventPopOut) {\n                            event.type = kCollapsedEventPopOut;\n                            break;\n                        }\n                    }\n                }\n                e = nil;\n            }\n            if(event.oldNick.length > 0 && event.type != kCollapsedEventMode) {\n                e = [self findEvent:event.oldNick chan:event.chan];\n                if(e)\n                    e.nick = event.nick;\n            }\n            \n            if(!e)\n                e = [self findEvent:event.nick chan:event.chan];\n            \n            if(e) {\n                if(e.type == kCollapsedEventMode) {\n                    e.type = event.type;\n                    e.msg = event.msg;\n                    if(event.fromMode)\n                        e.fromMode = event.fromMode;\n                    if(event.targetMode)\n                        e.targetMode = event.targetMode;\n                    e.hostname = event.hostname;\n                } else if(e.type == kCollapsedEventNickChange) {\n                    e.type = event.type;\n                    e.msg = event.msg;\n                    e.fromMode = event.fromMode;\n                    e.fromNick = event.fromNick;\n                } else if(event.type == kCollapsedEventMode) {\n                    e.fromMode = event.targetMode;\n                } else if(event.type == e.type) {\n                } else if(event.type == kCollapsedEventJoin) {\n                    if(e.type == kCollapsedEventPopIn)\n                        e.type = kCollapsedEventJoin;\n                    else\n                        e.type = kCollapsedEventPopOut;\n                    e.fromMode = event.fromMode;\n                    e.msg = nil;\n                } else if(e.type == kCollapsedEventPopOut) {\n                    e.type = event.type;\n                } else {\n                    e.type = kCollapsedEventPopIn;\n                }\n                e.eid = event.eid;\n                if(event.type == kCollapsedEventPart || event.type == kCollapsedEventQuit)\n                    e.msg = event.msg;\n                [e copyModes:event];\n            } else {\n                [self->_data addObject:event];\n            }\n        } else {\n            if(event.type == kCollapsedEventNickChange) {\n                for(CollapsedEvent *e1 in _data) {\n                    if(e1.type == kCollapsedEventNickChange && [[e1.nick lowercaseString] isEqualToString:[event.oldNick lowercaseString]]) {\n                        if([[e1.oldNick lowercaseString] isEqualToString:[event.nick lowercaseString]]) {\n                            [self->_data removeObject:e1];\n                        } else {\n                            e1.eid = event.eid;\n                            e1.nick = event.nick;\n                        }\n                        return;\n                    }\n                    if((e1.type == kCollapsedEventJoin || e1.type == kCollapsedEventPopOut) && [[e1.nick lowercaseString] isEqualToString:[event.oldNick lowercaseString]]) {\n                        e1.eid = event.eid;\n                        e1.oldNick = event.oldNick;\n                        e1.nick = event.nick;\n                        for(CollapsedEvent *e2 in _data) {\n                            if((e2.type == kCollapsedEventQuit || e2.type == kCollapsedEventPart) && [[e2.nick lowercaseString] isEqualToString:[event.nick lowercaseString]]) {\n                                e1.type = kCollapsedEventPopOut;\n                                [self->_data removeObject:e2];\n                                break;\n                            }\n                        }\n                        return;\n                    }\n                    if((e1.type == kCollapsedEventQuit || e1.type == kCollapsedEventPart) && [[e1.nick lowercaseString] isEqualToString:[event.oldNick lowercaseString]]) {\n                        e1.eid = event.eid;\n                        e1.type = kCollapsedEventPopOut;\n                        for(CollapsedEvent *e2 in _data) {\n                            if(e2.type == kCollapsedEventJoin && [[e2.nick lowercaseString] isEqualToString:[event.oldNick lowercaseString]]) {\n                                [self->_data removeObject:e2];\n                                break;\n                            }\n                        }\n                        return;\n                    }\n                }\n                [self->_data addObject:event];\n            } else if(event.type == kCollapsedEventConnectionStatus) {\n                for(CollapsedEvent *e1 in _data) {\n                    if([e1.msg isEqualToString:event.msg]) {\n                        e1.count++;\n                        return;\n                    }\n                }\n                [self->_data addObject:event];\n            } else {\n                [self->_data addObject:event];\n            }\n        }\n    }\n}\n-(BOOL)addEvent:(Event *)event {\n    @synchronized(self->_data) {\n        CollapsedEvent *c;\n        if([event.type hasSuffix:@\"user_channel_mode\"]) {\n            c = [self findEvent:event.nick chan:event.chan];\n            if(!c) {\n                c = [[CollapsedEvent alloc] init];\n                c.type = kCollapsedEventMode;\n                c.eid = event.eid;\n            }\n            if(event.ops) {\n                for(NSDictionary *op in [event.ops objectForKey:@\"add\"]) {\n                    if(![c addMode:[op objectForKey:@\"mode\"] server:self->_server])\n                        return NO;\n                    if(c.type == kCollapsedEventMode) {\n                        c.nick = [op objectForKey:@\"param\"];\n                        if(event.from.length) {\n                            c.fromNick = event.from;\n                            c.fromMode = event.fromMode;\n                        } else if(event.server.length) {\n                            c.fromNick = event.server;\n                            c.fromMode = @\"__the_server__\";\n                        }\n                        c.hostname = event.hostmask;\n                        c.targetMode = event.targetMode;\n                        c.chan = event.chan;\n                        [self addCollapsedEvent:c];\n                    } else {\n                        c.fromMode = event.targetMode;\n                    }\n                }\n                for(NSDictionary *op in [event.ops objectForKey:@\"remove\"]) {\n                    if(![c removeMode:[op objectForKey:@\"mode\"] server:self->_server])\n                        return NO;\n                    if(c.type == kCollapsedEventMode) {\n                        c.nick = [op objectForKey:@\"param\"];\n                        if(event.from.length) {\n                            c.fromNick = event.from;\n                            c.fromMode = event.fromMode;\n                        } else if(event.server.length) {\n                            c.fromNick = event.server;\n                            c.fromMode = @\"__the_server__\";\n                        }\n                        c.hostname = event.hostmask;\n                        c.targetMode = event.targetMode;\n                        c.chan = event.chan;\n                        [self addCollapsedEvent:c];\n                    } else {\n                        c.fromMode = event.targetMode;\n                    }\n                }\n            }\n        } else {\n            c = [[CollapsedEvent alloc] init];\n            c.eid = event.eid;\n            if(event.from.length)\n                c.nick = event.from;\n            else\n                c.nick = event.nick;\n            c.hostname = event.hostmask;\n            c.fromMode = event.fromMode;\n            c.chan = event.chan;\n            c.count = 1;\n            if([event.type hasSuffix:@\"joined_channel\"]) {\n                c.type = kCollapsedEventJoin;\n            } else if([event.type hasSuffix:@\"parted_channel\"]) {\n                c.type = kCollapsedEventPart;\n                c.msg = event.msg;\n            } else if([event.type hasSuffix:@\"quit\"]) {\n                c.type = kCollapsedEventQuit;\n                c.msg = event.msg;\n                if([[NSPredicate predicateWithFormat:@\"SELF MATCHES %@\", @\"^(?:[^\\\\s:\\\\/.]+\\\\.)+[a-z]{2,} (?:[^\\\\s:\\\\/.]+\\\\.)+[a-z]{2,}$\"] evaluateWithObject:event.msg]) {\n                    NSArray *parts = [event.msg componentsSeparatedByString:@\" \"];\n                    if(parts.count > 1 && ![[parts objectAtIndex:0] isEqualToString:[parts objectAtIndex:1]]) {\n                        BOOL match = NO;\n                        for(CollapsedEvent *ce in _data) {\n                            if(ce.type == kCollapsedEventNetSplit && [ce.msg isEqualToString:event.msg])\n                                match = YES;\n                        }\n                        if(!match && _data.count > 0) {\n                            CollapsedEvent *e = [[CollapsedEvent alloc] init];\n                            e.type = kCollapsedEventNetSplit;\n                            e.msg = event.msg;\n                            [self->_data addObject:e];\n                        }\n                    }\n                }\n            } else if([event.type hasSuffix:@\"nickchange\"]) {\n                c.type = kCollapsedEventNickChange;\n                c.oldNick = event.oldNick;\n            } else if([event.type isEqualToString:@\"socket_closed\"] || [event.type isEqualToString:@\"connecting_failed\"] || [event.type isEqualToString:@\"connecting_cancelled\"]) {\n                c.type = kCollapsedEventConnectionStatus;\n                c.msg = event.msg;\n            } else {\n                return NO;\n            }\n            [self addCollapsedEvent:c];\n        }\n        return YES;\n    }\n}\n-(NSString *)was:(CollapsedEvent *)e {\n    NSString *output = @\"\";\n    NSString *modes = [e modes:NO mode_modes:self->_mode_modes];\n    \n    if(e.oldNick && e.type != kCollapsedEventMode && e.type != kCollapsedEventNickChange)\n        output = [NSString stringWithFormat:@\"was %@\", e.oldNick];\n    if(modes.length) {\n        if(output.length > 0)\n            output = [output stringByAppendingString:@\"; \"];\n        output = [output stringByAppendingString:modes];\n    }\n    \n    if(output.length)\n        output = [NSString stringWithFormat:@\" (%c%@%@%c)\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, output, CLEAR];\n    \n    return output;\n}\n-(NSString *)collapse {\n    @synchronized(self->_data) {\n        NSString *output;\n        \n        if(self->_data.count == 0)\n            return nil;\n        \n        if(self->_data.count == 1 && [[self->_data objectAtIndex:0] modeCount] < ((((CollapsedEvent*)[self->_data objectAtIndex:0]).type == kCollapsedEventMode)?2:1)) {\n            CollapsedEvent *e = [self->_data objectAtIndex:0];\n            switch(e.type) {\n                case kCollapsedEventNetSplit:\n                    output = [e.msg stringByReplacingOccurrencesOfString:@\" \" withString:@\" ↮ \"];\n                    break;\n                case kCollapsedEventMode:\n                    output = [NSString stringWithFormat:@\"%c%@%@%c %c%@was %@\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, [self formatNick:e.nick mode:e.targetMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], CLEAR, COLOR_RGB, [UIColor messageTextColor].toHexString, [e modes:YES mode_modes:self->_mode_modes]];\n                    if(e.fromNick) {\n                        if([e.fromMode isEqualToString:@\"__the_server__\"])\n                            output = [output stringByAppendingFormat:@\" by the server %c%@%@%c\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, e.fromNick, CLEAR];\n                        else\n                            output = [output stringByAppendingFormat:@\" by%c %@\", CLEAR, [self formatNick:e.fromNick mode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil]];\n                    }\n                    break;\n                case kCollapsedEventJoin:\n                    if(self->_showChan)\n                        output = [NSString stringWithFormat:@\"%c%@→\\U0000FE0E\\u00a0%@%c%@ joined %@\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, [self formatNick:e.nick mode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], CLEAR, [self was:e], e.chan];\n                    else\n                        output = [NSString stringWithFormat:@\"%c%@→\\U0000FE0E\\u00a0%@%c%@ joined\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, [self formatNick:e.nick mode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], CLEAR, [self was:e]];\n                    if(!_server.isSlack)\n                        output = [output stringByAppendingFormat:@\" (%@)\", self->_noColor ? e.hostname.stripIRCColors : e.hostname];\n                    break;\n                case kCollapsedEventPart:\n                    if(self->_showChan)\n                        output = [NSString stringWithFormat:@\"%c%@←\\U0000FE0E\\u00a0%@%c%@ left %@\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, [self formatNick:e.nick mode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], CLEAR, [self was:e], e.chan];\n                    else\n                        output = [NSString stringWithFormat:@\"%c%@←\\U0000FE0E\\u00a0%@%c%@ left\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, [self formatNick:e.nick mode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], CLEAR, [self was:e]];\n                    if(!_server.isSlack)\n                        output = [output stringByAppendingFormat:@\" (%@)\", self->_noColor ? e.hostname.stripIRCColors : e.hostname];\n                    if(e.msg.length > 0)\n                        output = [output stringByAppendingFormat:@\": %@\", self->_noColor ? e.msg.stripIRCColors : e.msg];\n                    break;\n                case kCollapsedEventQuit:\n                    output = [NSString stringWithFormat:@\"%c%@⇐\\U0000FE0E\\u00a0%@%c%@ quit\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, [self formatNick:e.nick mode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], CLEAR, [self was:e]];\n                    if(!_server.isSlack && e.hostname.length > 0)\n                        output = [output stringByAppendingFormat:@\" (%@)\", self->_noColor ? e.hostname.stripIRCColors : e.hostname];\n                    if(e.msg.length > 0)\n                        output = [output stringByAppendingFormat:@\": %@\", self->_noColor ? e.msg.stripIRCColors : e.msg];\n                    break;\n                case kCollapsedEventNickChange:\n                    output = [NSString stringWithFormat:@\"%@ %c%@→\\U0000FE0E\\u00a0%@%c\", e.oldNick, COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, [self formatNick:e.nick mode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], CLEAR];\n                    break;\n                case kCollapsedEventPopIn:\n                    output = [NSString stringWithFormat:@\"%c%@↔\\U0000FE0E\\u00a0%@%c%@ popped in\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, [self formatNick:e.nick mode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], CLEAR, [self was:e]];\n                    if(self->_showChan)\n                        output = [output stringByAppendingFormat:@\" %@\", e.chan];\n                    break;\n                case kCollapsedEventPopOut:\n                    output = [NSString stringWithFormat:@\"%c%@↔\\U0000FE0E\\u00a0%@%c%@ nipped out\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, [self formatNick:e.nick mode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], CLEAR, [self was:e]];\n                    if(self->_showChan)\n                        output = [output stringByAppendingFormat:@\" %@\", e.chan];\n                    break;\n                case kCollapsedEventConnectionStatus:\n                    output = e.msg;\n                    if(e.count > 1)\n                        output = [output stringByAppendingFormat:@\" (x%i)\", e.count];\n                    break;\n            }\n        } else {\n            [self->_data sortUsingSelector:@selector(compare:)];\n            NSEnumerator *i = [self->_data objectEnumerator];\n            CollapsedEvent *last = nil;\n            CollapsedEvent *next = [i nextObject];\n            CollapsedEvent *e;\n            int groupcount = 0;\n            NSMutableString *message = [[NSMutableString alloc] init];\n            \n            while(next) {\n                e = next;\n                next = [i nextObject];\n                \n                if(message.length > 0 && e.type < kCollapsedEventNickChange && ((next == nil || next.type != e.type) && last != nil && last.type == e.type)) {\n\t\t\t\t\tif(groupcount == 1) {\n                        [message deleteCharactersInRange:NSMakeRange(message.length - 2, 2)];\n                        [message appendString:@\" \"];\n                    }\n                    [message appendString:@\"and \"];\n\t\t\t\t}\n                \n                if(last == nil || last.type != e.type) {\n                    switch(e.type) {\n                        case kCollapsedEventMode:\n                            if(message.length)\n                                [message appendString:@\"•\\u00a0\"];\n                            [message appendFormat:@\"%c%@mode:\\u00a0%c\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, CLEAR];\n                            break;\n                        case kCollapsedEventJoin:\n                            [message appendFormat:@\"%c%@→\\U0000FE0E\\u00a0%c\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, CLEAR];\n                            break;\n                        case kCollapsedEventPart:\n                            [message appendFormat:@\"%c%@←\\U0000FE0E\\u00a0%c\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, CLEAR];\n                            break;\n                        case kCollapsedEventQuit:\n                            [message appendFormat:@\"%c%@⇐\\U0000FE0E\\u00a0%c\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, CLEAR];\n                            break;\n                        case kCollapsedEventNickChange:\n                            if(message.length)\n                                [message appendString:@\"•\\u00a0\"];\n                            break;\n                        case kCollapsedEventPopIn:\n                        case kCollapsedEventPopOut:\n                            [message appendFormat:@\"%c%@↔\\U0000FE0E\\u00a0%c\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, CLEAR];\n                            break;\n                        default:\n                            break;\n                    }\n                }\n                \n                if(e.type == kCollapsedEventNickChange) {\n                    [message appendFormat:@\"%@ %c%@→\\U0000FE0E\\u00a0%@%c\", e.oldNick, COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, [self formatNick:e.nick mode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], CLEAR];\n                    [message appendString:[self was:e]];\n                } else if(e.type == kCollapsedEventNetSplit) {\n                    [message appendString:[e.msg stringByReplacingOccurrencesOfString:@\" \" withString:@\" ↮\\U0000FE0E\\u00a0\"]];\n                } else if(e.type == kCollapsedEventConnectionStatus) {\n                    if(e.msg) {\n                        [message appendString:e.msg];\n                        if(e.count > 1)\n                            [message appendFormat:@\" (x%i)\", e.count];\n                    }\n                } else if(!_showChan) {\n                    [message appendString:[self formatNick:e.nick mode:(e.type == kCollapsedEventMode)?e.targetMode:e.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil]];\n                    [message appendString:[self was:e]];\n                }\n                \n                if((next == nil || next.type != e.type) && !_showChan) {\n                    switch(e.type) {\n                        case kCollapsedEventJoin:\n                            [message appendString:@\" joined\"];\n                            break;\n                        case kCollapsedEventPart:\n                            [message appendString:@\" left\"];\n                            break;\n                        case kCollapsedEventQuit:\n                            [message appendString:@\" quit\"];\n                            break;\n                        case kCollapsedEventPopIn:\n                            [message appendString:@\" popped in\"];\n                            break;\n                        case kCollapsedEventPopOut:\n                            [message appendString:@\" nipped out\"];\n                            break;\n                        default:\n                            break;\n                    }\n                } else if(self->_showChan && e.type != kCollapsedEventNetSplit && e.type != kCollapsedEventConnectionStatus && e.type != kCollapsedEventNickChange) {\n                    if(groupcount == 0) {\n                        [message appendString:[self formatNick:e.nick mode:(e.type == kCollapsedEventMode)?e.targetMode:e.fromMode colorize:NO displayName:nil]];\n                        [message appendString:[self was:e]];\n                        switch(e.type) {\n                            case kCollapsedEventJoin:\n                                [message appendString:@\" joined \"];\n                                break;\n                            case kCollapsedEventPart:\n                                [message appendString:@\" left \"];\n                                break;\n                            case kCollapsedEventQuit:\n                                [message appendString:@\" quit\"];\n                                break;\n                            case kCollapsedEventPopIn:\n                                [message appendString:@\" popped in \"];\n                                break;\n                            case kCollapsedEventPopOut:\n                                [message appendString:@\" nipped out \"];\n                                break;\n                            default:\n                                break;\n                        }\n                    }\n                    if(e.type != kCollapsedEventQuit && e.chan)\n                        [message appendString:e.chan];\n                }\n                \n                if(next != nil && next.type == e.type && message.length > 0) {\n                    [message appendString:@\", \"];\n                    groupcount++;\n                } else if(next != nil) {\n                    [message appendString:@\" \"];\n                    groupcount = 0;\n                }\n                \n                last = e;\n            }\n            output = message;\n        }\n        \n        return output;\n    }\n}\n\n-(NSUInteger)count {\n    return _data.count;\n}\n\n-(NSString *)formatNick:(NSString *)nick mode:(NSString *)mode colorize:(BOOL)colorize displayName:(NSString *)displayName {\n    return [self formatNick:nick mode:mode colorize:colorize defaultColor:nil bold:YES displayName:displayName];\n}\n-(NSString *)formatNick:(NSString *)nick mode:(NSString *)mode colorize:(BOOL)colorize defaultColor:(NSString *)color displayName:(NSString *)displayName {\n    return [self formatNick:nick mode:mode colorize:colorize defaultColor:color bold:YES displayName:displayName];\n}\n-(NSString *)formatNick:(NSString *)nick mode:(NSString *)mode colorize:(BOOL)colorize defaultColor:(NSString *)color bold:(BOOL)bold displayName:(NSString *)displayName {\n    if(!displayName)\n        displayName = nick;\n    \n    NSDictionary *PREFIX = nil;\n    if(self->_server)\n        PREFIX = self->_server.PREFIX;\n    \n    if(!PREFIX || PREFIX.count == 0) {\n        PREFIX = @{_server?_server.MODE_OPER:@\"y\":@\"!\",\n                   self->_server?_server.MODE_OWNER:@\"q\":@\"~\",\n                   self->_server?_server.MODE_ADMIN:@\"a\":@\"&\",\n                   self->_server?_server.MODE_OP:@\"o\":@\"@\",\n                   self->_server?_server.MODE_HALFOP:@\"h\":@\"%\",\n                   self->_server?_server.MODE_VOICED:@\"v\":@\"+\"};\n    }\n    \n    NSDictionary *mode_colors = @{\n        self->_server?_server.MODE_OPER.lowercaseString:@\"y\":@\"E7AA00\",\n        self->_server?_server.MODE_OWNER.lowercaseString:@\"q\":@\"E7AA00\",\n        self->_server?_server.MODE_ADMIN.lowercaseString:@\"a\":@\"6500A5\",\n        self->_server?_server.MODE_OP.lowercaseString:@\"o\":@\"BA1719\",\n        self->_server?_server.MODE_HALFOP.lowercaseString:@\"h\":@\"B55900\",\n        self->_server?_server.MODE_VOICED.lowercaseString:@\"v\":@\"25B100\"\n    };\n    \n    NSMutableString *output = [[NSMutableString alloc] initWithCapacity:100];\n    [output appendFormat:@\"%c\", BOLD];\n    BOOL showSymbol = [[NetworkConnection sharedInstance] prefs] && [[[[NetworkConnection sharedInstance] prefs] objectForKey:@\"mode-showsymbol\"] boolValue];\n    \n    if(colorize && nick) {\n        color = [UIColor colorForNick:nick];\n    }\n    \n    if(mode.length) {\n        if([mode rangeOfString:self->_server?_server.MODE_OPER:@\"Y\"].location != NSNotFound)\n            mode = self->_server?_server.MODE_OPER:@\"Y\";\n        else if([mode rangeOfString:self->_server?_server.MODE_OPER.lowercaseString:@\"y\"].location != NSNotFound)\n            mode = self->_server?_server.MODE_OPER.lowercaseString:@\"y\";\n        else if([mode rangeOfString:self->_server?_server.MODE_OWNER:@\"q\"].location != NSNotFound)\n            mode = self->_server?_server.MODE_OWNER:@\"q\";\n        else if([mode rangeOfString:self->_server?_server.MODE_ADMIN:@\"a\"].location != NSNotFound)\n            mode = self->_server?_server.MODE_ADMIN:@\"a\";\n        else if([mode rangeOfString:self->_server?_server.MODE_OP:@\"o\"].location != NSNotFound)\n            mode = self->_server?_server.MODE_OP:@\"o\";\n        else if([mode rangeOfString:self->_server?_server.MODE_HALFOP:@\"h\"].location != NSNotFound)\n            mode = self->_server?_server.MODE_HALFOP:@\"h\";\n        else if([mode rangeOfString:self->_server?_server.MODE_VOICED:@\"v\"].location != NSNotFound)\n            mode = self->_server?_server.MODE_VOICED:@\"v\";\n        else\n            mode = [mode substringToIndex:1];\n        \n        if(showSymbol) {\n            if([PREFIX objectForKey:mode]) {\n                if([mode_colors objectForKey:mode.lowercaseString]) {\n                    [output appendFormat:@\"%c%@%@%c\\u202f\", COLOR_RGB, [mode_colors objectForKey:mode.lowercaseString], [PREFIX objectForKey:mode], COLOR_RGB];\n                } else {\n                    [output appendFormat:@\"%@\\u202f\", [PREFIX objectForKey:mode]];\n                }\n            }\n        } else {\n            if([mode_colors objectForKey:mode.lowercaseString]) {\n                [output appendFormat:@\"%c%@•%c\\u202f\", COLOR_RGB, [mode_colors objectForKey:mode.lowercaseString], COLOR_RGB];\n            } else {\n                [output appendString:@\"•\\u202f\"];\n            }\n        }\n    }\n\n    if(!bold)\n        [output appendFormat:@\"%c\", BOLD];\n    \n    if(color) {\n        [output appendFormat:@\"%c%@%@%c\", COLOR_RGB, color, displayName, COLOR_RGB];\n    } else {\n        [output appendFormat:@\"%@\", displayName];\n    }\n    \n    if(bold)\n        [output appendFormat:@\"%c\", BOLD];\n\n    return output;\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ColorFormatter.h",
    "content": "//\n//  ColorFormatter.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <Foundation/Foundation.h>\n#import \"ServersDataSource.h\"\n\n#define BOLD 0x02\n#define COLOR_MIRC 0x03\n#define COLOR_RGB 0x04\n#define MONO 0x11\n#define CLEAR 0x0f\n#define REVERSE 0x16\n#define ITALICS 0x1d\n#define STRIKETHROUGH 0x1e\n#define UNDERLINE 0x1f\n\n#define FONT_MIN 10\n#define FONT_MAX 24\n#define FONT_SIZE MIN(FONT_MAX, MAX(FONT_MIN, ceilf([[NSUserDefaults standardUserDefaults] floatForKey:@\"fontSize\"])))\n#define MESSAGE_LINE_SPACING 2\n#define MESSAGE_LINE_PADDING 4\n\n@interface ColorFormatter : NSObject\n+(NSRegularExpression*)email;\n+(NSRegularExpression*)ircChannelRegexForServer:(Server *)s;\n+(NSAttributedString *)format:(NSString *)input defaultColor:(UIColor *)color mono:(BOOL)mono linkify:(BOOL)linkify server:(Server *)server links:(NSArray **)links;\n+(NSAttributedString *)format:(NSString *)input defaultColor:(UIColor *)color mono:(BOOL)mono linkify:(BOOL)linkify server:(Server *)server links:(NSArray **)links largeEmoji:(BOOL)largeEmoji mentions:(NSDictionary *)mentions colorizeMentions:(BOOL)colorizeMentions mentionOffset:(NSInteger)mentionOffset mentionData:(NSDictionary *)mentionData;\n+(NSAttributedString *)format:(NSString *)input defaultColor:(UIColor *)color mono:(BOOL)mono linkify:(BOOL)linkify server:(Server *)server links:(NSArray **)links largeEmoji:(BOOL)largeEmoji mentions:(NSDictionary *)mentions colorizeMentions:(BOOL)colorizeMentions mentionOffset:(NSInteger)mentionOffset mentionData:(NSDictionary *)mentionData stripColors:(BOOL)stripColors;\n+(BOOL)shouldClearFontCache;\n+(void)clearFontCache;\n+(void)loadFonts;\n+(UIFont *)timestampFont;\n+(UIFont *)monoTimestampFont;\n+(UIFont *)awesomeFont;\n+(UIFont *)messageFont:(BOOL)mono;\n+(UIFont *)replyThreadFont;\n+(void)emojify:(NSMutableString *)text;\n+(NSString *)toIRC:(NSAttributedString *)string;\n+(NSAttributedString *)stripUnsupportedAttributes:(NSAttributedString *)input fontSize:(CGFloat)fontSize;\n+(NSArray *)webURLs:(NSString *)string;\n@end\n\n@interface NSString (ColorFormatter)\n-(NSString *)stripIRCFormatting;\n-(NSString *)stripIRCColors;\n-(NSString *)insertCodeSpans;\n-(BOOL)isBlockQuote;\n-(BOOL)isEmojiOnly;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ColorFormatter.m",
    "content": "//\n//  ColorFormatter.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <CoreText/CoreText.h>\n#import \"ColorFormatter.h\"\n#import \"LinkTextView.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"NSURL+IDN.h\"\n#import \"NetworkConnection.h\"\n\nid Courier = NULL, CourierBold, CourierOblique,CourierBoldOblique;\nid Helvetica, HelveticaBold, HelveticaOblique,HelveticaBoldOblique;\nid arrowFont, chalkboardFont, markerFont, awesomeFont, largeEmojiFont, replyThreadFont;\nUIFont *timestampFont, *monoTimestampFont;\nNSDictionary *emojiMap;\nNSDictionary *quotes;\nfloat ColorFormatterCachedFontSize = 0.0f;\n\nextern BOOL __compact;\n\n@implementation ColorFormatter\n\n+(BOOL)shouldClearFontCache {\n    return ColorFormatterCachedFontSize != FONT_SIZE;\n}\n\n+(void)clearFontCache {\n    CLS_LOG(@\"Clearing font cache\");\n    Courier = CourierBold = CourierBoldOblique = CourierOblique = Helvetica = HelveticaBold = HelveticaBoldOblique = HelveticaOblique = chalkboardFont = markerFont = arrowFont = NULL;\n    timestampFont = monoTimestampFont = awesomeFont = replyThreadFont = NULL;\n}\n\n+(UIFont *)timestampFont {\n    @synchronized (self) {\n        if(!timestampFont) {\n            timestampFont = [UIFont systemFontOfSize:FONT_SIZE - 2];\n        }\n        return timestampFont;\n    }\n}\n\n+(UIFont *)monoTimestampFont {\n    @synchronized (self) {\n        if(!monoTimestampFont) {\n            monoTimestampFont = [UIFont fontWithName:@\"Courier\" size:FONT_SIZE - 2];\n        }\n        return monoTimestampFont;\n    }\n}\n\n+(UIFont *)awesomeFont {\n    @synchronized (self) {\n        if(!awesomeFont) {\n            awesomeFont = [UIFont fontWithName:@\"FontAwesome\" size:FONT_SIZE];\n        }\n        return awesomeFont;\n    }\n}\n\n+(UIFont *)replyThreadFont {\n    @synchronized (self) {\n        if(!replyThreadFont) {\n            replyThreadFont = [UIFont fontWithName:@\"FontAwesome\" size:12];\n        }\n        return replyThreadFont;\n    }\n}\n\n+(UIFont *)messageFont:(BOOL)mono {\n    return mono?Courier:Helvetica;\n}\n\n+(NSRegularExpression *)emoji {\n    @synchronized (self) {\n        if(!emojiMap)\n            emojiMap = @{\n                @\"umbrella_with_rain_drops\":@\"☔\",\n                @\"coffee\":@\"☕\",\n                @\"aries\":@\"♈\",\n                @\"taurus\":@\"♉\",\n                @\"sagittarius\":@\"♐\",\n                @\"capricorn\":@\"♑\",\n                @\"aquarius\":@\"♒\",\n                @\"pisces\":@\"♓\",\n                @\"anchor\":@\"⚓\",\n                @\"white_check_mark\":@\"✅\",\n                @\"sparkles\":@\"✨\",\n                @\"question\":@\"❓\",\n                @\"grey_question\":@\"❔\",\n                @\"grey_exclamation\":@\"❕\",\n                @\"exclamation\":@\"❗\",\n                @\"heavy_exclamation_mark\":@\"❗\",\n                @\"heavy_plus_sign\":@\"➕\",\n                @\"heavy_minus_sign\":@\"➖\",\n                @\"heavy_division_sign\":@\"➗\",\n                @\"hash\":@\"#️⃣\",\n                @\"keycap_star\":@\"*️⃣\",\n                @\"zero\":@\"0️⃣\",\n                @\"one\":@\"1️⃣\",\n                @\"two\":@\"2️⃣\",\n                @\"three\":@\"3️⃣\",\n                @\"four\":@\"4️⃣\",\n                @\"five\":@\"5️⃣\",\n                @\"six\":@\"6️⃣\",\n                @\"seven\":@\"7️⃣\",\n                @\"eight\":@\"8️⃣\",\n                @\"nine\":@\"9️⃣\",\n                @\"copyright\":@\"©️\",\n                @\"registered\":@\"®️\",\n                @\"mahjong\":@\"🀄\",\n                @\"black_joker\":@\"🃏\",\n                @\"a\":@\"🅰️\",\n                @\"b\":@\"🅱️\",\n                @\"o2\":@\"🅾️\",\n                @\"parking\":@\"🅿️\",\n                @\"ab\":@\"🆎\",\n                @\"cl\":@\"🆑\",\n                @\"cool\":@\"🆒\",\n                @\"free\":@\"🆓\",\n                @\"id\":@\"🆔\",\n                @\"new\":@\"🆕\",\n                @\"ng\":@\"🆖\",\n                @\"ok\":@\"🆗\",\n                @\"sos\":@\"🆘\",\n                @\"up\":@\"🆙\",\n                @\"vs\":@\"🆚\",\n                @\"flag-ac\":@\"🇦🇨\",\n                @\"flag-ad\":@\"🇦🇩\",\n                @\"flag-ae\":@\"🇦🇪\",\n                @\"flag-af\":@\"🇦🇫\",\n                @\"flag-ag\":@\"🇦🇬\",\n                @\"flag-ai\":@\"🇦🇮\",\n                @\"flag-al\":@\"🇦🇱\",\n                @\"flag-am\":@\"🇦🇲\",\n                @\"flag-ao\":@\"🇦🇴\",\n                @\"flag-aq\":@\"🇦🇶\",\n                @\"flag-ar\":@\"🇦🇷\",\n                @\"flag-as\":@\"🇦🇸\",\n                @\"flag-at\":@\"🇦🇹\",\n                @\"flag-au\":@\"🇦🇺\",\n                @\"flag-aw\":@\"🇦🇼\",\n                @\"flag-ax\":@\"🇦🇽\",\n                @\"flag-az\":@\"🇦🇿\",\n                @\"flag-ba\":@\"🇧🇦\",\n                @\"flag-bb\":@\"🇧🇧\",\n                @\"flag-bd\":@\"🇧🇩\",\n                @\"flag-be\":@\"🇧🇪\",\n                @\"flag-bf\":@\"🇧🇫\",\n                @\"flag-bg\":@\"🇧🇬\",\n                @\"flag-bh\":@\"🇧🇭\",\n                @\"flag-bi\":@\"🇧🇮\",\n                @\"flag-bj\":@\"🇧🇯\",\n                @\"flag-bl\":@\"🇧🇱\",\n                @\"flag-bm\":@\"🇧🇲\",\n                @\"flag-bn\":@\"🇧🇳\",\n                @\"flag-bo\":@\"🇧🇴\",\n                @\"flag-bq\":@\"🇧🇶\",\n                @\"flag-br\":@\"🇧🇷\",\n                @\"flag-bs\":@\"🇧🇸\",\n                @\"flag-bt\":@\"🇧🇹\",\n                @\"flag-bv\":@\"🇧🇻\",\n                @\"flag-bw\":@\"🇧🇼\",\n                @\"flag-by\":@\"🇧🇾\",\n                @\"flag-bz\":@\"🇧🇿\",\n                @\"flag-ca\":@\"🇨🇦\",\n                @\"flag-cc\":@\"🇨🇨\",\n                @\"flag-cd\":@\"🇨🇩\",\n                @\"flag-cf\":@\"🇨🇫\",\n                @\"flag-cg\":@\"🇨🇬\",\n                @\"flag-ch\":@\"🇨🇭\",\n                @\"flag-ci\":@\"🇨🇮\",\n                @\"flag-ck\":@\"🇨🇰\",\n                @\"flag-cl\":@\"🇨🇱\",\n                @\"flag-cm\":@\"🇨🇲\",\n                @\"cn\":@\"🇨🇳\",\n                @\"flag-cn\":@\"🇨🇳\",\n                @\"flag-co\":@\"🇨🇴\",\n                @\"flag-cp\":@\"🇨🇵\",\n                @\"flag-sark\":@\"🇨🇶\",\n                @\"flag-cr\":@\"🇨🇷\",\n                @\"flag-cu\":@\"🇨🇺\",\n                @\"flag-cv\":@\"🇨🇻\",\n                @\"flag-cw\":@\"🇨🇼\",\n                @\"flag-cx\":@\"🇨🇽\",\n                @\"flag-cy\":@\"🇨🇾\",\n                @\"flag-cz\":@\"🇨🇿\",\n                @\"de\":@\"🇩🇪\",\n                @\"flag-de\":@\"🇩🇪\",\n                @\"flag-dg\":@\"🇩🇬\",\n                @\"flag-dj\":@\"🇩🇯\",\n                @\"flag-dk\":@\"🇩🇰\",\n                @\"flag-dm\":@\"🇩🇲\",\n                @\"flag-do\":@\"🇩🇴\",\n                @\"flag-dz\":@\"🇩🇿\",\n                @\"flag-ea\":@\"🇪🇦\",\n                @\"flag-ec\":@\"🇪🇨\",\n                @\"flag-ee\":@\"🇪🇪\",\n                @\"flag-eg\":@\"🇪🇬\",\n                @\"flag-eh\":@\"🇪🇭\",\n                @\"flag-er\":@\"🇪🇷\",\n                @\"es\":@\"🇪🇸\",\n                @\"flag-es\":@\"🇪🇸\",\n                @\"flag-et\":@\"🇪🇹\",\n                @\"flag-eu\":@\"🇪🇺\",\n                @\"flag-fi\":@\"🇫🇮\",\n                @\"flag-fj\":@\"🇫🇯\",\n                @\"flag-fk\":@\"🇫🇰\",\n                @\"flag-fm\":@\"🇫🇲\",\n                @\"flag-fo\":@\"🇫🇴\",\n                @\"fr\":@\"🇫🇷\",\n                @\"flag-fr\":@\"🇫🇷\",\n                @\"flag-ga\":@\"🇬🇦\",\n                @\"gb\":@\"🇬🇧\",\n                @\"uk\":@\"🇬🇧\",\n                @\"flag-gb\":@\"🇬🇧\",\n                @\"flag-gd\":@\"🇬🇩\",\n                @\"flag-ge\":@\"🇬🇪\",\n                @\"flag-gf\":@\"🇬🇫\",\n                @\"flag-gg\":@\"🇬🇬\",\n                @\"flag-gh\":@\"🇬🇭\",\n                @\"flag-gi\":@\"🇬🇮\",\n                @\"flag-gl\":@\"🇬🇱\",\n                @\"flag-gm\":@\"🇬🇲\",\n                @\"flag-gn\":@\"🇬🇳\",\n                @\"flag-gp\":@\"🇬🇵\",\n                @\"flag-gq\":@\"🇬🇶\",\n                @\"flag-gr\":@\"🇬🇷\",\n                @\"flag-gs\":@\"🇬🇸\",\n                @\"flag-gt\":@\"🇬🇹\",\n                @\"flag-gu\":@\"🇬🇺\",\n                @\"flag-gw\":@\"🇬🇼\",\n                @\"flag-gy\":@\"🇬🇾\",\n                @\"flag-hk\":@\"🇭🇰\",\n                @\"flag-hm\":@\"🇭🇲\",\n                @\"flag-hn\":@\"🇭🇳\",\n                @\"flag-hr\":@\"🇭🇷\",\n                @\"flag-ht\":@\"🇭🇹\",\n                @\"flag-hu\":@\"🇭🇺\",\n                @\"flag-ic\":@\"🇮🇨\",\n                @\"flag-id\":@\"🇮🇩\",\n                @\"flag-ie\":@\"🇮🇪\",\n                @\"flag-il\":@\"🇮🇱\",\n                @\"flag-im\":@\"🇮🇲\",\n                @\"flag-in\":@\"🇮🇳\",\n                @\"flag-io\":@\"🇮🇴\",\n                @\"flag-iq\":@\"🇮🇶\",\n                @\"flag-ir\":@\"🇮🇷\",\n                @\"flag-is\":@\"🇮🇸\",\n                @\"it\":@\"🇮🇹\",\n                @\"flag-it\":@\"🇮🇹\",\n                @\"flag-je\":@\"🇯🇪\",\n                @\"flag-jm\":@\"🇯🇲\",\n                @\"flag-jo\":@\"🇯🇴\",\n                @\"jp\":@\"🇯🇵\",\n                @\"flag-jp\":@\"🇯🇵\",\n                @\"flag-ke\":@\"🇰🇪\",\n                @\"flag-kg\":@\"🇰🇬\",\n                @\"flag-kh\":@\"🇰🇭\",\n                @\"flag-ki\":@\"🇰🇮\",\n                @\"flag-km\":@\"🇰🇲\",\n                @\"flag-kn\":@\"🇰🇳\",\n                @\"flag-kp\":@\"🇰🇵\",\n                @\"kr\":@\"🇰🇷\",\n                @\"flag-kr\":@\"🇰🇷\",\n                @\"flag-kw\":@\"🇰🇼\",\n                @\"flag-ky\":@\"🇰🇾\",\n                @\"flag-kz\":@\"🇰🇿\",\n                @\"flag-la\":@\"🇱🇦\",\n                @\"flag-lb\":@\"🇱🇧\",\n                @\"flag-lc\":@\"🇱🇨\",\n                @\"flag-li\":@\"🇱🇮\",\n                @\"flag-lk\":@\"🇱🇰\",\n                @\"flag-lr\":@\"🇱🇷\",\n                @\"flag-ls\":@\"🇱🇸\",\n                @\"flag-lt\":@\"🇱🇹\",\n                @\"flag-lu\":@\"🇱🇺\",\n                @\"flag-lv\":@\"🇱🇻\",\n                @\"flag-ly\":@\"🇱🇾\",\n                @\"flag-ma\":@\"🇲🇦\",\n                @\"flag-mc\":@\"🇲🇨\",\n                @\"flag-md\":@\"🇲🇩\",\n                @\"flag-me\":@\"🇲🇪\",\n                @\"flag-mf\":@\"🇲🇫\",\n                @\"flag-mg\":@\"🇲🇬\",\n                @\"flag-mh\":@\"🇲🇭\",\n                @\"flag-mk\":@\"🇲🇰\",\n                @\"flag-ml\":@\"🇲🇱\",\n                @\"flag-mm\":@\"🇲🇲\",\n                @\"flag-mn\":@\"🇲🇳\",\n                @\"flag-mo\":@\"🇲🇴\",\n                @\"flag-mp\":@\"🇲🇵\",\n                @\"flag-mq\":@\"🇲🇶\",\n                @\"flag-mr\":@\"🇲🇷\",\n                @\"flag-ms\":@\"🇲🇸\",\n                @\"flag-mt\":@\"🇲🇹\",\n                @\"flag-mu\":@\"🇲🇺\",\n                @\"flag-mv\":@\"🇲🇻\",\n                @\"flag-mw\":@\"🇲🇼\",\n                @\"flag-mx\":@\"🇲🇽\",\n                @\"flag-my\":@\"🇲🇾\",\n                @\"flag-mz\":@\"🇲🇿\",\n                @\"flag-na\":@\"🇳🇦\",\n                @\"flag-nc\":@\"🇳🇨\",\n                @\"flag-ne\":@\"🇳🇪\",\n                @\"flag-nf\":@\"🇳🇫\",\n                @\"flag-ng\":@\"🇳🇬\",\n                @\"flag-ni\":@\"🇳🇮\",\n                @\"flag-nl\":@\"🇳🇱\",\n                @\"flag-no\":@\"🇳🇴\",\n                @\"flag-np\":@\"🇳🇵\",\n                @\"flag-nr\":@\"🇳🇷\",\n                @\"flag-nu\":@\"🇳🇺\",\n                @\"flag-nz\":@\"🇳🇿\",\n                @\"flag-om\":@\"🇴🇲\",\n                @\"flag-pa\":@\"🇵🇦\",\n                @\"flag-pe\":@\"🇵🇪\",\n                @\"flag-pf\":@\"🇵🇫\",\n                @\"flag-pg\":@\"🇵🇬\",\n                @\"flag-ph\":@\"🇵🇭\",\n                @\"flag-pk\":@\"🇵🇰\",\n                @\"flag-pl\":@\"🇵🇱\",\n                @\"flag-pm\":@\"🇵🇲\",\n                @\"flag-pn\":@\"🇵🇳\",\n                @\"flag-pr\":@\"🇵🇷\",\n                @\"flag-ps\":@\"🇵🇸\",\n                @\"flag-pt\":@\"🇵🇹\",\n                @\"flag-pw\":@\"🇵🇼\",\n                @\"flag-py\":@\"🇵🇾\",\n                @\"flag-qa\":@\"🇶🇦\",\n                @\"flag-re\":@\"🇷🇪\",\n                @\"flag-ro\":@\"🇷🇴\",\n                @\"flag-rs\":@\"🇷🇸\",\n                @\"ru\":@\"🇷🇺\",\n                @\"flag-ru\":@\"🇷🇺\",\n                @\"flag-rw\":@\"🇷🇼\",\n                @\"flag-sa\":@\"🇸🇦\",\n                @\"flag-sb\":@\"🇸🇧\",\n                @\"flag-sc\":@\"🇸🇨\",\n                @\"flag-sd\":@\"🇸🇩\",\n                @\"flag-se\":@\"🇸🇪\",\n                @\"flag-sg\":@\"🇸🇬\",\n                @\"flag-sh\":@\"🇸🇭\",\n                @\"flag-si\":@\"🇸🇮\",\n                @\"flag-sj\":@\"🇸🇯\",\n                @\"flag-sk\":@\"🇸🇰\",\n                @\"flag-sl\":@\"🇸🇱\",\n                @\"flag-sm\":@\"🇸🇲\",\n                @\"flag-sn\":@\"🇸🇳\",\n                @\"flag-so\":@\"🇸🇴\",\n                @\"flag-sr\":@\"🇸🇷\",\n                @\"flag-ss\":@\"🇸🇸\",\n                @\"flag-st\":@\"🇸🇹\",\n                @\"flag-sv\":@\"🇸🇻\",\n                @\"flag-sx\":@\"🇸🇽\",\n                @\"flag-sy\":@\"🇸🇾\",\n                @\"flag-sz\":@\"🇸🇿\",\n                @\"flag-ta\":@\"🇹🇦\",\n                @\"flag-tc\":@\"🇹🇨\",\n                @\"flag-td\":@\"🇹🇩\",\n                @\"flag-tf\":@\"🇹🇫\",\n                @\"flag-tg\":@\"🇹🇬\",\n                @\"flag-th\":@\"🇹🇭\",\n                @\"flag-tj\":@\"🇹🇯\",\n                @\"flag-tk\":@\"🇹🇰\",\n                @\"flag-tl\":@\"🇹🇱\",\n                @\"flag-tm\":@\"🇹🇲\",\n                @\"flag-tn\":@\"🇹🇳\",\n                @\"flag-to\":@\"🇹🇴\",\n                @\"flag-tr\":@\"🇹🇷\",\n                @\"flag-tt\":@\"🇹🇹\",\n                @\"flag-tv\":@\"🇹🇻\",\n                @\"flag-tw\":@\"🇹🇼\",\n                @\"flag-tz\":@\"🇹🇿\",\n                @\"flag-ua\":@\"🇺🇦\",\n                @\"flag-ug\":@\"🇺🇬\",\n                @\"flag-um\":@\"🇺🇲\",\n                @\"flag-un\":@\"🇺🇳\",\n                @\"us\":@\"🇺🇸\",\n                @\"flag-us\":@\"🇺🇸\",\n                @\"flag-uy\":@\"🇺🇾\",\n                @\"flag-uz\":@\"🇺🇿\",\n                @\"flag-va\":@\"🇻🇦\",\n                @\"flag-vc\":@\"🇻🇨\",\n                @\"flag-ve\":@\"🇻🇪\",\n                @\"flag-vg\":@\"🇻🇬\",\n                @\"flag-vi\":@\"🇻🇮\",\n                @\"flag-vn\":@\"🇻🇳\",\n                @\"flag-vu\":@\"🇻🇺\",\n                @\"flag-wf\":@\"🇼🇫\",\n                @\"flag-ws\":@\"🇼🇸\",\n                @\"flag-xk\":@\"🇽🇰\",\n                @\"flag-ye\":@\"🇾🇪\",\n                @\"flag-yt\":@\"🇾🇹\",\n                @\"flag-za\":@\"🇿🇦\",\n                @\"flag-zm\":@\"🇿🇲\",\n                @\"flag-zw\":@\"🇿🇼\",\n                @\"koko\":@\"🈁\",\n                @\"sa\":@\"🈂️\",\n                @\"u7121\":@\"🈚\",\n                @\"u6307\":@\"🈯\",\n                @\"u7981\":@\"🈲\",\n                @\"u7a7a\":@\"🈳\",\n                @\"u5408\":@\"🈴\",\n                @\"u6e80\":@\"🈵\",\n                @\"u6709\":@\"🈶\",\n                @\"u6708\":@\"🈷️\",\n                @\"u7533\":@\"🈸\",\n                @\"u5272\":@\"🈹\",\n                @\"u55b6\":@\"🈺\",\n                @\"ideograph_advantage\":@\"🉐\",\n                @\"accept\":@\"🉑\",\n                @\"cyclone\":@\"🌀\",\n                @\"foggy\":@\"🌁\",\n                @\"closed_umbrella\":@\"🌂\",\n                @\"night_with_stars\":@\"🌃\",\n                @\"sunrise_over_mountains\":@\"🌄\",\n                @\"sunrise\":@\"🌅\",\n                @\"city_sunset\":@\"🌆\",\n                @\"city_sunrise\":@\"🌇\",\n                @\"rainbow\":@\"🌈\",\n                @\"bridge_at_night\":@\"🌉\",\n                @\"ocean\":@\"🌊\",\n                @\"volcano\":@\"🌋\",\n                @\"milky_way\":@\"🌌\",\n                @\"earth_africa\":@\"🌍\",\n                @\"earth_americas\":@\"🌎\",\n                @\"earth_asia\":@\"🌏\",\n                @\"globe_with_meridians\":@\"🌐\",\n                @\"new_moon\":@\"🌑\",\n                @\"waxing_crescent_moon\":@\"🌒\",\n                @\"first_quarter_moon\":@\"🌓\",\n                @\"moon\":@\"🌔\",\n                @\"waxing_gibbous_moon\":@\"🌔\",\n                @\"full_moon\":@\"🌕\",\n                @\"waning_gibbous_moon\":@\"🌖\",\n                @\"last_quarter_moon\":@\"🌗\",\n                @\"waning_crescent_moon\":@\"🌘\",\n                @\"crescent_moon\":@\"🌙\",\n                @\"new_moon_with_face\":@\"🌚\",\n                @\"first_quarter_moon_with_face\":@\"🌛\",\n                @\"last_quarter_moon_with_face\":@\"🌜\",\n                @\"full_moon_with_face\":@\"🌝\",\n                @\"sun_with_face\":@\"🌞\",\n                @\"star2\":@\"🌟\",\n                @\"stars\":@\"🌠\",\n                @\"thermometer\":@\"🌡️\",\n                @\"mostly_sunny\":@\"🌤️\",\n                @\"sun_small_cloud\":@\"🌤️\",\n                @\"barely_sunny\":@\"🌥️\",\n                @\"sun_behind_cloud\":@\"🌥️\",\n                @\"partly_sunny_rain\":@\"🌦️\",\n                @\"sun_behind_rain_cloud\":@\"🌦️\",\n                @\"rain_cloud\":@\"🌧️\",\n                @\"snow_cloud\":@\"🌨️\",\n                @\"lightning\":@\"🌩️\",\n                @\"lightning_cloud\":@\"🌩️\",\n                @\"tornado\":@\"🌪️\",\n                @\"tornado_cloud\":@\"🌪️\",\n                @\"fog\":@\"🌫️\",\n                @\"wind_blowing_face\":@\"🌬️\",\n                @\"hotdog\":@\"🌭\",\n                @\"taco\":@\"🌮\",\n                @\"burrito\":@\"🌯\",\n                @\"chestnut\":@\"🌰\",\n                @\"seedling\":@\"🌱\",\n                @\"evergreen_tree\":@\"🌲\",\n                @\"deciduous_tree\":@\"🌳\",\n                @\"palm_tree\":@\"🌴\",\n                @\"cactus\":@\"🌵\",\n                @\"hot_pepper\":@\"🌶️\",\n                @\"tulip\":@\"🌷\",\n                @\"cherry_blossom\":@\"🌸\",\n                @\"rose\":@\"🌹\",\n                @\"hibiscus\":@\"🌺\",\n                @\"sunflower\":@\"🌻\",\n                @\"blossom\":@\"🌼\",\n                @\"corn\":@\"🌽\",\n                @\"ear_of_rice\":@\"🌾\",\n                @\"herb\":@\"🌿\",\n                @\"four_leaf_clover\":@\"🍀\",\n                @\"maple_leaf\":@\"🍁\",\n                @\"fallen_leaf\":@\"🍂\",\n                @\"leaves\":@\"🍃\",\n                @\"brown_mushroom\":@\"🍄‍🟫\",\n                @\"mushroom\":@\"🍄\",\n                @\"tomato\":@\"🍅\",\n                @\"eggplant\":@\"🍆\",\n                @\"grapes\":@\"🍇\",\n                @\"melon\":@\"🍈\",\n                @\"watermelon\":@\"🍉\",\n                @\"tangerine\":@\"🍊\",\n                @\"lime\":@\"🍋‍🟩\",\n                @\"lemon\":@\"🍋\",\n                @\"banana\":@\"🍌\",\n                @\"pineapple\":@\"🍍\",\n                @\"apple\":@\"🍎\",\n                @\"green_apple\":@\"🍏\",\n                @\"pear\":@\"🍐\",\n                @\"peach\":@\"🍑\",\n                @\"cherries\":@\"🍒\",\n                @\"strawberry\":@\"🍓\",\n                @\"hamburger\":@\"🍔\",\n                @\"pizza\":@\"🍕\",\n                @\"meat_on_bone\":@\"🍖\",\n                @\"poultry_leg\":@\"🍗\",\n                @\"rice_cracker\":@\"🍘\",\n                @\"rice_ball\":@\"🍙\",\n                @\"rice\":@\"🍚\",\n                @\"curry\":@\"🍛\",\n                @\"ramen\":@\"🍜\",\n                @\"spaghetti\":@\"🍝\",\n                @\"bread\":@\"🍞\",\n                @\"fries\":@\"🍟\",\n                @\"sweet_potato\":@\"🍠\",\n                @\"dango\":@\"🍡\",\n                @\"oden\":@\"🍢\",\n                @\"sushi\":@\"🍣\",\n                @\"fried_shrimp\":@\"🍤\",\n                @\"fish_cake\":@\"🍥\",\n                @\"icecream\":@\"🍦\",\n                @\"shaved_ice\":@\"🍧\",\n                @\"ice_cream\":@\"🍨\",\n                @\"doughnut\":@\"🍩\",\n                @\"cookie\":@\"🍪\",\n                @\"chocolate_bar\":@\"🍫\",\n                @\"candy\":@\"🍬\",\n                @\"lollipop\":@\"🍭\",\n                @\"custard\":@\"🍮\",\n                @\"honey_pot\":@\"🍯\",\n                @\"cake\":@\"🍰\",\n                @\"bento\":@\"🍱\",\n                @\"stew\":@\"🍲\",\n                @\"fried_egg\":@\"🍳\",\n                @\"cooking\":@\"🍳\",\n                @\"fork_and_knife\":@\"🍴\",\n                @\"tea\":@\"🍵\",\n                @\"sake\":@\"🍶\",\n                @\"wine_glass\":@\"🍷\",\n                @\"cocktail\":@\"🍸\",\n                @\"tropical_drink\":@\"🍹\",\n                @\"beer\":@\"🍺\",\n                @\"beers\":@\"🍻\",\n                @\"baby_bottle\":@\"🍼\",\n                @\"knife_fork_plate\":@\"🍽️\",\n                @\"champagne\":@\"🍾\",\n                @\"popcorn\":@\"🍿\",\n                @\"ribbon\":@\"🎀\",\n                @\"gift\":@\"🎁\",\n                @\"birthday\":@\"🎂\",\n                @\"jack_o_lantern\":@\"🎃\",\n                @\"christmas_tree\":@\"🎄\",\n                @\"santa\":@\"🎅\",\n                @\"fireworks\":@\"🎆\",\n                @\"sparkler\":@\"🎇\",\n                @\"balloon\":@\"🎈\",\n                @\"tada\":@\"🎉\",\n                @\"confetti_ball\":@\"🎊\",\n                @\"tanabata_tree\":@\"🎋\",\n                @\"crossed_flags\":@\"🎌\",\n                @\"bamboo\":@\"🎍\",\n                @\"dolls\":@\"🎎\",\n                @\"flags\":@\"🎏\",\n                @\"wind_chime\":@\"🎐\",\n                @\"rice_scene\":@\"🎑\",\n                @\"school_satchel\":@\"🎒\",\n                @\"mortar_board\":@\"🎓\",\n                @\"medal\":@\"🎖️\",\n                @\"reminder_ribbon\":@\"🎗️\",\n                @\"studio_microphone\":@\"🎙️\",\n                @\"level_slider\":@\"🎚️\",\n                @\"control_knobs\":@\"🎛️\",\n                @\"film_frames\":@\"🎞️\",\n                @\"admission_tickets\":@\"🎟️\",\n                @\"carousel_horse\":@\"🎠\",\n                @\"ferris_wheel\":@\"🎡\",\n                @\"roller_coaster\":@\"🎢\",\n                @\"fishing_pole_and_fish\":@\"🎣\",\n                @\"microphone\":@\"🎤\",\n                @\"movie_camera\":@\"🎥\",\n                @\"cinema\":@\"🎦\",\n                @\"headphones\":@\"🎧\",\n                @\"art\":@\"🎨\",\n                @\"tophat\":@\"🎩\",\n                @\"circus_tent\":@\"🎪\",\n                @\"ticket\":@\"🎫\",\n                @\"clapper\":@\"🎬\",\n                @\"performing_arts\":@\"🎭\",\n                @\"video_game\":@\"🎮\",\n                @\"dart\":@\"🎯\",\n                @\"slot_machine\":@\"🎰\",\n                @\"8ball\":@\"🎱\",\n                @\"game_die\":@\"🎲\",\n                @\"bowling\":@\"🎳\",\n                @\"flower_playing_cards\":@\"🎴\",\n                @\"musical_note\":@\"🎵\",\n                @\"notes\":@\"🎶\",\n                @\"saxophone\":@\"🎷\",\n                @\"guitar\":@\"🎸\",\n                @\"musical_keyboard\":@\"🎹\",\n                @\"trumpet\":@\"🎺\",\n                @\"violin\":@\"🎻\",\n                @\"musical_score\":@\"🎼\",\n                @\"running_shirt_with_sash\":@\"🎽\",\n                @\"tennis\":@\"🎾\",\n                @\"ski\":@\"🎿\",\n                @\"basketball\":@\"🏀\",\n                @\"checkered_flag\":@\"🏁\",\n                @\"snowboarder\":@\"🏂\",\n                @\"woman-running\":@\"🏃‍♀️\",\n                @\"woman_running_facing_right\":@\"🏃‍♀️‍➡️\",\n                @\"man-running\":@\"🏃‍♂️\",\n                @\"runner\":@\"🏃‍♂️\",\n                @\"running\":@\"🏃‍♂️\",\n                @\"man_running_facing_right\":@\"🏃‍♂️‍➡️\",\n                @\"person_running_facing_right\":@\"🏃‍➡️\",\n                @\"woman-surfing\":@\"🏄‍♀️\",\n                @\"man-surfing\":@\"🏄‍♂️\",\n                @\"surfer\":@\"🏄‍♂️\",\n                @\"sports_medal\":@\"🏅\",\n                @\"trophy\":@\"🏆\",\n                @\"horse_racing\":@\"🏇\",\n                @\"football\":@\"🏈\",\n                @\"rugby_football\":@\"🏉\",\n                @\"woman-swimming\":@\"🏊‍♀️\",\n                @\"man-swimming\":@\"🏊‍♂️\",\n                @\"swimmer\":@\"🏊‍♂️\",\n                @\"woman-lifting-weights\":@\"🏋️‍♀️\",\n                @\"man-lifting-weights\":@\"🏋️‍♂️\",\n                @\"weight_lifter\":@\"🏋️‍♂️\",\n                @\"woman-golfing\":@\"🏌️‍♀️\",\n                @\"man-golfing\":@\"🏌️‍♂️\",\n                @\"golfer\":@\"🏌️‍♂️\",\n                @\"racing_motorcycle\":@\"🏍️\",\n                @\"racing_car\":@\"🏎️\",\n                @\"cricket_bat_and_ball\":@\"🏏\",\n                @\"volleyball\":@\"🏐\",\n                @\"field_hockey_stick_and_ball\":@\"🏑\",\n                @\"ice_hockey_stick_and_puck\":@\"🏒\",\n                @\"table_tennis_paddle_and_ball\":@\"🏓\",\n                @\"snow_capped_mountain\":@\"🏔️\",\n                @\"camping\":@\"🏕️\",\n                @\"beach_with_umbrella\":@\"🏖️\",\n                @\"building_construction\":@\"🏗️\",\n                @\"house_buildings\":@\"🏘️\",\n                @\"cityscape\":@\"🏙️\",\n                @\"derelict_house_building\":@\"🏚️\",\n                @\"classical_building\":@\"🏛️\",\n                @\"desert\":@\"🏜️\",\n                @\"desert_island\":@\"🏝️\",\n                @\"national_park\":@\"🏞️\",\n                @\"stadium\":@\"🏟️\",\n                @\"house\":@\"🏠\",\n                @\"house_with_garden\":@\"🏡\",\n                @\"office\":@\"🏢\",\n                @\"post_office\":@\"🏣\",\n                @\"european_post_office\":@\"🏤\",\n                @\"hospital\":@\"🏥\",\n                @\"bank\":@\"🏦\",\n                @\"atm\":@\"🏧\",\n                @\"hotel\":@\"🏨\",\n                @\"love_hotel\":@\"🏩\",\n                @\"convenience_store\":@\"🏪\",\n                @\"school\":@\"🏫\",\n                @\"department_store\":@\"🏬\",\n                @\"factory\":@\"🏭\",\n                @\"izakaya_lantern\":@\"🏮\",\n                @\"lantern\":@\"🏮\",\n                @\"japanese_castle\":@\"🏯\",\n                @\"european_castle\":@\"🏰\",\n                @\"rainbow-flag\":@\"🏳️‍🌈\",\n                @\"transgender_flag\":@\"🏳️‍⚧️\",\n                @\"waving_white_flag\":@\"🏳️\",\n                @\"pirate_flag\":@\"🏴‍☠️\",\n                @\"flag-england\":@\"🏴󠁧󠁢󠁥󠁮󠁧󠁿\",\n                @\"flag-scotland\":@\"🏴󠁧󠁢󠁳󠁣󠁴󠁿\",\n                @\"flag-wales\":@\"🏴󠁧󠁢󠁷󠁬󠁳󠁿\",\n                @\"waving_black_flag\":@\"🏴\",\n                @\"rosette\":@\"🏵️\",\n                @\"label\":@\"🏷️\",\n                @\"badminton_racquet_and_shuttlecock\":@\"🏸\",\n                @\"bow_and_arrow\":@\"🏹\",\n                @\"amphora\":@\"🏺\",\n                @\"skin-tone-2\":@\"🏻\",\n                @\"skin-tone-3\":@\"🏼\",\n                @\"skin-tone-4\":@\"🏽\",\n                @\"skin-tone-5\":@\"🏾\",\n                @\"skin-tone-6\":@\"🏿\",\n                @\"rat\":@\"🐀\",\n                @\"mouse2\":@\"🐁\",\n                @\"ox\":@\"🐂\",\n                @\"water_buffalo\":@\"🐃\",\n                @\"cow2\":@\"🐄\",\n                @\"tiger2\":@\"🐅\",\n                @\"leopard\":@\"🐆\",\n                @\"rabbit2\":@\"🐇\",\n                @\"black_cat\":@\"🐈‍⬛\",\n                @\"cat2\":@\"🐈\",\n                @\"dragon\":@\"🐉\",\n                @\"crocodile\":@\"🐊\",\n                @\"whale2\":@\"🐋\",\n                @\"snail\":@\"🐌\",\n                @\"snake\":@\"🐍\",\n                @\"racehorse\":@\"🐎\",\n                @\"ram\":@\"🐏\",\n                @\"goat\":@\"🐐\",\n                @\"sheep\":@\"🐑\",\n                @\"monkey\":@\"🐒\",\n                @\"rooster\":@\"🐓\",\n                @\"chicken\":@\"🐔\",\n                @\"service_dog\":@\"🐕‍🦺\",\n                @\"dog2\":@\"🐕\",\n                @\"pig2\":@\"🐖\",\n                @\"boar\":@\"🐗\",\n                @\"elephant\":@\"🐘\",\n                @\"octopus\":@\"🐙\",\n                @\"shell\":@\"🐚\",\n                @\"bug\":@\"🐛\",\n                @\"ant\":@\"🐜\",\n                @\"bee\":@\"🐝\",\n                @\"honeybee\":@\"🐝\",\n                @\"ladybug\":@\"🐞\",\n                @\"lady_beetle\":@\"🐞\",\n                @\"fish\":@\"🐟\",\n                @\"tropical_fish\":@\"🐠\",\n                @\"blowfish\":@\"🐡\",\n                @\"turtle\":@\"🐢\",\n                @\"hatching_chick\":@\"🐣\",\n                @\"baby_chick\":@\"🐤\",\n                @\"hatched_chick\":@\"🐥\",\n                @\"phoenix\":@\"🐦‍🔥\",\n                @\"black_bird\":@\"🐦‍⬛\",\n                @\"bird\":@\"🐦\",\n                @\"penguin\":@\"🐧\",\n                @\"koala\":@\"🐨\",\n                @\"poodle\":@\"🐩\",\n                @\"dromedary_camel\":@\"🐪\",\n                @\"camel\":@\"🐫\",\n                @\"dolphin\":@\"🐬\",\n                @\"flipper\":@\"🐬\",\n                @\"mouse\":@\"🐭\",\n                @\"cow\":@\"🐮\",\n                @\"tiger\":@\"🐯\",\n                @\"rabbit\":@\"🐰\",\n                @\"cat\":@\"🐱\",\n                @\"dragon_face\":@\"🐲\",\n                @\"whale\":@\"🐳\",\n                @\"horse\":@\"🐴\",\n                @\"monkey_face\":@\"🐵\",\n                @\"dog\":@\"🐶\",\n                @\"pig\":@\"🐷\",\n                @\"frog\":@\"🐸\",\n                @\"hamster\":@\"🐹\",\n                @\"wolf\":@\"🐺\",\n                @\"polar_bear\":@\"🐻‍❄️\",\n                @\"bear\":@\"🐻\",\n                @\"panda_face\":@\"🐼\",\n                @\"pig_nose\":@\"🐽\",\n                @\"feet\":@\"🐾\",\n                @\"paw_prints\":@\"🐾\",\n                @\"chipmunk\":@\"🐿️\",\n                @\"eyes\":@\"👀\",\n                @\"eye-in-speech-bubble\":@\"👁️‍🗨️\",\n                @\"eye\":@\"👁️\",\n                @\"ear\":@\"👂\",\n                @\"nose\":@\"👃\",\n                @\"lips\":@\"👄\",\n                @\"tongue\":@\"👅\",\n                @\"point_up_2\":@\"👆\",\n                @\"point_down\":@\"👇\",\n                @\"point_left\":@\"👈\",\n                @\"point_right\":@\"👉\",\n                @\"facepunch\":@\"👊\",\n                @\"punch\":@\"👊\",\n                @\"wave\":@\"👋\",\n                @\"ok_hand\":@\"👌\",\n                @\"+1\":@\"👍\",\n                @\"thumbsup\":@\"👍\",\n                @\"-1\":@\"👎\",\n                @\"thumbsdown\":@\"👎\",\n                @\"clap\":@\"👏\",\n                @\"open_hands\":@\"👐\",\n                @\"crown\":@\"👑\",\n                @\"womans_hat\":@\"👒\",\n                @\"eyeglasses\":@\"👓\",\n                @\"necktie\":@\"👔\",\n                @\"shirt\":@\"👕\",\n                @\"tshirt\":@\"👕\",\n                @\"jeans\":@\"👖\",\n                @\"dress\":@\"👗\",\n                @\"kimono\":@\"👘\",\n                @\"bikini\":@\"👙\",\n                @\"womans_clothes\":@\"👚\",\n                @\"purse\":@\"👛\",\n                @\"handbag\":@\"👜\",\n                @\"pouch\":@\"👝\",\n                @\"mans_shoe\":@\"👞\",\n                @\"shoe\":@\"👞\",\n                @\"athletic_shoe\":@\"👟\",\n                @\"high_heel\":@\"👠\",\n                @\"sandal\":@\"👡\",\n                @\"boot\":@\"👢\",\n                @\"footprints\":@\"👣\",\n                @\"bust_in_silhouette\":@\"👤\",\n                @\"busts_in_silhouette\":@\"👥\",\n                @\"boy\":@\"👦\",\n                @\"girl\":@\"👧\",\n                @\"male-farmer\":@\"👨‍🌾\",\n                @\"male-cook\":@\"👨‍🍳\",\n                @\"man_feeding_baby\":@\"👨‍🍼\",\n                @\"male-student\":@\"👨‍🎓\",\n                @\"male-singer\":@\"👨‍🎤\",\n                @\"male-artist\":@\"👨‍🎨\",\n                @\"male-teacher\":@\"👨‍🏫\",\n                @\"male-factory-worker\":@\"👨‍🏭\",\n                @\"man-boy-boy\":@\"👨‍👦‍👦\",\n                @\"man-boy\":@\"👨‍👦\",\n                @\"man-girl-boy\":@\"👨‍👧‍👦\",\n                @\"man-girl-girl\":@\"👨‍👧‍👧\",\n                @\"man-girl\":@\"👨‍👧\",\n                @\"man-man-boy\":@\"👨‍👨‍👦\",\n                @\"man-man-boy-boy\":@\"👨‍👨‍👦‍👦\",\n                @\"man-man-girl\":@\"👨‍👨‍👧\",\n                @\"man-man-girl-boy\":@\"👨‍👨‍👧‍👦\",\n                @\"man-man-girl-girl\":@\"👨‍👨‍👧‍👧\",\n                @\"man-woman-boy\":@\"👨‍👩‍👦\",\n                @\"family\":@\"👨‍👩‍👦\",\n                @\"man-woman-boy-boy\":@\"👨‍👩‍👦‍👦\",\n                @\"man-woman-girl\":@\"👨‍👩‍👧\",\n                @\"man-woman-girl-boy\":@\"👨‍👩‍👧‍👦\",\n                @\"man-woman-girl-girl\":@\"👨‍👩‍👧‍👧\",\n                @\"male-technologist\":@\"👨‍💻\",\n                @\"male-office-worker\":@\"👨‍💼\",\n                @\"male-mechanic\":@\"👨‍🔧\",\n                @\"male-scientist\":@\"👨‍🔬\",\n                @\"male-astronaut\":@\"👨‍🚀\",\n                @\"male-firefighter\":@\"👨‍🚒\",\n                @\"man_with_white_cane_facing_right\":@\"👨‍🦯‍➡️\",\n                @\"man_with_probing_cane\":@\"👨‍🦯\",\n                @\"red_haired_man\":@\"👨‍🦰\",\n                @\"curly_haired_man\":@\"👨‍🦱\",\n                @\"bald_man\":@\"👨‍🦲\",\n                @\"white_haired_man\":@\"👨‍🦳\",\n                @\"man_in_motorized_wheelchair_facing_right\":@\"👨‍🦼‍➡️\",\n                @\"man_in_motorized_wheelchair\":@\"👨‍🦼\",\n                @\"man_in_manual_wheelchair_facing_right\":@\"👨‍🦽‍➡️\",\n                @\"man_in_manual_wheelchair\":@\"👨‍🦽\",\n                @\"male-doctor\":@\"👨‍⚕️\",\n                @\"male-judge\":@\"👨‍⚖️\",\n                @\"male-pilot\":@\"👨‍✈️\",\n                @\"man-heart-man\":@\"👨‍❤️‍👨\",\n                @\"man-kiss-man\":@\"👨‍❤️‍💋‍👨\",\n                @\"man\":@\"👨\",\n                @\"female-farmer\":@\"👩‍🌾\",\n                @\"female-cook\":@\"👩‍🍳\",\n                @\"woman_feeding_baby\":@\"👩‍🍼\",\n                @\"female-student\":@\"👩‍🎓\",\n                @\"female-singer\":@\"👩‍🎤\",\n                @\"female-artist\":@\"👩‍🎨\",\n                @\"female-teacher\":@\"👩‍🏫\",\n                @\"female-factory-worker\":@\"👩‍🏭\",\n                @\"woman-boy-boy\":@\"👩‍👦‍👦\",\n                @\"woman-boy\":@\"👩‍👦\",\n                @\"woman-girl-boy\":@\"👩‍👧‍👦\",\n                @\"woman-girl-girl\":@\"👩‍👧‍👧\",\n                @\"woman-girl\":@\"👩‍👧\",\n                @\"woman-woman-boy\":@\"👩‍👩‍👦\",\n                @\"woman-woman-boy-boy\":@\"👩‍👩‍👦‍👦\",\n                @\"woman-woman-girl\":@\"👩‍👩‍👧\",\n                @\"woman-woman-girl-boy\":@\"👩‍👩‍👧‍👦\",\n                @\"woman-woman-girl-girl\":@\"👩‍👩‍👧‍👧\",\n                @\"female-technologist\":@\"👩‍💻\",\n                @\"female-office-worker\":@\"👩‍💼\",\n                @\"female-mechanic\":@\"👩‍🔧\",\n                @\"female-scientist\":@\"👩‍🔬\",\n                @\"female-astronaut\":@\"👩‍🚀\",\n                @\"female-firefighter\":@\"👩‍🚒\",\n                @\"woman_with_white_cane_facing_right\":@\"👩‍🦯‍➡️\",\n                @\"woman_with_probing_cane\":@\"👩‍🦯\",\n                @\"red_haired_woman\":@\"👩‍🦰\",\n                @\"curly_haired_woman\":@\"👩‍🦱\",\n                @\"bald_woman\":@\"👩‍🦲\",\n                @\"white_haired_woman\":@\"👩‍🦳\",\n                @\"woman_in_motorized_wheelchair_facing_right\":@\"👩‍🦼‍➡️\",\n                @\"woman_in_motorized_wheelchair\":@\"👩‍🦼\",\n                @\"woman_in_manual_wheelchair_facing_right\":@\"👩‍🦽‍➡️\",\n                @\"woman_in_manual_wheelchair\":@\"👩‍🦽\",\n                @\"female-doctor\":@\"👩‍⚕️\",\n                @\"female-judge\":@\"👩‍⚖️\",\n                @\"female-pilot\":@\"👩‍✈️\",\n                @\"woman-heart-man\":@\"👩‍❤️‍👨\",\n                @\"woman-heart-woman\":@\"👩‍❤️‍👩\",\n                @\"woman-kiss-man\":@\"👩‍❤️‍💋‍👨\",\n                @\"woman-kiss-woman\":@\"👩‍❤️‍💋‍👩\",\n                @\"woman\":@\"👩\",\n                @\"man_and_woman_holding_hands\":@\"👫\",\n                @\"woman_and_man_holding_hands\":@\"👫\",\n                @\"couple\":@\"👫\",\n                @\"two_men_holding_hands\":@\"👬\",\n                @\"men_holding_hands\":@\"👬\",\n                @\"two_women_holding_hands\":@\"👭\",\n                @\"women_holding_hands\":@\"👭\",\n                @\"female-police-officer\":@\"👮‍♀️\",\n                @\"male-police-officer\":@\"👮‍♂️\",\n                @\"cop\":@\"👮‍♂️\",\n                @\"women-with-bunny-ears-partying\":@\"👯‍♀️\",\n                @\"woman-with-bunny-ears-partying\":@\"👯‍♀️\",\n                @\"dancers\":@\"👯‍♀️\",\n                @\"men-with-bunny-ears-partying\":@\"👯‍♂️\",\n                @\"man-with-bunny-ears-partying\":@\"👯‍♂️\",\n                @\"woman_with_veil\":@\"👰‍♀️\",\n                @\"man_with_veil\":@\"👰‍♂️\",\n                @\"bride_with_veil\":@\"👰\",\n                @\"blond-haired-woman\":@\"👱‍♀️\",\n                @\"blond-haired-man\":@\"👱‍♂️\",\n                @\"person_with_blond_hair\":@\"👱‍♂️\",\n                @\"man_with_gua_pi_mao\":@\"👲\",\n                @\"woman-wearing-turban\":@\"👳‍♀️\",\n                @\"man-wearing-turban\":@\"👳‍♂️\",\n                @\"man_with_turban\":@\"👳‍♂️\",\n                @\"older_man\":@\"👴\",\n                @\"older_woman\":@\"👵\",\n                @\"baby\":@\"👶\",\n                @\"female-construction-worker\":@\"👷‍♀️\",\n                @\"male-construction-worker\":@\"👷‍♂️\",\n                @\"construction_worker\":@\"👷‍♂️\",\n                @\"princess\":@\"👸\",\n                @\"japanese_ogre\":@\"👹\",\n                @\"japanese_goblin\":@\"👺\",\n                @\"ghost\":@\"👻\",\n                @\"angel\":@\"👼\",\n                @\"alien\":@\"👽\",\n                @\"space_invader\":@\"👾\",\n                @\"imp\":@\"👿\",\n                @\"skull\":@\"💀\",\n                @\"woman-tipping-hand\":@\"💁‍♀️\",\n                @\"information_desk_person\":@\"💁‍♀️\",\n                @\"man-tipping-hand\":@\"💁‍♂️\",\n                @\"female-guard\":@\"💂‍♀️\",\n                @\"male-guard\":@\"💂‍♂️\",\n                @\"guardsman\":@\"💂‍♂️\",\n                @\"dancer\":@\"💃\",\n                @\"lipstick\":@\"💄\",\n                @\"nail_care\":@\"💅\",\n                @\"woman-getting-massage\":@\"💆‍♀️\",\n                @\"massage\":@\"💆‍♀️\",\n                @\"man-getting-massage\":@\"💆‍♂️\",\n                @\"woman-getting-haircut\":@\"💇‍♀️\",\n                @\"haircut\":@\"💇‍♀️\",\n                @\"man-getting-haircut\":@\"💇‍♂️\",\n                @\"barber\":@\"💈\",\n                @\"syringe\":@\"💉\",\n                @\"pill\":@\"💊\",\n                @\"kiss\":@\"💋\",\n                @\"love_letter\":@\"💌\",\n                @\"ring\":@\"💍\",\n                @\"gem\":@\"💎\",\n                @\"couplekiss\":@\"💏\",\n                @\"bouquet\":@\"💐\",\n                @\"couple_with_heart\":@\"💑\",\n                @\"wedding\":@\"💒\",\n                @\"heartbeat\":@\"💓\",\n                @\"broken_heart\":@\"💔\",\n                @\"two_hearts\":@\"💕\",\n                @\"sparkling_heart\":@\"💖\",\n                @\"heartpulse\":@\"💗\",\n                @\"cupid\":@\"💘\",\n                @\"blue_heart\":@\"💙\",\n                @\"green_heart\":@\"💚\",\n                @\"yellow_heart\":@\"💛\",\n                @\"purple_heart\":@\"💜\",\n                @\"gift_heart\":@\"💝\",\n                @\"revolving_hearts\":@\"💞\",\n                @\"heart_decoration\":@\"💟\",\n                @\"diamond_shape_with_a_dot_inside\":@\"💠\",\n                @\"bulb\":@\"💡\",\n                @\"anger\":@\"💢\",\n                @\"bomb\":@\"💣\",\n                @\"zzz\":@\"💤\",\n                @\"boom\":@\"💥\",\n                @\"collision\":@\"💥\",\n                @\"sweat_drops\":@\"💦\",\n                @\"droplet\":@\"💧\",\n                @\"dash\":@\"💨\",\n                @\"pile_of_poo\":@\"💩\",\n                @\"hankey\":@\"💩\",\n                @\"poop\":@\"💩\",\n                @\"shit\":@\"💩\",\n                @\"muscle\":@\"💪\",\n                @\"dizzy\":@\"💫\",\n                @\"speech_balloon\":@\"💬\",\n                @\"thought_balloon\":@\"💭\",\n                @\"white_flower\":@\"💮\",\n                @\"100\":@\"💯\",\n                @\"moneybag\":@\"💰\",\n                @\"currency_exchange\":@\"💱\",\n                @\"heavy_dollar_sign\":@\"💲\",\n                @\"credit_card\":@\"💳\",\n                @\"yen\":@\"💴\",\n                @\"dollar\":@\"💵\",\n                @\"euro\":@\"💶\",\n                @\"pound\":@\"💷\",\n                @\"money_with_wings\":@\"💸\",\n                @\"chart\":@\"💹\",\n                @\"seat\":@\"💺\",\n                @\"computer\":@\"💻\",\n                @\"briefcase\":@\"💼\",\n                @\"minidisc\":@\"💽\",\n                @\"floppy_disk\":@\"💾\",\n                @\"cd\":@\"💿\",\n                @\"dvd\":@\"📀\",\n                @\"file_folder\":@\"📁\",\n                @\"open_file_folder\":@\"📂\",\n                @\"page_with_curl\":@\"📃\",\n                @\"page_facing_up\":@\"📄\",\n                @\"date\":@\"📅\",\n                @\"calendar\":@\"📆\",\n                @\"card_index\":@\"📇\",\n                @\"chart_with_upwards_trend\":@\"📈\",\n                @\"chart_with_downwards_trend\":@\"📉\",\n                @\"bar_chart\":@\"📊\",\n                @\"clipboard\":@\"📋\",\n                @\"pushpin\":@\"📌\",\n                @\"round_pushpin\":@\"📍\",\n                @\"paperclip\":@\"📎\",\n                @\"straight_ruler\":@\"📏\",\n                @\"triangular_ruler\":@\"📐\",\n                @\"bookmark_tabs\":@\"📑\",\n                @\"ledger\":@\"📒\",\n                @\"notebook\":@\"📓\",\n                @\"notebook_with_decorative_cover\":@\"📔\",\n                @\"closed_book\":@\"📕\",\n                @\"book\":@\"📖\",\n                @\"open_book\":@\"📖\",\n                @\"green_book\":@\"📗\",\n                @\"blue_book\":@\"📘\",\n                @\"orange_book\":@\"📙\",\n                @\"books\":@\"📚\",\n                @\"name_badge\":@\"📛\",\n                @\"scroll\":@\"📜\",\n                @\"memo\":@\"📝\",\n                @\"pencil\":@\"📝\",\n                @\"telephone_receiver\":@\"📞\",\n                @\"pager\":@\"📟\",\n                @\"fax\":@\"📠\",\n                @\"satellite_antenna\":@\"📡\",\n                @\"loudspeaker\":@\"📢\",\n                @\"mega\":@\"📣\",\n                @\"outbox_tray\":@\"📤\",\n                @\"inbox_tray\":@\"📥\",\n                @\"package\":@\"📦\",\n                @\"e-mail\":@\"📧\",\n                @\"incoming_envelope\":@\"📨\",\n                @\"envelope_with_arrow\":@\"📩\",\n                @\"mailbox_closed\":@\"📪\",\n                @\"mailbox\":@\"📫\",\n                @\"mailbox_with_mail\":@\"📬\",\n                @\"mailbox_with_no_mail\":@\"📭\",\n                @\"postbox\":@\"📮\",\n                @\"postal_horn\":@\"📯\",\n                @\"newspaper\":@\"📰\",\n                @\"iphone\":@\"📱\",\n                @\"calling\":@\"📲\",\n                @\"vibration_mode\":@\"📳\",\n                @\"mobile_phone_off\":@\"📴\",\n                @\"no_mobile_phones\":@\"📵\",\n                @\"signal_strength\":@\"📶\",\n                @\"camera\":@\"📷\",\n                @\"camera_with_flash\":@\"📸\",\n                @\"video_camera\":@\"📹\",\n                @\"tv\":@\"📺\",\n                @\"radio\":@\"📻\",\n                @\"vhs\":@\"📼\",\n                @\"film_projector\":@\"📽️\",\n                @\"prayer_beads\":@\"📿\",\n                @\"twisted_rightwards_arrows\":@\"🔀\",\n                @\"repeat\":@\"🔁\",\n                @\"repeat_one\":@\"🔂\",\n                @\"arrows_clockwise\":@\"🔃\",\n                @\"arrows_counterclockwise\":@\"🔄\",\n                @\"low_brightness\":@\"🔅\",\n                @\"high_brightness\":@\"🔆\",\n                @\"mute\":@\"🔇\",\n                @\"speaker\":@\"🔈\",\n                @\"sound\":@\"🔉\",\n                @\"loud_sound\":@\"🔊\",\n                @\"battery\":@\"🔋\",\n                @\"electric_plug\":@\"🔌\",\n                @\"mag\":@\"🔍\",\n                @\"mag_right\":@\"🔎\",\n                @\"lock_with_ink_pen\":@\"🔏\",\n                @\"closed_lock_with_key\":@\"🔐\",\n                @\"key\":@\"🔑\",\n                @\"lock\":@\"🔒\",\n                @\"unlock\":@\"🔓\",\n                @\"bell\":@\"🔔\",\n                @\"no_bell\":@\"🔕\",\n                @\"bookmark\":@\"🔖\",\n                @\"link\":@\"🔗\",\n                @\"radio_button\":@\"🔘\",\n                @\"back\":@\"🔙\",\n                @\"end\":@\"🔚\",\n                @\"on\":@\"🔛\",\n                @\"soon\":@\"🔜\",\n                @\"top\":@\"🔝\",\n                @\"underage\":@\"🔞\",\n                @\"keycap_ten\":@\"🔟\",\n                @\"capital_abcd\":@\"🔠\",\n                @\"abcd\":@\"🔡\",\n                @\"1234\":@\"🔢\",\n                @\"symbols\":@\"🔣\",\n                @\"abc\":@\"🔤\",\n                @\"fire\":@\"🔥\",\n                @\"flashlight\":@\"🔦\",\n                @\"wrench\":@\"🔧\",\n                @\"hammer\":@\"🔨\",\n                @\"nut_and_bolt\":@\"🔩\",\n                @\"hocho\":@\"🔪\",\n                @\"knife\":@\"🔪\",\n                @\"gun\":@\"🔫\",\n                @\"microscope\":@\"🔬\",\n                @\"telescope\":@\"🔭\",\n                @\"crystal_ball\":@\"🔮\",\n                @\"six_pointed_star\":@\"🔯\",\n                @\"beginner\":@\"🔰\",\n                @\"trident\":@\"🔱\",\n                @\"black_square_button\":@\"🔲\",\n                @\"white_square_button\":@\"🔳\",\n                @\"red_circle\":@\"🔴\",\n                @\"large_blue_circle\":@\"🔵\",\n                @\"large_orange_diamond\":@\"🔶\",\n                @\"large_blue_diamond\":@\"🔷\",\n                @\"small_orange_diamond\":@\"🔸\",\n                @\"small_blue_diamond\":@\"🔹\",\n                @\"small_red_triangle\":@\"🔺\",\n                @\"small_red_triangle_down\":@\"🔻\",\n                @\"arrow_up_small\":@\"🔼\",\n                @\"arrow_down_small\":@\"🔽\",\n                @\"om_symbol\":@\"🕉️\",\n                @\"dove_of_peace\":@\"🕊️\",\n                @\"kaaba\":@\"🕋\",\n                @\"mosque\":@\"🕌\",\n                @\"synagogue\":@\"🕍\",\n                @\"menorah_with_nine_branches\":@\"🕎\",\n                @\"clock1\":@\"🕐\",\n                @\"clock2\":@\"🕑\",\n                @\"clock3\":@\"🕒\",\n                @\"clock4\":@\"🕓\",\n                @\"clock5\":@\"🕔\",\n                @\"clock6\":@\"🕕\",\n                @\"clock7\":@\"🕖\",\n                @\"clock8\":@\"🕗\",\n                @\"clock9\":@\"🕘\",\n                @\"clock10\":@\"🕙\",\n                @\"clock11\":@\"🕚\",\n                @\"clock12\":@\"🕛\",\n                @\"clock130\":@\"🕜\",\n                @\"clock230\":@\"🕝\",\n                @\"clock330\":@\"🕞\",\n                @\"clock430\":@\"🕟\",\n                @\"clock530\":@\"🕠\",\n                @\"clock630\":@\"🕡\",\n                @\"clock730\":@\"🕢\",\n                @\"clock830\":@\"🕣\",\n                @\"clock930\":@\"🕤\",\n                @\"clock1030\":@\"🕥\",\n                @\"clock1130\":@\"🕦\",\n                @\"clock1230\":@\"🕧\",\n                @\"candle\":@\"🕯️\",\n                @\"mantelpiece_clock\":@\"🕰️\",\n                @\"hole\":@\"🕳️\",\n                @\"man_in_business_suit_levitating\":@\"🕴️\",\n                @\"female-detective\":@\"🕵️‍♀️\",\n                @\"male-detective\":@\"🕵️‍♂️\",\n                @\"sleuth_or_spy\":@\"🕵️‍♂️\",\n                @\"dark_sunglasses\":@\"🕶️\",\n                @\"spider\":@\"🕷️\",\n                @\"spider_web\":@\"🕸️\",\n                @\"joystick\":@\"🕹️\",\n                @\"man_dancing\":@\"🕺\",\n                @\"linked_paperclips\":@\"🖇️\",\n                @\"lower_left_ballpoint_pen\":@\"🖊️\",\n                @\"lower_left_fountain_pen\":@\"🖋️\",\n                @\"lower_left_paintbrush\":@\"🖌️\",\n                @\"lower_left_crayon\":@\"🖍️\",\n                @\"raised_hand_with_fingers_splayed\":@\"🖐️\",\n                @\"middle_finger\":@\"🖕\",\n                @\"reversed_hand_with_middle_finger_extended\":@\"🖕\",\n                @\"spock-hand\":@\"🖖\",\n                @\"black_heart\":@\"🖤\",\n                @\"desktop_computer\":@\"🖥️\",\n                @\"printer\":@\"🖨️\",\n                @\"three_button_mouse\":@\"🖱️\",\n                @\"trackball\":@\"🖲️\",\n                @\"frame_with_picture\":@\"🖼️\",\n                @\"card_index_dividers\":@\"🗂️\",\n                @\"card_file_box\":@\"🗃️\",\n                @\"file_cabinet\":@\"🗄️\",\n                @\"wastebasket\":@\"🗑️\",\n                @\"spiral_note_pad\":@\"🗒️\",\n                @\"spiral_calendar_pad\":@\"🗓️\",\n                @\"compression\":@\"🗜️\",\n                @\"old_key\":@\"🗝️\",\n                @\"rolled_up_newspaper\":@\"🗞️\",\n                @\"dagger_knife\":@\"🗡️\",\n                @\"speaking_head_in_silhouette\":@\"🗣️\",\n                @\"left_speech_bubble\":@\"🗨️\",\n                @\"right_anger_bubble\":@\"🗯️\",\n                @\"ballot_box_with_ballot\":@\"🗳️\",\n                @\"world_map\":@\"🗺️\",\n                @\"mount_fuji\":@\"🗻\",\n                @\"tokyo_tower\":@\"🗼\",\n                @\"statue_of_liberty\":@\"🗽\",\n                @\"japan\":@\"🗾\",\n                @\"moyai\":@\"🗿\",\n                @\"grinning\":@\"😀\",\n                @\"grin\":@\"😁\",\n                @\"joy\":@\"😂\",\n                @\"smiley\":@\"😃\",\n                @\"smile\":@\"😄\",\n                @\"sweat_smile\":@\"😅\",\n                @\"laughing\":@\"😆\",\n                @\"satisfied\":@\"😆\",\n                @\"innocent\":@\"😇\",\n                @\"smiling_imp\":@\"😈\",\n                @\"wink\":@\"😉\",\n                @\"blush\":@\"😊\",\n                @\"yum\":@\"😋\",\n                @\"relieved\":@\"😌\",\n                @\"heart_eyes\":@\"😍\",\n                @\"sunglasses\":@\"😎\",\n                @\"smirk\":@\"😏\",\n                @\"neutral_face\":@\"😐\",\n                @\"expressionless\":@\"😑\",\n                @\"unamused\":@\"😒\",\n                @\"sweat\":@\"😓\",\n                @\"pensive\":@\"😔\",\n                @\"confused\":@\"😕\",\n                @\"confounded\":@\"😖\",\n                @\"kissing\":@\"😗\",\n                @\"kissing_heart\":@\"😘\",\n                @\"kissing_smiling_eyes\":@\"😙\",\n                @\"kissing_closed_eyes\":@\"😚\",\n                @\"stuck_out_tongue\":@\"😛\",\n                @\"stuck_out_tongue_winking_eye\":@\"😜\",\n                @\"stuck_out_tongue_closed_eyes\":@\"😝\",\n                @\"disappointed\":@\"😞\",\n                @\"worried\":@\"😟\",\n                @\"angry\":@\"😠\",\n                @\"rage\":@\"😡\",\n                @\"cry\":@\"😢\",\n                @\"persevere\":@\"😣\",\n                @\"triumph\":@\"😤\",\n                @\"disappointed_relieved\":@\"😥\",\n                @\"frowning\":@\"😦\",\n                @\"anguished\":@\"😧\",\n                @\"fearful\":@\"😨\",\n                @\"weary\":@\"😩\",\n                @\"sleepy\":@\"😪\",\n                @\"tired_face\":@\"😫\",\n                @\"grimacing\":@\"😬\",\n                @\"sob\":@\"😭\",\n                @\"face_exhaling\":@\"😮‍💨\",\n                @\"open_mouth\":@\"😮\",\n                @\"hushed\":@\"😯\",\n                @\"cold_sweat\":@\"😰\",\n                @\"scream\":@\"😱\",\n                @\"astonished\":@\"😲\",\n                @\"flushed\":@\"😳\",\n                @\"sleeping\":@\"😴\",\n                @\"face_with_spiral_eyes\":@\"😵‍💫\",\n                @\"dizzy_face\":@\"😵\",\n                @\"face_in_clouds\":@\"😶‍🌫️\",\n                @\"no_mouth\":@\"😶\",\n                @\"mask\":@\"😷\",\n                @\"smile_cat\":@\"😸\",\n                @\"joy_cat\":@\"😹\",\n                @\"smiley_cat\":@\"😺\",\n                @\"heart_eyes_cat\":@\"😻\",\n                @\"smirk_cat\":@\"😼\",\n                @\"kissing_cat\":@\"😽\",\n                @\"pouting_cat\":@\"😾\",\n                @\"crying_cat_face\":@\"😿\",\n                @\"scream_cat\":@\"🙀\",\n                @\"slightly_frowning_face\":@\"🙁\",\n                @\"head_shaking_horizontally\":@\"🙂‍↔️\",\n                @\"head_shaking_vertically\":@\"🙂‍↕️\",\n                @\"slightly_smiling_face\":@\"🙂\",\n                @\"upside_down_face\":@\"🙃\",\n                @\"face_with_rolling_eyes\":@\"🙄\",\n                @\"woman-gesturing-no\":@\"🙅‍♀️\",\n                @\"no_good\":@\"🙅‍♀️\",\n                @\"man-gesturing-no\":@\"🙅‍♂️\",\n                @\"woman-gesturing-ok\":@\"🙆‍♀️\",\n                @\"ok_woman\":@\"🙆‍♀️\",\n                @\"man-gesturing-ok\":@\"🙆‍♂️\",\n                @\"woman-bowing\":@\"🙇‍♀️\",\n                @\"man-bowing\":@\"🙇‍♂️\",\n                @\"bow\":@\"🙇\",\n                @\"see_no_evil\":@\"🙈\",\n                @\"hear_no_evil\":@\"🙉\",\n                @\"speak_no_evil\":@\"🙊\",\n                @\"woman-raising-hand\":@\"🙋‍♀️\",\n                @\"raising_hand\":@\"🙋‍♀️\",\n                @\"man-raising-hand\":@\"🙋‍♂️\",\n                @\"raised_hands\":@\"🙌\",\n                @\"woman-frowning\":@\"🙍‍♀️\",\n                @\"person_frowning\":@\"🙍‍♀️\",\n                @\"man-frowning\":@\"🙍‍♂️\",\n                @\"woman-pouting\":@\"🙎‍♀️\",\n                @\"person_with_pouting_face\":@\"🙎‍♀️\",\n                @\"man-pouting\":@\"🙎‍♂️\",\n                @\"pray\":@\"🙏\",\n                @\"rocket\":@\"🚀\",\n                @\"helicopter\":@\"🚁\",\n                @\"steam_locomotive\":@\"🚂\",\n                @\"railway_car\":@\"🚃\",\n                @\"bullettrain_side\":@\"🚄\",\n                @\"bullettrain_front\":@\"🚅\",\n                @\"train2\":@\"🚆\",\n                @\"metro\":@\"🚇\",\n                @\"light_rail\":@\"🚈\",\n                @\"station\":@\"🚉\",\n                @\"tram\":@\"🚊\",\n                @\"train\":@\"🚋\",\n                @\"bus\":@\"🚌\",\n                @\"oncoming_bus\":@\"🚍\",\n                @\"trolleybus\":@\"🚎\",\n                @\"busstop\":@\"🚏\",\n                @\"minibus\":@\"🚐\",\n                @\"ambulance\":@\"🚑\",\n                @\"fire_engine\":@\"🚒\",\n                @\"police_car\":@\"🚓\",\n                @\"oncoming_police_car\":@\"🚔\",\n                @\"taxi\":@\"🚕\",\n                @\"oncoming_taxi\":@\"🚖\",\n                @\"car\":@\"🚗\",\n                @\"red_car\":@\"🚗\",\n                @\"oncoming_automobile\":@\"🚘\",\n                @\"blue_car\":@\"🚙\",\n                @\"truck\":@\"🚚\",\n                @\"articulated_lorry\":@\"🚛\",\n                @\"tractor\":@\"🚜\",\n                @\"monorail\":@\"🚝\",\n                @\"mountain_railway\":@\"🚞\",\n                @\"suspension_railway\":@\"🚟\",\n                @\"mountain_cableway\":@\"🚠\",\n                @\"aerial_tramway\":@\"🚡\",\n                @\"ship\":@\"🚢\",\n                @\"woman-rowing-boat\":@\"🚣‍♀️\",\n                @\"man-rowing-boat\":@\"🚣‍♂️\",\n                @\"rowboat\":@\"🚣‍♂️\",\n                @\"speedboat\":@\"🚤\",\n                @\"traffic_light\":@\"🚥\",\n                @\"vertical_traffic_light\":@\"🚦\",\n                @\"construction\":@\"🚧\",\n                @\"rotating_light\":@\"🚨\",\n                @\"triangular_flag_on_post\":@\"🚩\",\n                @\"door\":@\"🚪\",\n                @\"no_entry_sign\":@\"🚫\",\n                @\"smoking\":@\"🚬\",\n                @\"no_smoking\":@\"🚭\",\n                @\"put_litter_in_its_place\":@\"🚮\",\n                @\"do_not_litter\":@\"🚯\",\n                @\"potable_water\":@\"🚰\",\n                @\"non-potable_water\":@\"🚱\",\n                @\"bike\":@\"🚲\",\n                @\"no_bicycles\":@\"🚳\",\n                @\"woman-biking\":@\"🚴‍♀️\",\n                @\"man-biking\":@\"🚴‍♂️\",\n                @\"bicyclist\":@\"🚴‍♂️\",\n                @\"woman-mountain-biking\":@\"🚵‍♀️\",\n                @\"man-mountain-biking\":@\"🚵‍♂️\",\n                @\"mountain_bicyclist\":@\"🚵‍♂️\",\n                @\"woman-walking\":@\"🚶‍♀️\",\n                @\"woman_walking_facing_right\":@\"🚶‍♀️‍➡️\",\n                @\"man-walking\":@\"🚶‍♂️\",\n                @\"walking\":@\"🚶‍♂️\",\n                @\"man_walking_facing_right\":@\"🚶‍♂️‍➡️\",\n                @\"person_walking_facing_right\":@\"🚶‍➡️\",\n                @\"no_pedestrians\":@\"🚷\",\n                @\"children_crossing\":@\"🚸\",\n                @\"mens\":@\"🚹\",\n                @\"womens\":@\"🚺\",\n                @\"restroom\":@\"🚻\",\n                @\"baby_symbol\":@\"🚼\",\n                @\"toilet\":@\"🚽\",\n                @\"wc\":@\"🚾\",\n                @\"shower\":@\"🚿\",\n                @\"bath\":@\"🛀\",\n                @\"bathtub\":@\"🛁\",\n                @\"passport_control\":@\"🛂\",\n                @\"customs\":@\"🛃\",\n                @\"baggage_claim\":@\"🛄\",\n                @\"left_luggage\":@\"🛅\",\n                @\"couch_and_lamp\":@\"🛋️\",\n                @\"sleeping_accommodation\":@\"🛌\",\n                @\"shopping_bags\":@\"🛍️\",\n                @\"bellhop_bell\":@\"🛎️\",\n                @\"bed\":@\"🛏️\",\n                @\"place_of_worship\":@\"🛐\",\n                @\"octagonal_sign\":@\"🛑\",\n                @\"shopping_trolley\":@\"🛒\",\n                @\"hindu_temple\":@\"🛕\",\n                @\"hut\":@\"🛖\",\n                @\"elevator\":@\"🛗\",\n                @\"wireless\":@\"🛜\",\n                @\"playground_slide\":@\"🛝\",\n                @\"wheel\":@\"🛞\",\n                @\"ring_buoy\":@\"🛟\",\n                @\"hammer_and_wrench\":@\"🛠️\",\n                @\"shield\":@\"🛡️\",\n                @\"oil_drum\":@\"🛢️\",\n                @\"motorway\":@\"🛣️\",\n                @\"railway_track\":@\"🛤️\",\n                @\"motor_boat\":@\"🛥️\",\n                @\"small_airplane\":@\"🛩️\",\n                @\"airplane_departure\":@\"🛫\",\n                @\"airplane_arriving\":@\"🛬\",\n                @\"satellite\":@\"🛰️\",\n                @\"passenger_ship\":@\"🛳️\",\n                @\"scooter\":@\"🛴\",\n                @\"motor_scooter\":@\"🛵\",\n                @\"canoe\":@\"🛶\",\n                @\"sled\":@\"🛷\",\n                @\"flying_saucer\":@\"🛸\",\n                @\"skateboard\":@\"🛹\",\n                @\"auto_rickshaw\":@\"🛺\",\n                @\"pickup_truck\":@\"🛻\",\n                @\"roller_skate\":@\"🛼\",\n                @\"large_orange_circle\":@\"🟠\",\n                @\"large_yellow_circle\":@\"🟡\",\n                @\"large_green_circle\":@\"🟢\",\n                @\"large_purple_circle\":@\"🟣\",\n                @\"large_brown_circle\":@\"🟤\",\n                @\"large_red_square\":@\"🟥\",\n                @\"large_blue_square\":@\"🟦\",\n                @\"large_orange_square\":@\"🟧\",\n                @\"large_yellow_square\":@\"🟨\",\n                @\"large_green_square\":@\"🟩\",\n                @\"large_purple_square\":@\"🟪\",\n                @\"large_brown_square\":@\"🟫\",\n                @\"heavy_equals_sign\":@\"🟰\",\n                @\"pinched_fingers\":@\"🤌\",\n                @\"white_heart\":@\"🤍\",\n                @\"brown_heart\":@\"🤎\",\n                @\"pinching_hand\":@\"🤏\",\n                @\"zipper_mouth_face\":@\"🤐\",\n                @\"money_mouth_face\":@\"🤑\",\n                @\"face_with_thermometer\":@\"🤒\",\n                @\"nerd_face\":@\"🤓\",\n                @\"thinking_face\":@\"🤔\",\n                @\"face_with_head_bandage\":@\"🤕\",\n                @\"robot_face\":@\"🤖\",\n                @\"hugging_face\":@\"🤗\",\n                @\"the_horns\":@\"🤘\",\n                @\"sign_of_the_horns\":@\"🤘\",\n                @\"call_me_hand\":@\"🤙\",\n                @\"raised_back_of_hand\":@\"🤚\",\n                @\"left-facing_fist\":@\"🤛\",\n                @\"right-facing_fist\":@\"🤜\",\n                @\"handshake\":@\"🤝\",\n                @\"crossed_fingers\":@\"🤞\",\n                @\"hand_with_index_and_middle_fingers_crossed\":@\"🤞\",\n                @\"i_love_you_hand_sign\":@\"🤟\",\n                @\"face_with_cowboy_hat\":@\"🤠\",\n                @\"clown_face\":@\"🤡\",\n                @\"nauseated_face\":@\"🤢\",\n                @\"rolling_on_the_floor_laughing\":@\"🤣\",\n                @\"drooling_face\":@\"🤤\",\n                @\"lying_face\":@\"🤥\",\n                @\"woman-facepalming\":@\"🤦‍♀️\",\n                @\"man-facepalming\":@\"🤦‍♂️\",\n                @\"face_palm\":@\"🤦\",\n                @\"sneezing_face\":@\"🤧\",\n                @\"face_with_raised_eyebrow\":@\"🤨\",\n                @\"face_with_one_eyebrow_raised\":@\"🤨\",\n                @\"star-struck\":@\"🤩\",\n                @\"grinning_face_with_star_eyes\":@\"🤩\",\n                @\"zany_face\":@\"🤪\",\n                @\"grinning_face_with_one_large_and_one_small_eye\":@\"🤪\",\n                @\"shushing_face\":@\"🤫\",\n                @\"face_with_finger_covering_closed_lips\":@\"🤫\",\n                @\"face_with_symbols_on_mouth\":@\"🤬\",\n                @\"serious_face_with_symbols_covering_mouth\":@\"🤬\",\n                @\"face_with_hand_over_mouth\":@\"🤭\",\n                @\"smiling_face_with_smiling_eyes_and_hand_covering_mouth\":@\"🤭\",\n                @\"face_vomiting\":@\"🤮\",\n                @\"face_with_open_mouth_vomiting\":@\"🤮\",\n                @\"exploding_head\":@\"🤯\",\n                @\"shocked_face_with_exploding_head\":@\"🤯\",\n                @\"pregnant_woman\":@\"🤰\",\n                @\"breast-feeding\":@\"🤱\",\n                @\"palms_up_together\":@\"🤲\",\n                @\"selfie\":@\"🤳\",\n                @\"prince\":@\"🤴\",\n                @\"woman_in_tuxedo\":@\"🤵‍♀️\",\n                @\"man_in_tuxedo\":@\"🤵‍♂️\",\n                @\"person_in_tuxedo\":@\"🤵\",\n                @\"mrs_claus\":@\"🤶\",\n                @\"mother_christmas\":@\"🤶\",\n                @\"woman-shrugging\":@\"🤷‍♀️\",\n                @\"man-shrugging\":@\"🤷‍♂️\",\n                @\"shrug\":@\"🤷\",\n                @\"woman-cartwheeling\":@\"🤸‍♀️\",\n                @\"man-cartwheeling\":@\"🤸‍♂️\",\n                @\"person_doing_cartwheel\":@\"🤸\",\n                @\"woman-juggling\":@\"🤹‍♀️\",\n                @\"man-juggling\":@\"🤹‍♂️\",\n                @\"juggling\":@\"🤹\",\n                @\"fencer\":@\"🤺\",\n                @\"woman-wrestling\":@\"🤼‍♀️\",\n                @\"man-wrestling\":@\"🤼‍♂️\",\n                @\"wrestlers\":@\"🤼\",\n                @\"woman-playing-water-polo\":@\"🤽‍♀️\",\n                @\"man-playing-water-polo\":@\"🤽‍♂️\",\n                @\"water_polo\":@\"🤽\",\n                @\"woman-playing-handball\":@\"🤾‍♀️\",\n                @\"man-playing-handball\":@\"🤾‍♂️\",\n                @\"handball\":@\"🤾\",\n                @\"diving_mask\":@\"🤿\",\n                @\"wilted_flower\":@\"🥀\",\n                @\"drum_with_drumsticks\":@\"🥁\",\n                @\"clinking_glasses\":@\"🥂\",\n                @\"tumbler_glass\":@\"🥃\",\n                @\"spoon\":@\"🥄\",\n                @\"goal_net\":@\"🥅\",\n                @\"first_place_medal\":@\"🥇\",\n                @\"second_place_medal\":@\"🥈\",\n                @\"third_place_medal\":@\"🥉\",\n                @\"boxing_glove\":@\"🥊\",\n                @\"martial_arts_uniform\":@\"🥋\",\n                @\"curling_stone\":@\"🥌\",\n                @\"lacrosse\":@\"🥍\",\n                @\"softball\":@\"🥎\",\n                @\"flying_disc\":@\"🥏\",\n                @\"croissant\":@\"🥐\",\n                @\"avocado\":@\"🥑\",\n                @\"cucumber\":@\"🥒\",\n                @\"bacon\":@\"🥓\",\n                @\"potato\":@\"🥔\",\n                @\"carrot\":@\"🥕\",\n                @\"baguette_bread\":@\"🥖\",\n                @\"green_salad\":@\"🥗\",\n                @\"shallow_pan_of_food\":@\"🥘\",\n                @\"stuffed_flatbread\":@\"🥙\",\n                @\"egg\":@\"🥚\",\n                @\"glass_of_milk\":@\"🥛\",\n                @\"peanuts\":@\"🥜\",\n                @\"kiwifruit\":@\"🥝\",\n                @\"pancakes\":@\"🥞\",\n                @\"dumpling\":@\"🥟\",\n                @\"fortune_cookie\":@\"🥠\",\n                @\"takeout_box\":@\"🥡\",\n                @\"chopsticks\":@\"🥢\",\n                @\"bowl_with_spoon\":@\"🥣\",\n                @\"cup_with_straw\":@\"🥤\",\n                @\"coconut\":@\"🥥\",\n                @\"broccoli\":@\"🥦\",\n                @\"pie\":@\"🥧\",\n                @\"pretzel\":@\"🥨\",\n                @\"cut_of_meat\":@\"🥩\",\n                @\"sandwich\":@\"🥪\",\n                @\"canned_food\":@\"🥫\",\n                @\"leafy_green\":@\"🥬\",\n                @\"mango\":@\"🥭\",\n                @\"moon_cake\":@\"🥮\",\n                @\"bagel\":@\"🥯\",\n                @\"smiling_face_with_3_hearts\":@\"🥰\",\n                @\"yawning_face\":@\"🥱\",\n                @\"smiling_face_with_tear\":@\"🥲\",\n                @\"partying_face\":@\"🥳\",\n                @\"woozy_face\":@\"🥴\",\n                @\"hot_face\":@\"🥵\",\n                @\"cold_face\":@\"🥶\",\n                @\"ninja\":@\"🥷\",\n                @\"disguised_face\":@\"🥸\",\n                @\"face_holding_back_tears\":@\"🥹\",\n                @\"pleading_face\":@\"🥺\",\n                @\"sari\":@\"🥻\",\n                @\"lab_coat\":@\"🥼\",\n                @\"goggles\":@\"🥽\",\n                @\"hiking_boot\":@\"🥾\",\n                @\"womans_flat_shoe\":@\"🥿\",\n                @\"crab\":@\"🦀\",\n                @\"lion_face\":@\"🦁\",\n                @\"scorpion\":@\"🦂\",\n                @\"turkey\":@\"🦃\",\n                @\"unicorn_face\":@\"🦄\",\n                @\"eagle\":@\"🦅\",\n                @\"duck\":@\"🦆\",\n                @\"bat\":@\"🦇\",\n                @\"shark\":@\"🦈\",\n                @\"owl\":@\"🦉\",\n                @\"fox_face\":@\"🦊\",\n                @\"butterfly\":@\"🦋\",\n                @\"deer\":@\"🦌\",\n                @\"gorilla\":@\"🦍\",\n                @\"lizard\":@\"🦎\",\n                @\"rhinoceros\":@\"🦏\",\n                @\"shrimp\":@\"🦐\",\n                @\"squid\":@\"🦑\",\n                @\"giraffe_face\":@\"🦒\",\n                @\"zebra_face\":@\"🦓\",\n                @\"hedgehog\":@\"🦔\",\n                @\"sauropod\":@\"🦕\",\n                @\"t-rex\":@\"🦖\",\n                @\"cricket\":@\"🦗\",\n                @\"kangaroo\":@\"🦘\",\n                @\"llama\":@\"🦙\",\n                @\"peacock\":@\"🦚\",\n                @\"hippopotamus\":@\"🦛\",\n                @\"parrot\":@\"🦜\",\n                @\"raccoon\":@\"🦝\",\n                @\"lobster\":@\"🦞\",\n                @\"mosquito\":@\"🦟\",\n                @\"microbe\":@\"🦠\",\n                @\"badger\":@\"🦡\",\n                @\"swan\":@\"🦢\",\n                @\"mammoth\":@\"🦣\",\n                @\"dodo\":@\"🦤\",\n                @\"sloth\":@\"🦥\",\n                @\"otter\":@\"🦦\",\n                @\"orangutan\":@\"🦧\",\n                @\"skunk\":@\"🦨\",\n                @\"flamingo\":@\"🦩\",\n                @\"oyster\":@\"🦪\",\n                @\"beaver\":@\"🦫\",\n                @\"bison\":@\"🦬\",\n                @\"seal\":@\"🦭\",\n                @\"guide_dog\":@\"🦮\",\n                @\"probing_cane\":@\"🦯\",\n                @\"bone\":@\"🦴\",\n                @\"leg\":@\"🦵\",\n                @\"foot\":@\"🦶\",\n                @\"tooth\":@\"🦷\",\n                @\"female_superhero\":@\"🦸‍♀️\",\n                @\"male_superhero\":@\"🦸‍♂️\",\n                @\"superhero\":@\"🦸\",\n                @\"female_supervillain\":@\"🦹‍♀️\",\n                @\"male_supervillain\":@\"🦹‍♂️\",\n                @\"supervillain\":@\"🦹\",\n                @\"safety_vest\":@\"🦺\",\n                @\"ear_with_hearing_aid\":@\"🦻\",\n                @\"motorized_wheelchair\":@\"🦼\",\n                @\"manual_wheelchair\":@\"🦽\",\n                @\"mechanical_arm\":@\"🦾\",\n                @\"mechanical_leg\":@\"🦿\",\n                @\"cheese_wedge\":@\"🧀\",\n                @\"cupcake\":@\"🧁\",\n                @\"salt\":@\"🧂\",\n                @\"beverage_box\":@\"🧃\",\n                @\"garlic\":@\"🧄\",\n                @\"onion\":@\"🧅\",\n                @\"falafel\":@\"🧆\",\n                @\"waffle\":@\"🧇\",\n                @\"butter\":@\"🧈\",\n                @\"mate_drink\":@\"🧉\",\n                @\"ice_cube\":@\"🧊\",\n                @\"bubble_tea\":@\"🧋\",\n                @\"troll\":@\"🧌\",\n                @\"woman_standing\":@\"🧍‍♀️\",\n                @\"man_standing\":@\"🧍‍♂️\",\n                @\"standing_person\":@\"🧍\",\n                @\"woman_kneeling\":@\"🧎‍♀️\",\n                @\"woman_kneeling_facing_right\":@\"🧎‍♀️‍➡️\",\n                @\"man_kneeling\":@\"🧎‍♂️\",\n                @\"man_kneeling_facing_right\":@\"🧎‍♂️‍➡️\",\n                @\"person_kneeling_facing_right\":@\"🧎‍➡️\",\n                @\"kneeling_person\":@\"🧎\",\n                @\"deaf_woman\":@\"🧏‍♀️\",\n                @\"deaf_man\":@\"🧏‍♂️\",\n                @\"deaf_person\":@\"🧏\",\n                @\"face_with_monocle\":@\"🧐\",\n                @\"farmer\":@\"🧑‍🌾\",\n                @\"cook\":@\"🧑‍🍳\",\n                @\"person_feeding_baby\":@\"🧑‍🍼\",\n                @\"mx_claus\":@\"🧑‍🎄\",\n                @\"student\":@\"🧑‍🎓\",\n                @\"singer\":@\"🧑‍🎤\",\n                @\"artist\":@\"🧑‍🎨\",\n                @\"teacher\":@\"🧑‍🏫\",\n                @\"factory_worker\":@\"🧑‍🏭\",\n                @\"technologist\":@\"🧑‍💻\",\n                @\"office_worker\":@\"🧑‍💼\",\n                @\"mechanic\":@\"🧑‍🔧\",\n                @\"scientist\":@\"🧑‍🔬\",\n                @\"astronaut\":@\"🧑‍🚀\",\n                @\"firefighter\":@\"🧑‍🚒\",\n                @\"people_holding_hands\":@\"🧑‍🤝‍🧑\",\n                @\"person_with_white_cane_facing_right\":@\"🧑‍🦯‍➡️\",\n                @\"person_with_probing_cane\":@\"🧑‍🦯\",\n                @\"red_haired_person\":@\"🧑‍🦰\",\n                @\"curly_haired_person\":@\"🧑‍🦱\",\n                @\"bald_person\":@\"🧑‍🦲\",\n                @\"white_haired_person\":@\"🧑‍🦳\",\n                @\"person_in_motorized_wheelchair_facing_right\":@\"🧑‍🦼‍➡️\",\n                @\"person_in_motorized_wheelchair\":@\"🧑‍🦼\",\n                @\"person_in_manual_wheelchair_facing_right\":@\"🧑‍🦽‍➡️\",\n                @\"person_in_manual_wheelchair\":@\"🧑‍🦽\",\n                @\"family_adult_adult_child\":@\"🧑‍🧑‍🧒\",\n                @\"family_adult_adult_child_child\":@\"🧑‍🧑‍🧒‍🧒\",\n                @\"family_adult_child_child\":@\"🧑‍🧒‍🧒\",\n                @\"family_adult_child\":@\"🧑‍🧒\",\n                @\"health_worker\":@\"🧑‍⚕️\",\n                @\"judge\":@\"🧑‍⚖️\",\n                @\"pilot\":@\"🧑‍✈️\",\n                @\"adult\":@\"🧑\",\n                @\"child\":@\"🧒\",\n                @\"older_adult\":@\"🧓\",\n                @\"woman_with_beard\":@\"🧔‍♀️\",\n                @\"man_with_beard\":@\"🧔‍♂️\",\n                @\"bearded_person\":@\"🧔\",\n                @\"person_with_headscarf\":@\"🧕\",\n                @\"woman_in_steamy_room\":@\"🧖‍♀️\",\n                @\"man_in_steamy_room\":@\"🧖‍♂️\",\n                @\"person_in_steamy_room\":@\"🧖‍♂️\",\n                @\"woman_climbing\":@\"🧗‍♀️\",\n                @\"person_climbing\":@\"🧗‍♀️\",\n                @\"man_climbing\":@\"🧗‍♂️\",\n                @\"woman_in_lotus_position\":@\"🧘‍♀️\",\n                @\"person_in_lotus_position\":@\"🧘‍♀️\",\n                @\"man_in_lotus_position\":@\"🧘‍♂️\",\n                @\"female_mage\":@\"🧙‍♀️\",\n                @\"mage\":@\"🧙‍♀️\",\n                @\"male_mage\":@\"🧙‍♂️\",\n                @\"female_fairy\":@\"🧚‍♀️\",\n                @\"fairy\":@\"🧚‍♀️\",\n                @\"male_fairy\":@\"🧚‍♂️\",\n                @\"female_vampire\":@\"🧛‍♀️\",\n                @\"vampire\":@\"🧛‍♀️\",\n                @\"male_vampire\":@\"🧛‍♂️\",\n                @\"mermaid\":@\"🧜‍♀️\",\n                @\"merman\":@\"🧜‍♂️\",\n                @\"merperson\":@\"🧜‍♂️\",\n                @\"female_elf\":@\"🧝‍♀️\",\n                @\"male_elf\":@\"🧝‍♂️\",\n                @\"elf\":@\"🧝‍♂️\",\n                @\"female_genie\":@\"🧞‍♀️\",\n                @\"male_genie\":@\"🧞‍♂️\",\n                @\"genie\":@\"🧞‍♂️\",\n                @\"female_zombie\":@\"🧟‍♀️\",\n                @\"male_zombie\":@\"🧟‍♂️\",\n                @\"zombie\":@\"🧟‍♂️\",\n                @\"brain\":@\"🧠\",\n                @\"orange_heart\":@\"🧡\",\n                @\"billed_cap\":@\"🧢\",\n                @\"scarf\":@\"🧣\",\n                @\"gloves\":@\"🧤\",\n                @\"coat\":@\"🧥\",\n                @\"socks\":@\"🧦\",\n                @\"red_envelope\":@\"🧧\",\n                @\"firecracker\":@\"🧨\",\n                @\"jigsaw\":@\"🧩\",\n                @\"test_tube\":@\"🧪\",\n                @\"petri_dish\":@\"🧫\",\n                @\"dna\":@\"🧬\",\n                @\"compass\":@\"🧭\",\n                @\"abacus\":@\"🧮\",\n                @\"fire_extinguisher\":@\"🧯\",\n                @\"toolbox\":@\"🧰\",\n                @\"bricks\":@\"🧱\",\n                @\"magnet\":@\"🧲\",\n                @\"luggage\":@\"🧳\",\n                @\"lotion_bottle\":@\"🧴\",\n                @\"thread\":@\"🧵\",\n                @\"yarn\":@\"🧶\",\n                @\"safety_pin\":@\"🧷\",\n                @\"teddy_bear\":@\"🧸\",\n                @\"broom\":@\"🧹\",\n                @\"basket\":@\"🧺\",\n                @\"roll_of_paper\":@\"🧻\",\n                @\"soap\":@\"🧼\",\n                @\"sponge\":@\"🧽\",\n                @\"receipt\":@\"🧾\",\n                @\"nazar_amulet\":@\"🧿\",\n                @\"ballet_shoes\":@\"🩰\",\n                @\"one-piece_swimsuit\":@\"🩱\",\n                @\"briefs\":@\"🩲\",\n                @\"shorts\":@\"🩳\",\n                @\"thong_sandal\":@\"🩴\",\n                @\"light_blue_heart\":@\"🩵\",\n                @\"grey_heart\":@\"🩶\",\n                @\"pink_heart\":@\"🩷\",\n                @\"drop_of_blood\":@\"🩸\",\n                @\"adhesive_bandage\":@\"🩹\",\n                @\"stethoscope\":@\"🩺\",\n                @\"x-ray\":@\"🩻\",\n                @\"crutch\":@\"🩼\",\n                @\"yo-yo\":@\"🪀\",\n                @\"kite\":@\"🪁\",\n                @\"parachute\":@\"🪂\",\n                @\"boomerang\":@\"🪃\",\n                @\"magic_wand\":@\"🪄\",\n                @\"pinata\":@\"🪅\",\n                @\"nesting_dolls\":@\"🪆\",\n                @\"maracas\":@\"🪇\",\n                @\"flute\":@\"🪈\",\n                @\"harp\":@\"🪉\",\n                @\"shovel\":@\"🪏\",\n                @\"ringed_planet\":@\"🪐\",\n                @\"chair\":@\"🪑\",\n                @\"razor\":@\"🪒\",\n                @\"axe\":@\"🪓\",\n                @\"diya_lamp\":@\"🪔\",\n                @\"banjo\":@\"🪕\",\n                @\"military_helmet\":@\"🪖\",\n                @\"accordion\":@\"🪗\",\n                @\"long_drum\":@\"🪘\",\n                @\"coin\":@\"🪙\",\n                @\"carpentry_saw\":@\"🪚\",\n                @\"screwdriver\":@\"🪛\",\n                @\"ladder\":@\"🪜\",\n                @\"hook\":@\"🪝\",\n                @\"mirror\":@\"🪞\",\n                @\"window\":@\"🪟\",\n                @\"plunger\":@\"🪠\",\n                @\"sewing_needle\":@\"🪡\",\n                @\"knot\":@\"🪢\",\n                @\"bucket\":@\"🪣\",\n                @\"mouse_trap\":@\"🪤\",\n                @\"toothbrush\":@\"🪥\",\n                @\"headstone\":@\"🪦\",\n                @\"placard\":@\"🪧\",\n                @\"rock\":@\"🪨\",\n                @\"mirror_ball\":@\"🪩\",\n                @\"identification_card\":@\"🪪\",\n                @\"low_battery\":@\"🪫\",\n                @\"hamsa\":@\"🪬\",\n                @\"folding_hand_fan\":@\"🪭\",\n                @\"hair_pick\":@\"🪮\",\n                @\"khanda\":@\"🪯\",\n                @\"fly\":@\"🪰\",\n                @\"worm\":@\"🪱\",\n                @\"beetle\":@\"🪲\",\n                @\"cockroach\":@\"🪳\",\n                @\"potted_plant\":@\"🪴\",\n                @\"wood\":@\"🪵\",\n                @\"feather\":@\"🪶\",\n                @\"lotus\":@\"🪷\",\n                @\"coral\":@\"🪸\",\n                @\"empty_nest\":@\"🪹\",\n                @\"nest_with_eggs\":@\"🪺\",\n                @\"hyacinth\":@\"🪻\",\n                @\"jellyfish\":@\"🪼\",\n                @\"wing\":@\"🪽\",\n                @\"leafless_tree\":@\"🪾\",\n                @\"goose\":@\"🪿\",\n                @\"anatomical_heart\":@\"🫀\",\n                @\"lungs\":@\"🫁\",\n                @\"people_hugging\":@\"🫂\",\n                @\"pregnant_man\":@\"🫃\",\n                @\"pregnant_person\":@\"🫄\",\n                @\"person_with_crown\":@\"🫅\",\n                @\"fingerprint\":@\"🫆\",\n                @\"moose\":@\"🫎\",\n                @\"donkey\":@\"🫏\",\n                @\"blueberries\":@\"🫐\",\n                @\"bell_pepper\":@\"🫑\",\n                @\"olive\":@\"🫒\",\n                @\"flatbread\":@\"🫓\",\n                @\"tamale\":@\"🫔\",\n                @\"fondue\":@\"🫕\",\n                @\"teapot\":@\"🫖\",\n                @\"pouring_liquid\":@\"🫗\",\n                @\"beans\":@\"🫘\",\n                @\"jar\":@\"🫙\",\n                @\"ginger_root\":@\"🫚\",\n                @\"pea_pod\":@\"🫛\",\n                @\"root_vegetable\":@\"🫜\",\n                @\"splatter\":@\"🫟\",\n                @\"melting_face\":@\"🫠\",\n                @\"saluting_face\":@\"🫡\",\n                @\"face_with_open_eyes_and_hand_over_mouth\":@\"🫢\",\n                @\"face_with_peeking_eye\":@\"🫣\",\n                @\"face_with_diagonal_mouth\":@\"🫤\",\n                @\"dotted_line_face\":@\"🫥\",\n                @\"biting_lip\":@\"🫦\",\n                @\"bubbles\":@\"🫧\",\n                @\"shaking_face\":@\"🫨\",\n                @\"face_with_bags_under_eyes\":@\"🫩\",\n                @\"hand_with_index_finger_and_thumb_crossed\":@\"🫰\",\n                @\"rightwards_hand\":@\"🫱\",\n                @\"leftwards_hand\":@\"🫲\",\n                @\"palm_down_hand\":@\"🫳\",\n                @\"palm_up_hand\":@\"🫴\",\n                @\"index_pointing_at_the_viewer\":@\"🫵\",\n                @\"heart_hands\":@\"🫶\",\n                @\"leftwards_pushing_hand\":@\"🫷\",\n                @\"rightwards_pushing_hand\":@\"🫸\",\n                @\"bangbang\":@\"‼️\",\n                @\"interrobang\":@\"⁉️\",\n                @\"tm\":@\"™️\",\n                @\"information_source\":@\"ℹ️\",\n                @\"left_right_arrow\":@\"↔️\",\n                @\"arrow_up_down\":@\"↕️\",\n                @\"arrow_upper_left\":@\"↖️\",\n                @\"arrow_upper_right\":@\"↗️\",\n                @\"arrow_lower_right\":@\"↘️\",\n                @\"arrow_lower_left\":@\"↙️\",\n                @\"leftwards_arrow_with_hook\":@\"↩️\",\n                @\"arrow_right_hook\":@\"↪️\",\n                @\"watch\":@\"⌚\",\n                @\"hourglass\":@\"⌛\",\n                @\"keyboard\":@\"⌨️\",\n                @\"eject\":@\"⏏️\",\n                @\"fast_forward\":@\"⏩\",\n                @\"rewind\":@\"⏪\",\n                @\"arrow_double_up\":@\"⏫\",\n                @\"arrow_double_down\":@\"⏬\",\n                @\"black_right_pointing_double_triangle_with_vertical_bar\":@\"⏭️\",\n                @\"black_left_pointing_double_triangle_with_vertical_bar\":@\"⏮️\",\n                @\"black_right_pointing_triangle_with_double_vertical_bar\":@\"⏯️\",\n                @\"alarm_clock\":@\"⏰\",\n                @\"stopwatch\":@\"⏱️\",\n                @\"timer_clock\":@\"⏲️\",\n                @\"hourglass_flowing_sand\":@\"⏳\",\n                @\"double_vertical_bar\":@\"⏸️\",\n                @\"black_square_for_stop\":@\"⏹️\",\n                @\"black_circle_for_record\":@\"⏺️\",\n                @\"m\":@\"Ⓜ️\",\n                @\"black_small_square\":@\"▪️\",\n                @\"white_small_square\":@\"▫️\",\n                @\"arrow_forward\":@\"▶️\",\n                @\"arrow_backward\":@\"◀️\",\n                @\"white_medium_square\":@\"◻️\",\n                @\"black_medium_square\":@\"◼️\",\n                @\"white_medium_small_square\":@\"◽\",\n                @\"black_medium_small_square\":@\"◾\",\n                @\"sunny\":@\"☀️\",\n                @\"cloud\":@\"☁️\",\n                @\"umbrella\":@\"☂️\",\n                @\"snowman\":@\"☃️\",\n                @\"comet\":@\"☄️\",\n                @\"phone\":@\"☎️\",\n                @\"telephone\":@\"☎️\",\n                @\"ballot_box_with_check\":@\"☑️\",\n                @\"shamrock\":@\"☘️\",\n                @\"point_up\":@\"☝️\",\n                @\"skull_and_crossbones\":@\"☠️\",\n                @\"radioactive_sign\":@\"☢️\",\n                @\"biohazard_sign\":@\"☣️\",\n                @\"orthodox_cross\":@\"☦️\",\n                @\"star_and_crescent\":@\"☪️\",\n                @\"peace_symbol\":@\"☮️\",\n                @\"yin_yang\":@\"☯️\",\n                @\"wheel_of_dharma\":@\"☸️\",\n                @\"white_frowning_face\":@\"☹️\",\n                @\"relaxed\":@\"☺️\",\n                @\"female_sign\":@\"♀️\",\n                @\"male_sign\":@\"♂️\",\n                @\"gemini\":@\"♊\",\n                @\"cancer\":@\"♋\",\n                @\"leo\":@\"♌\",\n                @\"virgo\":@\"♍\",\n                @\"libra\":@\"♎\",\n                @\"scorpius\":@\"♏\",\n                @\"chess_pawn\":@\"♟️\",\n                @\"spades\":@\"♠️\",\n                @\"clubs\":@\"♣️\",\n                @\"hearts\":@\"♥️\",\n                @\"diamonds\":@\"♦️\",\n                @\"hotsprings\":@\"♨️\",\n                @\"recycle\":@\"♻️\",\n                @\"infinity\":@\"♾️\",\n                @\"wheelchair\":@\"♿\",\n                @\"hammer_and_pick\":@\"⚒️\",\n                @\"crossed_swords\":@\"⚔️\",\n                @\"medical_symbol\":@\"⚕️\",\n                @\"staff_of_aesculapius\":@\"⚕️\",\n                @\"scales\":@\"⚖️\",\n                @\"alembic\":@\"⚗️\",\n                @\"gear\":@\"⚙️\",\n                @\"atom_symbol\":@\"⚛️\",\n                @\"fleur_de_lis\":@\"⚜️\",\n                @\"warning\":@\"⚠️\",\n                @\"zap\":@\"⚡\",\n                @\"transgender_symbol\":@\"⚧️\",\n                @\"white_circle\":@\"⚪\",\n                @\"black_circle\":@\"⚫\",\n                @\"coffin\":@\"⚰️\",\n                @\"funeral_urn\":@\"⚱️\",\n                @\"soccer\":@\"⚽\",\n                @\"baseball\":@\"⚾\",\n                @\"snowman_without_snow\":@\"⛄\",\n                @\"partly_sunny\":@\"⛅\",\n                @\"thunder_cloud_and_rain\":@\"⛈️\",\n                @\"ophiuchus\":@\"⛎\",\n                @\"pick\":@\"⛏️\",\n                @\"helmet_with_white_cross\":@\"⛑️\",\n                @\"broken_chain\":@\"⛓️‍💥\",\n                @\"chains\":@\"⛓️\",\n                @\"no_entry\":@\"⛔\",\n                @\"shinto_shrine\":@\"⛩️\",\n                @\"church\":@\"⛪\",\n                @\"mountain\":@\"⛰️\",\n                @\"umbrella_on_ground\":@\"⛱️\",\n                @\"fountain\":@\"⛲\",\n                @\"golf\":@\"⛳\",\n                @\"ferry\":@\"⛴️\",\n                @\"boat\":@\"⛵\",\n                @\"sailboat\":@\"⛵\",\n                @\"skier\":@\"⛷️\",\n                @\"ice_skate\":@\"⛸️\",\n                @\"woman-bouncing-ball\":@\"⛹️‍♀️\",\n                @\"man-bouncing-ball\":@\"⛹️‍♂️\",\n                @\"person_with_ball\":@\"⛹️‍♂️\",\n                @\"tent\":@\"⛺\",\n                @\"fuelpump\":@\"⛽\",\n                @\"scissors\":@\"✂️\",\n                @\"airplane\":@\"✈️\",\n                @\"email\":@\"✉️\",\n                @\"envelope\":@\"✉️\",\n                @\"fist\":@\"✊\",\n                @\"hand\":@\"✋\",\n                @\"raised_hand\":@\"✋\",\n                @\"v\":@\"✌️\",\n                @\"writing_hand\":@\"✍️\",\n                @\"pencil2\":@\"✏️\",\n                @\"black_nib\":@\"✒️\",\n                @\"heavy_check_mark\":@\"✔️\",\n                @\"heavy_multiplication_x\":@\"✖️\",\n                @\"latin_cross\":@\"✝️\",\n                @\"star_of_david\":@\"✡️\",\n                @\"eight_spoked_asterisk\":@\"✳️\",\n                @\"eight_pointed_black_star\":@\"✴️\",\n                @\"snowflake\":@\"❄️\",\n                @\"sparkle\":@\"❇️\",\n                @\"x\":@\"❌\",\n                @\"negative_squared_cross_mark\":@\"❎\",\n                @\"heavy_heart_exclamation_mark_ornament\":@\"❣️\",\n                @\"heart_on_fire\":@\"❤️‍🔥\",\n                @\"mending_heart\":@\"❤️‍🩹\",\n                @\"heart\":@\"❤️\",\n                @\"arrow_right\":@\"➡️\",\n                @\"curly_loop\":@\"➰\",\n                @\"loop\":@\"➿\",\n                @\"arrow_heading_up\":@\"⤴️\",\n                @\"arrow_heading_down\":@\"⤵️\",\n                @\"arrow_left\":@\"⬅️\",\n                @\"arrow_up\":@\"⬆️\",\n                @\"arrow_down\":@\"⬇️\",\n                @\"black_large_square\":@\"⬛\",\n                @\"white_large_square\":@\"⬜\",\n                @\"star\":@\"⭐\",\n                @\"o\":@\"⭕\",\n                @\"wavy_dash\":@\"〰️\",\n                @\"part_alternation_mark\":@\"〽️\",\n                @\"congratulations\":@\"㊗️\",\n                @\"secret\":@\"㊙️\",\n\n                @\"like\":@\"👍\",\n                @\"thumbs_up\":@\"👍\",\n                @\"dislike\":@\"👎\",\n                @\"thumbs_down\":@\"👎\",\n                @\"doge\":@\"🐕\",\n                @\"aubergine\":@\"🍆\",\n                @\"gust_of_wind\":@\"💨\",\n                @\"party_popper\":@\"🎉\",\n                @\"shock\":@\"😱\",\n                @\"atom\":@\"⚛️\",\n                @\"<3\":@\"❤️\",\n                @\"</3\":@\"💔\",\n                @\"simple_smile\":@\"🙂\",\n                @\":)\":@\"🙂\",\n                @\":-)\":@\"🙂\",\n                @\")\":@\"🙂\",\n                @\"-)\":@\"🙂\",\n                @\"=D\":@\"😃\",\n                @\":D\":@\"😀\",\n                @\"D\":@\"😀\",\n                @\":(\":@\"😞\",\n                @\"(\":@\"😞\",\n                @\":'(\":@\"😢\",\n                @\"'(\":@\"😢\",\n                @\":_(\":@\"😭\",\n                @\"_(\":@\"😭\",\n                @\"loudly_crying_face\":@\"😭\",\n                @\"sad_tears\":@\"😭\",\n                @\"bawl\":@\"😭\",\n                @\";)\":@\"😉\",\n                @\";p\":@\"😜\",\n                @\"XD\":@\"😆\",\n                @\"^_^\":@\"😄\",\n                @\"^_^;\":@\"😅\",\n                @\"rofl\":@\"🤣\",\n                @\":|\":@\"😐\",\n                @\"|\":@\"😐\",\n                @\">.<\":@\"😣\",\n                @\"ufo\":@\"🛸\",\n                @\"female_wizard\":@\"🧙‍♀️\",\n                @\"male_wizard\":@\"🧙‍♂️\",\n                @\"brontosaurus\":@\"🦕\",\n                @\"diplodocus\":@\"🦕\",\n                @\"tyrannosaurus\":@\"🦖\",\n                @\"steak\":@\"🥩\",\n                @\"soup_tin\":@\"🥫\",\n                @\"baseball_cap\":@\"🧢\",\n                @\"female_yoga\":@\"🧘‍♀️\",\n                @\"male_yoga\":@\"🧘‍♂️\",\n                @\"female_sauna\":@\"🧖‍♀️\",\n                @\"male_sauna\":@\"🧖‍♂️\",\n                @\"hijab\":@\"🧕\",\n                @\"ladybird\":@\"🐞\",\n                @\"ladybug\":@\"🐞\",\n                @\"ladybeetle\":@\"🐞\",\n                @\"coccinellid\":@\"🐞\",\n                @\"diamond\":@\"💎\",\n                @\"angel_face\":@\"😇\",\n                @\"smiling_devil\":@\"😈\",\n                @\"frowning_devil\":@\"👿\",\n                @\"mad_rage\":@\"😡\",\n                @\"angry_rage\":@\"😡\",\n                @\"mad\":@\"😠\",\n                @\"steam_train\":@\"🚂\",\n                @\"graduation_cap\":@\"🎓\",\n                @\"lightbulb\":@\"💡\",\n                @\"cool_dude\":@\"😎\",\n                @\"deal_with_it\":@\"😎\",\n                @\"liar\":@\"🤥\",\n                @\"bunny\":@\"🐰\",\n                @\"bunny2\":@\"🐇\",\n                @\"cigarette\":@\"🚬\",\n                @\"fag\":@\"🚬\",\n                @\"water_wave\":@\"🌊\",\n                @\"crazy_face\":@\"🤪\",\n                @\"sh\":@\"🤫\",\n                @\"angry_swearing\":@\"🤬\",\n                @\"mad_swearing\":@\"🤬\",\n                @\"cursing\":@\"🤬\",\n                @\"swearing\":@\"🤬\",\n                @\"pissed_off\":@\"🤬\",\n                @\"fuck\":@\"🤬\",\n                @\"oops\":@\"🤭\",\n                @\"throwing_up\":@\"🤮\",\n                @\"being_sick\":@\"🤮\",\n                @\"mind_blown\":@\"🤯\",\n                @\"lightning_bolt\":@\"⚡\",\n                @\"confetti\":@\"🎊\",\n                @\"rubbish\":@\"🗑️\",\n                @\"trash\":@\"🗑️\",\n                @\"garbage\":@\"🗑️\",\n                @\"bin\":@\"🗑️\",\n                @\"wastepaper_basket\":@\"🗑️\",\n            };\n        \n        static NSRegularExpression *_pattern;\n        if(!_pattern) {\n            NSError *err;\n            NSString *pattern = [NSString stringWithFormat:@\"\\\\B:(%@):\\\\B\", [[[[[emojiMap.allKeys componentsJoinedByString:@\"|\"] stringByReplacingOccurrencesOfString:@\"-\" withString:@\"\\\\-\"] stringByReplacingOccurrencesOfString:@\"+\" withString:@\"\\\\+\"] stringByReplacingOccurrencesOfString:@\"(\" withString:@\"\\\\(\"] stringByReplacingOccurrencesOfString:@\")\" withString:@\"\\\\)\"]];\n            _pattern = [NSRegularExpression\n                        regularExpressionWithPattern:pattern\n                        options:NSRegularExpressionCaseInsensitive\n                        error:&err];\n        }\n        return _pattern;\n    }\n}\n\n+(NSRegularExpression *)emojiOnlyPattern {\n    @synchronized (self) {\n        if(!emojiMap)\n            [self emoji];\n        \n        static NSRegularExpression *_pattern;\n        if(!_pattern) {\n            NSString *pattern = [[NSString stringWithFormat:@\"(?:%@|\\xE2\\x80\\x8D|\\xEF\\xB8\\x8F)\", [emojiMap.allValues componentsJoinedByString:@\"|\"]] stringByReplacingOccurrencesOfString:@\"|:)\" withString:@\"\"];\n            NSMutableString *pattern_escaped = [@\"\" mutableCopy];\n            \n            NSScanner *scanner = [NSScanner scannerWithString:pattern];\n            while (![scanner isAtEnd]) {\n                NSString *tempString;\n                [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@\"*\"] intoString:&tempString];\n                if([scanner isAtEnd]){\n                    [pattern_escaped appendString:tempString];\n                }\n                else {\n                    [pattern_escaped appendFormat:@\"%@\\\\%@\", tempString, [pattern substringWithRange:NSMakeRange([scanner scanLocation], 1)]];\n                    [scanner setScanLocation:[scanner scanLocation]+1];\n                }\n            }\n            _pattern = [NSRegularExpression regularExpressionWithPattern:pattern_escaped options:NSRegularExpressionCaseInsensitive error:nil];\n        }\n        return _pattern;\n    }\n}\n\n+(NSRegularExpression *)spotify {\n    @synchronized (self) {\n        static NSRegularExpression *_pattern = nil;\n        if(!_pattern) {\n            NSString *pattern = @\"spotify:([^<>()\\\"\\\\s]+)\";\n            _pattern = [NSRegularExpression\n                        regularExpressionWithPattern:pattern\n                        options:NSRegularExpressionCaseInsensitive\n                        error:nil];\n        }\n        return _pattern;\n    }\n}\n\n+(NSRegularExpression *)geo {\n    @synchronized (self) {\n        static NSRegularExpression *_pattern = nil;\n        if(!_pattern) {\n            NSString *pattern = @\"geo:([^<>()\\\"\\\\s]+)\";\n            _pattern = [NSRegularExpression\n                        regularExpressionWithPattern:pattern\n                        options:NSRegularExpressionCaseInsensitive\n                        error:nil];\n        }\n        return _pattern;\n    }\n}\n\n+(NSRegularExpression *)email {\n    @synchronized (self) {\n        static NSRegularExpression *_pattern = nil;\n        if(!_pattern) {\n            //Ported from Android: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/util/Patterns.java\n            NSString *pattern = @\"[a-zA-Z0-9\\\\+\\\\.\\\\_\\\\%\\\\-\\\\+]{1,256}\\\\@[a-zA-Z0-9][a-zA-Z0-9\\\\-]{0,64}(\\\\.[a-zA-Z0-9][a-zA-Z0-9\\\\-]{0,25})+\";\n            _pattern = [NSRegularExpression\n                        regularExpressionWithPattern:pattern\n                        options:NSRegularExpressionCaseInsensitive\n                        error:nil];\n        }\n        return _pattern;\n    }\n}\n\n+(NSRegularExpression *)webURL {\n    @synchronized (self) {\n        static NSRegularExpression *_pattern = nil;\n        if(!_pattern) {\n            //Ported from Android: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/util/Patterns.java\n            NSString *IANA_TOP_LEVEL_DOMAINS = @\"(?:\\\n(?:aaa|aarp|abarth|abb|abbott|abbvie|abc|able|abogado|abudhabi|academy|accenture|accountant|accountants|aco|actor|adac|ads|adult|aeg|aero|aetna|afamilycompany|afl|africa|agakhan|agency|aig|aigo|airbus|airforce|airtel|akdn|alfaromeo|alibaba|alipay|allfinanz|allstate|ally|alsace|alstom|americanexpress|americanfamily|amex|amfam|amica|amsterdam|analytics|android|anquan|anz|aol|apartments|app|apple|aquarelle|arab|aramco|archi|army|arpa|art|arte|asda|asia|associates|athleta|attorney|auction|audi|audible|audio|auspost|author|auto|autos|avianca|aws|axa|azure|a[cdefgilmoqrstuwxz])\\\n|(?:baby|baidu|banamex|bananarepublic|band|bank|bar|barcelona|barclaycard|barclays|barefoot|bargains|baseball|basketball|bauhaus|bayern|bbc|bbt|bbva|bcg|bcn|beats|beauty|beer|bentley|berlin|best|bestbuy|bet|bharti|bible|bid|bike|bing|bingo|bio|biz|black|blackfriday|blockbuster|blog|bloomberg|blue|bms|bmw|bnpparibas|boats|boehringer|bofa|bom|bond|boo|book|booking|bosch|bostik|boston|bot|boutique|box|bradesco|bridgestone|broadway|broker|brother|brussels|budapest|bugatti|build|builders|business|buy|buzz|bzh|b[abdefghijmnorstvwyz])\\\n|(?:cab|cafe|cal|call|calvinklein|cam|camera|camp|cancerresearch|canon|capetown|capital|capitalone|car|caravan|cards|care|career|careers|cars|cartier|casa|case|caseih|cash|casino|cat|catering|catholic|cba|cbn|cbre|cbs|ceb|center|ceo|cern|cfa|cfd|chanel|channel|charity|chase|chat|cheap|chintai|christmas|chrome|chrysler|church|cipriani|circle|cisco|citadel|citi|citic|city|cityeats|claims|cleaning|click|clinic|clinique|clothing|cloud|club|clubmed|coach|codes|coffee|college|cologne|com|comcast|commbank|community|company|compare|computer|comsec|condos|construction|consulting|contact|contractors|cooking|cookingchannel|cool|coop|corsica|country|coupon|coupons|courses|cpa|credit|creditcard|creditunion|cricket|crown|crs|cruise|cruises|csc|cuisinella|cymru|cyou|c[acdfghiklmnoruvwxyz])\\\n|(?:dabur|dad|dance|data|date|dating|datsun|day|dclk|dds|deal|dealer|deals|degree|delivery|dell|deloitte|delta|democrat|dental|dentist|desi|design|dev|dhl|diamonds|diet|digital|direct|directory|discount|discover|dish|diy|dnp|docs|doctor|dodge|dog|domains|dot|download|drive|dtv|dubai|duck|dunlop|dupont|durban|dvag|dvr|d[ejkmoz])\\\n|(?:earth|eat|eco|edeka|edu|education|email|emerck|energy|engineer|engineering|enterprises|epson|equipment|ericsson|erni|esq|estate|esurance|etisalat|eurovision|eus|events|everbank|exchange|expert|exposed|express|extraspace|e[cegrstu])\\\n|(?:fage|fail|fairwinds|faith|family|fan|fans|farm|farmers|fashion|fast|fedex|feedback|ferrari|ferrero|fiat|fidelity|fido|film|final|finance|financial|fire|firestone|firmdale|fish|fishing|fit|fitness|flickr|flights|flir|florist|flowers|fly|foo|food|foodnetwork|football|ford|forex|forsale|forum|foundation|fox|free|fresenius|frl|frogans|frontdoor|frontier|ftr|fujitsu|fujixerox|fun|fund|furniture|futbol|fyi|f[ijkmor])\\\n|(?:gal|gallery|gallo|gallup|game|games|gap|garden|gay|gbiz|gdn|gea|gent|genting|george|ggee|gift|gifts|gives|giving|glade|glass|gle|global|globo|gmail|gmbh|gmo|gmx|godaddy|gold|goldpoint|golf|goo|goodyear|goog|google|gop|got|gov|grainger|graphics|gratis|green|gripe|grocery|group|guardian|gucci|guge|guide|guitars|guru|g[abdefghilmnpqrstuwy])\\\n|(?:hair|hamburg|hangout|haus|hbo|hdfc|hdfcbank|health|healthcare|help|helsinki|here|hermes|hgtv|hiphop|hisamitsu|hitachi|hiv|hkt|hockey|holdings|holiday|homedepot|homegoods|homes|homesense|honda|horse|hospital|host|hosting|hot|hoteles|hotels|hotmail|house|how|hsbc|hughes|hyatt|hyundai|h[kmnrtu])\\\n|(?:ibm|icbc|ice|icu|ieee|ifm|ikano|imamat|imdb|immo|immobilien|inc|industries|infiniti|info|ing|ink|institute|insurance|insure|int|intel|international|intuit|investments|ipiranga|irish|ismaili|ist|istanbul|itau|itv|iveco|i[delmnoqrst])\\\n|(?:jaguar|java|jcb|jcp|jeep|jetzt|jewelry|jio|jll|jmp|jnj|jobs|joburg|jot|joy|jpmorgan|jprs|juegos|juniper|j[emop])\\\n|(?:kaufen|kddi|kerryhotels|kerrylogistics|kerryproperties|kfh|kia|kim|kinder|kindle|kitchen|kiwi|koeln|komatsu|kosher|kpmg|kpn|krd|kred|kuokgroup|kyoto|k[eghimnprwyz])\\\n|(?:lacaixa|ladbrokes|lamborghini|lamer|lancaster|lancia|lancome|land|landrover|lanxess|lasalle|lat|latino|latrobe|law|lawyer|lds|lease|leclerc|lefrak|legal|lego|lexus|lgbt|liaison|lidl|life|lifeinsurance|lifestyle|lighting|like|lilly|limited|limo|lincoln|linde|link|lipsy|live|living|lixil|llc|loan|loans|locker|locus|loft|lol|london|lotte|lotto|love|lpl|lplfinancial|ltd|ltda|lundbeck|lupin|luxe|luxury|l[abcikrstuvy])\\\n|(?:macys|madrid|maif|maison|makeup|man|management|mango|map|market|marketing|markets|marriott|marshalls|maserati|mattel|mba|mckinsey|med|media|meet|melbourne|meme|memorial|men|menu|merckmsd|metlife|miami|microsoft|mil|mini|mint|mit|mitsubishi|mlb|mls|mma|mobi|mobile|moda|moe|moi|mom|monash|money|monster|mopar|mormon|mortgage|moscow|moto|motorcycles|mov|movie|movistar|msd|mtn|mtr|museum|mutual|m[acdeghklmnopqrstuvwxyz])\\\n|(?:nab|nadex|nagoya|name|nationwide|natura|navy|nba|nec|net|netbank|netflix|network|neustar|new|newholland|news|next|nextdirect|nexus|nfl|ngo|nhk|nico|nike|nikon|ninja|nissan|nissay|nokia|northwesternmutual|norton|now|nowruz|nowtv|nra|nrw|ntt|nyc|n[acefgilopruz])\\\n|(?:obi|observer|off|office|okinawa|olayan|olayangroup|oldnavy|ollo|omega|one|ong|onl|online|onyourside|ooo|open|oracle|orange|org|organic|origins|osaka|otsuka|ott|ovh|om)\\\n|(?:page|panasonic|paris|pars|partners|parts|party|passagens|pay|pccw|pet|pfizer|pharmacy|phd|philips|phone|photo|photography|photos|physio|piaget|pics|pictet|pictures|pid|pin|ping|pink|pioneer|pizza|place|play|playstation|plumbing|plus|pnc|pohl|poker|politie|porn|post|pramerica|praxi|press|prime|pro|prod|productions|prof|progressive|promo|properties|property|protection|pru|prudential|pub|pwc|p[aefghklmnrstwy])\\\n|(?:qpon|quebec|quest|qvc|qa)\\\n|(?:racing|radio|raid|read|realestate|realtor|realty|recipes|red|redstone|redumbrella|rehab|reise|reisen|reit|reliance|ren|rent|rentals|repair|report|republican|rest|restaurant|review|reviews|rexroth|rich|richardli|ricoh|rightathome|ril|rio|rip|rmit|rocher|rocks|rodeo|rogers|room|rsvp|rugby|ruhr|run|rwe|ryukyu|r[eosuw])\\\n|(?:saarland|safe|safety|sakura|sale|salon|samsclub|samsung|sandvik|sandvikcoromant|sanofi|sap|sarl|sas|save|saxo|sbi|sbs|sca|scb|schaeffler|schmidt|scholarships|school|schule|schwarz|science|scjohnson|scor|scot|search|seat|secure|security|seek|select|sener|services|ses|seven|sew|sex|sexy|sfr|shangrila|sharp|shaw|shell|shia|shiksha|shoes|shop|shopping|shouji|show|showtime|shriram|silk|sina|singles|site|ski|skin|sky|skype|sling|smart|smile|sncf|soccer|social|softbank|software|sohu|solar|solutions|song|sony|soy|space|sport|spot|spreadbetting|srl|srt|stada|staples|star|statebank|statefarm|stc|stcgroup|stockholm|storage|store|stream|studio|study|style|sucks|supplies|supply|support|surf|surgery|suzuki|swatch|swiftcover|swiss|sydney|symantec|systems|s[abcdeghijklmnorstuvxyz])\\\n|(?:tab|taipei|talk|taobao|target|tatamotors|tatar|tattoo|tax|taxi|tci|tdk|team|tech|technology|tel|telefonica|temasek|tennis|teva|thd|theater|theatre|tiaa|tickets|tienda|tiffany|tips|tires|tirol|tjmaxx|tjx|tkmaxx|tmall|today|tokyo|tools|top|toray|toshiba|total|tours|town|toyota|toys|trade|trading|training|travel|travelchannel|travelers|travelersinsurance|trust|trv|tube|tui|tunes|tushu|tvs|t[cdfghjklmnortvwz])\\\n|(?:ubank|ubs|uconnect|unicom|university|uno|uol|ups|u[agksyz])\\\n|(?:vacations|vana|vanguard|vegas|ventures|verisign|versicherung|vet|viajes|video|vig|viking|villas|vin|vip|virgin|visa|vision|vistaprint|viva|vivo|vlaanderen|vodka|volkswagen|volvo|vote|voting|voto|voyage|vuelos|v[aceginu])\\\n|(?:wales|walmart|walter|wang|wanggou|warman|watch|watches|weather|weatherchannel|webcam|weber|website|wed|wedding|weibo|weir|whoswho|wien|wiki|williamhill|win|windows|wine|winners|wme|wolterskluwer|woodside|work|works|world|wow|wtc|wtf|w[fs])\\\n|(?:\\\\u03b5\\\\u03bb|\\\\u03b5\\\\u03c5|\\\\u0431\\\\u0433|\\\\u0431\\\\u0435\\\\u043b|\\\\u0434\\\\u0435\\\\u0442\\\\u0438|\\\\u0435\\\\u044e|\\\\u043a\\\\u0430\\\\u0442\\\\u043e\\\\u043b\\\\u0438\\\\u043a|\\\\u043a\\\\u043e\\\\u043c|\\\\u043c\\\\u043a\\\\u0434|\\\\u043c\\\\u043e\\\\u043d|\\\\u043c\\\\u043e\\\\u0441\\\\u043a\\\\u0432\\\\u0430|\\\\u043e\\\\u043d\\\\u043b\\\\u0430\\\\u0439\\\\u043d|\\\\u043e\\\\u0440\\\\u0433|\\\\u0440\\\\u0443\\\\u0441|\\\\u0440\\\\u0444|\\\\u0441\\\\u0430\\\\u0439\\\\u0442|\\\\u0441\\\\u0440\\\\u0431|\\\\u0443\\\\u043a\\\\u0440|\\\\u049b\\\\u0430\\\\u0437|\\\\u0570\\\\u0561\\\\u0575|\\\\u05e7\\\\u05d5\\\\u05dd|\\\\u0627\\\\u0628\\\\u0648\\\\u0638\\\\u0628\\\\u064a|\\\\u0627\\\\u062a\\\\u0635\\\\u0627\\\\u0644\\\\u0627\\\\u062a|\\\\u0627\\\\u0631\\\\u0627\\\\u0645\\\\u0643\\\\u0648|\\\\u0627\\\\u0644\\\\u0627\\\\u0631\\\\u062f\\\\u0646|\\\\u0627\\\\u0644\\\\u062c\\\\u0632\\\\u0627\\\\u0626\\\\u0631|\\\\u0627\\\\u0644\\\\u0633\\\\u0639\\\\u0648\\\\u062f\\\\u064a\\\\u0629|\\\\u0627\\\\u0644\\\\u0639\\\\u0644\\\\u064a\\\\u0627\\\\u0646|\\\\u0627\\\\u0644\\\\u0645\\\\u063a\\\\u0631\\\\u0628|\\\\u0627\\\\u0645\\\\u0627\\\\u0631\\\\u0627\\\\u062a|\\\\u0627\\\\u06cc\\\\u0631\\\\u0627\\\\u0646|\\\\u0628\\\\u0627\\\\u0631\\\\u062a|\\\\u0628\\\\u0627\\\\u0632\\\\u0627\\\\u0631|\\\\u0628\\\\u064a\\\\u062a\\\\u0643|\\\\u0628\\\\u06be\\\\u0627\\\\u0631\\\\u062a|\\\\u062a\\\\u0648\\\\u0646\\\\u0633|\\\\u0633\\\\u0648\\\\u062f\\\\u0627\\\\u0646|\\\\u0633\\\\u0648\\\\u0631\\\\u064a\\\\u0629|\\\\u0634\\\\u0628\\\\u0643\\\\u0629|\\\\u0639\\\\u0631\\\\u0627\\\\u0642|\\\\u0639\\\\u0631\\\\u0628|\\\\u0639\\\\u0645\\\\u0627\\\\u0646|\\\\u0641\\\\u0644\\\\u0633\\\\u0637\\\\u064a\\\\u0646|\\\\u0642\\\\u0637\\\\u0631|\\\\u0643\\\\u0627\\\\u062b\\\\u0648\\\\u0644\\\\u064a\\\\u0643|\\\\u0643\\\\u0648\\\\u0645|\\\\u0645\\\\u0635\\\\u0631|\\\\u0645\\\\u0644\\\\u064a\\\\u0633\\\\u064a\\\\u0627|\\\\u0645\\\\u0648\\\\u0631\\\\u064a\\\\u062a\\\\u0627\\\\u0646\\\\u064a\\\\u0627|\\\\u0645\\\\u0648\\\\u0642\\\\u0639|\\\\u0647\\\\u0645\\\\u0631\\\\u0627\\\\u0647|\\\\u067e\\\\u0627\\\\u06a9\\\\u0633\\\\u062a\\\\u0627\\\\u0646|\\\\u0680\\\\u0627\\\\u0631\\\\u062a|\\\\u0915\\\\u0949\\\\u092e|\\\\u0928\\\\u0947\\\\u091f|\\\\u092d\\\\u093e\\\\u0930\\\\u0924|\\\\u092d\\\\u093e\\\\u0930\\\\u0924\\\\u092e\\\\u094d|\\\\u092d\\\\u093e\\\\u0930\\\\u094b\\\\u0924|\\\\u0938\\\\u0902\\\\u0917\\\\u0920\\\\u0928|\\\\u09ac\\\\u09be\\\\u0982\\\\u09b2\\\\u09be|\\\\u09ad\\\\u09be\\\\u09b0\\\\u09a4|\\\\u09ad\\\\u09be\\\\u09f0\\\\u09a4|\\\\u0a2d\\\\u0a3e\\\\u0a30\\\\u0a24|\\\\u0aad\\\\u0abe\\\\u0ab0\\\\u0aa4|\\\\u0b2d\\\\u0b3e\\\\u0b30\\\\u0b24|\\\\u0b87\\\\u0ba8\\\\u0bcd\\\\u0ba4\\\\u0bbf\\\\u0baf\\\\u0bbe|\\\\u0b87\\\\u0bb2\\\\u0b99\\\\u0bcd\\\\u0b95\\\\u0bc8|\\\\u0b9a\\\\u0bbf\\\\u0b99\\\\u0bcd\\\\u0b95\\\\u0baa\\\\u0bcd\\\\u0baa\\\\u0bc2\\\\u0bb0\\\\u0bcd|\\\\u0c2d\\\\u0c3e\\\\u0c30\\\\u0c24\\\\u0c4d|\\\\u0cad\\\\u0cbe\\\\u0cb0\\\\u0ca4|\\\\u0d2d\\\\u0d3e\\\\u0d30\\\\u0d24\\\\u0d02|\\\\u0dbd\\\\u0d82\\\\u0d9a\\\\u0dcf|\\\\u0e04\\\\u0e2d\\\\u0e21|\\\\u0e44\\\\u0e17\\\\u0e22|\\\\u10d2\\\\u10d4|\\\\u307f\\\\u3093\\\\u306a|\\\\u30af\\\\u30e9\\\\u30a6\\\\u30c9|\\\\u30b0\\\\u30fc\\\\u30b0\\\\u30eb|\\\\u30b3\\\\u30e0|\\\\u30b9\\\\u30c8\\\\u30a2|\\\\u30bb\\\\u30fc\\\\u30eb|\\\\u30d5\\\\u30a1\\\\u30c3\\\\u30b7\\\\u30e7\\\\u30f3|\\\\u30dd\\\\u30a4\\\\u30f3\\\\u30c8|\\\\u4e16\\\\u754c|\\\\u4e2d\\\\u4fe1|\\\\u4e2d\\\\u56fd|\\\\u4e2d\\\\u570b|\\\\u4e2d\\\\u6587\\\\u7f51|\\\\u4f01\\\\u4e1a|\\\\u4f5b\\\\u5c71|\\\\u4fe1\\\\u606f|\\\\u5065\\\\u5eb7|\\\\u516b\\\\u5366|\\\\u516c\\\\u53f8|\\\\u516c\\\\u76ca|\\\\u53f0\\\\u6e7e|\\\\u53f0\\\\u7063|\\\\u5546\\\\u57ce|\\\\u5546\\\\u5e97|\\\\u5546\\\\u6807|\\\\u5609\\\\u91cc|\\\\u5609\\\\u91cc\\\\u5927\\\\u9152\\\\u5e97|\\\\u5728\\\\u7ebf|\\\\u5927\\\\u4f17\\\\u6c7d\\\\u8f66|\\\\u5927\\\\u62ff|\\\\u5929\\\\u4e3b\\\\u6559|\\\\u5a31\\\\u4e50|\\\\u5bb6\\\\u96fb|\\\\u5de5\\\\u884c|\\\\u5e7f\\\\u4e1c|\\\\u5fae\\\\u535a|\\\\u6148\\\\u5584|\\\\u6211\\\\u7231\\\\u4f60|\\\\u624b\\\\u673a|\\\\u624b\\\\u8868|\\\\u62db\\\\u8058|\\\\u653f\\\\u52a1|\\\\u653f\\\\u5e9c|\\\\u65b0\\\\u52a0\\\\u5761|\\\\u65b0\\\\u95fb|\\\\u65f6\\\\u5c1a|\\\\u66f8\\\\u7c4d|\\\\u673a\\\\u6784|\\\\u6de1\\\\u9a6c\\\\u9521|\\\\u6e38\\\\u620f|\\\\u6fb3\\\\u9580|\\\\u70b9\\\\u770b|\\\\u73e0\\\\u5b9d|\\\\u79fb\\\\u52a8|\\\\u7ec4\\\\u7ec7\\\\u673a\\\\u6784|\\\\u7f51\\\\u5740|\\\\u7f51\\\\u5e97|\\\\u7f51\\\\u7ad9|\\\\u7f51\\\\u7edc|\\\\u8054\\\\u901a|\\\\u8bfa\\\\u57fa\\\\u4e9a|\\\\u8c37\\\\u6b4c|\\\\u8d2d\\\\u7269|\\\\u901a\\\\u8ca9|\\\\u96c6\\\\u56e2|\\\\u96fb\\\\u8a0a\\\\u76c8\\\\u79d1|\\\\u98de\\\\u5229\\\\u6d66|\\\\u98df\\\\u54c1|\\\\u9910\\\\u5385|\\\\u9999\\\\u683c\\\\u91cc\\\\u62c9|\\\\u9999\\\\u6e2f|\\\\ub2f7\\\\ub137|\\\\ub2f7\\\\ucef4|\\\\uc0bc\\\\uc131|\\\\ud55c\\\\uad6d|verm\\\\xf6gensberater|verm\\\\xf6gensberatung|xbox|xerox|xfinity|xihuan|xin|xn\\\\-\\\\-11b4c3d|xn\\\\-\\\\-1ck2e1b|xn\\\\-\\\\-1qqw23a|xn\\\\-\\\\-2scrj9c|xn\\\\-\\\\-30rr7y|xn\\\\-\\\\-3bst00m|xn\\\\-\\\\-3ds443g|xn\\\\-\\\\-3e0b707e|xn\\\\-\\\\-3hcrj9c|xn\\\\-\\\\-3oq18vl8pn36a|xn\\\\-\\\\-3pxu8k|xn\\\\-\\\\-42c2d9a|xn\\\\-\\\\-45br5cyl|xn\\\\-\\\\-45brj9c|xn\\\\-\\\\-45q11c|xn\\\\-\\\\-4gbrim|xn\\\\-\\\\-54b7fta0cc|xn\\\\-\\\\-55qw42g|xn\\\\-\\\\-55qx5d|xn\\\\-\\\\-5su34j936bgsg|xn\\\\-\\\\-5tzm5g|xn\\\\-\\\\-6frz82g|xn\\\\-\\\\-6qq986b3xl|xn\\\\-\\\\-80adxhks|xn\\\\-\\\\-80ao21a|xn\\\\-\\\\-80aqecdr1a|xn\\\\-\\\\-80asehdb|xn\\\\-\\\\-80aswg|xn\\\\-\\\\-8y0a063a|xn\\\\-\\\\-90a3ac|xn\\\\-\\\\-90ae|xn\\\\-\\\\-90ais|xn\\\\-\\\\-9dbq2a|xn\\\\-\\\\-9et52u|xn\\\\-\\\\-9krt00a|xn\\\\-\\\\-b4w605ferd|xn\\\\-\\\\-bck1b9a5dre4c|xn\\\\-\\\\-c1avg|xn\\\\-\\\\-c2br7g|xn\\\\-\\\\-cck2b3b|xn\\\\-\\\\-cg4bki|xn\\\\-\\\\-clchc0ea0b2g2a9gcd|xn\\\\-\\\\-czr694b|xn\\\\-\\\\-czrs0t|xn\\\\-\\\\-czru2d|xn\\\\-\\\\-d1acj3b|xn\\\\-\\\\-d1alf|xn\\\\-\\\\-e1a4c|xn\\\\-\\\\-eckvdtc9d|xn\\\\-\\\\-efvy88h|xn\\\\-\\\\-estv75g|xn\\\\-\\\\-fct429k|xn\\\\-\\\\-fhbei|xn\\\\-\\\\-fiq228c5hs|xn\\\\-\\\\-fiq64b|xn\\\\-\\\\-fiqs8s|xn\\\\-\\\\-fiqz9s|xn\\\\-\\\\-fjq720a|xn\\\\-\\\\-flw351e|xn\\\\-\\\\-fpcrj9c3d|xn\\\\-\\\\-fzc2c9e2c|xn\\\\-\\\\-fzys8d69uvgm|xn\\\\-\\\\-g2xx48c|xn\\\\-\\\\-gckr3f0f|xn\\\\-\\\\-gecrj9c|xn\\\\-\\\\-gk3at1e|xn\\\\-\\\\-h2breg3eve|xn\\\\-\\\\-h2brj9c|xn\\\\-\\\\-h2brj9c8c|xn\\\\-\\\\-hxt814e|xn\\\\-\\\\-i1b6b1a6a2e|xn\\\\-\\\\-imr513n|xn\\\\-\\\\-io0a7i|xn\\\\-\\\\-j1aef|xn\\\\-\\\\-j1amh|xn\\\\-\\\\-j6w193g|xn\\\\-\\\\-jlq61u9w7b|xn\\\\-\\\\-jvr189m|xn\\\\-\\\\-kcrx77d1x4a|xn\\\\-\\\\-kprw13d|xn\\\\-\\\\-kpry57d|xn\\\\-\\\\-kpu716f|xn\\\\-\\\\-kput3i|xn\\\\-\\\\-l1acc|xn\\\\-\\\\-lgbbat1ad8j|xn\\\\-\\\\-mgb9awbf|xn\\\\-\\\\-mgba3a3ejt|xn\\\\-\\\\-mgba3a4f16a|xn\\\\-\\\\-mgba7c0bbn0a|xn\\\\-\\\\-mgbaakc7dvf|xn\\\\-\\\\-mgbaam7a8h|xn\\\\-\\\\-mgbab2bd|xn\\\\-\\\\-mgbah1a3hjkrd|xn\\\\-\\\\-mgbai9azgqp6j|xn\\\\-\\\\-mgbayh7gpa|xn\\\\-\\\\-mgbbh1a|xn\\\\-\\\\-mgbbh1a71e|xn\\\\-\\\\-mgbc0a9azcg|xn\\\\-\\\\-mgbca7dzdo|xn\\\\-\\\\-mgberp4a5d4ar|xn\\\\-\\\\-mgbgu82a|xn\\\\-\\\\-mgbi4ecexp|xn\\\\-\\\\-mgbpl2fh|xn\\\\-\\\\-mgbt3dhd|xn\\\\-\\\\-mgbtx2b|xn\\\\-\\\\-mgbx4cd0ab|xn\\\\-\\\\-mix891f|xn\\\\-\\\\-mk1bu44c|xn\\\\-\\\\-mxtq1m|xn\\\\-\\\\-ngbc5azd|xn\\\\-\\\\-ngbe9e0a|xn\\\\-\\\\-ngbrx|xn\\\\-\\\\-node|xn\\\\-\\\\-nqv7f|xn\\\\-\\\\-nqv7fs00ema|xn\\\\-\\\\-nyqy26a|xn\\\\-\\\\-o3cw4h|xn\\\\-\\\\-ogbpf8fl|xn\\\\-\\\\-otu796d|xn\\\\-\\\\-p1acf|xn\\\\-\\\\-p1ai|xn\\\\-\\\\-pbt977c|xn\\\\-\\\\-pgbs0dh|xn\\\\-\\\\-pssy2u|xn\\\\-\\\\-q9jyb4c|xn\\\\-\\\\-qcka1pmc|xn\\\\-\\\\-qxa6a|xn\\\\-\\\\-qxam|xn\\\\-\\\\-rhqv96g|xn\\\\-\\\\-rovu88b|xn\\\\-\\\\-rvc1e0am3e|xn\\\\-\\\\-s9brj9c|xn\\\\-\\\\-ses554g|xn\\\\-\\\\-t60b56a|xn\\\\-\\\\-tckwe|xn\\\\-\\\\-tiq49xqyj|xn\\\\-\\\\-unup4y|xn\\\\-\\\\-vermgensberater\\\\-ctb|xn\\\\-\\\\-vermgensberatung\\\\-pwb|xn\\\\-\\\\-vhquv|xn\\\\-\\\\-vuq861b|xn\\\\-\\\\-w4r85el8fhu5dnra|xn\\\\-\\\\-w4rs40l|xn\\\\-\\\\-wgbh1c|xn\\\\-\\\\-wgbl6a|xn\\\\-\\\\-xhq521b|xn\\\\-\\\\-xkc2al3hye2a|xn\\\\-\\\\-xkc2dl3a5ee0h|xn\\\\-\\\\-y9a3aq|xn\\\\-\\\\-yfro4i67o|xn\\\\-\\\\-ygbi2ammx|xn\\\\-\\\\-zfr164b|xxx|xyz)\\\n|(?:yachts|yahoo|yamaxun|yandex|yodobashi|yoga|yokohama|you|youtube|yun|y[et])\\\n|(?:zappos|zara|zero|zip|zone|zuerich|z[amw]))\";\n            NSString *IP_ADDRESS_STRING = @\"((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\\\.(25[0-5]|2[0-4]\\\n[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\\\.(25[0-5]|2[0-4][0-9]|[0-1]\\\n[0-9]{2}|[1-9][0-9]|[1-9]|0)\\\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}\\\n|[1-9][0-9]|[0-9]))\";\n            NSString *UCS_CHAR = @\"[\\\n\\u00A0-\\uD7FF\\\n\\uF900-\\uFDCF\\\n\\uFDF0-\\uFFEF\\\n&&[^\\u00A0[\\u2000-\\u200A]\\u2028\\u2029\\u202F\\u3000]]\";\n\n            NSString *LABEL_CHAR = [NSString stringWithFormat:@\"a-zA-Z0-9%@\", UCS_CHAR];\n            NSString *IRI_LABEL = [NSString stringWithFormat:@\"[%@](?:[%@_\\\\-]{0,61}[%@]){0,1}\", LABEL_CHAR, LABEL_CHAR, LABEL_CHAR];\n            NSString *PUNYCODE_TLD = @\"xn\\\\-\\\\-[\\\\w\\\\-]{0,58}\\\\w\";\n            NSString *PROTOCOL = @\"[a-z_-]+://\";\n            NSString *WORD_BOUNDARY = @\"(?=\\\\b|$|^)\";\n            NSString *USER_INFO = @\"(?:[a-zA-Z0-9\\\\$\\\\-\\\\_\\\\.\\\\+\\\\!\\\\*\\\\'\\\\(\\\\)\\\n\\\\,\\\\;\\\\?\\\\&\\\\=]|(?:\\\\%[a-fA-F0-9]{2})){1,64}(?:\\\\:(?:[a-zA-Z0-9\\\\$\\\\-\\\\_\\\n\\\\.\\\\+\\\\!\\\\*\\\\'\\\\(\\\\)\\\\,\\\\;\\\\?\\\\&\\\\=]|(?:\\\\%[a-fA-F0-9]{2})){1,25})?\\\\@\";\n            NSString *PORT_NUMBER = @\"\\\\:\\\\d{1,5}\";\n            NSString *PATH_AND_QUERY = [NSString stringWithFormat:@\"[/\\\\?](?:(?:[%@;/\\\\?:@&=#~\\\\-\\\\.\\\\+!\\\\*'\\\\(\\\\),_\\\\$])|(?:%%[a-fA-F0-9]{2}))*\", LABEL_CHAR];\n            NSString *STRICT_TLD = [NSString stringWithFormat:@\"(?:%@|%@)\", IANA_TOP_LEVEL_DOMAINS, PUNYCODE_TLD];\n            NSString *STRICT_HOST_NAME = [NSString stringWithFormat:@\"(?:(?:%@\\\\.)+%@)\", IRI_LABEL, STRICT_TLD];\n            NSString *STRICT_DOMAIN_NAME = [NSString stringWithFormat:@\"(?:%@|%@)\", STRICT_HOST_NAME, IP_ADDRESS_STRING];\n            NSString *RELAXED_DOMAIN_NAME = [NSString stringWithFormat:@\"(?:(?:%@(?:\\\\.(?=\\\\S))?)+|%@)\", IRI_LABEL, IP_ADDRESS_STRING];\n\n            NSString *WEB_URL_WITHOUT_PROTOCOL = [NSString stringWithFormat:@\"(\\\n%@\\\n(?<!:\\\\/\\\\/)\\\n(\\\n(?:%@)\\\n(?:%@)?\\\n)\\\n(?:%@)?\\\n%@\\\n)\", WORD_BOUNDARY, STRICT_DOMAIN_NAME, PORT_NUMBER, PATH_AND_QUERY, WORD_BOUNDARY];\n            \n            NSString *WEB_URL_WITH_PROTOCOL = [NSString stringWithFormat:@\"(\\\n%@\\\n(?:\\\n(?:%@(?:%@)?)\\\n(?:%@)?\\\n(?:%@)?\\\n)\\\n(?:%@)?\\\n%@\\\n)\", WORD_BOUNDARY, PROTOCOL, USER_INFO, RELAXED_DOMAIN_NAME, PORT_NUMBER, PATH_AND_QUERY, WORD_BOUNDARY];\n            \n            NSString *pattern = [NSString stringWithFormat:@\"(%@|%@)\", WEB_URL_WITH_PROTOCOL, WEB_URL_WITHOUT_PROTOCOL];\n            _pattern = [NSRegularExpression\n                regularExpressionWithPattern:pattern\n                options:NSRegularExpressionCaseInsensitive|NSRegularExpressionUseUnicodeWordBoundaries\n                error:nil];\n        }\n        return _pattern;\n    }\n}\n\n+(NSRegularExpression *)ircChannelRegexForServer:(Server *)s {\n    @synchronized (self) {\n        NSString *pattern;\n        if(s && s.CHANTYPES.length) {\n            pattern = [NSString stringWithFormat:@\"(\\\\s|^)([%@][^\\\\ufe0e\\\\ufe0f\\\\u20e3<>\\\",\\\\s\\\\u0001][^<>\\\",\\\\s\\\\u0001]*)\", s.CHANTYPES];\n        } else {\n            pattern = [NSString stringWithFormat:@\"(\\\\s|^)([#][^\\\\ufe0e\\\\ufe0f\\\\u20e3<>\\\",\\\\s\\\\u0001][^<>\\\",\\\\s\\\\u0001]*)\"];\n        }\n        \n        return [NSRegularExpression\n                regularExpressionWithPattern:pattern\n                options:NSRegularExpressionCaseInsensitive\n                error:nil];\n    }\n}\n\n+(BOOL)unbalanced:(NSString *)input {\n    if(!quotes)\n        quotes = @{@\"\\\"\":@\"\\\"\",@\"'\": @\"'\",@\")\": @\"(\",@\"]\": @\"[\",@\"}\": @\"{\",@\">\": @\"<\",@\"”\": @\"“\",@\"’\": @\"‘\",@\"»\": @\"«\"};\n    \n    NSString *lastChar = [input substringFromIndex:input.length - 1];\n    \n    return [quotes objectForKey:lastChar] && [input componentsSeparatedByString:lastChar].count != [input componentsSeparatedByString:[quotes objectForKey:lastChar]].count;\n}\n\n+(void)setFont:(id)font start:(int)start length:(int)length attributes:(NSMutableArray *)attributes {\n    [attributes addObject:@{NSFontAttributeName:font,\n                            @\"start\":@(start),\n                            @\"length\":@(length)\n                            }];\n}\n\n+(void)loadFonts {\n    @synchronized (self) {\n        monoTimestampFont = [UIFont fontWithName:@\"Hack\" size:FONT_SIZE - 3];\n        timestampFont = [UIFont systemFontOfSize:FONT_SIZE - 2];\n        arrowFont = nil;\n        awesomeFont = [UIFont fontWithName:@\"FontAwesome\" size:FONT_SIZE];\n        Courier = [UIFont fontWithName:@\"Hack\" size:FONT_SIZE - 1];\n        CourierBold = [UIFont fontWithName:@\"Hack-Bold\" size:FONT_SIZE - 1];\n        CourierOblique = [UIFont fontWithName:@\"Hack-Italic\" size:FONT_SIZE - 1];\n        CourierBoldOblique = [UIFont fontWithName:@\"Hack-BoldItalic\" size:FONT_SIZE - 1];\n        chalkboardFont = [UIFont fontWithName:@\"ChalkboardSE-Light\" size:FONT_SIZE];\n        markerFont = [UIFont fontWithName:@\"MarkerFelt-Thin\" size:FONT_SIZE];\n        UIFontDescriptor *bodyFontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody];\n        UIFontDescriptor *boldBodyFontDescriptor = [bodyFontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold];\n        UIFontDescriptor *italicBodyFontDescriptor = [bodyFontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic];\n        UIFontDescriptor *boldItalicBodyFontDescriptor = [bodyFontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold|UIFontDescriptorTraitItalic];\n        Helvetica = [UIFont fontWithDescriptor:bodyFontDescriptor size:FONT_SIZE];\n        HelveticaBold = [UIFont fontWithDescriptor:boldBodyFontDescriptor size:FONT_SIZE];\n        HelveticaOblique = [UIFont fontWithDescriptor:italicBodyFontDescriptor size:FONT_SIZE];\n        HelveticaBoldOblique = [UIFont fontWithDescriptor:boldItalicBodyFontDescriptor size:FONT_SIZE];\n        largeEmojiFont = [UIFont fontWithDescriptor:bodyFontDescriptor size:FONT_SIZE * 2];\n        ColorFormatterCachedFontSize = FONT_SIZE;\n    }\n}\n\n+(void)emojify:(NSMutableString *)text {\n    [self _emojify:text mentions:nil];\n}\n\n+(void)_emojify:(NSMutableString *)text mentions:(NSMutableDictionary *)mentions {\n    NSInteger offset = 0;\n    NSArray *results = [[self emoji] matchesInString:[text lowercaseString] options:0 range:NSMakeRange(0, text.length)];\n    for(NSTextCheckingResult *result in results) {\n        for(int i = 1; i < result.numberOfRanges; i++) {\n            NSRange range = [result rangeAtIndex:i];\n            range.location -= offset;\n            NSString *token = [text substringWithRange:range];\n            if([emojiMap objectForKey:token.lowercaseString]) {\n                NSString *emoji = [emojiMap objectForKey:token.lowercaseString];\n                [text replaceCharactersInRange:NSMakeRange(range.location - 1, range.length + 2) withString:emoji];\n                offset += range.length - emoji.length + 2;\n                if(mentions) {\n                    [self _offsetMentions:mentions start:range.location offset:range.length - emoji.length + 2];\n                }\n            }\n        }\n    }\n}\n\n+(NSAttributedString *)format:(NSString *)input defaultColor:(UIColor *)color mono:(BOOL)mono linkify:(BOOL)linkify server:(Server *)server links:(NSArray **)links {\n    return [self format:input defaultColor:color mono:mono linkify:linkify server:server links:links largeEmoji:NO mentions:nil colorizeMentions:NO mentionOffset:0 mentionData:nil];\n}\n+(void)_offsetMentions:(NSMutableDictionary *)mentions start:(NSInteger)start offset:(NSInteger)offset {\n    for(NSString *key in mentions.allKeys) {\n        NSArray *mention = [mentions objectForKey:key];\n        NSMutableArray *new_mention = [[NSMutableArray alloc] initWithCapacity:mention.count];\n        for(NSArray *position in mention) {\n            if([[position objectAtIndex:0] intValue] >= start) {\n                [new_mention addObject:@[@([[position objectAtIndex:0] intValue] - offset),\n                                         @([[position objectAtIndex:1] intValue])]];\n            } else {\n                [new_mention addObject:position];\n            }\n        }\n        [mentions setObject:new_mention forKey:key];\n    }\n}\n\n+(NSAttributedString *)format:(NSString *)input defaultColor:(UIColor *)color mono:(BOOL)monospace linkify:(BOOL)linkify server:(Server *)server links:(NSArray **)links largeEmoji:(BOOL)largeEmoji mentions:(NSDictionary *)m colorizeMentions:(BOOL)colorizeMentions mentionOffset:(NSInteger)mentionOffset mentionData:(NSDictionary *)mentionData {\n    return [self format:input defaultColor:color mono:monospace linkify:linkify server:server links:links largeEmoji:largeEmoji mentions:m colorizeMentions:colorizeMentions mentionOffset:mentionOffset mentionData:mentionData stripColors:NO];\n}\n\n+(NSAttributedString *)format:(NSString *)input defaultColor:(UIColor *)color mono:(BOOL)monospace linkify:(BOOL)linkify server:(Server *)server links:(NSArray **)links largeEmoji:(BOOL)largeEmoji mentions:(NSDictionary *)m colorizeMentions:(BOOL)colorizeMentions mentionOffset:(NSInteger)mentionOffset mentionData:(NSDictionary *)mentionData stripColors:(BOOL)stripColors {\n    int bold = -1, italics = -1, underline = -1, fg = -1, bg = -1, mono = -1, strike = -1;\n    UIColor *fgColor = nil, *bgColor = nil, *oldFgColor = nil, *oldBgColor = nil;\n    id font, boldFont, italicFont, boldItalicFont;\n    NSMutableArray *matches = [[NSMutableArray alloc] init];\n    NSMutableDictionary *mentions = m.mutableCopy;\n    \n    if(!Courier) {\n        dispatch_sync(dispatch_get_main_queue(), ^{\n            [self loadFonts];\n        });\n    }\n    \n    if(monospace) {\n        font = Courier;\n        boldFont = CourierBold;\n        italicFont = CourierOblique;\n        boldItalicFont = CourierBoldOblique;\n    } else {\n        font = Helvetica;\n        boldFont = HelveticaBold;\n        italicFont = HelveticaOblique;\n        boldItalicFont = HelveticaBoldOblique;\n    }\n    NSMutableArray *attributes = [[NSMutableArray alloc] init];\n    NSMutableArray *arrowIndex = [[NSMutableArray alloc] init];\n    NSMutableArray *thinSpaceIndex = [[NSMutableArray alloc] init];\n\n    NSMutableString *text = [[NSMutableString alloc] initWithFormat:@\"%@%c\", [input stringByReplacingOccurrencesOfString:@\"  \" withString:@\"\\u00A0 \"], CLEAR];\n    \n    if(mentions) {\n        [self _offsetMentions:mentions start:0 offset:-mentionOffset];\n        \n        for(NSUInteger i = 0; i < text.length; i++) {\n            NSRange r = [text rangeOfComposedCharacterSequenceAtIndex:i];\n            if(r.length > 1) {\n                //iOS uses UTF-16 internally, if the combined character length differs between the two encodings then we need to adjust our offsets by 1 byte\n                NSString *c = [text substringWithRange:r];\n                NSData *utf8 = [c dataUsingEncoding:NSUTF8StringEncoding];\n                NSData *utf16 = [c dataUsingEncoding:NSUTF16StringEncoding];\n                if(utf8.length != utf16.length) {\n                    [self _offsetMentions:mentions start:i offset:-1];\n                    i++;\n                }\n            }\n        }\n        \n        for(NSString *key in mentions.allKeys) {\n            NSArray *mention = [mentions objectForKey:key];\n            for(NSArray *old_position in mention) {\n                NSMutableArray *position = old_position.mutableCopy;\n                if([[position objectAtIndex:0] intValue] >= 0 && [[position objectAtIndex:0] intValue] + [[position objectAtIndex:1] intValue] <= input.length) {\n                    [text replaceCharactersInRange:NSMakeRange([[position objectAtIndex:0] intValue], [[position objectAtIndex:1] intValue]) withString:[@\"\" stringByPaddingToLength:[[position objectAtIndex:1] intValue] withString:@\"A\" startingAtIndex:0]];\n                }\n            }\n        }\n    }\n    \n    BOOL disableConvert = [[NetworkConnection sharedInstance] prefs] && [[[[NetworkConnection sharedInstance] prefs] objectForKey:@\"emoji-disableconvert\"] boolValue];\n    if(!disableConvert) {\n        [self _emojify:text mentions:mentions];\n    }\n    \n    NSUInteger oldLength = 0;\n    for(int i = 0; i < text.length; i++) {\n        if(oldLength) {\n            NSInteger delta = oldLength - text.length;\n            if(mentions && delta) {\n                [self _offsetMentions:mentions start:i offset:delta];\n            }\n        }\n        oldLength = text.length;\n        switch([text characterAtIndex:i]) {\n            case 0x2190:\n            case 0x2192:\n            case 0x2194:\n            case 0x21D0:\n                if(arrowFont && i < text.length - 1 && [text characterAtIndex:i+1] == 0xFE0E) {\n                    [arrowIndex addObject:@(i)];\n                }\n                break;\n            case 0x202f:\n                [thinSpaceIndex addObject:@(i)];\n                break;\n            case BOLD:\n                if(bold == -1) {\n                    bold = i;\n                } else {\n                    if(mono != -1) {\n                        [self setFont:Courier start:mono length:(bold - mono) attributes:attributes];\n                        mono = i;\n                    }\n                    if(italics != -1) {\n                        if(italics < bold - 1) {\n                            [self setFont:italicFont start:italics length:(bold - italics) attributes:attributes];\n                        }\n                        [self setFont:boldItalicFont start:bold length:(i - bold) attributes:attributes];\n                        italics = i;\n                    } else {\n                        [self setFont:boldFont start:bold length:(i - bold) attributes:attributes];\n                    }\n                    bold = -1;\n                }\n                [text deleteCharactersInRange:NSMakeRange(i,1)];\n                i--;\n                continue;\n            case ITALICS:\n                if(italics == -1) {\n                    italics = i;\n                } else {\n                    if(mono != -1) {\n                        [self setFont:Courier start:mono length:(italics - mono) attributes:attributes];\n                        mono = i;\n                    }\n                    if(bold != -1) {\n                        if(bold < italics - 1) {\n                            [self setFont:boldFont start:bold length:(italics - bold) attributes:attributes];\n                        }\n                        [self setFont:boldItalicFont start:italics length:(i - italics) attributes:attributes];\n                        bold = i;\n                    } else {\n                        [self setFont:italicFont start:italics length:(i - italics) attributes:attributes];\n                    }\n                    italics = -1;\n                }\n                [text deleteCharactersInRange:NSMakeRange(i,1)];\n                i--;\n                continue;\n            case MONO:\n                if(mono == -1) {\n                    mono = i;\n                    boldFont = CourierBold;\n                    italicFont = CourierOblique;\n                    boldItalicFont = CourierBoldOblique;\n                    if(!fgColor && !bgColor) {\n                        fg = bg = i;\n                        fgColor = [UIColor codeSpanForegroundColor];\n                        bgColor = [UIColor codeSpanBackgroundColor];\n                    }\n                } else {\n                    [self setFont:Courier start:mono length:(i - mono) attributes:attributes];\n                    if(!monospace) {\n                        boldFont = HelveticaBold;\n                        italicFont = HelveticaOblique;\n                        boldItalicFont = HelveticaBoldOblique;\n                    }\n                    if(fg >= mono || bg >= mono) {\n                        if(fgColor)\n                            [attributes addObject:@{\n                                                NSBackgroundColorAttributeName:fgColor,\n                                                @\"start\":@(fg),\n                                                @\"length\":@(i - fg)\n                                                }];\n                        if(bgColor)\n                            [attributes addObject:@{\n                                                NSBackgroundColorAttributeName:bgColor,\n                                                @\"start\":@(bg),\n                                                @\"length\":@(i - bg)\n                                                }];\n                        fgColor = bgColor = nil;\n                        fg = bg = -1;\n                    }\n                    mono = -1;\n                }\n                [text deleteCharactersInRange:NSMakeRange(i,1)];\n                i--;\n                continue;\n            case UNDERLINE:\n                if(underline == -1) {\n                    underline = i;\n                } else {\n                    [attributes addObject:@{\n                     NSUnderlineStyleAttributeName:@1,\n                     @\"start\":@(underline),\n                     @\"length\":@(i - underline)\n                     }];\n                    underline = -1;\n                }\n                [text deleteCharactersInRange:NSMakeRange(i,1)];\n                i--;\n                continue;\n            case STRIKETHROUGH:\n                if(strike == -1) {\n                    strike = i;\n                } else {\n                    [attributes addObject:@{\n                                            NSStrikethroughStyleAttributeName:@1,\n                                            @\"start\":@(strike),\n                                            @\"length\":@(i - strike)\n                                            }];\n                    strike = -1;\n                }\n                [text deleteCharactersInRange:NSMakeRange(i,1)];\n                i--;\n                continue;\n            case REVERSE:\n            case 0x12:\n                if(fg != -1 && fgColor)\n                        [attributes addObject:@{\n                                                NSForegroundColorAttributeName:fgColor,\n                                                @\"start\":@(fg),\n                                                @\"length\":@(i - fg)\n                                                }];\n                if(bg != -1 && bgColor)\n                        [attributes addObject:@{\n                                                NSBackgroundColorAttributeName:bgColor,\n                                                @\"start\":@(bg),\n                                                @\"length\":@(i - bg)\n                                                }];\n                \n                fg = bg = i;\n                oldFgColor = fgColor;\n                fgColor = bgColor;\n                bgColor = oldFgColor;\n                if(!fgColor)\n                    fgColor = [UIColor mIRCColor:[UIColor isDarkTheme]?1:0 background:NO];\n                if(!bgColor)\n                    bgColor = [UIColor mIRCColor:[UIColor isDarkTheme]?0:1 background:YES];\n                [text deleteCharactersInRange:NSMakeRange(i,1)];\n                i--;\n                continue;\n            case COLOR_MIRC:\n            case COLOR_RGB:\n                oldFgColor = fgColor;\n                oldBgColor = bgColor;\n                BOOL rgb = [text characterAtIndex:i] == COLOR_RGB;\n                int count = 0;\n                int fg_color = -1;\n                [text deleteCharactersInRange:NSMakeRange(i,1)];\n                if(i < text.length) {\n                    while(i+count < text.length && (([text characterAtIndex:i+count] >= '0' && [text characterAtIndex:i+count] <= '9') ||\n                                                    (rgb && (([text characterAtIndex:i+count] >= 'a' && [text characterAtIndex:i+count] <= 'f')||\n                                                            ([text characterAtIndex:i+count] >= 'A' && [text characterAtIndex:i+count] <= 'F'))))) {\n                        if((++count == 2 && !rgb) || (count == 6))\n                            break;\n                    }\n                    if(count > 0) {\n                        if(count < 3 && !rgb) {\n                            fg_color = [[text substringWithRange:NSMakeRange(i, count)] intValue];\n                            if(fg_color > IRC_COLOR_COUNT) {\n                                count--;\n                                fg_color /= 10;\n                            } else if(fg_color == 99) {\n                                fg_color = -1;\n                                fgColor = nil;\n                            }\n                        } else {\n                            fgColor = [UIColor colorFromHexString:[text substringWithRange:NSMakeRange(i, count)]];\n                            fg_color = -1;\n                        }\n                        if(fg != -1 && !stripColors) {\n                            if(oldFgColor)\n                                [attributes addObject:@{\n                                                        NSForegroundColorAttributeName:oldFgColor,\n                                                        @\"start\":@(fg),\n                                                        @\"length\":@(i - fg)\n                                                        }];\n                        }\n                        [text deleteCharactersInRange:NSMakeRange(i,count)];\n                        fg = i;\n                    } else {\n                        fgColor = nil;\n                        bgColor = nil;\n                    }\n                }\n                if(i < text.length && [text characterAtIndex:i] == ',') {\n                    [text deleteCharactersInRange:NSMakeRange(i,1)];\n                    count = 0;\n                    while(i+count < text.length && (([text characterAtIndex:i+count] >= '0' && [text characterAtIndex:i+count] <= '9') ||\n                                                    (rgb && (([text characterAtIndex:i+count] >= 'a' && [text characterAtIndex:i+count] <= 'f')||\n                                                             ([text characterAtIndex:i+count] >= 'A' && [text characterAtIndex:i+count] <= 'F'))))) {\n                        if(++count == 2 && !rgb)\n                            break;\n                    }\n                    if(count > 0) {\n                        if(count < 3 && !rgb) {\n                            int color = [[text substringWithRange:NSMakeRange(i, count)] intValue];\n                            if(color > IRC_COLOR_COUNT) {\n                                count--;\n                                color /= 10;\n                            }\n                            if(color == 99) {\n                                bgColor = nil;\n                            } else {\n                                bgColor = [UIColor mIRCColor:color background:YES];\n                            }\n                        } else {\n                            bgColor = [UIColor colorFromHexString:[text substringWithRange:NSMakeRange(i, count)]];\n                        }\n                        if(bg != -1) {\n                            if(oldBgColor && !stripColors)\n                                [attributes addObject:@{\n                                                        NSBackgroundColorAttributeName:oldBgColor,\n                                                        @\"start\":@(bg),\n                                                        @\"length\":@(i - bg)\n                                                        }];\n                        }\n                        [text deleteCharactersInRange:NSMakeRange(i,count)];\n                        bg = i;\n                    } else {\n                        [text insertString:@\",\" atIndex:i];\n                    }\n                }\n                if(fg_color != -1)\n                    fgColor = [UIColor mIRCColor:fg_color background:bgColor != nil];\n                if(fg != -1 && fgColor == nil) {\n                    if(oldFgColor && !stripColors)\n                        [attributes addObject:@{\n                                                NSForegroundColorAttributeName:oldFgColor,\n                                                @\"start\":@(fg),\n                                                @\"length\":@(i - fg)\n                                                }];\n                    fg = -1;\n                }\n                if(bg != -1 && bgColor == nil) {\n                    if(oldBgColor && !stripColors)\n                        [attributes addObject:@{\n                                                NSBackgroundColorAttributeName:oldBgColor,\n                                                @\"start\":@(bg),\n                                                @\"length\":@(i - bg)\n                                                }];\n                    bg = -1;\n                }\n                i--;\n                continue;\n            case CLEAR:\n                if(fg != -1 && !stripColors) {\n                    [attributes addObject:@{\n                     NSForegroundColorAttributeName:fgColor,\n                     @\"start\":@(fg),\n                     @\"length\":@(i - fg)\n                     }];\n                }\n                fg = -1;\n                if(bg != -1 && !stripColors) {\n                    [attributes addObject:@{\n                     NSBackgroundColorAttributeName:bgColor,\n                     @\"start\":@(bg),\n                     @\"length\":@(i - bg)\n                     }];\n                }\n                bg = -1;\n                if(mono != -1) {\n                    [self setFont:Courier start:mono length:(i - mono) attributes:attributes];\n                }\n                if(bold != -1 && italics != -1) {\n                    if(bold < italics) {\n                        [self setFont:boldFont start:bold length:(italics - bold) attributes:attributes];\n                        [self setFont:boldItalicFont start:italics length:(i - italics) attributes:attributes];\n                    } else {\n                        [self setFont:italicFont start:italics length:(bold - italics) attributes:attributes];\n                        [self setFont:boldItalicFont start:bold length:(i - bold) attributes:attributes];\n                    }\n                } else if(bold != -1) {\n                    [self setFont:boldFont start:bold length:(i - bold) attributes:attributes];\n                } else if(italics != -1) {\n                    [self setFont:italicFont start:italics length:(i - italics) attributes:attributes];\n                }\n                if(underline != -1) {\n                    [attributes addObject:@{\n                     NSUnderlineStyleAttributeName:@1,\n                     @\"start\":@(underline),\n                     @\"length\":@(i - underline)\n                     }];\n                }\n                if(strike != -1) {\n                    [attributes addObject:@{\n                                            NSStrikethroughStyleAttributeName:@1,\n                                            @\"start\":@(strike),\n                                            @\"length\":@(i - strike)\n                                            }];\n                }\n                bold = italics = underline = mono = strike = -1;\n                if(!monospace) {\n                    boldFont = HelveticaBold;\n                    italicFont = HelveticaOblique;\n                    boldItalicFont = HelveticaBoldOblique;\n                }\n                [text deleteCharactersInRange:NSMakeRange(i,1)];\n                i--;\n                continue;\n        }\n    }\n    \n    NSMutableAttributedString *output = [[NSMutableAttributedString alloc] initWithString:text];\n    [output addAttributes:@{NSFontAttributeName:font} range:NSMakeRange(0, text.length)];\n    if(color)\n        [output addAttributes:@{(NSString *)NSForegroundColorAttributeName:color} range:NSMakeRange(0, text.length)];\n\n    for(NSNumber *i in arrowIndex) {\n        [output addAttributes:@{NSFontAttributeName:arrowFont} range:NSMakeRange([i intValue], 2)];\n    }\n    \n    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];\n    if(__compact)\n        paragraphStyle.lineSpacing = 0;\n    else\n        paragraphStyle.lineSpacing = MESSAGE_LINE_SPACING;\n    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;\n    [output addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [output length])];\n    \n    for(NSDictionary *dict in attributes) {\n        if([[dict objectForKey:@\"start\"] intValue] >= 0 && [[dict objectForKey:@\"length\"] intValue] > 0)\n            [output addAttributes:dict range:NSMakeRange([[dict objectForKey:@\"start\"] intValue], [[dict objectForKey:@\"length\"] intValue])];\n    }\n    \n    NSRange r = NSMakeRange(0, text.length);\n    do {\n        r = [text rangeOfString:@\"comic sans\" options:NSCaseInsensitiveSearch range:r];\n        if(r.location != NSNotFound) {\n            [output addAttributes:@{NSFontAttributeName:chalkboardFont} range:r];\n            r.location++;\n            r.length = text.length - r.location;\n        }\n    } while(r.location != NSNotFound);\n    \n    r = NSMakeRange(0, text.length);\n    do {\n        r = [text rangeOfString:@\"marker felt\" options:NSCaseInsensitiveSearch range:r];\n        if(r.location != NSNotFound) {\n            [output addAttributes:@{NSFontAttributeName:markerFont} range:r];\n            r.location++;\n            r.length = text.length - r.location;\n        }\n    } while(r.location != NSNotFound);\n    \n    if(linkify) {\n        NSArray *results = [[self email] matchesInString:[[output string] lowercaseString] options:0 range:NSMakeRange(0, [output length])];\n        for(NSTextCheckingResult *result in results) {\n            NSString *url = [[output string] substringWithRange:result.range];\n            url = [NSString stringWithFormat:@\"mailto:%@\", url];\n            [matches addObject:[NSTextCheckingResult linkCheckingResultWithRange:result.range URL:[NSURL URLWithString:url]]];\n        }\n        results = [[self spotify] matchesInString:[[output string] lowercaseString] options:0 range:NSMakeRange(0, [output length])];\n        for(NSTextCheckingResult *result in results) {\n            NSString *url = [[output string] substringWithRange:result.range];\n            [matches addObject:[NSTextCheckingResult linkCheckingResultWithRange:result.range URL:[NSURL URLWithString:url]]];\n        }\n        results = [[self geo] matchesInString:[[output string] lowercaseString] options:0 range:NSMakeRange(0, [output length])];\n        for(NSTextCheckingResult *result in results) {\n            NSString *url = [NSString stringWithFormat:@\"http://maps.apple.com/?ll=%@\",[[output string] substringWithRange:NSMakeRange(result.range.location+4, result.range.length-4)]];\n            [matches addObject:[NSTextCheckingResult linkCheckingResultWithRange:result.range URL:[NSURL URLWithString:url]]];\n        }\n        if(server) {\n            results = [[self ircChannelRegexForServer:server] matchesInString:[[output string] lowercaseString] options:0 range:NSMakeRange(0, [output length])];\n            if(results.count) {\n                for(NSTextCheckingResult *match in results) {\n                    NSRange matchRange = [match rangeAtIndex:2];\n                    unichar lastChar = [[output string] characterAtIndex:matchRange.location + matchRange.length - 1];\n                    if([self unbalanced:[output.string substringWithRange:matchRange]] || lastChar == '.' || lastChar == '?' || lastChar == '!' || lastChar == ',' || lastChar == ':' || lastChar == ';') {\n                        matchRange.length--;\n                    }\n                    if(matchRange.length > 1) {\n                        NSRange ranges[1] = {NSMakeRange(matchRange.location, matchRange.length)};\n                        [matches addObject:[NSTextCheckingResult regularExpressionCheckingResultWithRanges:ranges count:1 regularExpression:match.regularExpression]];\n                    }\n                }\n            }\n        }\n        [matches addObjectsFromArray:[self webURLs:output.string]];\n    } else {\n        if(server) {\n            NSArray *results = [[self ircChannelRegexForServer:server] matchesInString:[[output string] lowercaseString] options:0 range:NSMakeRange(0, [output length])];\n            if(results.count) {\n                for(NSTextCheckingResult *match in results) {\n                    NSRange matchRange = [match rangeAtIndex:2];\n                    if([[[output string] substringWithRange:matchRange] hasSuffix:@\".\"]) {\n                        NSRange ranges[1] = {NSMakeRange(matchRange.location, matchRange.length - 1)};\n                        [matches addObject:[NSTextCheckingResult regularExpressionCheckingResultWithRanges:ranges count:1 regularExpression:match.regularExpression]];\n                    } else {\n                        NSRange ranges[1] = {NSMakeRange(matchRange.location, matchRange.length)};\n                        [matches addObject:[NSTextCheckingResult regularExpressionCheckingResultWithRanges:ranges count:1 regularExpression:match.regularExpression]];\n                    }\n                }\n            }\n        }\n    }\n    if(links)\n        *links = [NSArray arrayWithArray:matches];\n    \n    if(largeEmoji) {\n        NSUInteger start = 0;\n        if(![text isEmojiOnly]) {\n            for(; start < text.length; start++)\n                if([[text substringFromIndex:start] isEmojiOnly])\n                    break;\n        }\n        \n        [output addAttributes:@{NSFontAttributeName:largeEmojiFont} range:NSMakeRange(start, text.length - start)];\n    }\n    \n    for(NSNumber *i in thinSpaceIndex) {\n        [output addAttributes:@{NSFontAttributeName:Helvetica} range:NSMakeRange([i intValue], 1)];\n    }\n    \n    if(mentions) {\n        for(NSString *nick in mentions.allKeys) {\n            NSArray *mention = [mentions objectForKey:nick];\n            for(int i = 0; i < mention.count; i++) {\n                int start = [[[mention objectAtIndex:i] objectAtIndex:0] intValue];\n                int length = [[[mention objectAtIndex:i] objectAtIndex:1] intValue];\n                NSString *name = nick;\n                if(start > 0 && start < output.string.length && [output.string characterAtIndex:start-1] == '@') {\n                    if([mentionData objectForKey:nick])\n                        name = [[mentionData objectForKey:nick] objectForKey:@\"display_name\"];\n                    else if(server.isSlack)\n                        name = [[UsersDataSource sharedInstance] getDisplayName:nick cid:server.cid];\n                    if(!name)\n                        name = nick;\n                }\n                if(!name || start < 0 || start + length >= (output.length + 1))\n                    continue;\n                [output replaceCharactersInRange:NSMakeRange(start, length) withString:name];\n                if(colorizeMentions && ![nick.lowercaseString isEqualToString:server.nick.lowercaseString]) {\n                    [output addAttribute:NSForegroundColorAttributeName value:[UIColor colorFromHexString:[UIColor colorForNick:nick]] range:NSMakeRange(start, name.length)];\n                } else {\n                    [output addAttribute:NSForegroundColorAttributeName value:[UIColor collapsedRowNickColor] range:NSMakeRange(start, name.length)];\n                }\n                NSInteger delta = nick.length - name.length;\n                if(delta) {\n                    [self _offsetMentions:mentions start:start offset:delta];\n                }\n            }\n        }\n    }\n\n    return output;\n}\n\n+(NSString *)toIRC:(NSAttributedString *)string {\n    NSString *text = string.string;\n    NSMutableString *formattedMsg = [[NSMutableString alloc] init];\n    \n    int index = 0;\n    NSRange range;\n    while(index < string.length) {\n        BOOL shouldClear = NO;\n        for(NSString *key in [string attributesAtIndex:index effectiveRange:&range]) {\n            NSString *fgColor = nil;\n            NSString *bgColor = nil;\n            int fgColormIRC = -1;\n            int bgColormIRC = -1;\n            if([key isEqualToString:NSFontAttributeName]) {\n                UIFont *font = [string attribute:key atIndex:index effectiveRange:nil];\n                if(font.fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold && ![[font.fontDescriptor objectForKey:@\"NSCTFontUIUsageAttribute\"] isEqualToString:@\"CTFontRegularUsage\"] && ![[font.fontDescriptor objectForKey:@\"NSCTFontUIUsageAttribute\"] isEqualToString:@\"UICTFontTextStyleBody\"]) {\n                    [formattedMsg appendFormat:@\"%c\", BOLD];\n                    shouldClear = YES;\n                }\n                if(font.fontDescriptor.symbolicTraits & UIFontDescriptorTraitItalic) {\n                    [formattedMsg appendFormat:@\"%c\", ITALICS];\n                    shouldClear = YES;\n                }\n            } else if([key isEqualToString:NSUnderlineStyleAttributeName]) {\n                NSNumber *style = [string attribute:key atIndex:index effectiveRange:nil];\n                if(style.integerValue != NSUnderlineStyleNone)\n                    [formattedMsg appendFormat:@\"%c\", UNDERLINE];\n                shouldClear = YES;\n            } else if([key isEqualToString:NSStrikethroughStyleAttributeName]) {\n                [formattedMsg appendFormat:@\"%c\", STRIKETHROUGH];\n                shouldClear = YES;\n            } else if([key isEqualToString:NSForegroundColorAttributeName]) {\n                UIColor *c = [string attribute:key atIndex:index effectiveRange:nil];\n                if(![c isEqual:[UIColor textareaTextColor]]) {\n                    fgColor = [c toHexString];\n                    fgColormIRC = [UIColor mIRCColor:c];\n                }\n            } else if([key isEqualToString:NSBackgroundColorAttributeName]) {\n                UIColor *c = [string attribute:key atIndex:index effectiveRange:nil];\n                if(![c isEqual:[UIColor textareaTextColor]]) {\n                    bgColor = [c toHexString];\n                    bgColormIRC = [UIColor mIRCColor:c];\n                }\n            }\n            \n            if(fgColor || bgColor) {\n                if((fgColormIRC != -1 && (!bgColor || bgColormIRC != -1)) || (!fgColor && bgColormIRC != -1)) {\n                    [formattedMsg appendFormat:@\"%c\", COLOR_MIRC];\n                    if(fgColormIRC != -1)\n                        [formattedMsg appendFormat:@\"%i\",fgColormIRC];\n                    if(bgColormIRC != -1)\n                        [formattedMsg appendFormat:@\",%i\",bgColormIRC];\n                } else {\n                    [formattedMsg appendFormat:@\"%c\", COLOR_RGB];\n                    if(fgColor)\n                        [formattedMsg appendString:fgColor];\n                    if(bgColor)\n                        [formattedMsg appendFormat:@\",%@\",bgColor];\n                }\n                shouldClear = YES;\n            }\n        }\n        \n        if(shouldClear)\n            [formattedMsg appendFormat:@\"%@%c\", [text substringWithRange:range], CLEAR];\n        else\n            [formattedMsg appendString:[text substringWithRange:range]];\n\n        index += range.length;\n    }\n    \n    return formattedMsg;\n}\n\n+(NSAttributedString *)stripUnsupportedAttributes:(NSAttributedString *)input fontSize:(CGFloat)fontSize {\n    NSMutableAttributedString *output = [[NSMutableAttributedString alloc] initWithString:input.string];\n    [output addAttribute:NSForegroundColorAttributeName value:[UIColor messageTextColor] range:NSMakeRange(0, input.length)];\n    \n    int index = 0;\n    NSRange range;\n    while(index < input.length) {\n        for(NSString *key in [input attributesAtIndex:index effectiveRange:&range]) {\n            if([key isEqualToString:NSFontAttributeName]) {\n                UIFont *font = [input attribute:key atIndex:index effectiveRange:nil];\n                [output addAttribute:key value:[UIFont fontWithDescriptor:font.fontDescriptor size:fontSize] range:range];\n            } else if([key isEqualToString:NSForegroundColorAttributeName] || [key isEqualToString:NSBackgroundColorAttributeName]) {\n                UIColor *c = [input attribute:key atIndex:index effectiveRange:nil];\n                CGFloat r,g,b,a;\n                [c getRed:&r green:&g blue:&b alpha:&a];\n                if([key isEqualToString:NSForegroundColorAttributeName] && (r > 0 || g > 0 || b > 0)) {\n                    [output addAttribute:key value:c range:range];\n                }\n                if([key isEqualToString:NSBackgroundColorAttributeName] && !(r == 1 && g == 1 && b == 1)) {\n                    [output addAttribute:key value:c range:range];\n                }\n            } else if([key isEqualToString:NSUnderlineStyleAttributeName] || [key isEqualToString:NSStrikethroughStyleAttributeName]) {\n                [output addAttribute:key value:[input attribute:key atIndex:index effectiveRange:nil] range:range];\n            }\n        }\n        index += range.length;\n    }\n    \n    return output;\n}\n\n+(NSArray *)webURLs:(NSString *)string {\n    NSMutableArray *matches = [[NSMutableArray alloc] init];\n    static NSMutableCharacterSet *urlSet = nil;\n    @synchronized (self) {\n        if(!urlSet) {\n            urlSet = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;\n            [urlSet addCharactersInString:@\"#%\"];\n        }\n    }\n    \n    if(string.length) {\n        NSArray *results = [[self webURL] matchesInString:string.lowercaseString options:0 range:NSMakeRange(0, string.length)];\n        NSPredicate *ipAddress = [NSPredicate predicateWithFormat:@\"SELF MATCHES %@\", @\"[0-9\\\\.]+\"];\n        \n        for(NSTextCheckingResult *result in results) {\n            BOOL overlap = NO;\n            for(NSTextCheckingResult *match in matches) {\n                if(result.range.location >= match.range.location && result.range.location <= match.range.location + match.range.length) {\n                    overlap = YES;\n                    break;\n                }\n            }\n            if(!overlap) {\n                NSRange range = result.range;\n                if(range.location + range.length < string.length && [string characterAtIndex:range.location + range.length - 1] != '/' && [string characterAtIndex:range.location + range.length] == '/')\n                    range.length++;\n                NSString *url = [string substringWithRange:result.range];\n                if([url hasSuffix:@\".\"] || [url hasSuffix:@\"?\"] || [url hasSuffix:@\"!\"] || [url hasSuffix:@\",\"] || [url hasSuffix:@\":\"] || [url hasSuffix:@\";\"]) {\n                    url = [url substringToIndex:url.length - 1];\n                    range.length--;\n                }\n                if([self unbalanced:url]) {\n                    url = [url substringToIndex:url.length - 1];\n                    range.length--;\n                }\n\n                NSString *scheme = nil;\n                NSString *credentials = @\"\";\n                NSString *hostname = @\"\";\n                NSString *rest = @\"\";\n                if([url rangeOfString:@\"://\"].location != NSNotFound)\n                    scheme = [[url componentsSeparatedByString:@\"://\"] objectAtIndex:0];\n                NSInteger start = (scheme.length?(scheme.length + 3):0);\n                \n                for(NSInteger i = start; i < url.length; i++) {\n                    char c = [url characterAtIndex:i];\n                    if(c == ':') { //Search for @ credentials\n                        for(NSInteger j = i; j < url.length; j++) {\n                            char c = [url characterAtIndex:j];\n                            if(c == '@') {\n                                j++;\n                                credentials = [url substringWithRange:NSMakeRange(start, j - start)];\n                                i = j;\n                                start += credentials.length;\n                                break;\n                            } else if(c == '/') {\n                                break;\n                            }\n                        }\n                        if(credentials.length)\n                            continue;\n                    }\n                    if(c == ':' || c == '/' || i == url.length - 1) {\n                        if(i < url.length - 1) {\n                            hostname = [NSURL IDNEncodedHostname:[url substringWithRange:NSMakeRange(start, i - start)]];\n                            rest = [url substringFromIndex:i];\n                        } else {\n                            hostname = [NSURL IDNEncodedHostname:[url substringFromIndex:start]];\n                        }\n                        break;\n                    }\n                }\n                \n                if(!scheme) {\n                    if([url hasPrefix:@\"irc.\"])\n                        scheme = @\"irc\";\n                    else\n                        scheme = @\"http\";\n                }\n                \n                url = [[NSString stringWithFormat:@\"%@://%@%@%@\", scheme, credentials, hostname, rest] stringByAddingPercentEncodingWithAllowedCharacters:urlSet];\n                \n                if([ipAddress evaluateWithObject:url]) {\n                    continue;\n                }\n                \n                [matches addObject:[NSTextCheckingResult linkCheckingResultWithRange:range URL:[NSURL URLWithString:url]]];\n            }\n        }\n        \n        results = [[NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber|NSTextCheckingTypeAddress error:nil] matchesInString:string options:0 range:NSMakeRange(0, string.length)];\n        for(NSTextCheckingResult *result in results) {\n            NSString *url = nil;\n            switch (result.resultType) {\n                case NSTextCheckingTypePhoneNumber:\n                    url = [NSString stringWithFormat:@\"telprompt:%@\", [result.phoneNumber stringByReplacingOccurrencesOfString:@\" \" withString:@\"\"]];\n                    break;\n                case NSTextCheckingTypeAddress:\n                    url = [NSString stringWithFormat:@\"https://maps.apple.com/?address=%@\", [result.addressComponents.allValues componentsJoinedByString:@\",\"]];\n                    break;\n                default:\n                    break;\n            }\n            \n            if(url) {\n                url = [url stringByAddingPercentEncodingWithAllowedCharacters:urlSet];\n                [matches addObject:[NSTextCheckingResult linkCheckingResultWithRange:result.range URL:[NSURL URLWithString:url]]];\n                url = nil;\n            }\n        }\n\n    }\n    return matches;\n}\n@end\n\n@implementation NSString (ColorFormatter)\n-(NSString *)stripIRCFormatting {\n    return [[ColorFormatter format:self defaultColor:[UIColor blackColor] mono:NO linkify:NO server:nil links:nil] string];\n}\n-(NSString *)stripIRCColors {\n    NSMutableString *text = self.mutableCopy;\n    BOOL rgb;\n    int fg_color;\n    \n    for(int i = 0; i < text.length; i++) {\n        switch([text characterAtIndex:i]) {\n            case COLOR_MIRC:\n            case COLOR_RGB:\n                rgb = [text characterAtIndex:i] == COLOR_RGB;\n                int count = 0;\n                [text deleteCharactersInRange:NSMakeRange(i,1)];\n                if(i < text.length) {\n                    while(i+count < text.length && (([text characterAtIndex:i+count] >= '0' && [text characterAtIndex:i+count] <= '9') ||\n                                                    (rgb && (([text characterAtIndex:i+count] >= 'a' && [text characterAtIndex:i+count] <= 'f')||\n                                                             ([text characterAtIndex:i+count] >= 'A' && [text characterAtIndex:i+count] <= 'F'))))) {\n                        if((++count == 2 && !rgb) || (count == 6))\n                            break;\n                    }\n                    if(count > 0) {\n                        if(count < 3 && !rgb) {\n                            fg_color = [[text substringWithRange:NSMakeRange(i, count)] intValue];\n                            if(fg_color > IRC_COLOR_COUNT) {\n                                count--;\n                            }\n                        }\n                        [text deleteCharactersInRange:NSMakeRange(i,count)];\n                    }\n                }\n                if(i < text.length && [text characterAtIndex:i] == ',') {\n                    [text deleteCharactersInRange:NSMakeRange(i,1)];\n                    count = 0;\n                    while(i+count < text.length && (([text characterAtIndex:i+count] >= '0' && [text characterAtIndex:i+count] <= '9') ||\n                                                    (rgb && (([text characterAtIndex:i+count] >= 'a' && [text characterAtIndex:i+count] <= 'f')||\n                                                             ([text characterAtIndex:i+count] >= 'A' && [text characterAtIndex:i+count] <= 'F'))))) {\n                        if(++count == 2 && !rgb)\n                            break;\n                    }\n                    if(count > 0) {\n                        if(count < 3 && !rgb) {\n                            int color = [[text substringWithRange:NSMakeRange(i, count)] intValue];\n                            if(color > IRC_COLOR_COUNT) {\n                                count--;\n                            }\n                        }\n                        [text deleteCharactersInRange:NSMakeRange(i,count)];\n                    } else {\n                        [text insertString:@\",\" atIndex:i];\n                    }\n                }\n                i--;\n                continue;\n        }\n    }\n    return text;\n}\n-(BOOL)isEmojiOnly {\n    if(!self || !self.length)\n        return NO;\n    \n    return [[ColorFormatter emojiOnlyPattern] stringByReplacingMatchesInString:self options:0 range:NSMakeRange(0, self.length) withTemplate:@\"\"].length == 0;\n}\n-(BOOL)isBlockQuote {\n    @synchronized (self) {\n        static NSPredicate *_pattern;\n        if(!_pattern) {\n            _pattern = [NSPredicate predicateWithFormat:@\"SELF MATCHES %@\", @\"(^|\\\\n)>(?![<>]|[\\\\W_](?:[<>/OoDpb|\\\\\\\\{}()\\\\[\\\\]](?=\\\\s|$)))([^\\\\n]+)\"];\n        }\n        return [_pattern evaluateWithObject:self];\n    }\n}\n-(NSString *)insertCodeSpans {\n    static NSRegularExpression *_pattern = nil;\n    @synchronized (self) {\n        if(!_pattern) {\n            NSString *pattern = @\"`([^`\\\\n]+?)`\";\n            _pattern = [NSRegularExpression\n                        regularExpressionWithPattern:pattern\n                        options:NSRegularExpressionCaseInsensitive\n                        error:nil];\n        }\n    }\n    NSMutableString *output = self.mutableCopy;\n    NSArray *result = [_pattern matchesInString:self options:0 range:NSMakeRange(0, self.length)];\n    while(result.count) {\n        NSRange range = [[result objectAtIndex:0] range];\n        [output replaceCharactersInRange:NSMakeRange(range.location, 1) withString:[NSString stringWithFormat:@\"%c\", MONO]];\n        [output replaceCharactersInRange:NSMakeRange(range.location + range.length - 1, 1) withString:[NSString stringWithFormat:@\"%c\", MONO]];\n        result = [_pattern matchesInString:self options:0 range:NSMakeRange(range.location + range.length, self.length - range.location - range.length)];\n    }\n    return output;\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/DisplayOptionsViewController.h",
    "content": "//\n//  DisplayOptionsViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"BuffersDataSource.h\"\n\n@interface DisplayOptionsViewController : UITableViewController {\n    Buffer *_buffer;\n    UISwitch *_showMembers;\n    UISwitch *_notifyAll;\n    UISwitch *_trackUnread;\n    UISwitch *_showJoinPart;\n    UISwitch *_collapseJoinPart;\n    UISwitch *_expandDisco;\n    UISwitch *_readOnSelect;\n    UISwitch *_disableInlineFiles;\n    UISwitch *_disableNickSuggestions;\n    UISwitch *_inlineImages;\n    UISwitch *_replyCollapse;\n    UISwitch *_muted;\n    UISwitch *_nocolors;\n    UISwitch *_typingStatus;\n}\n@property (strong) Buffer *buffer;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/DisplayOptionsViewController.m",
    "content": "//\n//  DisplayOptionsViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"DisplayOptionsViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@implementation DisplayOptionsViewController\n\n- (id)initWithStyle:(UITableViewStyle)style {\n    self = [super initWithStyle:style];\n    if (self) {\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveButtonPressed:)];\n        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];\n    }\n    return self;\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)saveButtonPressed:(id)sender {\n    UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n    [spinny startAnimating];\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinny];\n    NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithDictionary:[[NetworkConnection sharedInstance] prefs]];\n    NSMutableDictionary *disableTrackUnread = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *enableTrackUnread = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *notifyAll = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *disableNotifyAll = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *hideJoinPart = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *showJoinPart = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *expandJoinPart = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *collapseJoinPart = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *expandDisco = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *enableReadOnSelect = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *disableReadOnSelect = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *disableInlineFiles = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *inlineImages = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *disableInlineImages = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *hiddenMembers = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *replyCollapse = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *muted = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *disableMuted = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *colors = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *nocolors = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *disableTypingStatus = [[NSMutableDictionary alloc] init];\n    NSMutableDictionary *enableTypingStatus = [[NSMutableDictionary alloc] init];\n\n    if([self->_buffer.type isEqualToString:@\"channel\"]) {\n        NSMutableDictionary *disableNickSuggestions = [[[NSUserDefaults standardUserDefaults] objectForKey:@\"disable-nick-suggestions\"] mutableCopy];\n        if(!disableNickSuggestions)\n            disableNickSuggestions = [[NSMutableDictionary alloc] init];\n        \n        [disableNickSuggestions setObject:@(!_disableNickSuggestions.on) forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        [[NSUserDefaults standardUserDefaults] setObject:disableNickSuggestions forKey:@\"disable-nick-suggestions\"];\n        \n        if([[prefs objectForKey:@\"channel-enableReadOnSelect\"] isKindOfClass:[NSDictionary class]])\n            [enableReadOnSelect addEntriesFromDictionary:[prefs objectForKey:@\"channel-enableReadOnSelect\"]];\n        if([[prefs objectForKey:@\"channel-disableReadOnSelect\"] isKindOfClass:[NSDictionary class]])\n            [disableReadOnSelect addEntriesFromDictionary:[prefs objectForKey:@\"channel-disableReadOnSelect\"]];\n        if([[prefs objectForKey:@\"enableReadOnSelect\"] intValue] == 1) {\n            if(self->_readOnSelect.on)\n                [disableReadOnSelect removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [disableReadOnSelect setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(disableReadOnSelect.count)\n                [prefs setObject:enableReadOnSelect forKey:@\"channel-disableReadOnSelect\"];\n            else\n                [prefs removeObjectForKey:@\"channel-disableReadOnSelect\"];\n        } else {\n            if(!_readOnSelect.on)\n                [enableReadOnSelect removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [enableReadOnSelect setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(enableReadOnSelect.count)\n                [prefs setObject:enableReadOnSelect forKey:@\"channel-enableReadOnSelect\"];\n            else\n                [prefs removeObjectForKey:@\"channel-enableReadOnSelect\"];\n        }\n        \n        if([[prefs objectForKey:@\"channel-disableTrackUnread\"] isKindOfClass:[NSDictionary class]])\n            [disableTrackUnread addEntriesFromDictionary:[prefs objectForKey:@\"channel-disableTrackUnread\"]];\n        if([[prefs objectForKey:@\"channel-enableTrackUnread\"] isKindOfClass:[NSDictionary class]])\n            [enableTrackUnread addEntriesFromDictionary:[prefs objectForKey:@\"channel-enableTrackUnread\"]];\n        if([[prefs objectForKey:@\"disableTrackUnread\"] intValue] == 1) {\n            if(!_trackUnread.on)\n                [enableTrackUnread removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [enableTrackUnread setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(enableTrackUnread.count)\n                [prefs setObject:enableTrackUnread forKey:@\"channel-enableTrackUnread\"];\n            else\n                [prefs removeObjectForKey:@\"channel-enableTrackUnread\"];\n        } else {\n            if(self->_trackUnread.on)\n                [disableTrackUnread removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [disableTrackUnread setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(disableTrackUnread.count)\n                [prefs setObject:disableTrackUnread forKey:@\"channel-disableTrackUnread\"];\n            else\n                [prefs removeObjectForKey:@\"channel-disableTrackUnread\"];\n        }\n\n        if([[prefs objectForKey:@\"channel-notifications-all\"] isKindOfClass:[NSDictionary class]])\n            [notifyAll addEntriesFromDictionary:[prefs objectForKey:@\"channel-notifications-all\"]];\n        if([[prefs objectForKey:@\"channel-notifications-all-disable\"] isKindOfClass:[NSDictionary class]])\n            [disableNotifyAll addEntriesFromDictionary:[prefs objectForKey:@\"channel-notifications-all-disable\"]];\n        if([[prefs objectForKey:@\"notifications-all\"] intValue] == 1) {\n            if(!_notifyAll.on)\n                [disableNotifyAll setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [disableNotifyAll removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(disableNotifyAll.count)\n                [prefs setObject:disableNotifyAll forKey:@\"channel-notifications-all-disable\"];\n            else\n                [prefs removeObjectForKey:@\"channel-notifications-all-disable\"];\n        } else {\n            if(self->_notifyAll.on)\n                [notifyAll setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [notifyAll removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(notifyAll.count)\n                [prefs setObject:notifyAll forKey:@\"channel-notifications-all\"];\n            else\n                [prefs removeObjectForKey:@\"channel-notifications-all\"];\n        }\n        \n        if([[prefs objectForKey:@\"hideJoinPart\"] intValue] == 1) {\n            if([[prefs objectForKey:@\"channel-showJoinPart\"] isKindOfClass:[NSDictionary class]])\n                [showJoinPart addEntriesFromDictionary:[prefs objectForKey:@\"channel-showJoinPart\"]];\n            if(!self->_showJoinPart.on)\n                [showJoinPart removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [showJoinPart setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(showJoinPart.count)\n                [prefs setObject:showJoinPart forKey:@\"channel-showJoinPart\"];\n            else\n                [prefs removeObjectForKey:@\"channel-showJoinPart\"];\n        } else {\n            if([[prefs objectForKey:@\"channel-hideJoinPart\"] isKindOfClass:[NSDictionary class]])\n                [hideJoinPart addEntriesFromDictionary:[prefs objectForKey:@\"channel-hideJoinPart\"]];\n            if(self->_showJoinPart.on)\n                [hideJoinPart removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [hideJoinPart setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(hideJoinPart.count)\n                [prefs setObject:hideJoinPart forKey:@\"channel-hideJoinPart\"];\n            else\n                [prefs removeObjectForKey:@\"channel-hideJoinPart\"];\n        }\n\n        if([[prefs objectForKey:@\"channel-expandJoinPart\"] isKindOfClass:[NSDictionary class]])\n            [expandJoinPart addEntriesFromDictionary:[prefs objectForKey:@\"channel-expandJoinPart\"]];\n        if(self->_collapseJoinPart.on)\n            [expandJoinPart removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        else\n            [expandJoinPart setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        if(expandJoinPart.count)\n            [prefs setObject:expandJoinPart forKey:@\"channel-expandJoinPart\"];\n        else\n            [prefs removeObjectForKey:@\"channel-expandJoinPart\"];\n        \n        if([[prefs objectForKey:@\"channel-collapseJoinPart\"] isKindOfClass:[NSDictionary class]])\n            [collapseJoinPart addEntriesFromDictionary:[prefs objectForKey:@\"channel-collapseJoinPart\"]];\n        if(!_collapseJoinPart.on)\n            [collapseJoinPart removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        else\n            [collapseJoinPart setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        if(collapseJoinPart.count)\n            [prefs setObject:collapseJoinPart forKey:@\"channel-collapseJoinPart\"];\n        else\n            [prefs removeObjectForKey:@\"channel-collapseJoinPart\"];\n        \n        if([[prefs objectForKey:@\"channel-hiddenMembers\"] isKindOfClass:[NSDictionary class]])\n            [hiddenMembers addEntriesFromDictionary:[prefs objectForKey:@\"channel-hiddenMembers\"]];\n        if(self->_showMembers.on)\n            [hiddenMembers removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        else\n            [hiddenMembers setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        if(hiddenMembers.count)\n            [prefs setObject:hiddenMembers forKey:@\"channel-hiddenMembers\"];\n        else\n            [prefs removeObjectForKey:@\"channel-hiddenMembers\"];\n        \n        if([[prefs objectForKey:@\"channel-files-disableinline\"] isKindOfClass:[NSDictionary class]])\n            [disableInlineFiles addEntriesFromDictionary:[prefs objectForKey:@\"channel-files-disableinline\"]];\n        if(self->_disableInlineFiles.on)\n            [disableInlineFiles removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        else\n            [disableInlineFiles setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        if(disableInlineFiles.count)\n            [prefs setObject:disableInlineFiles forKey:@\"channel-files-disableinline\"];\n        else\n            [prefs removeObjectForKey:@\"channel-files-disableinline\"];\n\n        if([[prefs objectForKey:@\"channel-inlineimages\"] isKindOfClass:[NSDictionary class]])\n            [inlineImages addEntriesFromDictionary:[prefs objectForKey:@\"channel-inlineimages\"]];\n        if(self->_inlineImages.on)\n            [inlineImages setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        else\n            [inlineImages removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        if(inlineImages.count)\n            [prefs setObject:inlineImages forKey:@\"channel-inlineimages\"];\n        else\n            [prefs removeObjectForKey:@\"channel-inlineimages\"];\n\n        if([[prefs objectForKey:@\"channel-inlineimages-disable\"] isKindOfClass:[NSDictionary class]])\n            [disableInlineImages addEntriesFromDictionary:[prefs objectForKey:@\"channel-inlineimages-disable\"]];\n        if(self->_inlineImages.on)\n            [disableInlineImages removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        else\n            [disableInlineImages setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        if(disableInlineImages.count)\n            [prefs setObject:disableInlineImages forKey:@\"channel-inlineimages-disable\"];\n        else\n            [prefs removeObjectForKey:@\"channel-inlineimages-disable\"];\n        \n        if([[prefs objectForKey:@\"channel-reply-collapse\"] isKindOfClass:[NSDictionary class]])\n            [replyCollapse addEntriesFromDictionary:[prefs objectForKey:@\"channel-reply-collapse\"]];\n        if(self->_replyCollapse.on)\n            [replyCollapse setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        else\n            [replyCollapse removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n        if(replyCollapse.count)\n            [prefs setObject:replyCollapse forKey:@\"channel-reply-collapse\"];\n        else\n            [prefs removeObjectForKey:@\"channel-reply-collapse\"];\n        \n        if([[prefs objectForKey:@\"notifications-mute\"] intValue] == 1) {\n            if([[prefs objectForKey:@\"channel-notifications-mute-disable\"] isKindOfClass:[NSDictionary class]])\n                [disableMuted addEntriesFromDictionary:[prefs objectForKey:@\"channel-notifications-mute-disable\"]];\n            if(self->_muted.on)\n                [disableMuted removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [disableMuted setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(disableMuted.count)\n                [prefs setObject:disableMuted forKey:@\"channel-notifications-mute-disable\"];\n            else\n                [prefs removeObjectForKey:@\"channel-notifications-mute-disable\"];\n        } else {\n            if([[prefs objectForKey:@\"channel-notifications-mute\"] isKindOfClass:[NSDictionary class]])\n                [muted addEntriesFromDictionary:[prefs objectForKey:@\"channel-notifications-mute\"]];\n            if(self->_muted.on)\n                [muted setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [muted removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(muted.count)\n                [prefs setObject:muted forKey:@\"channel-notifications-mute\"];\n            else\n                [prefs removeObjectForKey:@\"channel-notifications-mute\"];\n        }\n        \n        if([[prefs objectForKey:@\"chat-nocolor\"] intValue] == 1) {\n            if([[prefs objectForKey:@\"channel-chat-color\"] isKindOfClass:[NSDictionary class]])\n                [colors addEntriesFromDictionary:[prefs objectForKey:@\"channel-chat-color\"]];\n            if(self->_nocolors.on)\n                [colors setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [colors removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(colors.count)\n                [prefs setObject:colors forKey:@\"channel-chat-color\"];\n            else\n                [prefs removeObjectForKey:@\"channel-chat-color\"];\n        } else {\n            if([[prefs objectForKey:@\"channel-chat-nocolor\"] isKindOfClass:[NSDictionary class]])\n                [nocolors addEntriesFromDictionary:[prefs objectForKey:@\"channel-chat-nocolor\"]];\n            if(self->_nocolors.on)\n                [nocolors removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [nocolors setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(nocolors.count)\n                [prefs setObject:nocolors forKey:@\"channel-chat-nocolor\"];\n            else\n                [prefs removeObjectForKey:@\"channel-chat-nocolor\"];\n        }\n        \n        if([[prefs objectForKey:@\"channel-disableTypingStatus\"] isKindOfClass:[NSDictionary class]])\n            [disableTypingStatus addEntriesFromDictionary:[prefs objectForKey:@\"channel-disableTypingStatus\"]];\n        if([[prefs objectForKey:@\"channel-enableTypingStatus\"] isKindOfClass:[NSDictionary class]])\n            [enableTypingStatus addEntriesFromDictionary:[prefs objectForKey:@\"channel-enableTypingStatus\"]];\n        if([[prefs objectForKey:@\"disableTypingStatus\"] intValue] == 1) {\n            if(!_typingStatus.on)\n                [enableTypingStatus removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [enableTypingStatus setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(enableTypingStatus.count)\n                [prefs setObject:enableTypingStatus forKey:@\"channel-enableTypingStatus\"];\n            else\n                [prefs removeObjectForKey:@\"channel-enableTypingStatus\"];\n        } else {\n            if(self->_typingStatus.on)\n                [disableTypingStatus removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [disableTypingStatus setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(disableTypingStatus.count)\n                [prefs setObject:disableTypingStatus forKey:@\"channel-disableTypingStatus\"];\n            else\n                [prefs removeObjectForKey:@\"channel-disableTypingStatus\"];\n        }\n    } else {\n        if([[prefs objectForKey:@\"buffer-disableReadOnSelect\"] isKindOfClass:[NSDictionary class]])\n            [disableReadOnSelect addEntriesFromDictionary:[prefs objectForKey:@\"buffer-disableReadOnSelect\"]];\n        if([[prefs objectForKey:@\"enableReadOnSelect\"] intValue] == 1) {\n            if(self->_readOnSelect.on)\n                [disableReadOnSelect removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [disableReadOnSelect setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(disableReadOnSelect.count)\n                [prefs setObject:enableReadOnSelect forKey:@\"buffer-disableReadOnSelect\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-disableReadOnSelect\"];\n        } else {\n            if(!_readOnSelect.on)\n                [enableReadOnSelect removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [enableReadOnSelect setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(enableReadOnSelect.count)\n                [prefs setObject:enableReadOnSelect forKey:@\"buffer-enableReadOnSelect\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-enableReadOnSelect\"];\n        }\n        \n        if([[prefs objectForKey:@\"buffer-disableTrackUnread\"] isKindOfClass:[NSDictionary class]])\n            [disableTrackUnread addEntriesFromDictionary:[prefs objectForKey:@\"buffer-disableTrackUnread\"]];\n        if([[prefs objectForKey:@\"buffer-enableTrackUnread\"] isKindOfClass:[NSDictionary class]])\n            [enableTrackUnread addEntriesFromDictionary:[prefs objectForKey:@\"buffer-enableTrackUnread\"]];\n        if([[prefs objectForKey:@\"disableTrackUnread\"] intValue] == 1) {\n            if(!_trackUnread.on)\n                [enableTrackUnread removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [enableTrackUnread setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(enableTrackUnread.count)\n                [prefs setObject:enableTrackUnread forKey:@\"buffer-enableTrackUnread\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-enableTrackUnread\"];\n        } else {\n            if(self->_trackUnread.on)\n                [disableTrackUnread removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [disableTrackUnread setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(disableTrackUnread.count)\n                [prefs setObject:disableTrackUnread forKey:@\"buffer-disableTrackUnread\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-disableTrackUnread\"];\n        }\n        \n        if([[prefs objectForKey:@\"notifications-mute\"] intValue] == 1) {\n            if([[prefs objectForKey:@\"buffer-notifications-mute-disable\"] isKindOfClass:[NSDictionary class]])\n                [disableMuted addEntriesFromDictionary:[prefs objectForKey:@\"buffer-notifications-mute-disable\"]];\n            if(self->_muted.on)\n                [disableMuted removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [disableMuted setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(disableMuted.count)\n                [prefs setObject:disableMuted forKey:@\"buffer-notifications-mute-disable\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-notifications-mute-disable\"];\n        } else {\n            if([[prefs objectForKey:@\"buffer-notifications-mute\"] isKindOfClass:[NSDictionary class]])\n                [muted addEntriesFromDictionary:[prefs objectForKey:@\"buffer-notifications-mute\"]];\n            if(self->_muted.on)\n                [muted setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [muted removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(muted.count)\n                [prefs setObject:muted forKey:@\"buffer-notifications-mute\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-notifications-mute\"];\n        }\n        \n        if([self->_buffer.type isEqualToString:@\"conversation\"]) {\n            if([[prefs objectForKey:@\"buffer-hideJoinPart\"] isKindOfClass:[NSDictionary class]])\n                [hideJoinPart addEntriesFromDictionary:[prefs objectForKey:@\"buffer-hideJoinPart\"]];\n            if(self->_showJoinPart.on)\n                [hideJoinPart removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [hideJoinPart setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(hideJoinPart.count)\n                [prefs setObject:hideJoinPart forKey:@\"buffer-hideJoinPart\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-hideJoinPart\"];\n\n            if([[prefs objectForKey:@\"buffer-expandJoinPart\"] isKindOfClass:[NSDictionary class]])\n                [expandJoinPart addEntriesFromDictionary:[prefs objectForKey:@\"buffer-expandJoinPart\"]];\n            if(self->_collapseJoinPart.on)\n                [expandJoinPart removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [expandJoinPart setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(expandJoinPart.count)\n                [prefs setObject:expandJoinPart forKey:@\"buffer-expandJoinPart\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-expandJoinPart\"];\n            \n            if([[prefs objectForKey:@\"buffer-collapseJoinPart\"] isKindOfClass:[NSDictionary class]])\n                [collapseJoinPart addEntriesFromDictionary:[prefs objectForKey:@\"buffer-collapseJoinPart\"]];\n            if(!_collapseJoinPart.on)\n                [collapseJoinPart removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [collapseJoinPart setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(collapseJoinPart.count)\n                [prefs setObject:expandJoinPart forKey:@\"buffer-collapseJoinPart\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-collapseJoinPart\"];\n\n            if([[prefs objectForKey:@\"buffer-files-disableinline\"] isKindOfClass:[NSDictionary class]])\n                [disableInlineFiles addEntriesFromDictionary:[prefs objectForKey:@\"buffer-files-disableinline\"]];\n            if(self->_disableInlineFiles.on)\n                [disableInlineFiles removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [disableInlineFiles setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(disableInlineFiles.count)\n                [prefs setObject:disableInlineFiles forKey:@\"buffer-files-disableinline\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-files-disableinline\"];\n            \n            if([[prefs objectForKey:@\"buffer-reply-collapse\"] isKindOfClass:[NSDictionary class]])\n                [replyCollapse addEntriesFromDictionary:[prefs objectForKey:@\"buffer-reply-collapse\"]];\n            if(self->_replyCollapse.on)\n                [replyCollapse setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [replyCollapse removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(replyCollapse.count)\n                [prefs setObject:replyCollapse forKey:@\"buffer-reply-collapse\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-reply-collapse\"];\n            \n            if([[prefs objectForKey:@\"buffer-disableTypingStatus\"] isKindOfClass:[NSDictionary class]])\n                [disableTypingStatus addEntriesFromDictionary:[prefs objectForKey:@\"buffer-disableTypingStatus\"]];\n            if([[prefs objectForKey:@\"buffer-enableTypingStatus\"] isKindOfClass:[NSDictionary class]])\n                [enableTypingStatus addEntriesFromDictionary:[prefs objectForKey:@\"buffer-enableTypingStatus\"]];\n            if([[prefs objectForKey:@\"disableTypingStatus\"] intValue] == 1) {\n                if(!_typingStatus.on)\n                    [enableTypingStatus removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n                else\n                    [enableTypingStatus setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n                if(enableTypingStatus.count)\n                    [prefs setObject:enableTypingStatus forKey:@\"buffer-enableTypingStatus\"];\n                else\n                    [prefs removeObjectForKey:@\"buffer-enableTypingStatus\"];\n            } else {\n                if(self->_typingStatus.on)\n                    [disableTypingStatus removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n                else\n                    [disableTypingStatus setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n                if(disableTypingStatus.count)\n                    [prefs setObject:disableTypingStatus forKey:@\"buffer-disableTypingStatus\"];\n                else\n                    [prefs removeObjectForKey:@\"buffer-disableTypingStatus\"];\n            }\n        }\n        \n        if([self->_buffer.type isEqualToString:@\"console\"]) {\n            if([[prefs objectForKey:@\"buffer-expandDisco\"] isKindOfClass:[NSDictionary class]])\n                [expandDisco addEntriesFromDictionary:[prefs objectForKey:@\"buffer-expandDisco\"]];\n            if(self->_expandDisco.on)\n                [expandDisco removeObjectForKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            else\n                [expandDisco setObject:@YES forKey:[NSString stringWithFormat:@\"%i\", _buffer.bid]];\n            if(expandDisco.count)\n                [prefs setObject:expandDisco forKey:@\"buffer-expandDisco\"];\n            else\n                [prefs removeObjectForKey:@\"buffer-expandDisco\"];\n        }\n    }\n    \n    SBJson5Writer *writer = [[SBJson5Writer alloc] init];\n    NSString *json = [writer stringWithObject:prefs];\n    \n    [[NetworkConnection sharedInstance] setPrefs:json handler:^(IRCCloudJSONObject *result) {\n        if([[result objectForKey:@\"success\"] boolValue]) {\n            [self dismissViewControllerAnimated:YES completion:nil];\n        } else {\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to save settings, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n            [self presentViewController:alert animated:YES completion:nil];\n            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveButtonPressed:)];\n        }\n    }];\n}\n\n-(void)cancelButtonPressed:(id)sender {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    \n    switch(event) {\n        case kIRCEventUserInfo:\n            [self refresh];\n            break;\n        default:\n            break;\n    }\n}\n\n-(void)refresh {\n    NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n    \n    if([self->_buffer.type isEqualToString:@\"channel\"]) {\n        if([[prefs objectForKey:@\"enableReadOnSelect\"] intValue] == 1) {\n            if([[[prefs objectForKey:@\"channel-disableReadOnSelect\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_readOnSelect.on = NO;\n            else\n                self->_readOnSelect.on = YES;\n        } else {\n            if([[[prefs objectForKey:@\"channel-enableReadOnSelect\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_readOnSelect.on = YES;\n            else\n                self->_readOnSelect.on = NO;\n        }\n        \n        if([[prefs objectForKey:@\"disableTrackUnread\"] intValue] == 1) {\n            if([[[prefs objectForKey:@\"channel-enableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_trackUnread.on = YES;\n            else\n                self->_trackUnread.on = NO;\n        } else {\n            if([[[prefs objectForKey:@\"channel-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_trackUnread.on = NO;\n            else\n                self->_trackUnread.on = YES;\n        }\n        \n        if([[prefs objectForKey:@\"disableTypingStatus\"] intValue] == 1) {\n            if([[[prefs objectForKey:@\"channel-enableTypingStatus\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_typingStatus.on = YES;\n            else\n                self->_typingStatus.on = NO;\n        } else {\n            if([[[prefs objectForKey:@\"channel-disableTypingStatus\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_typingStatus.on = NO;\n            else\n                self->_typingStatus.on = YES;\n        }\n        \n        if([[prefs objectForKey:@\"notifications-all\"] intValue] == 1) {\n            if([[[prefs objectForKey:@\"channel-notifications-all-disable\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_notifyAll.on = NO;\n            else\n                self->_notifyAll.on = YES;\n        } else {\n            if([[[prefs objectForKey:@\"channel-notifications-all\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_notifyAll.on = YES;\n            else\n                self->_notifyAll.on = NO;\n        }\n        \n        if([[prefs objectForKey:@\"hideJoinPart\"] intValue] == 1) {\n            if([[[prefs objectForKey:@\"channel-showJoinPart\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_showJoinPart.on = YES;\n            else\n                self->_showJoinPart.on = NO;\n        } else {\n            if([[[prefs objectForKey:@\"channel-hideJoinPart\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_showJoinPart.on = NO;\n            else\n                self->_showJoinPart.on = YES;\n        }\n\n        if([[prefs objectForKey:@\"expandJoinPart\"] intValue]) {\n            if([[[prefs objectForKey:@\"channel-collapseJoinPart\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_collapseJoinPart.on = YES;\n            else\n                self->_collapseJoinPart.on = NO;\n        } else {\n            if([[[prefs objectForKey:@\"channel-expandJoinPart\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_collapseJoinPart.on = NO;\n            else\n                self->_collapseJoinPart.on = YES;\n        }\n        if([[[prefs objectForKey:@\"channel-hiddenMembers\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n            self->_showMembers.on = NO;\n        else\n            self->_showMembers.on = YES;\n        \n        if([[[prefs objectForKey:@\"channel-files-disableinline\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n            self->_disableInlineFiles.on = NO;\n        else\n            self->_disableInlineFiles.on = YES;\n        \n        self->_inlineImages.on = [[prefs objectForKey:@\"inlineimages\"] boolValue];\n        if(self->_inlineImages.on) {\n            NSDictionary *disableMap = [prefs objectForKey:@\"channel-inlineimages-disable\"];\n            \n            if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_inlineImages.on = NO;\n        } else {\n            NSDictionary *enableMap = [prefs objectForKey:@\"channel-inlineimages\"];\n            \n            if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_inlineImages.on = YES;\n        }\n        \n        if([[[prefs objectForKey:@\"channel-reply-collapse\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n            self->_replyCollapse.on = YES;\n        else\n            self->_replyCollapse.on = NO;\n\n        self->_muted.on = [[prefs objectForKey:@\"notifications-mute\"] boolValue];\n        if(self->_muted.on) {\n            NSDictionary *disableMap = [prefs objectForKey:@\"channel-notifications-mute-disable\"];\n            \n            if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_muted.on = NO;\n        } else {\n            NSDictionary *enableMap = [prefs objectForKey:@\"channel-notifications-mute\"];\n            \n            if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_muted.on = YES;\n        }\n\n        self->_nocolors.on = ![[prefs objectForKey:@\"chat-nocolor\"] boolValue];\n        if(self->_nocolors.on) {\n            NSDictionary *disableMap = [prefs objectForKey:@\"channel-chat-nocolor\"];\n            \n            if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_nocolors.on = NO;\n        } else {\n            NSDictionary *enableMap = [prefs objectForKey:@\"channel-chat-color\"];\n            \n            if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_nocolors.on = YES;\n        }\n    } else {\n        if([[prefs objectForKey:@\"enableReadOnSelect\"] intValue] == 1) {\n            if([[[prefs objectForKey:@\"buffer-disableReadOnSelect\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_readOnSelect.on = NO;\n            else\n                self->_readOnSelect.on = YES;\n        } else {\n            if([[[prefs objectForKey:@\"buffer-enableReadOnSelect\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_readOnSelect.on = YES;\n            else\n                self->_readOnSelect.on = NO;\n        }\n        \n        if([[prefs objectForKey:@\"disableTrackUnread\"] intValue] == 1) {\n            if([[[prefs objectForKey:@\"buffer-enableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_trackUnread.on = YES;\n            else\n                self->_trackUnread.on = NO;\n        } else {\n            if([[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_trackUnread.on = NO;\n            else\n                self->_trackUnread.on = YES;\n        }\n        \n        if([[prefs objectForKey:@\"hideJoinPart\"] intValue] == 1) {\n            if([[[prefs objectForKey:@\"buffer-showJoinPart\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_showJoinPart.on = YES;\n            else\n                self->_showJoinPart.on = NO;\n        } else {\n            if([[[prefs objectForKey:@\"buffer-hideJoinPart\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_showJoinPart.on = NO;\n            else\n                self->_showJoinPart.on = YES;\n        }\n\n        if([[prefs objectForKey:@\"expandJoinPart\"] intValue]) {\n            if([[[prefs objectForKey:@\"buffer-collapseJoinPart\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_collapseJoinPart.on = YES;\n            else\n                self->_collapseJoinPart.on = NO;\n        } else {\n            if([[[prefs objectForKey:@\"buffer-expandJoinPart\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n                self->_collapseJoinPart.on = NO;\n            else\n                self->_collapseJoinPart.on = YES;\n        }\n\n        if([[[prefs objectForKey:@\"buffer-expandDisco\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n            self->_expandDisco.on = NO;\n        else\n            self->_expandDisco.on = YES;\n        \n        if([[[prefs objectForKey:@\"buffer-files-disableinline\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n            self->_disableInlineFiles.on = NO;\n        else\n            self->_disableInlineFiles.on = YES;\n        \n        self->_inlineImages.on = [[prefs objectForKey:@\"inlineimages\"] boolValue];\n        if(self->_inlineImages.on) {\n            NSDictionary *disableMap = [prefs objectForKey:@\"buffer-inlineimages-disable\"];\n            \n            if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_inlineImages.on = NO;\n        } else {\n            NSDictionary *enableMap = [prefs objectForKey:@\"buffer-inlineimages\"];\n            \n            if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_inlineImages.on = YES;\n        }\n\n        if([[[prefs objectForKey:@\"buffer-reply-collapse\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue] == 1)\n            self->_replyCollapse.on = YES;\n        else\n            self->_replyCollapse.on = NO;\n        \n        self->_muted.on = [[prefs objectForKey:@\"notifications-mute\"] boolValue];\n        if(self->_muted.on) {\n            NSDictionary *disableMap = [prefs objectForKey:@\"buffer-notifications-mute-disable\"];\n            \n            if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_muted.on = NO;\n        } else {\n            NSDictionary *enableMap = [prefs objectForKey:@\"buffer-notifications-mute\"];\n            \n            if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_muted.on = YES;\n        }\n        \n        self->_nocolors.on = ![[prefs objectForKey:@\"buffer-nocolor\"] boolValue];\n        if(self->_nocolors.on) {\n            NSDictionary *disableMap = [prefs objectForKey:@\"buffer-chat-nocolor\"];\n            \n            if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_nocolors.on = NO;\n        } else {\n            NSDictionary *enableMap = [prefs objectForKey:@\"buffer-chat-color\"];\n            \n            if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                self->_nocolors.on = YES;\n        }\n    }\n    self->_collapseJoinPart.enabled = self->_showJoinPart.on;\n    self->_disableNickSuggestions.on = !([[[[NSUserDefaults standardUserDefaults] objectForKey:@\"disable-nick-suggestions\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue]);\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n\n    self->_showMembers = [[UISwitch alloc] init];\n    self->_notifyAll = [[UISwitch alloc] init];\n    self->_trackUnread = [[UISwitch alloc] init];\n    self->_showJoinPart = [[UISwitch alloc] init];\n    [self->_showJoinPart addTarget:self action:@selector(showJoinPartToggled:) forControlEvents:UIControlEventValueChanged];\n    self->_collapseJoinPart = [[UISwitch alloc] init];\n    self->_expandDisco = [[UISwitch alloc] init];\n    self->_readOnSelect = [[UISwitch alloc] init];\n    self->_disableInlineFiles = [[UISwitch alloc] init];\n    self->_disableNickSuggestions = [[UISwitch alloc] init];\n    self->_replyCollapse = [[UISwitch alloc] init];\n    self->_inlineImages = [[UISwitch alloc] init];\n    [self->_inlineImages addTarget:self action:@selector(thirdPartyNotificationPreviewsToggled:) forControlEvents:UIControlEventValueChanged];\n    self->_muted = [[UISwitch alloc] init];\n    self->_nocolors = [[UISwitch alloc] init];\n    self->_typingStatus = [[UISwitch alloc] init];\n\n    [self refresh];\n}\n\n-(void)thirdPartyNotificationPreviewsToggled:(UISwitch *)sender {\n    if(sender.on) {\n        UIAlertController *ac = [UIAlertController alertControllerWithTitle:@\"Warning\" message:@\"External URLs may load insecurely and could result in your IP address being revealed to external site operators\" preferredStyle:UIAlertControllerStyleAlert];\n        \n        [ac addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {\n            sender.on = NO;\n        }]];\n        \n        [ac addAction:[UIAlertAction actionWithTitle:@\"Enable\" style:UIAlertActionStyleDefault handler:nil]];\n        \n        [self presentViewController:ac animated:YES completion:nil];\n    }\n}\n\n-(void)showJoinPartToggled:(id)sender {\n    self->_collapseJoinPart.enabled = self->_showJoinPart.on;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    if(indexPath.section == 1)\n        return ([UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody].pointSize * 2) + 32;\n    else\n        return UITableViewAutomaticDimension;\n}\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    int count;\n    if([self->_buffer.type isEqualToString:@\"channel\"])\n        count = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)?12:13;\n    else if([self->_buffer.type isEqualToString:@\"console\"])\n        count = 5;\n    else\n        count = 10;\n#ifdef ENTERPRISE\n    count--;\n#endif\n    return count;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSUInteger row = indexPath.row;\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"settingscell\"];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@\"settingscell\"];\n    \n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    cell.accessoryView = nil;\n    \n    if(![self->_buffer.type isEqualToString:@\"channel\"] && row > 1)\n        row+=3;\n    else if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && row > 1)\n        row++;\n    \n#ifdef ENTERPRISE\n    if(row >= 5)\n        row++;\n#endif\n    \n    switch(row) {\n        case 0:\n            cell.textLabel.text = @\"Unread message indicator\";\n            cell.accessoryView = self->_trackUnread;\n            break;\n        case 1:\n            cell.textLabel.text = @\"Mark as read automatically\";\n            cell.accessoryView = self->_readOnSelect;\n            break;\n        case 2:\n            cell.textLabel.text = @\"Member list\";\n            cell.accessoryView = self->_showMembers;\n            break;\n        case 3:\n            cell.textLabel.text = @\"Notify on all messages\";\n            cell.accessoryView = self->_notifyAll;\n            break;\n        case 4:\n            cell.textLabel.text = @\"Suggest nicks as you type\";\n            cell.accessoryView = self->_disableNickSuggestions;\n            break;\n        case 5:\n            cell.textLabel.text = @\"Format colours\";\n            cell.accessoryView = self->_nocolors;\n            break;\n        case 6:\n            cell.textLabel.text = @\"Mute notifications\";\n            cell.accessoryView = self->_muted;\n            break;\n        case 7:\n            if([self->_buffer.type isEqualToString:@\"console\"]) {\n                cell.textLabel.text = @\"Group repeated disconnects\";\n                cell.accessoryView = self->_expandDisco;\n            } else {\n                cell.textLabel.text = @\"Show joins/parts\";\n                cell.accessoryView = self->_showJoinPart;\n            }\n            break;\n        case 8:\n            cell.textLabel.text = @\"Collapse joins/parts\";\n            cell.accessoryView = self->_collapseJoinPart;\n            break;\n        case 9:\n            cell.textLabel.text = @\"Collapse reply threads\";\n            cell.accessoryView = self->_replyCollapse;\n            break;\n        case 10:\n            cell.textLabel.text = @\"Embed uploaded files\";\n            cell.accessoryView = self->_disableInlineFiles;\n            break;\n        case 11:\n            cell.textLabel.text = @\"Embed external media\";\n            cell.accessoryView = self->_inlineImages;\n            break;\n        case 12:\n            cell.textLabel.text = @\"Share typing status\";\n            cell.accessoryView = self->_typingStatus;\n            break;\n    }\n    return cell;\n}\n\n/*\n// Override to support conditional editing of the table view.\n- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    // Return NO if you do not want the specified item to be editable.\n    return YES;\n}\n*/\n\n/*\n// Override to support editing the table view.\n- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    if (editingStyle == UITableViewCellEditingStyleDelete) {\n        // Delete the row from the data source\n        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];\n    }   \n    else if (editingStyle == UITableViewCellEditingStyleInsert) {\n        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view\n    }   \n}\n*/\n\n/*\n// Override to support rearranging the table view.\n- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath\n{\n}\n*/\n\n/*\n// Override to support conditional rearranging of the table view.\n- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    // Return NO if you do not want the item to be re-orderable.\n    return YES;\n}\n*/\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [self.tableView deselectRowAtIndexPath:indexPath animated:NO];\n    [self.tableView endEditing:YES];\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/EditConnectionViewController.h",
    "content": "//\n//  EditConnectionViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n\n@protocol NetworkListDelegate <NSObject>\n-(void)setNetwork:(NSString *)network host:(NSString *)host port:(int)port SSL:(BOOL)SSL;\n@end\n\n@interface EditConnectionViewController : UITableViewController<UITextFieldDelegate,NetworkListDelegate,UITextViewDelegate,UIGestureRecognizerDelegate> {\n    UITextField *_server;\n    UITextField *_port;\n    UISwitch *_ssl;\n    UITextField *_nickname;\n    UITextField *_realname;\n    UITextField *_nspass;\n    UITextField *_serverpass;\n    UISwitch *_revealnspass;\n    UISwitch *_revealserverpass;\n    UITextField *_network;\n    UITextView *_commands;\n    UITextView *_channels;\n    int _cid;\n    int _slack;\n    NSString *_netname;\n    NSURL *_url;\n    BOOL keyboardShown;\n    CGFloat keyboardOverlap;\n    NSIndexPath *_activeCellIndexPath;\n}\n-(void)setServer:(int)cid;\n-(void)setURL:(NSURL *)url;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/EditConnectionViewController.m",
    "content": "//\n//  EditConnectionViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"EditConnectionViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"AppDelegate.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n#import \"FontAwesome.h\"\n#import \"ColorFormatter.h\"\n\n@interface NetworkListViewController : UITableViewController {\n    id<NetworkListDelegate> _delegate;\n    NSString *_selection;\n    NSArray *_networks;\n    \n    UIActivityIndicatorView *_activityIndicator;\n}\n@property (copy) NSString *selection;\n-(id)initWithDelegate:(id)delegate;\n- (void)fetchServerList;\n@end\n\nstatic NSString * const NetworksListLink = @\"https://www.irccloud.com/static/networks.json\";\nstatic NSString * const FetchedDataNetworksKey = @\"networks\";\nstatic NSString * const NetworkNameKey = @\"name\";\nstatic NSString * const NetworkServersKey = @\"servers\";\nstatic NSString * const ServerHostNameKey = @\"hostname\";\nstatic NSString * const ServerPortKey = @\"port\";\nstatic NSString * const ServerHasSSLKey = @\"ssl\";\n\n@implementation NetworkListViewController\n\n-(id)initWithDelegate:(id)delegate {\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        self->_delegate = delegate;\n        self.navigationItem.title = @\"Networks\";\n        [self fetchServerList];\n    }\n    return self;\n}\n         \n- (void)fetchServerList\n{\n    self->_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n    self->_activityIndicator.autoresizingMask = (UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin);\n    self->_activityIndicator.center = (CGPoint){(self.view.bounds.size.width * 0.5), (self.view.bounds.size.height * 0.5)};\n    [self->_activityIndicator startAnimating];\n    [self.view addSubview:self->_activityIndicator];\n\n#ifdef DEBUG\n    [[NSURLCache sharedURLCache] removeAllCachedResponses];\n#endif\n    \n    [[[NetworkConnection sharedInstance].urlSession dataTaskWithURL:[NSURL URLWithString:NetworksListLink] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n        if (error) {\n            CLS_LOG(@\"Error fetching remote networks list. Error %li : %@\", (long)error.code, error.userInfo);\n            \n            self->_networks = @[];\n        } else {\n            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];\n            NSMutableArray *networks = [[NSMutableArray alloc] initWithCapacity:[(NSArray *)dict[FetchedDataNetworksKey] count]];\n            for (NSDictionary *network in dict[FetchedDataNetworksKey]) {\n                NSDictionary *server = [(NSArray *)network[NetworkServersKey] objectAtIndex:0];\n                if(server) {\n                    [networks addObject:@{\n                        @\"network\": network[NetworkNameKey],\n                        @\"host\": server[ServerHostNameKey],\n                        @\"port\": server[ServerPortKey],\n                        @\"SSL\": server[ServerHasSSLKey]\n                    }];\n                }\n            }\n            self->_networks = networks;\n        }\n        \n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self->_activityIndicator stopAnimating];\n            [self->_activityIndicator removeFromSuperview];\n            [self.tableView reloadData];\n        }];\n    }] resume];\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return [self->_networks count];\n}\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    return 54;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"networkcell\"];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@\"networkcell\"];\n    \n    NSDictionary *row = [self->_networks objectAtIndex:indexPath.row];\n    [[cell.textLabel subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];\n    cell.textLabel.clipsToBounds = NO;\n    UILabel *icon = [[UILabel alloc] initWithFrame:CGRectMake(2,2.4,16,16)];\n    icon.font = [UIFont fontWithName:@\"FontAwesome\" size:cell.textLabel.font.pointSize];\n    icon.textAlignment = NSTextAlignmentCenter;\n    if([[row objectForKey:@\"SSL\"] boolValue])\n        icon.text = FA_SHIELD;\n    else\n        icon.text = FA_GLOBE;\n/* icon on the right instead\n     if([[row objectForKey:@\"SSL\"] boolValue]) {\n     UIImageView *icon = [[UIImageView alloc] initWithFrame:CGRectMake([cell.textLabel.text sizeWithFont:[UIFont boldSystemFontOfSize:18]].width + 2,2,16,16)];\n     icon.image = [UIImage imageNamed:@\"world_shield\"];\n     [cell.textLabel addSubview:icon];\n     }\n*/\n    [cell.textLabel addSubview:icon];\n    icon.textColor = [UITableViewCell appearance].textLabelColor;\n    cell.textLabel.text = [NSString stringWithFormat:@\"     %@\",[row objectForKey:@\"network\"]];\n    cell.detailTextLabel.text = [row objectForKey:@\"host\"];\n    \n    if([self->_selection isEqualToString:cell.textLabel.text])\n        cell.accessoryType = UITableViewCellAccessoryCheckmark;\n    else\n        cell.accessoryType = UITableViewCellAccessoryNone;\n    \n    return cell;\n}\n\n/*\n // Override to support conditional editing of the table view.\n - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath\n {\n // Return NO if you do not want the specified item to be editable.\n return YES;\n }\n */\n\n/*\n // Override to support editing the table view.\n - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath\n {\n if (editingStyle == UITableViewCellEditingStyleDelete) {\n // Delete the row from the data source\n [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];\n }\n else if (editingStyle == UITableViewCellEditingStyleInsert) {\n // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view\n }\n }\n */\n\n/*\n // Override to support rearranging the table view.\n - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath\n {\n }\n */\n\n/*\n // Override to support conditional rearranging of the table view.\n - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath\n {\n // Return NO if you do not want the item to be re-orderable.\n return YES;\n }\n */\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    self->_selection = [self tableView:tableView cellForRowAtIndexPath:indexPath].textLabel.text;\n    [tableView reloadData];\n    NSDictionary *row = [self->_networks objectAtIndex:indexPath.row];\n    [self->_delegate setNetwork:[row objectForKey:@\"network\"] host:[row objectForKey:@\"host\"] port:[[row objectForKey:@\"port\"] intValue] SSL:[[row objectForKey:@\"SSL\"] boolValue]];\n    [self.navigationController popViewControllerAnimated:YES];\n}\n\n@end\n\n@implementation EditConnectionViewController\n\n- (id)initWithStyle:(UITableViewStyle)style {\n    self = [super initWithStyle:style];\n    if (self) {\n        self->_cid = -1;\n        self.navigationItem.title = @\"New Connection\";\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveButtonPressed:)];\n    }\n    return self;\n}\n\n-(void)dealloc {\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n//From: http://stackoverflow.com/a/13867108/1406639\n- (void)keyboardWillShow:(NSNotification *)aNotification\n{\n    if (@available(iOS 13.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp) {\n            return;\n        }\n    }\n    if(keyboardShown)\n        return;\n    \n    keyboardShown = YES;\n    \n    // Get the keyboard size\n    UIScrollView *tableView;\n    if([self.tableView.superview isKindOfClass:[UIScrollView class]])\n        tableView = (UIScrollView *)self.tableView.superview;\n    else\n        tableView = self.tableView;\n    NSDictionary *userInfo = [aNotification userInfo];\n    NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];\n    CGRect keyboardRect = [tableView.superview convertRect:[aValue CGRectValue] fromView:nil];\n    \n    // Get the keyboard's animation details\n    NSTimeInterval animationDuration;\n    [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];\n    UIViewAnimationCurve animationCurve;\n    [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];\n    \n    // Determine how much overlap exists between tableView and the keyboard\n    CGRect tableFrame = tableView.frame;\n    CGFloat tableLowerYCoord = tableFrame.origin.y + tableFrame.size.height;\n    keyboardOverlap = tableLowerYCoord - keyboardRect.origin.y;\n    if(self.inputAccessoryView && keyboardOverlap>0)\n    {\n        CGFloat accessoryHeight = self.inputAccessoryView.frame.size.height;\n        keyboardOverlap -= accessoryHeight;\n        \n        tableView.contentInset = UIEdgeInsetsMake(0, 0, accessoryHeight, 0);\n        tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, accessoryHeight, 0);\n    }\n    \n    if(keyboardOverlap < 0)\n        keyboardOverlap = 0;\n    \n    if(keyboardOverlap != 0)\n    {\n        tableFrame.size.height -= keyboardOverlap;\n        \n        NSTimeInterval delay = 0;\n        if(keyboardRect.size.height)\n        {\n            delay = (1 - keyboardOverlap/keyboardRect.size.height)*animationDuration;\n            animationDuration = animationDuration * keyboardOverlap/keyboardRect.size.height;\n        }\n        \n        [UIView animateWithDuration:animationDuration delay:delay\n                            options:UIViewAnimationOptionBeginFromCurrentState\n                         animations:^{ tableView.frame = tableFrame; }\n                         completion:^(BOOL finished){ [self tableAnimationEnded:nil finished:nil contextInfo:nil]; }];\n    }\n}\n\n//From: http://stackoverflow.com/a/13867108/1406639\n- (void)keyboardWillHide:(NSNotification *)aNotification {\n    if(!keyboardShown)\n        return;\n    \n    keyboardShown = NO;\n    \n    UIScrollView *tableView;\n    if([self.tableView.superview isKindOfClass:[UIScrollView class]])\n        tableView = (UIScrollView *)self.tableView.superview;\n    else\n        tableView = self.tableView;\n    if(self.inputAccessoryView)\n    {\n        tableView.contentInset = UIEdgeInsetsZero;\n        tableView.scrollIndicatorInsets = UIEdgeInsetsZero;\n    }\n    \n    if(keyboardOverlap == 0)\n        return;\n    \n    // Get the size & animation details of the keyboard\n    NSDictionary *userInfo = [aNotification userInfo];\n    NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];\n    CGRect keyboardRect = [tableView.superview convertRect:[aValue CGRectValue] fromView:nil];\n    \n    NSTimeInterval animationDuration;\n    [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];\n    UIViewAnimationCurve animationCurve;\n    [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];\n    \n    CGRect tableFrame = tableView.frame;\n    tableFrame.size.height += keyboardOverlap;\n    \n    if(keyboardRect.size.height)\n        animationDuration = animationDuration * keyboardOverlap/keyboardRect.size.height;\n    \n    [UIView animateWithDuration:animationDuration delay:0\n                        options:UIViewAnimationOptionBeginFromCurrentState\n                     animations:^{ tableView.frame = tableFrame; }\n                     completion:nil];\n}\n\n//From: http://stackoverflow.com/a/13867108/1406639\n- (void)tableAnimationEnded:(NSString*)animationID finished:(NSNumber *)finished contextInfo:(void *)context {\n    // Scroll to the active cell\n    if(self->_activeCellIndexPath) {\n        [self.tableView scrollToRowAtIndexPath:self->_activeCellIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];\n//        [self.tableView selectRowAtIndexPath:self->_activeCellIndexPath animated:NO scrollPosition:UITableViewScrollPositionBottom];\n    }\n}\n\n-(void)saveButtonPressed:(id)sender {\n    UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n    [spinny startAnimating];\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinny];\n    \n    IRCCloudAPIResultHandler handler = ^(IRCCloudJSONObject *result) {\n        if([[result objectForKey:@\"success\"] boolValue]) {\n            if(self->_cid == -1)\n                ((AppDelegate *)([UIApplication sharedApplication].delegate)).mainViewController.cidToOpen = [[result objectForKey:@\"cid\"] intValue];\n            if(self.presentingViewController) {\n                [self.tableView endEditing:YES];\n                [self dismissViewControllerAnimated:YES completion:nil];\n                [[NSNotificationCenter defaultCenter] removeObserver:self];\n            } else if([[result objectForKey:@\"cid\"] intValue]) {\n                self->_cid = [[result objectForKey:@\"cid\"] intValue];\n            }\n        } else {\n            NSString *msg = [result objectForKey:@\"message\"];\n            if([msg isEqualToString:@\"hostname\"]) {\n                msg = @\"Invalid hostname\";\n            } else if([msg isEqualToString:@\"nickname\"]) {\n                msg = @\"Invalid nickname\";\n            } else if([msg isEqualToString:@\"realname\"]) {\n                msg = @\"Invalid real name\";\n            } else if([msg isEqualToString:@\"passworded_servers\"]) {\n                msg = @\"You can’t connect to passworded servers with free accounts\";\n            } else if([msg isEqualToString:@\"networks\"]) {\n                msg = @\"You’ve exceeded the connection limit for free accounts\";\n            } else if([msg isEqualToString:@\"sts_policy\"]) {\n                msg = @\"You can’t disable secure connections to this network because it’s using a strict transport security policy\";\n            } else if([msg isEqualToString:@\"unverified\"]) {\n                msg = @\"You can’t connect to external servers until you confirm your email address\";\n            }\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:msg preferredStyle:UIAlertControllerStyleAlert];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n            [self presentViewController:alert animated:YES completion:nil];\n\n            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveButtonPressed:)];\n        }\n    };\n    \n    if(self->_cid == -1) {\n        [[NetworkConnection sharedInstance] addServer:self->_server.text port:[self->_port.text intValue] ssl:(self->_ssl.on)?1:0 netname:self->_netname nick:self->_nickname.text realname:self->_realname.text serverPass:self->_serverpass.text nickservPass:self->_nspass.text joinCommands:self->_commands.text channels:self->_channels.text handler:handler];\n    } else if(self->_slack) {\n        [[NetworkConnection sharedInstance] setNetworkName:self->_network.text cid:self->_cid handler:handler];\n    } else {\n        self->_netname = self->_network.text;\n        if([self->_netname.lowercaseString isEqualToString:self->_server.text.lowercaseString])\n            self->_netname = nil;\n        [[NetworkConnection sharedInstance] editServer:self->_cid hostname:self->_server.text port:[self->_port.text intValue] ssl:(self->_ssl.on)?1:0 netname:self->_netname nick:self->_nickname.text realname:self->_realname.text serverPass:self->_serverpass.text nickservPass:self->_nspass.text joinCommands:self->_commands.text handler:handler];\n    }\n}\n\n-(void)cancelButtonPressed:(id)sender {\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n    [self.tableView endEditing:YES];\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)logoutButtonPressed:(id)sender {\n    [[NetworkConnection sharedInstance] logout];\n    [(AppDelegate *)([UIApplication sharedApplication].delegate) showLoginView];\n}\n\n-(void)setServer:(int)cid {\n    self.navigationItem.title = @\"Edit Connection\";\n    self->_cid = cid;\n    [self refresh];\n}\n\n-(void)setNetwork:(NSString *)network host:(NSString *)host port:(int)port SSL:(BOOL)SSL {\n    self->_network.text = self->_netname = network;\n    self->_server.text = host;\n    self->_port.text = [NSString stringWithFormat:@\"%i\", port];\n    self->_ssl.on = SSL;\n    [self.tableView reloadData];\n}\n\n-(void)setURL:(NSURL *)url {\n    self->_url = url;\n    self->_network.text = self->_netname = url.host;\n    [self refresh];\n}\n\n-(void)updateWidth:(float)width view:(UIView *)v {\n    v.frame = CGRectMake(v.frame.origin.x, v.frame.origin.y, width, 22);\n}\n\n-(void)refresh {\n    float width = self.tableView.frame.size.width / 3;\n    [self updateWidth:width view:_server];\n    [self updateWidth:width view:_port];\n    [self updateWidth:width view:_nickname];\n    [self updateWidth:width view:_realname];\n    [self updateWidth:width view:_nspass];\n    [self updateWidth:width view:_serverpass];\n    [self updateWidth:width view:_network];\n    [self updateWidth:width view:_commands];\n    [self updateWidth:width view:_channels];\n\n    self->_nspass.secureTextEntry = !self->_revealnspass.on;\n    self->_serverpass.secureTextEntry = !self->_revealserverpass.on;\n\n    if(self->_url) {\n        int port = [self->_url.port intValue];\n        int ssl = [self->_url.scheme hasSuffix:@\"s\"]?1:0;\n        if(port == 0)\n            port = (ssl == 1)?6697:6667;\n        \n        self->_server.text = self->_url.host;\n        self->_port.text = [NSString stringWithFormat:@\"%i\", port];\n        if(ssl == 1)\n            self->_ssl.on = YES;\n        else\n            self->_ssl.on = NO;\n        \n        if(self->_url.path && _url.path.length > 1)\n            self->_channels.text = [self->_url.path substringFromIndex:1];\n    } else {\n        Server *server = [[ServersDataSource sharedInstance] getServer:self->_cid];\n        if(server) {\n            self->_slack = server.slack;\n            self->_network.text = self->_netname = server.name;\n            if(self->_netname.length == 0)\n                self->_network.text = self->_netname = server.hostname;\n            \n            if([server.hostname isKindOfClass:[NSString class]] && server.hostname.length)\n                self->_server.text = server.hostname;\n            else\n                self->_server.text = @\"\";\n            \n            self->_port.text = [NSString stringWithFormat:@\"%i\", server.port];\n            \n            self->_ssl.on = (server.ssl > 0);\n\n            if([server.nick isKindOfClass:[NSString class]] && server.nick.length)\n                self->_nickname.text = server.nick;\n            else\n                self->_nickname.text = @\"\";\n            \n            if([server.realname isKindOfClass:[NSString class]] && server.realname.length)\n                self->_realname.text = server.realname;\n            else\n                self->_realname.text = @\"\";\n            \n            if([server.nickserv_pass isKindOfClass:[NSString class]] && server.nickserv_pass.length)\n                self->_nspass.text = server.nickserv_pass;\n            else\n                self->_nspass.text = @\"\";\n            \n            if([server.server_pass isKindOfClass:[NSString class]] && server.server_pass.length)\n                self->_serverpass.text = server.server_pass;\n            else\n                self->_serverpass.text = @\"\";\n            \n            if([server.join_commands isKindOfClass:[NSString class]] && server.join_commands.length)\n                self->_commands.text = server.join_commands;\n            else\n                self->_commands.text = @\"\";\n        }\n    }\n}\n\n- (void)textFieldDidBeginEditing:(UITextField *)textField {\n    if(textField == self->_server)\n        self->_activeCellIndexPath = [NSIndexPath indexPathForRow:1 inSection:0];\n    else if(textField == self->_port)\n        self->_activeCellIndexPath = [NSIndexPath indexPathForRow:1 inSection:0];\n    if(textField == self->_nickname)\n        self->_activeCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:1];\n    if(textField == self->_realname)\n        self->_activeCellIndexPath = [NSIndexPath indexPathForRow:1 inSection:1];\n    if(textField == self->_nspass)\n        self->_activeCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:2];\n    if(textField == self->_serverpass)\n        self->_activeCellIndexPath = [NSIndexPath indexPathForRow:1 inSection:2];\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {\n    if(touch.view.tag == 1) {\n        [[NetworkConnection sharedInstance] resendVerifyEmailWithHandler:^(IRCCloudJSONObject *result) {\n            if([[result objectForKey:@\"success\"] boolValue]) {\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Confirmation Sent\" message:@\"You should shortly receive an email with a link to confirm your address.\" preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n            } else {\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Confirmation Failed\" message:[NSString stringWithFormat:@\"Unable to send confirmation message: %@. Please try again shortly.\", [result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n            }\n        }];\n    }\n    return ![touch.view isKindOfClass:[UIControl class]];\n}\n\n- (void)hideKeyboard:(id)sender {\n    [self.view endEditing:YES];\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    \n    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard:)];\n    tap.delegate = self;\n    tap.cancelsTouchesInView = NO;\n    [self.view addGestureRecognizer:tap];\n\n    NSDictionary *userInfo = [NetworkConnection sharedInstance].userInfo;\n    NSString *name = [userInfo objectForKey:@\"name\"];\n    \n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n\n    self->_network = [[UITextField alloc] initWithFrame:CGRectZero];\n    self->_network.placeholder = @\"Network\";\n    self->_network.text = @\"\";\n    self->_network.textAlignment = NSTextAlignmentRight;\n    self->_network.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_network.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    self->_network.autocorrectionType = UITextAutocorrectionTypeNo;\n    self->_network.keyboardType = UIKeyboardTypeDefault;\n    self->_network.adjustsFontSizeToFitWidth = YES;\n    self->_network.returnKeyType = UIReturnKeyDone;\n    self->_network.delegate = self;\n    \n    self->_server = [[UITextField alloc] initWithFrame:CGRectZero];\n    self->_server.placeholder = @\"irc.example.net\";\n    self->_server.text = @\"\";\n    self->_server.textAlignment = NSTextAlignmentRight;\n    self->_server.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_server.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    self->_server.autocorrectionType = UITextAutocorrectionTypeNo;\n    self->_server.keyboardType = UIKeyboardTypeURL;\n    self->_server.adjustsFontSizeToFitWidth = YES;\n    self->_server.returnKeyType = UIReturnKeyDone;\n    self->_server.delegate = self;\n    \n    self->_port = [[UITextField alloc] initWithFrame:CGRectZero];\n    self->_port.text = @\"6667\";\n    self->_port.textAlignment = NSTextAlignmentRight;\n    self->_port.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_port.keyboardType = UIKeyboardTypeNumberPad;\n    self->_port.returnKeyType = UIReturnKeyDone;\n    self->_port.delegate = self;\n    \n    self->_ssl = [[UISwitch alloc] init];\n\n    self->_nickname = [[UITextField alloc] initWithFrame:CGRectZero];\n    self->_nickname.text = @\"\";\n    self->_nickname.textAlignment = NSTextAlignmentRight;\n    self->_nickname.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_nickname.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    self->_nickname.autocorrectionType = UITextAutocorrectionTypeNo;\n    self->_nickname.keyboardType = UIKeyboardTypeDefault;\n    self->_nickname.adjustsFontSizeToFitWidth = YES;\n    self->_nickname.returnKeyType = UIReturnKeyDone;\n    self->_nickname.delegate = self;\n    if(name && [name isKindOfClass:[NSString class]] && name.length) {\n        NSRange range = [name rangeOfString:@\" \"];\n        if(range.location != NSNotFound && range.location > 0)\n            self->_nickname.text = [[name substringToIndex:range.location] lowercaseString];\n    }\n    \n    self->_realname = [[UITextField alloc] initWithFrame:CGRectZero];\n    self->_realname.text = @\"\";\n    self->_realname.textAlignment = NSTextAlignmentRight;\n    self->_realname.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_realname.autocapitalizationType = UITextAutocapitalizationTypeWords;\n    self->_realname.autocorrectionType = UITextAutocorrectionTypeDefault;\n    self->_realname.keyboardType = UIKeyboardTypeDefault;\n    self->_realname.adjustsFontSizeToFitWidth = YES;\n    self->_realname.returnKeyType = UIReturnKeyDone;\n    self->_realname.delegate = self;\n    if(name && [name isKindOfClass:[NSString class]] && name.length) {\n        self->_realname.text = name;\n    }\n    \n    self->_nspass = [[UITextField alloc] initWithFrame:CGRectZero];\n    self->_nspass.text = @\"\";\n    self->_nspass.textAlignment = NSTextAlignmentRight;\n    self->_nspass.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_nspass.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    self->_nspass.autocorrectionType = UITextAutocorrectionTypeNo;\n    self->_nspass.keyboardType = UIKeyboardTypeDefault;\n    self->_nspass.adjustsFontSizeToFitWidth = YES;\n    self->_nspass.returnKeyType = UIReturnKeyDone;\n    self->_nspass.delegate = self;\n    self->_nspass.secureTextEntry = YES;\n\n    self->_revealnspass = [[UISwitch alloc] init];\n    [self->_revealnspass addTarget:self action:@selector(refresh) forControlEvents:UIControlEventValueChanged];\n\n    self->_serverpass = [[UITextField alloc] initWithFrame:CGRectZero];\n    self->_serverpass.text = @\"\";\n    self->_serverpass.textAlignment = NSTextAlignmentRight;\n    self->_serverpass.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_serverpass.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    self->_serverpass.autocorrectionType = UITextAutocorrectionTypeNo;\n    self->_serverpass.keyboardType = UIKeyboardTypeDefault;\n    self->_serverpass.adjustsFontSizeToFitWidth = YES;\n    self->_serverpass.returnKeyType = UIReturnKeyDone;\n    self->_serverpass.delegate = self;\n    self->_serverpass.secureTextEntry = YES;\n    \n    self->_revealserverpass = [[UISwitch alloc] init];\n    [self->_revealserverpass addTarget:self action:@selector(refresh) forControlEvents:UIControlEventValueChanged];\n\n    self->_commands = [[UITextView alloc] initWithFrame:CGRectZero];\n    self->_commands.text = @\"\";\n    self->_commands.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_commands.backgroundColor = [UIColor clearColor];\n    self->_commands.delegate = self;\n    self->_commands.font = self->_server.font;\n    self->_commands.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    self->_commands.keyboardAppearance = [UITextField appearance].keyboardAppearance;\n    \n    self->_channels = [[UITextView alloc] initWithFrame:CGRectZero];\n    self->_channels.text = @\"\";\n    self->_channels.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_channels.backgroundColor = [UIColor clearColor];\n    self->_channels.delegate = self;\n    self->_channels.font = self->_server.font;\n    self->_channels.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    self->_channels.keyboardAppearance = [UITextField appearance].keyboardAppearance;\n    \n    if([NetworkConnection sharedInstance].userInfo && [[NetworkConnection sharedInstance].userInfo objectForKey:@\"verified\"] && [[[NetworkConnection sharedInstance].userInfo objectForKey:@\"verified\"] intValue] == 0) {\n        UITextView *unverified = [[UITextView alloc] init];\n        unverified.backgroundColor = [UIColor networkErrorBackgroundColor];\n        unverified.textAlignment = NSTextAlignmentCenter;\n        unverified.textColor = [UIColor networkErrorColor];\n        unverified.font = [UIFont systemFontOfSize:FONT_SIZE];\n        unverified.text = @\"You can't connect to external servers until you confirm your email address.\\n\\nIf you're still waiting for the email, you can tap here to send yourself another confirmation.\";\n        unverified.tag = 1;\n        unverified.editable = NO;\n        unverified.userInteractionEnabled = YES;\n\n        self.tableView.tableHeaderView = unverified;\n    }\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    \n    [self refresh];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    if(self.presentingViewController) {\n        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];\n    } else {\n        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@\"Logout\" style:UIBarButtonItemStylePlain target:self action:@selector(logoutButtonPressed:)];\n    }\n\n    UILabel *unverified = (UILabel *)self.tableView.tableHeaderView;\n    \n    if(unverified) {\n        CGSize size = [unverified sizeThatFits:self.tableView.bounds.size];\n        unverified.frame = CGRectMake(0,0,self.tableView.bounds.size.width,size.height + 12);\n        self.tableView.tableHeaderView = unverified;\n    }\n    \n    [self refresh];\n}\n\n- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {\n    if(textView == self->_channels || (textView == self->_commands && _cid != -1))\n        self->_activeCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:3];\n    else if(textView == self->_commands)\n        self->_activeCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:4];\n    return YES;\n}\n\n- (BOOL)textFieldShouldReturn:(UITextField *)textField {\n    [self.tableView endEditing:YES];\n    return NO;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    Server *s;\n    \n    switch(event) {\n        case kIRCEventUserInfo:\n            if(self.presentingViewController) {\n                [self.tableView endEditing:YES];\n                [self dismissViewControllerAnimated:YES completion:nil];\n                [[NSNotificationCenter defaultCenter] removeObserver:self];\n            } else {\n                [self refresh];\n            }\n            break;\n        case kIRCEventMakeServer:\n            s = notification.object;\n            if(s.cid == self->_cid) {\n                [(AppDelegate *)([UIApplication sharedApplication].delegate) showMainView:YES];\n                [[NSNotificationCenter defaultCenter] removeObserver:self];\n            }\n            break;\n        default:\n            break;\n    }\n}\n\n#pragma mark - Table view data source\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    if(indexPath.section >= 3)\n        return ([UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody].pointSize * 2) + 32;\n    else\n        return UITableViewAutomaticDimension;\n}\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    if(self->_slack)\n        return 1;\n    else if(self->_cid == -1)\n        return 5;\n    else\n        return 4;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    switch(section) {\n        case 0:\n            if(self->_slack)\n                return 1;\n            else\n                return 4;\n        case 1:\n            return 2;\n        case 2:\n            return 4;\n        case 3:\n            return 1;\n        case 4:\n            return 1;\n    }\n    return 0;\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {\n    switch (section) {\n        case 0:\n            return @\"Server Settings\";\n        case 1:\n            return @\"Your Identity\";\n        case 2:\n            return @\"Passwords\";\n        case 3:\n            return (self->_cid==-1)?@\"Channels To Join\":@\"Commands To Run On Connect\";\n        case 4:\n            return @\"Commands To Run On Connect\";\n    }\n    return nil;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSUInteger row = indexPath.row;\n    NSString *identifier = [NSString stringWithFormat:@\"connectioncell-%li-%li\", (long)indexPath.section, (long)indexPath.row];\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];\n    \n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    cell.accessoryView = nil;\n    cell.detailTextLabel.text = nil;\n    cell.accessoryType = UITableViewCellAccessoryNone;\n    \n    switch(indexPath.section) {\n        case 0:\n            switch(row) {\n                case 0:\n                    if(self->_cid!=-1 || _url) {\n                        cell.textLabel.text = @\"Name\";\n                        cell.accessoryView = self->_network;\n                    } else {\n                        cell.textLabel.text = @\"Network\";\n                        if(self->_netname.length)\n                            cell.detailTextLabel.text = self->_netname;\n                        else\n                            cell.detailTextLabel.text = @\"Choose a Network\";\n                        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;\n                    }\n                    break;\n                case 1:\n                    cell.textLabel.text = @\"Hostname\";\n                    cell.accessoryView = self->_server;\n                    break;\n                case 2:\n                    cell.textLabel.text = @\"Port\";\n                    cell.accessoryView = self->_port;\n                    break;\n                case 3:\n                    cell.textLabel.text = @\"Secure port\";\n                    cell.accessoryView = self->_ssl;\n                    break;\n            }\n            break;\n        case 1:\n            switch(row) {\n                case 0:\n                    cell.textLabel.text = @\"Nickname\";\n                    cell.accessoryView = self->_nickname;\n                    break;\n                case 1:\n                    cell.textLabel.text = @\"Full name (optional)\";\n                    cell.accessoryView = self->_realname;\n                    break;\n            }\n            break;\n        case 2:\n            switch(row) {\n                case 0:\n                    cell.textLabel.text = @\"NickServ password\";\n                    cell.accessoryView = self->_nspass;\n                    break;\n                case 1:\n                    cell.textLabel.text = @\"Reveal NickServ password\";\n                    cell.accessoryView = self->_revealnspass;\n                    break;\n                case 2:\n                    cell.textLabel.text = @\"Server password\";\n                    cell.accessoryView = self->_serverpass;\n                    break;\n                case 3:\n                    cell.textLabel.text = @\"Reveal server password\";\n                    cell.accessoryView = self->_revealserverpass;\n                    break;\n            }\n            break;\n        case 3:\n            cell.textLabel.text = nil;\n            [((self->_cid==-1)?_channels:self->_commands) removeFromSuperview];\n            ((self->_cid==-1)?_channels:self->_commands).frame = CGRectInset(cell.contentView.bounds, 4, 4);\n            [cell.contentView addSubview:(self->_cid==-1)?_channels:self->_commands];\n            break;\n        case 4:\n            cell.textLabel.text = nil;\n            [self->_commands removeFromSuperview];\n            self->_commands.frame = CGRectInset(cell.contentView.bounds, 4, 4);\n            [cell.contentView addSubview:self->_commands];\n            break;\n    }\n    \n    return cell;\n}\n\n/*\n// Override to support conditional editing of the table view.\n- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    // Return NO if you do not want the specified item to be editable.\n    return YES;\n}\n*/\n\n/*\n// Override to support editing the table view.\n- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    if (editingStyle == UITableViewCellEditingStyleDelete) {\n        // Delete the row from the data source\n        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];\n    }   \n    else if (editingStyle == UITableViewCellEditingStyleInsert) {\n        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view\n    }   \n}\n*/\n\n/*\n// Override to support rearranging the table view.\n- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath\n{\n}\n*/\n\n/*\n// Override to support conditional rearranging of the table view.\n- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    // Return NO if you do not want the item to be re-orderable.\n    return YES;\n}\n*/\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    self->_activeCellIndexPath = indexPath;\n    [self.tableView deselectRowAtIndexPath:indexPath animated:NO];\n    [self.tableView endEditing:YES];\n    if(self->_cid == -1 && indexPath.section == 0 && indexPath.row == 0) {\n        NetworkListViewController *nvc = [[NetworkListViewController alloc] initWithDelegate:self];\n        nvc.selection = self->_netname;\n        [self.navigationController pushViewController:nvc animated:YES];\n    } else {\n        UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];\n        if(cell.accessoryView)\n            [cell.accessoryView becomeFirstResponder];\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/EventsDataSource.h",
    "content": "//\n//  EventsDataSource.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import \"IRCCloudJSONObject.h\"\n\n#define ROW_MESSAGE 0\n#define ROW_TIMESTAMP 1\n#define ROW_BACKLOG 2\n#define ROW_LASTSEENEID 3\n#define ROW_SOCKETCLOSED 4\n#define ROW_FAILED 5\n#define ROW_ME_MESSAGE 6\n#define ROW_THUMBNAIL 7\n#define ROW_FILE 8\n#define ROW_REPLY_COUNT 9\n#define TYPE_TIMESTMP @\"__timestamp__\"\n#define TYPE_BACKLOG @\"__backlog__\"\n#define TYPE_LASTSEENEID @\"__lastseeneid\"\n#define TYPE_THUMBNAIL @\"__thumbnail__\"\n#define TYPE_FILE @\"__file__\"\n#define TYPE_REPLY_COUNT @\"__reply_count__\"\n\n@interface Event : NSObject<NSSecureCoding> {\n    int _cid;\n    int _bid;\n    NSTimeInterval _eid;\n    NSString *_timestamp;\n    NSString *_type;\n    NSString *_msg;\n    NSString *_hostmask;\n    NSString *_from;\n    NSString *_fromNick;\n    NSString *_fromMode;\n    NSString *_nick;\n    NSString *_oldNick;\n    NSString *_server;\n    NSString *_diff;\n    NSString *_formattedMsg;\n    NSString *_formattedPrefix;\n    NSString *_accessibilityLabel;\n    NSString *_accessibilityValue;\n    NSAttributedString *_formatted;\n    NSAttributedString *_formattedNick;\n    NSAttributedString *_formattedRealname;\n    NSString *_realname;\n    BOOL _isHighlight;\n    BOOL _isSelf;\n    BOOL _toChan;\n    BOOL _toBuffer;\n    UIColor *_color;\n    UIColor *_bgColor;\n    NSDictionary *_ops;\n    NSTimeInterval _groupEid;\n    int _rowType;\n    NSString *_groupMsg;\n    BOOL _linkify;\n    NSString *_targetMode;\n    int _reqid;\n    BOOL _pending;\n    BOOL _monospace;\n    float _height;\n    NSArray *_links;\n    NSArray *_realnameLinks;\n    NSString *_to;\n    NSString *_command;\n    NSString *_day;\n    NSString *_ignoreMask;\n    NSString *_chan;\n    NSTimer *_expirationTimer;\n    NSDictionary *_entities;\n    float _timestampPosition;\n    BOOL _isHeader;\n    NSTimeInterval _serverTime;\n    BOOL _isEmojiOnly;\n    float _estimatedWidth;\n    BOOL _isQuoted;\n    BOOL _isCodeBlock;\n    int _childEventCount;\n    BOOL _hasReplyRow;\n    NSTimeInterval _parent;\n    NSString *_UUID;\n    NSInteger _row;\n    NSString *_avatar;\n    NSString *_avatarURL;\n    int _cachedAvatarSize;\n    NSURL *_cachedAvatarURL;\n    NSString *_msgid;\n    BOOL _isReply;\n    int _replyCount;\n    NSInteger _mentionOffset;\n    NSMutableSet *_replyNicks;\n    BOOL _edited;\n    BOOL _collapsed;\n    NSTimeInterval _lastEditEID;\n    BOOL _deleted;\n    BOOL _redacted;\n    NSString *_redactedReason;\n}\n@property (assign) int cid, bid, rowType, reqId, childEventCount, replyCount;\n@property (assign) NSTimeInterval eid, groupEid, serverTime, parent, lastEditEID;\n@property (copy) NSString *timestamp, *type, *msg, *hostmask, *from, *fromMode, *nick, *oldNick, *server, *diff, *groupMsg, *targetMode, *formattedMsg, *to, *command, *day, *chan, *realname, *accessibilityLabel, *accessibilityValue, *avatar, *avatarURL, *fromNick, *msgid, *formattedPrefix, *account, *redactedReason;\n@property (assign) BOOL isHighlight, isSelf, toChan, toBuffer, linkify, pending, monospace, isHeader, isEmojiOnly, isQuoted, isCodeBlock, hasReply, isReply, edited, collapsed, hasReplyRow, deleted, redacted;\n@property (copy) NSDictionary *ops,*entities;\n@property (strong) UIColor *color, *bgColor;\n@property (copy) NSAttributedString *formatted, *formattedNick, *formattedRealname, *formattedPadded;\n@property (assign) float height, timestampPosition, avatarHeight, estimatedWidth;\n@property (strong) NSArray *links, *realnameLinks;\n@property (strong) NSMutableSet *replyNicks;\n@property (strong) NSTimer *expirationTimer;\n@property (assign) NSInteger row, mentionOffset;\n-(NSComparisonResult)compare:(Event *)aEvent;\n-(BOOL)isImportant:(NSString *)bufferType;\n-(BOOL)isMessage;\n-(NSString *)ignoreMask;\n-(NSTimeInterval)time;\n-(NSString *)UUID;\n-(Event *)copy;\n-(NSURL *)avatar:(int)size;\n-(NSString *)reply;\n-(BOOL)hasSameAccount:(NSString *)account;\n@end\n\n@interface EventsDataSource : NSObject {\n    NSMutableDictionary *_events;\n    NSMutableDictionary *_events_sorted;\n    NSMutableDictionary *_dirtyBIDs;\n    NSMutableDictionary *_lastEIDs;\n    NSMutableDictionary *_msgIDs;\n    NSDictionary *_formatterMap;\n    NSUInteger _widthForHeightCache;\n}\n@property (readonly) NSDictionary *formatterMap;\n@property NSUInteger widthForHeightCache;\n+(EventsDataSource *)sharedInstance;\n-(void)serialize;\n-(void)clear;\n-(void)clearFormattingCache;\n-(void)clearHeightCache;\n-(void)addEvent:(Event *)event;\n-(Event *)addJSONObject:(IRCCloudJSONObject *)object;\n-(Event *)event:(NSTimeInterval)eid buffer:(int)bid;\n-(Event *)message:(NSString *)msgid buffer:(int)bid;\n-(void)removeEvent:(NSTimeInterval)eid buffer:(int)bid;\n-(void)removeEventsForBuffer:(int)bid;\n-(void)pruneEventsForBuffer:(int)bid maxSize:(int)size;\n-(NSArray *)eventsForBuffer:(int)bid;\n-(NSUInteger)sizeOfBuffer:(int)bid;\n-(void)removeEventsBefore:(NSTimeInterval)min_eid buffer:(int)bid;\n-(int)unreadStateForBuffer:(int)bid lastSeenEid:(NSTimeInterval)lastSeenEid type:(NSString *)type;\n-(int)highlightCountForBuffer:(int)bid lastSeenEid:(NSTimeInterval)lastSeenEid type:(NSString *)type;\n-(int)highlightStateForBuffer:(int)bid lastSeenEid:(NSTimeInterval)lastSeenEid type:(NSString *)type;\n-(NSTimeInterval)lastEidForBuffer:(int)bid;\n-(void)clearPendingAndFailed;\n-(void)reformat;\n+(NSString *)reason:(NSString *)reason;\n+(NSString *)SSLreason:(NSDictionary *)info;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/EventsDataSource.m",
    "content": "//\n//  EventsDataSource.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"EventsDataSource.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"ColorFormatter.h\"\n#import \"BuffersDataSource.h\"\n#import \"ServersDataSource.h\"\n#import \"ChannelsDataSource.h\"\n#import \"UsersDataSource.h\"\n#import \"Ignore.h\"\n#import \"NetworkConnection.h\"\n#import \"ImageCache.h\"\n\n@implementation Event\n+ (BOOL)supportsSecureCoding {\n    return YES;\n}\n-(NSComparisonResult)compare:(Event *)aEvent {\n    if(aEvent.pending && !_pending)\n        return NSOrderedAscending;\n    if(!aEvent.pending && _pending)\n        return NSOrderedDescending;\n    if(aEvent.eid > _eid)\n        return NSOrderedAscending;\n    else if(aEvent.eid < _eid)\n        return NSOrderedDescending;\n    else\n        return NSOrderedSame;\n}\n-(BOOL)isImportant:(NSString *)bufferType {\n    if(self->_isSelf)\n        return NO;\n    if(!_type)\n        return NO;\n    if(self->_rowType == ROW_THUMBNAIL || _rowType == ROW_FILE)\n        return NO;\n    \n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_cid];\n    if(s) {\n        Ignore *ignore = s.ignore;\n        NSString *from = self->_fromNick;\n        if(![from isKindOfClass:NSString.class])\n            from = nil;\n        \n        NSString *hostmask = self->_hostmask;\n        if(![hostmask isKindOfClass:NSString.class])\n            hostmask = nil;\n        \n        if(!from.length)\n            from = [self->_nick isKindOfClass:NSString.class]?self->_nick:nil;\n        \n        if(from != nil && hostmask != nil && [ignore match:[NSString stringWithFormat:@\"%@!%@\",from,hostmask]])\n            return NO;\n    }\n    \n    if([self->_type isEqualToString:@\"notice\"] || [self->_type isEqualToString:@\"channel_invite\"]) {\n        // Notices sent from the server (with no nick sender) aren't important\n        // e.g. *** Looking up your hostname...\n        if(self->_from.length == 0 || self->_from == self->_server)\n            return NO;\n        \n        // Notices and invites sent to a buffer shouldn't notify in the server buffer\n        if([bufferType isEqualToString:@\"console\"] && (self->_toChan || self->_toBuffer))\n            return NO;\n    }\n\n    return [self isMessage];\n}\n-(BOOL)isMessage {\n    return ([self->_type isEqualToString:@\"buffer_msg\"]\n            ||[self->_type isEqualToString:@\"buffer_me_msg\"]\n            ||[self->_type isEqualToString:@\"notice\"]\n            ||[self->_type isEqualToString:@\"channel_invite\"]\n            ||[self->_type isEqualToString:@\"callerid\"]\n            ||[self->_type isEqualToString:@\"wallops\"]);\n}\n-(NSString *)description {\n    return [NSString stringWithFormat:@\"{cid: %i, bid: %i, eid: %f, group: %f, type: %@, from: %@, msg: %@, self: %i, header: %i, reqid: %i, pending: %i, formatted: %@}\", _cid, _bid, _eid, _groupEid, _type, _from, _msg, _isSelf, _isHeader, _reqid, _pending, _formatted];\n}\n-(NSString *)ignoreMask {\n    if(!_ignoreMask) {\n        NSString *from = self->_from;\n        if(!from.length)\n            from = self->_nick;\n        \n        if(from) {\n            self->_ignoreMask = [NSString stringWithFormat:@\"%@!%@\", from, _hostmask];\n        }\n    }\n    return _ignoreMask;\n}\n-(Event *)copy {\n    BOOL pending = self->_pending;\n    self->_pending = NO;\n    NSError *error = nil;\n    Event *e = [NSKeyedUnarchiver unarchivedObjectOfClass:Event.class fromData:[NSKeyedArchiver archivedDataWithRootObject:self requiringSecureCoding:YES error:nil] error:&error];\n    if(error)\n        CLS_LOG(@\"Error: %@\", error);\n    self->_pending = e.pending = pending;\n    return e;\n}\n-(instancetype)initWithCoder:(NSCoder *)aDecoder{\n    self = [super init];\n    if(self) {\n        decodeInt(self->_cid);\n        decodeInt(self->_bid);\n        decodeDouble(self->_eid);\n        decodeObjectOfClass(NSString.class, self->_type);\n        decodeObjectOfClass(NSString.class, self->_msg);\n        decodeObjectOfClass(NSString.class, self->_hostmask);\n        decodeObjectOfClass(NSString.class, self->_from);\n        decodeObjectOfClass(NSString.class, self->_fromMode);\n        decodeObjectOfClass(NSString.class, self->_nick);\n        decodeObjectOfClass(NSString.class, self->_oldNick);\n        decodeObjectOfClass(NSString.class, self->_server);\n        decodeObjectOfClass(NSString.class, self->_diff);\n        decodeObjectOfClass(NSString.class, self->_realname);\n        decodeBool(self->_isHighlight);\n        decodeBool(self->_isSelf);\n        decodeBool(self->_toChan);\n        decodeBool(self->_toBuffer);\n        decodeObjectOfClass(UIColor.class, self->_color);\n        NSSet *set = [NSSet setWithObjects:NSDictionary.class, NSMutableArray.class, NSString.class, NSNumber.class, NSNull.class, nil];\n        decodeObjectOfClasses(set, self->_ops);\n        decodeInt(self->_rowType);\n        decodeBool(self->_linkify);\n        decodeObjectOfClass(NSString.class, self->_targetMode);\n        decodeInt(self->_reqid);\n        decodeBool(self->_pending);\n        decodeBool(self->_monospace);\n        decodeObjectOfClass(NSString.class, self->_to);\n        decodeObjectOfClass(NSString.class, self->_command);\n        decodeObjectOfClass(NSString.class, self->_day);\n        decodeObjectOfClass(NSString.class, self->_ignoreMask);\n        decodeObjectOfClass(NSString.class, self->_chan);\n        [NSSet setWithObjects:NSArray.class, NSDictionary.class, NSString.class, NSNumber.class, NSNull.class, nil];\n        decodeObjectOfClasses(set, self->_entities);\n        decodeFloat(self->_timestampPosition);\n        decodeDouble(self->_serverTime);\n        decodeObjectOfClass(NSString.class, self->_avatar);\n        decodeObjectOfClass(NSString.class, self->_avatarURL);\n        decodeObjectOfClass(NSString.class, self->_fromNick);\n        decodeObjectOfClass(NSString.class, self->_msgid);\n        decodeBool(self->_edited);\n        decodeDouble(self->_lastEditEID);\n        decodeObjectOfClass(NSString.class, self->_account);\n        decodeBool(self->_deleted);\n        decodeBool(self->_redacted);\n        decodeObjectOfClass(NSString.class, self->_redactedReason);\n\n        if(self->_rowType == ROW_TIMESTAMP)\n            self->_bgColor = [UIColor timestampBackgroundColor];\n        else if(self->_rowType == ROW_LASTSEENEID)\n            self->_bgColor = [UIColor contentBackgroundColor];\n        else\n            decodeObjectOfClass(UIColor.class, self->_bgColor);\n        \n        if(self->_pending) {\n            self->_height = 0;\n            self->_pending = NO;\n            self->_rowType = ROW_FAILED;\n            self->_color = [UIColor networkErrorColor];\n            self->_bgColor = [UIColor errorBackgroundColor];\n        }\n    }\n    return self;\n}\n\n-(void)encodeWithCoder:(NSCoder *)aCoder {\n    encodeInt(self->_cid);\n    encodeInt(self->_bid);\n    encodeDouble(self->_eid);\n    encodeObject(self->_type);\n    encodeObject(self->_msg);\n    encodeObject(self->_hostmask);\n    encodeObject(self->_from);\n    encodeObject(self->_fromMode);\n    encodeObject(self->_nick);\n    encodeObject(self->_oldNick);\n    encodeObject(self->_server);\n    encodeObject(self->_diff);\n    encodeObject(self->_realname);\n    encodeBool(self->_isHighlight);\n    encodeBool(self->_isSelf);\n    encodeBool(self->_toChan);\n    encodeBool(self->_toBuffer);\n    @try {\n        encodeObject(self->_color);\n    }\n    @catch (NSException *exception) {\n        self->_color = [UIColor blackColor];\n        encodeObject(self->_color);\n    }\n    encodeObject(self->_ops);\n    encodeInt(self->_rowType);\n    encodeBool(self->_linkify);\n    encodeObject(self->_targetMode);\n    encodeInt(self->_reqid);\n    encodeBool(self->_pending);\n    encodeBool(self->_monospace);\n    encodeObject(self->_to);\n    encodeObject(self->_command);\n    encodeObject(self->_day);\n    encodeObject(self->_ignoreMask);\n    encodeObject(self->_chan);\n    encodeObject(self->_entities);\n    encodeFloat(self->_timestampPosition);\n    encodeDouble(self->_serverTime);\n    encodeObject(self->_avatar);\n    encodeObject(self->_avatarURL);\n    encodeObject(self->_fromNick);\n    encodeObject(self->_msgid);\n    encodeBool(self->_edited);\n    encodeDouble(self->_lastEditEID);\n    encodeObject(self->_account);\n    encodeBool(self->_deleted);\n    encodeBool(self->_redacted);\n    encodeObject(self->_redactedReason);\n\n    if(self->_rowType != ROW_TIMESTAMP && _rowType != ROW_LASTSEENEID)\n        encodeObject(self->_bgColor);\n}\n\n-(NSTimeInterval)time {\n    if(self->_serverTime > 0)\n        return _serverTime / 1000;\n    else if(self->_collapsed && self->_groupEid > 0)\n        return (self->_groupEid / 1000000) + [NetworkConnection sharedInstance].clockOffset;\n    else\n        return (self->_eid / 1000000) + [NetworkConnection sharedInstance].clockOffset;\n}\n\n-(NSString *)UUID {\n    if(!_UUID)\n        self->_UUID = [[NSUUID UUID] UUIDString];\n    return _UUID;\n}\n\n-(NSString *)reply {\n    if([[self->_entities objectForKey:@\"reply\"] isKindOfClass:NSString.class])\n        return [self->_entities objectForKey:@\"reply\"];\n    else if([[[self->_entities objectForKey:@\"known_client_tags\"] objectForKey:@\"reply\"] isKindOfClass:NSString.class])\n        return [[self->_entities objectForKey:@\"known_client_tags\"] objectForKey:@\"reply\"];\n    else\n        return nil;\n}\n\n-(NSURL *)avatar:(int)size {\n#ifndef ENTERPRISE\n    BOOL isIRCCloudAvatar = NO;\n    if([self isMessage] && (!_cachedAvatarURL || size != self->_cachedAvatarSize || ![[ImageCache sharedInstance] isValidURL:self->_cachedAvatarURL])) {\n        if(self->_avatar.length) {\n            self->_cachedAvatarURL = [NSURL URLWithString:[[NetworkConnection sharedInstance].avatarURITemplate relativeStringWithVariables:@{@\"id\":self->_avatar, @\"modifiers\":[NSString stringWithFormat:@\"s%i\", size]} error:nil]];\n        } else if([self->_avatarURL hasPrefix:@\"https://\"]) {\n            if([self->_avatarURL containsString:@\"{size}\"]) {\n                CSURITemplate *template = [CSURITemplate URITemplateWithString:self->_avatarURL error:nil];\n                if(size <= 72)\n                    self->_cachedAvatarURL = [NSURL URLWithString:[template relativeStringWithVariables:@{@\"size\":@\"72\"} error:nil]];\n                else if(size <= 192)\n                    self->_cachedAvatarURL = [NSURL URLWithString:[template relativeStringWithVariables:@{@\"size\":@\"192\"} error:nil]];\n                else\n                    self->_cachedAvatarURL = [NSURL URLWithString:[template relativeStringWithVariables:@{@\"size\":@\"512\"} error:nil]];\n            } else {\n                self->_cachedAvatarURL = [NSURL URLWithString:self->_avatarURL];\n            }\n        } else {\n            self->_cachedAvatarURL = nil;\n            if([self->_hostmask rangeOfString:@\"@\"].location != NSNotFound) {\n                NSString *ident = [self->_hostmask substringToIndex:[self->_hostmask rangeOfString:@\"@\"].location];\n                if([ident hasPrefix:@\"~\"])\n                    ident = [ident substringFromIndex:1];\n                if([ident hasPrefix:@\"uid\"] || [ident hasPrefix:@\"sid\"]) {\n                    ident = [ident substringFromIndex:3];\n                    if(ident.length && [ident intValue]) {\n                        self->_cachedAvatarURL = [NSURL URLWithString:[[NetworkConnection sharedInstance].avatarRedirectURITemplate relativeStringWithVariables:@{@\"id\":ident, @\"modifiers\":[NSString stringWithFormat:@\"s%i\", size]} error:nil]];\n                        if([[ImageCache sharedInstance] isValidURL:self->_cachedAvatarURL])\n                            isIRCCloudAvatar = YES;\n                        else\n                            self->_cachedAvatarURL = nil;\n                    }\n                }\n            }\n            if(!_cachedAvatarURL) {\n                NSString *n = self->_realname.lowercaseString;\n                if(n.length) {\n                    NSArray *results = [[ColorFormatter email] matchesInString:n options:0 range:NSMakeRange(0, n.length)];\n                    if(results.count == 1) {\n                        NSString *email = [n substringWithRange:[results.firstObject range]];\n                        self->_cachedAvatarURL = [NSURL URLWithString:[NSString stringWithFormat:@\"https://www.gravatar.com/avatar/%@?size=%i&default=404\", [ImageCache md5:email].lowercaseString, size]];\n                        isIRCCloudAvatar = NO;\n                    }\n                }\n            }\n        }\n        if(self->_cachedAvatarURL && !_avatar.length && !isIRCCloudAvatar && ![[ServersDataSource sharedInstance] getServer:self->_cid].isSlack) {\n            BOOL inlineMediaPref = NO;\n            Buffer *buffer = [[BuffersDataSource sharedInstance] getBuffer:self->_bid];\n            NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n            if(buffer && prefs) {\n                inlineMediaPref = [[prefs objectForKey:@\"inlineimages\"] boolValue];\n                if(inlineMediaPref) {\n                    NSDictionary *disableMap;\n                    \n                    if([buffer.type isEqualToString:@\"channel\"]) {\n                        disableMap = [prefs objectForKey:@\"channel-inlineimages-disable\"];\n                    } else {\n                        disableMap = [prefs objectForKey:@\"buffer-inlineimages-disable\"];\n                    }\n                    \n                    if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] boolValue])\n                        inlineMediaPref = NO;\n                } else {\n                    NSDictionary *enableMap;\n                    \n                    if([buffer.type isEqualToString:@\"channel\"]) {\n                        enableMap = [prefs objectForKey:@\"channel-inlineimages\"];\n                    } else {\n                        enableMap = [prefs objectForKey:@\"buffer-inlineimages\"];\n                    }\n                    \n                    if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] boolValue])\n                        inlineMediaPref = YES;\n                }\n                \n                if([[NSUserDefaults standardUserDefaults] boolForKey:@\"inlineWifiOnly\"] && ![NetworkConnection sharedInstance].isWifi) {\n                    inlineMediaPref = NO;\n                }\n            }\n            if(!inlineMediaPref)\n                self->_cachedAvatarURL = nil;\n        }\n    }\n    if(self->_cachedAvatarURL)\n        self->_cachedAvatarSize = size;\n#endif\n    return _cachedAvatarURL;\n}\n-(BOOL)hasSameAccount:(NSString *)account {\n    return self->_account && ![self->_account isEqualToString:@\"*\"] && [self->_account isEqualToString:account];\n}\n@end\n\n@implementation EventsDataSource\n+(EventsDataSource *)sharedInstance {\n    static EventsDataSource *sharedInstance;\n\t\n    @synchronized(self) {\n        if(!sharedInstance)\n            sharedInstance = [[EventsDataSource alloc] init];\n\t\t\n        return sharedInstance;\n    }\n\treturn nil;\n}\n\n-(id)init {\n    self = [super init];\n    if(self) {\n        [NSKeyedArchiver setClassName:@\"IRCCloud.Event\" forClass:Event.class];\n        [NSKeyedUnarchiver setClass:Event.class forClassName:@\"IRCCloud.Event\"];\n\n#ifndef EXTENSION\n        if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"cacheVersion\"] isEqualToString:[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleVersion\"]]) {\n            NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"events\"];\n            \n            @try {\n                NSError* error = nil;\n                self->_events = [[NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:NSDictionary.class, NSArray.class, Event.class,NSString.class,NSNumber.class,NSMutableArray.class,nil] fromData:[NSData dataWithContentsOfFile:cacheFile] error:&error] mutableCopy];\n                if(error)\n                    @throw [NSException exceptionWithName:@\"NSError\" reason:error.debugDescription userInfo:@{ @\"NSError\" : error }];\n            } @catch(NSException *e) {\n                CLS_LOG(@\"Exception: %@\", e);\n                [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n                [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"cacheVersion\"];\n                [[ServersDataSource sharedInstance] clear];\n                [[BuffersDataSource sharedInstance] clear];\n                [[ChannelsDataSource sharedInstance] clear];\n                [[UsersDataSource sharedInstance] clear];\n            }\n        }\n#endif\n        self->_dirtyBIDs = [[NSMutableDictionary alloc] init];\n        self->_lastEIDs = [[NSMutableDictionary alloc] init];\n        self->_events_sorted = [[NSMutableDictionary alloc] init];\n        self->_msgIDs = [[NSMutableDictionary alloc] init];\n        if(self->_events) {\n            for(NSNumber *bid in _events) {\n                NSMutableArray *events = [self->_events objectForKey:bid];\n                NSMutableDictionary *events_sorted = [[NSMutableDictionary alloc] init];\n                NSMutableDictionary *msgids = [[NSMutableDictionary alloc] init];\n                if(events.count > 1000) {\n                    CLS_LOG(@\"Cleaning up excessive backlog in BID: bid%@\", bid);\n                    Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:bid.intValue];\n                    if(b) {\n                        b.scrolledUp = NO;\n                        b.scrolledUpFrom = -1;\n                        b.savedScrollOffset = -1;\n                    }\n                    while(events.count > 1000) {\n                        Event *e = [events firstObject];\n                        [events removeObject:e];\n                    }\n                }\n\n                for(Event *e in events) {\n                    [events_sorted setObject:e forKey:@(e.eid)];\n                    if(e.msgid.length)\n                        [msgids setObject:e forKey:e.msgid];\n                    if(!e.pending) {\n                        if(![self->_lastEIDs objectForKey:@(e.bid)] || [[self->_lastEIDs objectForKey:@(e.bid)] doubleValue] < e.eid)\n                            [self->_lastEIDs setObject:@(e.eid) forKey:@(e.bid)];\n                    }\n                }\n                [self->_events_sorted setObject:events_sorted forKey:bid];\n                [self->_msgIDs setObject:msgids forKey:bid];\n                [[self->_events objectForKey:bid] sortUsingSelector:@selector(compare:)];\n            }\n            [self clearPendingAndFailed];\n        } else {\n            self->_events = [[NSMutableDictionary alloc] init];\n        }\n        \n        void (^error)(Event *event, IRCCloudJSONObject *object) = ^(Event *event, IRCCloudJSONObject *object) {\n            event.from = @\"\";\n            event.color = [UIColor networkErrorColor];\n            event.bgColor = [UIColor errorBackgroundColor];\n        };\n        \n        void (^notice)(Event *event, IRCCloudJSONObject *object) = ^(Event *event, IRCCloudJSONObject *object) {\n            event.bgColor = [UIColor noticeBackgroundColor];\n            if(object) {\n                event.chan = [object objectForKey:@\"target\"];\n                event.nick = [object objectForKey:@\"target\"];\n                if([[object objectForKey:@\"statusmsg\"] isKindOfClass:[NSString class]])\n                    event.targetMode = [object objectForKey:@\"statusmsg\"];\n                else\n                    event.targetMode = nil;\n            }\n            event.monospace = YES;\n            event.isHighlight = NO;\n        };\n        \n        void (^status)(Event *event, IRCCloudJSONObject *object) = ^(Event *event, IRCCloudJSONObject *object) {\n            event.from = @\"\";\n            event.bgColor = [UIColor statusBackgroundColor];\n            if([object objectForKey:@\"parts\"] && [[object objectForKey:@\"parts\"] length] > 0)\n                event.msg = [NSString stringWithFormat:@\"%@: %@\", [object objectForKey:@\"parts\"], event.msg];\n            else if([object objectForKey:@\"msg\"])\n                event.msg = [object objectForKey:@\"msg\"];\n            event.monospace = YES;\n            if(![event.type isEqualToString:@\"server_motd\"] && ![event.type isEqualToString:@\"zurna_motd\"])\n                event.linkify = NO;\n        };\n        \n        void (^unhandled_line)(Event *event, IRCCloudJSONObject *object) = ^(Event *event, IRCCloudJSONObject *object) {\n            if(object) {\n                event.from = @\"\";\n                event.msg = @\"\";\n                if([object objectForKey:@\"command\"])\n                    event.msg = [[object objectForKey:@\"command\"] stringByAppendingString:@\" \"];\n                if([object objectForKey:@\"raw\"])\n                    event.msg = [event.msg stringByAppendingString:[object objectForKey:@\"raw\"]];\n                else\n                    event.msg = [event.msg stringByAppendingString:[object objectForKey:@\"msg\"]];\n            }\n            event.color = [UIColor networkErrorColor];\n            event.bgColor = [UIColor errorBackgroundColor];\n        };\n        \n        void (^kicked_channel)(Event *event, IRCCloudJSONObject *object) = ^(Event *event, IRCCloudJSONObject *object) {\n            event.from = @\"\";\n            if(object) {\n                event.oldNick = [object objectForKey:@\"nick\"];\n                event.nick = [object objectForKey:@\"kicker\"];\n                event.fromMode = [object objectForKey:@\"kicker_mode\"];\n                event.hostmask = [object objectForKey:@\"kicker_hostmask\"];\n            }\n            event.color = [UIColor timestampColor];\n            event.linkify = NO;\n            if(event.isSelf)\n                event.rowType = ROW_SOCKETCLOSED;\n        };\n        \n        void (^motd)(Event *event, IRCCloudJSONObject *object) = ^(Event *event, IRCCloudJSONObject *object) {\n            if(object) {\n                NSArray *lines = [object objectForKey:@\"lines\"];\n                event.from = @\"\";\n                if([lines count]) {\n                    NSMutableString *motd = [[NSMutableString alloc] init];\n                    if([[object objectForKey:@\"start\"] length]) {\n                        [motd appendFormat:@\"%@\\n\", [object objectForKey:@\"start\"]];\n                    }\n                    \n                    for(NSString *line in lines) {\n                        [motd appendFormat:@\"%@\\n\", line];\n                    }\n                    event.msg = motd;\n                }\n            }\n            event.bgColor = [UIColor selfBackgroundColor];\n            event.monospace = YES;\n        };\n        \n        void (^cap)(Event *event, IRCCloudJSONObject *object) = ^(Event *event, IRCCloudJSONObject *object) {\n            event.bgColor = [UIColor statusBackgroundColor];\n            event.linkify = NO;\n            event.from = nil;\n            if(object) {\n                if([event.type isEqualToString:@\"cap_ls\"])\n                    event.msg = [NSString stringWithFormat:@\"%cCAP%c Server supports: \", BOLD, BOLD];\n                else if([event.type isEqualToString:@\"cap_list\"])\n                    event.msg = [NSString stringWithFormat:@\"%cCAP%c Enabled: \", BOLD, BOLD];\n                else if([event.type isEqualToString:@\"cap_req\"])\n                    event.msg = [NSString stringWithFormat:@\"%cCAP%c Requesting: \", BOLD, BOLD];\n                else if([event.type isEqualToString:@\"cap_ack\"])\n                    event.msg = [NSString stringWithFormat:@\"%cCAP%c Acknowledged: \", BOLD, BOLD];\n                else if([event.type isEqualToString:@\"cap_nak\"])\n                    event.msg = [NSString stringWithFormat:@\"%cCAP%c Rejected: \", BOLD, BOLD];\n                else if([event.type isEqualToString:@\"cap_new\"])\n                    event.msg = [NSString stringWithFormat:@\"%cCAP%c Server added: \", BOLD, BOLD];\n                else if([event.type isEqualToString:@\"cap_del\"])\n                    event.msg = [NSString stringWithFormat:@\"%cCAP%c Server removed: \", BOLD, BOLD];\n                else if([event.type isEqualToString:@\"cap_raw\"])\n                    event.msg = [object objectForKey:@\"line\"];\n                else if([event.type isEqualToString:@\"cap_invalid\"])\n                    event.msg = [NSString stringWithFormat:@\"%cCAP%c %@\", BOLD, BOLD, event.msg];\n                if([object objectForKey:@\"caps\"])\n                    event.msg = [event.msg stringByAppendingString:[[object objectForKey:@\"caps\"] componentsJoinedByString:@\" | \"]];\n            }\n            event.monospace = YES;\n        };\n        \n        self->_formatterMap = @{@\"too_fast\":error, @\"sasl_fail\":error, @\"sasl_too_long\":error, @\"sasl_aborted\":error,\n                          @\"sasl_already\":error, @\"no_bots\":error, @\"msg_services\":error, @\"bad_ping\":error, @\"error\":status,\n                          @\"not_for_halfops\":error, @\"ambiguous_error_message\":error, @\"list_syntax\":error, @\"who_syntax\":error,\n                          @\"wait\":status, @\"stats\": status, @\"statslinkinfo\": status, @\"statscommands\": status, @\"statscline\": status, @\"statsnline\": status, @\"statsiline\": status, @\"statskline\": status, @\"statsqline\": status, @\"statsyline\": status, @\"statsbline\": status, @\"statsgline\": status, @\"statstline\": status, @\"statseline\": status, @\"statsvline\": status, @\"statslline\": status, @\"statsuptime\": status, @\"statsoline\": status, @\"statshline\": status, @\"statssline\": status, @\"statsuline\": status, @\"statsdebug\": status, @\"endofstats\": status, @\"spamfilter\": status,\n                          @\"server_motdstart\": status, @\"server_welcome\": status, @\"server_endofmotd\": status,\n                          @\"server_nomotd\": status, @\"server_luserclient\": status, @\"server_luserop\": status,\n                          @\"server_luserconns\": status, @\"server_luserme\": status, @\"server_n_local\": status,\n                          @\"server_luserchannels\": status, @\"server_n_global\": status, @\"server_yourhost\": status,\n                          @\"server_created\": status, @\"server_luserunknown\": status,\n                          @\"btn_metadata_set\": status, @\"logged_in_as\": status, @\"sasl_success\": status, @\"you_are_operator\": status,\n                          @\"server_snomask\": status, @\"starircd_welcome\": status, @\"zurna_motd\": status, @\"codepage\": status, @\"logged_out\": status,\n                          @\"nick_locked\": status, @\"text\": status, @\"admin_info\": status,\n                          @\"cap_ls\": cap, @\"cap_list\": cap, @\"cap_req\": cap, @\"cap_ack\": cap, @\"cap_raw\": cap, @\"cap_nak\": cap, @\"cap_new\": cap, @\"cap_del\": cap, @\"cap_invalid\": cap, \n                          @\"unhandled_line\":unhandled_line, @\"unparsed_line\":unhandled_line,\n                          @\"kicked_channel\":kicked_channel, @\"you_kicked_channel\":kicked_channel,\n                          @\"motd_response\":motd, @\"server_motd\":motd, @\"info_response\":motd,\n                          @\"notice\":notice, @\"newsflash\":notice, @\"generic_server_info\":notice, @\"list_usage\":notice,\n                          @\"buffer_msg\": ^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  if([[object objectForKey:@\"statusmsg\"] isKindOfClass:[NSString class]])\n                                      event.targetMode = [object objectForKey:@\"statusmsg\"];\n                                  else\n                                      event.targetMode = nil;\n                              }\n                          },\n                          @\"socket_closed\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              event.rowType = ROW_SOCKETCLOSED;\n                              event.color = [UIColor timestampColor];\n                              if(object) {\n                                  if([object objectForKey:@\"pool_lost\"])\n                                      event.msg = @\"Connection pool lost\";\n                                  else if([object objectForKey:@\"server_ping_timeout\"])\n                                      event.msg = @\"Server PING timed out\";\n                                  else if([object objectForKey:@\"reason\"] && [[object objectForKey:@\"reason\"] length] > 0) {\n                                      event.msg = [@\"Connection lost: \" stringByAppendingString:[EventsDataSource reason:[object objectForKey:@\"reason\"]]];\n                                  } else if([object objectForKey:@\"abnormal\"])\n                                      event.msg = @\"Connection closed unexpectedly\";\n                                  else\n                                      event.msg = @\"\";\n                              }\n                          },\n                          @\"user_channel_mode\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  event.targetMode = [object objectForKey:@\"newmode\"];\n                                  event.chan = [object objectForKey:@\"channel\"];\n                              }\n                              event.isSelf = NO;\n                          },\n                          @\"buffer_me_msg\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  if([[object objectForKey:@\"display_name\"] isKindOfClass:NSString.class])\n                                      event.nick = [object objectForKey:@\"display_name\"];\n                                  else\n                                      event.nick = [object objectForKey:@\"from\"];\n                                  event.fromNick = [object objectForKey:@\"from\"];\n                                  event.from = @\"\";\n                              }\n                          },\n                          @\"nickname_in_use\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  event.from = [object objectForKey:@\"nick\"];\n                              }\n                              event.msg = @\"is already in use\";\n                              event.color = [UIColor networkErrorColor];\n                              event.bgColor = [UIColor errorBackgroundColor];\n                          },\n                          @\"connecting_cancelled\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              if(object) {\n                                  if([object objectForKey:@\"sts\"])\n                                      event.msg = @\"Upgrading connection security\";\n                                  else\n                                      event.msg = @\"Cancelled\";\n                              }\n                              event.color = [UIColor networkErrorColor];\n                              event.bgColor = [UIColor errorBackgroundColor];\n                          },\n                          @\"connecting_failed\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.rowType = ROW_SOCKETCLOSED;\n                              event.color = [UIColor timestampColor];\n                              event.from = @\"\";\n                              if(object) {\n                                  NSString *reason = [object objectForKey:@\"reason\"];\n                                  if([reason isKindOfClass:[NSString class]] && [reason length]) {\n                                      if([reason isEqualToString:@\"ssl_verify_error\"]) {\n                                          NSDictionary *error = [object objectForKey:@\"ssl_verify_error\"];\n                                          if([error objectForKey:@\"type\"]) {\n                                              event.msg = [@\"Strict transport security error: \" stringByAppendingString:[EventsDataSource SSLreason:error]];\n                                          } else {\n                                              event.msg = @\"Strict transport security error\";\n                                          }\n                                      } else {\n                                          event.msg = [@\"Failed to connect: \" stringByAppendingString:[EventsDataSource reason:reason]];\n                                      }\n                                  } else {\n                                      event.msg = @\"Failed to connect.\";\n                                  }\n                              }\n                          },\n                          @\"quit_server\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              event.msg = @\"⇐ You disconnected\";\n                              event.color = [UIColor timestampColor];\n                              event.isSelf = NO;\n                          },\n                          @\"self_details\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                              if(object) {\n                                  event.from = @\"\";\n                                  if([[object objectForKey:@\"user\"] length]) {\n                                      event.msg = [NSString stringWithFormat:@\"Your hostmask: %c%@%c\", BOLD, [object objectForKey:@\"usermask\"], BOLD];\n                                      if([object objectForKey:@\"server_realname\"]) {\n                                          Event *e1 = [NSKeyedUnarchiver unarchivedObjectOfClass:Event.class fromData:[NSKeyedArchiver archivedDataWithRootObject:event requiringSecureCoding:NO error:nil] error:nil];\n                                          e1.eid++;\n                                          e1.msg = [NSString stringWithFormat:@\"Your name: %c%@%c\", BOLD, [object objectForKey:@\"server_realname\"], BOLD];\n                                          e1.linkify = YES;\n                                          [self addEvent:e1];\n                                      }\n                                  } else if([object objectForKey:@\"server_realname\"]) {\n                                      event.msg = [NSString stringWithFormat:@\"Your name: %c%@%c\", BOLD, [object objectForKey:@\"server_realname\"], BOLD];\n                                      event.linkify = YES;\n                                  }\n                              }\n                              event.monospace = YES;\n                          },\n                          @\"myinfo\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              if(object) {\n                                  event.msg = [NSString stringWithFormat:@\"Host: %@\\n\", [object objectForKey:@\"server\"]];\n                                  event.msg = [event.msg stringByAppendingFormat:@\"IRCd: %@\\n\", [object objectForKey:@\"version\"]];\n                                  event.msg = [event.msg stringByAppendingFormat:@\"User modes: %@\\n\", [object objectForKey:@\"user_modes\"]];\n                                  event.msg = [event.msg stringByAppendingFormat:@\"Channel modes: %@\\n\", [object objectForKey:@\"channel_modes\"]];\n                                  if([[object objectForKey:@\"rest\"] length])\n                                      event.msg = [event.msg stringByAppendingFormat:@\"Parametric channel modes: %@\\n\", [object objectForKey:@\"rest\"]];\n                              }\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                              event.monospace = YES;\n                          },\n                          @\"user_mode\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              if(object)\n                                  event.msg = [NSString stringWithFormat:@\"Your user mode is: %c+%@%c\", BOLD, [object objectForKey:@\"newmode\"], BOLD];\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.monospace = YES;\n                          },\n                          @\"your_unique_id\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              if(object)\n                                  event.msg = [NSString stringWithFormat:@\"Your unique ID is: %c%@%c\", BOLD, [object objectForKey:@\"unique_id\"], BOLD];\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.monospace = YES;\n                          },\n                          @\"kill\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              if(object) {\n                                  event.msg = @\"You were killed\";\n                                  if([object objectForKey:@\"from\"])\n                                      event.msg = [event.msg stringByAppendingFormat:@\" by %@\", [object objectForKey:@\"from\"]];\n                                  if([object objectForKey:@\"killer_hostmask\"])\n                                      event.msg = [event.msg stringByAppendingFormat:@\" (%@)\", [object objectForKey:@\"killer_hostmask\"]];\n                                  if([object objectForKey:@\"reason\"])\n                                      event.msg = [event.msg stringByAppendingFormat:@\": %@\", [object objectForKey:@\"reason\"]];\n                              }\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                          },\n                          @\"banned\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              if(object) {\n                                  event.msg = @\"You were banned\";\n                                  if([object objectForKey:@\"server\"])\n                                      event.msg = [event.msg stringByAppendingFormat:@\" from %@\", [object objectForKey:@\"server\"]];\n                                  if([object objectForKey:@\"reason\"])\n                                      event.msg = [event.msg stringByAppendingFormat:@\": %@\", [object objectForKey:@\"reason\"]];\n                              }\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                          },\n                          @\"channel_topic\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  event.from = [[object objectForKey:@\"author\"] length]?[object objectForKey:@\"author\"]:[object objectForKey:@\"server\"];\n                                  if([object objectForKey:@\"topic\"] && [[object objectForKey:@\"topic\"] length])\n                                      event.msg = [NSString stringWithFormat:@\"set the topic: %@\", [object objectForKey:@\"topic\"]];\n                                  else\n                                      event.msg = @\"cleared the topic\";\n                              }\n                              event.bgColor = [UIColor statusBackgroundColor];\n                          },\n                          @\"channel_mode\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  event.nick = event.from;\n                                  event.from = @\"\";\n                                  if(event.server && [event.server isKindOfClass:[NSString class]] && event.server.length)\n                                      event.msg = [NSString stringWithFormat:@\"Channel mode set to: %c%@%c by the server %c%@%c\", BOLD, [object objectForKey:@\"diff\"], CLEAR, BOLD, event.server, CLEAR];\n                                  else\n                                      event.msg = [NSString stringWithFormat:@\"Channel mode set to: %c%@%c\", BOLD, [object objectForKey:@\"diff\"], BOLD];\n                              }\n                              event.linkify = NO;\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.isSelf = NO;\n                          },\n                          @\"channel_mode_is\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              if(object) {\n                                  if([[object objectForKey:@\"diff\"] length] > 0)\n                                      event.msg = [NSString stringWithFormat:@\"Channel mode is: %c%@%c\", BOLD, [object objectForKey:@\"diff\"], BOLD];\n                                  else\n                                      event.msg = @\"No channel mode\";\n                              }\n                              event.bgColor = [UIColor statusBackgroundColor];\n                          },\n                          @\"channel_mode_list_change\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  BOOL unknown = YES;\n                                  NSDictionary *ops = [object objectForKey:@\"ops\"];\n                                  if(ops) {\n                                      NSArray *add = [ops objectForKey:@\"add\"];\n                                      if(add.count > 0) {\n                                          NSDictionary *op = [add objectAtIndex:0];\n                                          if([[op objectForKey:@\"mode\"] isEqualToString:@\"b\"]) {\n                                              event.nick = event.from;\n                                              event.from = @\"\";\n                                              event.msg = [NSString stringWithFormat:@\"banned %c%@%c (%c14+b%c)\", BOLD, [op objectForKey:@\"param\"], BOLD, COLOR_MIRC, COLOR_MIRC];\n                                              unknown = NO;\n                                          } else if([[op objectForKey:@\"mode\"] isEqualToString:@\"e\"]) {\n                                              event.nick = event.from;\n                                              event.from = @\"\";\n                                              event.msg = [NSString stringWithFormat:@\"exempted %c%@%c from bans (%c14+e%c)\", BOLD, [op objectForKey:@\"param\"], BOLD, COLOR_MIRC, COLOR_MIRC];\n                                              unknown = NO;\n                                          } else if([[op objectForKey:@\"mode\"] isEqualToString:@\"q\"]) {\n                                              if([[op objectForKey:@\"param\"] rangeOfString:@\"@\"].location == NSNotFound && [[op objectForKey:@\"param\"] rangeOfString:@\"$\"].location == NSNotFound) {\n                                                  event.type = @\"user_channel_mode\";\n                                              } else {\n                                                  event.nick = event.from;\n                                                  event.from = @\"\";\n                                                  event.msg = [NSString stringWithFormat:@\"quieted %c%@%c (%c14+q%c)\", BOLD, [op objectForKey:@\"param\"], BOLD, COLOR_MIRC, COLOR_MIRC];\n                                              }\n                                              unknown = NO;\n                                          } else if([[op objectForKey:@\"mode\"] isEqualToString:@\"I\"]) {\n                                              event.nick = event.from;\n                                              event.from = @\"\";\n                                              event.msg = [NSString stringWithFormat:@\"added %c%@%c to the invite list (%c14+I%c)\", BOLD, [op objectForKey:@\"param\"], BOLD, COLOR_MIRC, COLOR_MIRC];\n                                              unknown = NO;\n                                          }\n                                      }\n                                      NSArray *remove = [ops objectForKey:@\"remove\"];\n                                      if(remove.count > 0) {\n                                          NSDictionary *op = [remove objectAtIndex:0];\n                                          if([[op objectForKey:@\"mode\"] isEqualToString:@\"b\"]) {\n                                              event.nick = event.from;\n                                              event.from = @\"\";\n                                              event.msg = [NSString stringWithFormat:@\"un-banned %c%@%c (%c14-b%c)\", BOLD, [op objectForKey:@\"param\"], BOLD, COLOR_MIRC, COLOR_MIRC];\n                                              unknown = NO;\n                                          } else if([[op objectForKey:@\"mode\"] isEqualToString:@\"e\"]) {\n                                              event.nick = event.from;\n                                              event.from = @\"\";\n                                              event.msg = [NSString stringWithFormat:@\"un-exempted %c%@%c from bans (%c14-e%c)\", BOLD, [op objectForKey:@\"param\"], BOLD, COLOR_MIRC, COLOR_MIRC];\n                                              unknown = NO;\n                                          } else if([[op objectForKey:@\"mode\"] isEqualToString:@\"q\"]) {\n                                              if([[op objectForKey:@\"param\"] rangeOfString:@\"@\"].location == NSNotFound && [[op objectForKey:@\"param\"] rangeOfString:@\"$\"].location == NSNotFound) {\n                                                  event.type = @\"user_channel_mode\";\n                                              } else {\n                                                  event.nick = event.from;\n                                                  event.from = @\"\";\n                                                  event.msg = [NSString stringWithFormat:@\"un-quieted %c%@%c (%c14-q%c)\", BOLD, [op objectForKey:@\"param\"], BOLD, COLOR_MIRC, COLOR_MIRC];\n                                              }\n                                              unknown = NO;\n                                          } else if([[op objectForKey:@\"mode\"] isEqualToString:@\"I\"]) {\n                                              event.nick = event.from;\n                                              event.from = @\"\";\n                                              event.msg = [NSString stringWithFormat:@\"removed %c%@%c from the invite list (%c14-I%c)\", BOLD, [op objectForKey:@\"param\"], BOLD, COLOR_MIRC, COLOR_MIRC];\n                                              unknown = NO;\n                                          }\n                                      }\n                                  }\n                                  if(unknown) {\n                                      event.nick = event.from;\n                                      event.from = @\"\";\n                                      event.msg = [NSString stringWithFormat:@\"set channel mode %c%@%c\", BOLD, [object objectForKey:@\"diff\"], BOLD];\n                                  }\n                              }\n                              event.isSelf = NO;\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                          },\n                          @\"hidden_host_set\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                              event.from = @\"\";\n                              if(object)\n                                  event.msg = [NSString stringWithFormat:@\"%c%@%c %@\", BOLD, [object objectForKey:@\"hidden_host\"], BOLD, event.msg];\n                              event.monospace = YES;\n                          },\n                          @\"inviting_to_channel\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              if(object)\n                                  event.msg = [NSString stringWithFormat:@\"You invited %@ to join %@\", [object objectForKey:@\"recipient\"], [object objectForKey:@\"channel\"]];\n                              event.bgColor = [UIColor noticeBackgroundColor];\n                              event.monospace = YES;\n                          },\n                          @\"channel_invite\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  event.msg = [NSString stringWithFormat:@\"Invite to join %@\", [object objectForKey:@\"channel\"]];\n                                  event.oldNick = [object objectForKey:@\"channel\"];\n                              }\n                              event.bgColor = [UIColor noticeBackgroundColor];\n                              event.monospace = YES;\n                          },\n                          @\"callerid\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = event.nick;\n                              event.isHighlight = YES;\n                              event.linkify = NO;\n                              event.monospace = YES;\n                              if(object) {\n                                  event.hostmask = [object objectForKey:@\"usermask\"];\n                                  event.msg = [event.msg stringByAppendingFormat:@\" Tap to add %c%@%c to the whitelist.\", BOLD, event.nick, CLEAR];\n                              }\n                          },\n                          @\"target_callerid\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object)\n                                  event.from = [object objectForKey:@\"target_nick\"];\n                              event.color = [UIColor networkErrorColor];\n                              event.bgColor = [UIColor errorBackgroundColor];\n                              event.monospace = YES;\n                          },\n                          @\"target_notified\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object)\n                                  event.from = [object objectForKey:@\"target_nick\"];\n                              event.color = [UIColor networkErrorColor];\n                              event.bgColor = [UIColor errorBackgroundColor];\n                              event.monospace = YES;\n                          },\n                          @\"link_channel\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.from = @\"\";\n                              if(object) {\n                                  if([[object objectForKey:@\"invalid_chan\"] isKindOfClass:[NSString class]] && [[object objectForKey:@\"invalid_chan\"] length]) {\n                                      if([[object objectForKey:@\"valid_chan\"] isKindOfClass:[NSString class]] && [[object objectForKey:@\"valid_chan\"] length]) {\n                                          event.msg = [NSString stringWithFormat:@\"%@ → %@ %@\", [object objectForKey:@\"invalid_chan\"], [object objectForKey:@\"valid_chan\"], event.msg];\n                                      } else {\n                                          event.msg = [NSString stringWithFormat:@\"%@ %@\", [object objectForKey:@\"invalid_chan\"], event.msg];\n                                      }\n                                  }\n                              }\n                              event.color = [UIColor networkErrorColor];\n                              event.bgColor = [UIColor errorBackgroundColor];\n                              event.monospace = YES;\n                          },\n                          @\"version\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                              event.from = @\"\";\n                              if(object)\n                                  event.msg = [NSString stringWithFormat:@\"%c%@%c %@\", BOLD, [object objectForKey:@\"server_version\"], BOLD, [object objectForKey:@\"comments\"]];\n                              event.monospace = YES;\n                          },\n                          @\"rehashed_config\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.bgColor = [UIColor noticeBackgroundColor];\n                              event.linkify = NO;\n                              event.from = @\"\";\n                              if(object)\n                                  event.msg = [NSString stringWithFormat:@\"Rehashed config: %@ (%@)\", [object objectForKey:@\"file\"], event.msg];\n                              event.monospace = YES;\n                          },\n                          @\"knock\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.bgColor = [UIColor noticeBackgroundColor];\n                              event.linkify = NO;\n                              event.monospace = YES;\n                              if(object) {\n                                  if(event.nick.length) {\n                                      event.from = event.nick;\n                                      if(event.hostmask.length)\n                                          event.msg = [event.msg stringByAppendingFormat:@\" (%@)\", event.hostmask];\n                                  } else {\n                                      event.msg = [NSString stringWithFormat:@\"%@ %@\", [object objectForKey:@\"userhost\"], event.msg];\n                                  }\n                              }\n                          },\n                          @\"unknown_umode\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.color = [UIColor networkErrorColor];\n                              event.bgColor = [UIColor errorBackgroundColor];\n                              event.linkify = NO;\n                              event.from = @\"\";\n                              if(object && [[object objectForKey:@\"flag\"] length])\n                                  event.msg = [NSString stringWithFormat:@\"%c%@%c %@\", BOLD, [object objectForKey:@\"flag\"], BOLD, event.msg];\n                          },\n                          @\"kill_deny\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.color = [UIColor networkErrorColor];\n                              event.bgColor = [UIColor errorBackgroundColor];\n                              if(object)\n                                  event.from = [object objectForKey:@\"channel\"];\n                          },\n                          @\"chan_own_priv_needed\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.color = [UIColor networkErrorColor];\n                              event.bgColor = [UIColor errorBackgroundColor];\n                              if(object)\n                                  event.from = [object objectForKey:@\"channel\"];\n                          },\n                          @\"chan_forbidden\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.color = [UIColor networkErrorColor];\n                              event.bgColor = [UIColor errorBackgroundColor];\n                              if(object)\n                                  event.from = [object objectForKey:@\"channel\"];\n                          },\n                          @\"time\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                              event.from = @\"\";\n                              event.monospace = YES;\n                              if(object) {\n                                  event.msg = [object objectForKey:@\"time_string\"];\n                                  if([[object objectForKey:@\"time_stamp\"] length]) {\n                                      event.msg = [event.msg stringByAppendingFormat:@\" (%@)\", [object objectForKey:@\"time_stamp\"]];\n                                  }\n                                  event.msg = [event.msg stringByAppendingFormat:@\" — %c%@%c\", BOLD, [object objectForKey:@\"time_server\"], CLEAR];\n                              }\n                          },\n                          @\"watch_status\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                              if(object) {\n                                  event.from = [object objectForKey:@\"watch_nick\"];\n                                  event.msg = [event.msg stringByAppendingFormat:@\" (%@@%@)\", [object objectForKey:@\"username\"], [object objectForKey:@\"userhost\"]];\n                              }\n                              event.monospace = YES;\n                          },\n                          @\"sqline_nick\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                              if(object)\n                                  event.from = [object objectForKey:@\"charset\"];\n                              event.monospace = YES;\n                          },\n                          @\"you_parted_channel\":^(Event *event, IRCCloudJSONObject *object) {\n                              event.rowType = ROW_SOCKETCLOSED;\n                          },\n                          @\"user_chghost\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  event.msg = [NSString stringWithFormat:@\"changed host: %@@%@ → %@@%@\", [object objectForKey:@\"user\"], [object objectForKey:@\"userhost\"], [object objectForKey:@\"from_name\"], [object objectForKey:@\"from_host\"]];\n                              }\n                              event.color = [UIColor collapsedRowTextColor];\n                              event.linkify = NO;\n                          },\n                          @\"loaded_module\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  event.msg = [NSString stringWithFormat:@\"%c%@%c %@\", BOLD, [object objectForKey:@\"module\"], BOLD, [object objectForKey:@\"msg\"]];\n                              }\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                              event.monospace = YES;\n                          },\n                          @\"unloaded_module\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  event.msg = [NSString stringWithFormat:@\"%c%@%c %@\", BOLD, [object objectForKey:@\"module\"], BOLD, [object objectForKey:@\"msg\"]];\n                              }\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = NO;\n                              event.monospace = YES;\n                          },\n                          @\"invite_notify\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  event.msg = [NSString stringWithFormat:@\"invited %@ to join %@\", [object objectForKey:@\"target\"], [object objectForKey:@\"channel\"]];\n                              }\n                              event.bgColor = [UIColor statusBackgroundColor];\n                              event.linkify = YES;\n                              event.monospace = YES;\n                          },\n                          @\"channel_name_change\":^(Event *event, IRCCloudJSONObject *object) {\n                              if(object) {\n                                  event.msg = [NSString stringWithFormat:@\"renamed the channel: %@ → %c%@%c\", [object objectForKey:@\"old_name\"], BOLD, [object objectForKey:@\"new_name\"], BOLD];\n                              }\n                              event.color = [UIColor timestampColor];\n                          },\n      };\n    }\n    return self;\n}\n\n-(void)serialize {\n#ifndef EXTENSION\n    NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"events\"];\n    \n    NSMutableDictionary *events = [[NSMutableDictionary alloc] init];\n    NSArray *bids;\n    @synchronized(self->_events) {\n        bids = self->_events.allKeys;\n    }\n    \n    for(NSNumber *bid in bids) {\n        NSMutableArray *e;\n        @synchronized(self->_events) {\n            e = [[self->_events objectForKey:bid] mutableCopy];\n        }\n        [e sortUsingSelector:@selector(compare:)];\n        if(e.count > 50) {\n            Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:bid.intValue];\n            if(b && !b.scrolledUp && [self highlightStateForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type] == 0) {\n                e = [[e subarrayWithRange:NSMakeRange(e.count - 50, 50)] mutableCopy];\n            }\n        }\n        if(e && bid)\n            [events setObject:e forKey:bid];\n    }\n    \n    @synchronized(self) {\n        @try {\n            NSError* error = nil;\n            [[NSKeyedArchiver archivedDataWithRootObject:events requiringSecureCoding:YES error:&error] writeToFile:cacheFile atomically:YES];\n            if(error)\n                CLS_LOG(@\"Error archiving: %@\", error);\n            [[NSURL fileURLWithPath:cacheFile] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL];\n        }\n        @catch (NSException *exception) {\n            [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n        }\n    }\n#endif\n}\n\n-(void)clear {\n    @synchronized(self->_events) {\n        [self->_events removeAllObjects];\n        [self->_events_sorted removeAllObjects];\n        [self->_msgIDs removeAllObjects];\n        [self->_dirtyBIDs removeAllObjects];\n        [self->_lastEIDs removeAllObjects];\n        CLS_LOG(@\"EventsDataSource cleared\");\n    }\n}\n\n-(void)addEvent:(Event *)event {\n#ifndef EXTENSION\n    @synchronized(self->_events) {\n        NSMutableArray *events = [self->_events objectForKey:@(event.bid)];\n        if(!events) {\n            events = [[NSMutableArray alloc] init];\n            [self->_events setObject:events forKey:@(event.bid)];\n        }\n        [events addObject:event];\n        NSMutableDictionary *events_sorted = [self->_events_sorted objectForKey:@(event.bid)];\n        if(!events_sorted) {\n            events_sorted = [[NSMutableDictionary alloc] init];\n            [self->_events_sorted setObject:events_sorted forKey:@(event.bid)];\n        }\n        [events_sorted setObject:event forKey:@(event.eid)];\n        if(event.msgid.length) {\n            NSMutableDictionary *msgids = [self->_msgIDs objectForKey:@(event.bid)];\n            if(!msgids) {\n                msgids = [[NSMutableDictionary alloc] init];\n                [self->_msgIDs setObject:msgids forKey:@(event.bid)];\n            }\n            [msgids setObject:event forKey:event.msgid];\n        }\n        if(!event.pending && (![self->_lastEIDs objectForKey:@(event.bid)] || [[self->_lastEIDs objectForKey:@(event.bid)] doubleValue] < event.eid)) {\n            [self->_lastEIDs setObject:@(event.eid) forKey:@(event.bid)];\n        } else {\n            [self->_dirtyBIDs setObject:@YES forKey:@(event.bid)];\n        }\n\n    }\n#endif\n}\n\n-(Event *)addJSONObject:(IRCCloudJSONObject *)object {\n#ifdef EXTENSION\n    return nil;\n#else\n    Event *event = [self event:object.eid buffer:object.bid];\n    if(!event) {\n        event = [[Event alloc] init];\n        event.bid = object.bid;\n        event.eid = object.eid;\n        if([[object objectForKey:@\"msgid\"] isKindOfClass:[NSString class]])\n            event.msgid = [object objectForKey:@\"msgid\"];\n        else\n            event.msgid = nil;\n        [self addEvent: event];\n    }\n    \n    event.cid = object.cid;\n    event.bid = object.bid;\n    event.eid = object.eid;\n    event.type = object.type;\n    event.msg = [[object objectForKey:@\"msg\"] precomposedStringWithCanonicalMapping];\n    event.hostmask = [object objectForKey:@\"hostmask\"];\n    if([[object objectForKey:@\"display_name\"] isKindOfClass:NSString.class])\n        event.from = [object objectForKey:@\"display_name\"];\n    else\n        event.from = [object objectForKey:@\"from\"];\n    event.fromMode = [object objectForKey:@\"from_mode\"];\n    event.fromNick = [object objectForKey:@\"from\"];\n    if([object objectForKey:@\"newnick\"])\n        event.nick = [object objectForKey:@\"newnick\"];\n    else\n        event.nick = [object objectForKey:@\"nick\"];\n    if([[object objectForKey:@\"from_realname\"] isKindOfClass:[NSString class]])\n        event.realname = [object objectForKey:@\"from_realname\"];\n    else\n        event.realname = nil;\n    event.oldNick = [object objectForKey:@\"oldnick\"];\n    if([[object objectForKey:@\"server\"] isKindOfClass:[NSString class]])\n        event.server = [object objectForKey:@\"server\"];\n    else\n        event.server = nil;\n    event.diff = [object objectForKey:@\"diff\"];\n    event.isHighlight = [[object objectForKey:@\"highlight\"] boolValue];\n    event.isSelf = [[object objectForKey:@\"self\"] boolValue];\n    event.toChan = [[object objectForKey:@\"to_chan\"] boolValue];\n    event.toBuffer = [[object objectForKey:@\"to_buffer\"] boolValue];\n    event.ops = [object objectForKey:@\"ops\"];\n    event.chan = [object objectForKey:@\"chan\"];\n    if([object objectForKey:@\"reqid\"])\n        event.reqId = [[object objectForKey:@\"reqid\"] intValue];\n    else\n        event.reqId = -1;\n    event.color = [UIColor messageTextColor];\n    event.bgColor = [UIColor contentBackgroundColor];\n    event.rowType = 0;\n    event.formatted = nil;\n    event.formattedMsg = nil;\n    event.formattedNick = nil;\n    event.formattedRealname = nil;\n    event.groupMsg = nil;\n    event.linkify = YES;\n    event.targetMode = nil;\n    event.pending = NO;\n    event.monospace = NO;\n    event.entities = [object objectForKey:@\"entities\"];\n    event.serverTime = [[object objectForKey:@\"server_time\"] doubleValue];\n    if([[object objectForKey:@\"avatar\"] isKindOfClass:[NSString class]])\n        event.avatar = [object objectForKey:@\"avatar\"];\n    else\n        event.avatar = nil;\n    if([[object objectForKey:@\"avatar_url\"] isKindOfClass:[NSString class]])\n        event.avatarURL = [object objectForKey:@\"avatar_url\"];\n    else\n        event.avatarURL = nil;\n    if([[object objectForKey:@\"msgid\"] isKindOfClass:[NSString class]])\n        event.msgid = [object objectForKey:@\"msgid\"];\n    else\n        event.msgid = nil;\n\n    if([[object objectForKey:@\"target_account\"] isKindOfClass:[NSString class]])\n        event.account = [object objectForKey:@\"target_account\"];\n    else if([[object objectForKey:@\"from_account\"] isKindOfClass:[NSString class]])\n        event.account = [object objectForKey:@\"from_account\"];\n    else if([[object objectForKey:@\"account\"] isKindOfClass:[NSString class]])\n        event.account = [object objectForKey:@\"account\"];\n    else\n        event.account = nil;\n\n    void (^formatter)(Event *event, IRCCloudJSONObject *object) = [self->_formatterMap objectForKey:object.type];\n    if(formatter)\n        formatter(event, object);\n        \n    if([event isMessage] && !event.from.length && event.server.length) {\n        event.from = event.fromNick = event.server;\n    }\n\n    if([object objectForKey:@\"value\"] && ![event.type hasPrefix:@\"cap_\"]) {\n        event.msg = [NSString stringWithFormat:@\"%@ %@\", [object objectForKey:@\"value\"], event.msg];\n    }\n\n    if(event.isHighlight)\n        event.bgColor = [UIColor highlightBackgroundColor];\n\n    if(event.isSelf && event.rowType != ROW_SOCKETCLOSED && ![event.type isEqualToString:@\"notice\"])\n        event.bgColor = [UIColor selfBackgroundColor];\n    \n    return event;\n#endif\n}\n\n-(Event *)event:(NSTimeInterval)eid buffer:(int)bid {\n    @synchronized(self->_events) {\n        return [[self->_events_sorted objectForKey:@(bid)] objectForKey:@(eid)];\n    }\n}\n\n-(Event *)message:(NSString *)msgid buffer:(int)bid {\n    @synchronized(self->_events) {\n        return [[self->_msgIDs objectForKey:@(bid)] objectForKey:msgid];\n    }\n}\n\n-(void)removeEvent:(NSTimeInterval)eid buffer:(int)bid {\n    @synchronized(self->_events) {\n        for(Event *event in [self->_events objectForKey:@(bid)]) {\n            if(event.eid == eid) {\n                [[self->_events objectForKey:@(bid)] removeObject:event];\n                [[self->_events_sorted objectForKey:@(bid)] removeObjectForKey:@(eid)];\n                if(event.msgid.length)\n                    [[self->_msgIDs objectForKey:@(bid)] removeObjectForKey:event.msgid];\n                break;\n            }\n        }\n    }\n}\n\n-(void)removeEventsForBuffer:(int)bid {\n    @synchronized(self->_events) {\n        [self->_events removeObjectForKey:@(bid)];\n        [self->_events_sorted removeObjectForKey:@(bid)];\n        [self->_msgIDs removeObjectForKey:@(bid)];\n        CLS_LOG(@\"Removing all events for bid%i\", bid);\n    }\n}\n\n-(void)pruneEventsForBuffer:(int)bid maxSize:(int)size {\n    @synchronized(self->_events) {\n        if([[self->_events objectForKey:@(bid)] count] > size) {\n            CLS_LOG(@\"Pruning events for bid%i (%lu, max = %i)\", bid, (unsigned long)[[self->_events objectForKey:@(bid)] count], size);\n            NSMutableArray *events = [self eventsForBuffer:bid].mutableCopy;\n            while(events.count > size) {\n                Event *e = [events objectAtIndex:0];\n                [events removeObject:e];\n                [[self->_events objectForKey:@(bid)] removeObject:e];\n                [[self->_events_sorted objectForKey:@(bid)] removeObjectForKey:@(e.eid)];\n                if(e.msgid.length)\n                    [[self->_msgIDs objectForKey:@(bid)] removeObjectForKey:e.msgid];\n            }\n        }\n    }\n}\n\n-(NSArray *)eventsForBuffer:(int)bid {\n    @synchronized(self->_events) {\n        if([self->_dirtyBIDs objectForKey:@(bid)]) {\n            CLS_LOG(@\"Buffer bid%i needs sorting\", bid);\n            [[self->_events objectForKey:@(bid)] sortUsingSelector:@selector(compare:)];\n            [self->_dirtyBIDs removeObjectForKey:@(bid)];\n        }\n        return [NSArray arrayWithArray:[self->_events objectForKey:@(bid)]];\n    }\n}\n\n-(NSUInteger)sizeOfBuffer:(int)bid {\n    @synchronized(self->_events) {\n        return [[self->_events objectForKey:@(bid)] count];\n    }\n}\n\n-(NSTimeInterval)lastEidForBuffer:(int)bid {\n    @synchronized(self->_events) {\n        return [[self->_lastEIDs objectForKey:@(bid)] doubleValue];\n    }\n}\n\n-(void)removeEventsBefore:(NSTimeInterval)min_eid buffer:(int)bid {\n    CLS_LOG(@\"Removing events for bid%i older than %.0f\", bid, min_eid);\n    @synchronized(self->_events) {\n        NSArray *events = [self->_events objectForKey:@(bid)];\n        NSMutableArray *eventsToRemove = [[NSMutableArray alloc] init];\n        for(Event *event in events) {\n            if(event.eid < min_eid) {\n                [eventsToRemove addObject:event];\n            }\n        }\n        for(Event *event in eventsToRemove) {\n            [[self->_events objectForKey:@(bid)] removeObject:event];\n            [[self->_events_sorted objectForKey:@(bid)] removeObjectForKey:@(event.eid)];\n            if(event.msgid.length)\n                [[self->_msgIDs objectForKey:@(bid)] removeObjectForKey:event.msgid];\n        }\n    }\n}\n\n-(int)unreadStateForBuffer:(int)bid lastSeenEid:(NSTimeInterval)lastSeenEid type:(NSString *)type {\n    @synchronized(self->_events) {\n        if(![self->_events objectForKey:@(bid)])\n            return 0;\n    }\n    Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:bid];\n    Server *s = [[ServersDataSource sharedInstance] getServer:b.cid];\n    Ignore *ignore = s.ignore;\n\n    NSArray *copy;\n    @synchronized(self->_events) {\n        copy = [self eventsForBuffer:bid];\n    }\n    for(Event *event in copy.reverseObjectEnumerator) {\n        if(event.eid <= lastSeenEid) {\n            break;\n        } else if([event isImportant:type]) {\n            if(event.ignoreMask && [ignore match:event.ignoreMask])\n                continue;\n            return 1;\n        }\n    }\n    return 0;\n}\n\n-(int)highlightCountForBuffer:(int)bid lastSeenEid:(NSTimeInterval)lastSeenEid type:(NSString *)type {\n    @synchronized(self->_events) {\n        if(![self->_events objectForKey:@(bid)])\n            return 0;\n    }\n    int count = 0;\n    Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:bid];\n    Server *s = [[ServersDataSource sharedInstance] getServer:b.cid];\n    Ignore *ignore = s.ignore;\n    NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n    BOOL muted = [[prefs objectForKey:@\"notifications-mute\"] boolValue];\n    if(muted) {\n        NSDictionary *disableMap;\n        \n        if([b.type isEqualToString:@\"channel\"]) {\n            disableMap = [prefs objectForKey:@\"channel-notifications-mute-disable\"];\n        } else {\n            disableMap = [prefs objectForKey:@\"buffer-notifications-mute-disable\"];\n        }\n        \n        if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] boolValue])\n            muted = NO;\n    } else {\n        NSDictionary *enableMap;\n        \n        if([b.type isEqualToString:@\"channel\"]) {\n            enableMap = [prefs objectForKey:@\"channel-notifications-mute\"];\n        } else {\n            enableMap = [prefs objectForKey:@\"buffer-notifications-mute\"];\n        }\n        \n        if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] boolValue])\n            muted = YES;\n    }\n    if(muted)\n        return 0;\n\n    NSArray *copy;\n    @synchronized(self->_events) {\n        copy = [self eventsForBuffer:bid];\n    }\n    for(Event *event in copy.reverseObjectEnumerator) {\n        if(event.eid <= lastSeenEid) {\n            break;\n        } else if([event isImportant:type] && (event.isHighlight || [type isEqualToString:@\"conversation\"])) {\n            if(event.ignoreMask && [ignore match:event.ignoreMask])\n                continue;\n            count++;\n        }\n    }\n    return count + b.extraHighlights;\n}\n\n-(int)highlightStateForBuffer:(int)bid lastSeenEid:(NSTimeInterval)lastSeenEid type:(NSString *)type {\n    @synchronized(self->_events) {\n        if(![self->_events objectForKey:@(bid)])\n            return 0;\n    }\n    Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:bid];\n    Server *s = [[ServersDataSource sharedInstance] getServer:b.cid];\n    Ignore *ignore = s.ignore;\n    NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n    BOOL muted = [[prefs objectForKey:@\"notifications-mute\"] boolValue];\n    if(muted) {\n        NSDictionary *disableMap;\n        \n        if([b.type isEqualToString:@\"channel\"]) {\n            disableMap = [prefs objectForKey:@\"channel-notifications-mute-disable\"];\n        } else {\n            disableMap = [prefs objectForKey:@\"buffer-notifications-mute-disable\"];\n        }\n        \n        if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] boolValue])\n            muted = NO;\n    } else {\n        NSDictionary *enableMap;\n        \n        if([b.type isEqualToString:@\"channel\"]) {\n            enableMap = [prefs objectForKey:@\"channel-notifications-mute\"];\n        } else {\n            enableMap = [prefs objectForKey:@\"buffer-notifications-mute\"];\n        }\n        \n        if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] boolValue])\n            muted = YES;\n    }\n    if(muted)\n        return 0;\n\n    NSArray *copy;\n    @synchronized(self->_events) {\n        copy = [self eventsForBuffer:bid];\n    }\n    for(Event *event in copy.reverseObjectEnumerator) {\n        if(event.eid <= lastSeenEid) {\n            break;\n        } else if([event isImportant:type] && (event.isHighlight || [type isEqualToString:@\"conversation\"])) {\n            if(event.ignoreMask && [ignore match:event.ignoreMask])\n                continue;\n            return 1;\n        }\n    }\n    return b.extraHighlights ? 1 : 0;\n}\n\n-(void)clearFormattingCache {\n    @synchronized(self->_events) {\n        for(NSNumber *bid in _events) {\n            NSArray *events = [self->_events objectForKey:bid];\n            for(Event *e in events) {\n                e.formatted = nil;\n                e.formattedNick = nil;\n                e.formattedRealname = nil;\n                e.timestamp = nil;\n                e.height = 0;\n                e.isHeader = NO;\n                e.isCodeBlock = NO;\n                e.isQuoted = NO;\n            }\n        }\n    }\n}\n\n\n-(void)clearHeightCache {\n    @synchronized(self->_events) {\n        for(NSNumber *bid in _events) {\n            NSArray *events = [self->_events objectForKey:bid];\n            for(Event *e in events) {\n                e.height = 0;\n            }\n        }\n    }\n}\n-(void)reformat {\n    @synchronized(self->_events) {\n        for(NSNumber *bid in _events) {\n            NSArray *events = [self->_events objectForKey:bid];\n            for(Event *e in events) {\n                e.color = [UIColor messageTextColor];\n                if(e.rowType == ROW_LASTSEENEID)\n                    e.bgColor = [UIColor contentBackgroundColor];\n                else if(e.rowType == ROW_TIMESTAMP)\n                    e.bgColor = [UIColor timestampBackgroundColor];\n                else\n                    e.bgColor = [UIColor contentBackgroundColor];\n                e.formatted = nil;\n                e.formattedNick = nil;\n                e.formattedRealname = nil;\n                e.timestamp = nil;\n                e.height = 0;\n                e.isHeader = NO;\n                void (^formatter)(Event *event, IRCCloudJSONObject *object) = [self->_formatterMap objectForKey:e.type];\n                if(formatter)\n                    formatter(e, nil);\n                \n                if(e.isHighlight)\n                    e.bgColor = [UIColor highlightBackgroundColor];\n                \n                if(e.isSelf && e.rowType != ROW_SOCKETCLOSED)\n                    e.bgColor = [UIColor selfBackgroundColor];\n            }\n        }\n    }\n\n}\n\n-(void)clearPendingAndFailed {\n    @synchronized(self->_events) {\n        NSMutableArray *eventsToRemove = [[NSMutableArray alloc] init];\n        for(NSNumber *bid in _events) {\n            NSArray *events = [[self->_events objectForKey:bid] copy];\n            for(Event *e in events) {\n                if((e.pending || e.rowType == ROW_FAILED) && e.reqId != -1)\n                    [eventsToRemove addObject:e];\n            }\n        }\n        for(Event *e in eventsToRemove) {\n            [[self->_events objectForKey:@(e.bid)] removeObject:e];\n            [[self->_events_sorted objectForKey:@(e.bid)] removeObjectForKey:@(e.eid)];\n            if(e.msgid.length)\n                [[self->_msgIDs objectForKey:@(e.bid)] removeObjectForKey:e.msgid];\n            if(e.expirationTimer && [e.expirationTimer isValid])\n                [e.expirationTimer invalidate];\n            e.expirationTimer = nil;\n        }\n    }\n}\n\n+(NSString *)reason:(NSString *)reason {\n    static NSDictionary *r;\n    if(!r)\n        r = @{@\"pool_lost\":@\"Connection pool failed\",\n              @\"no_pool\":@\"No available connection pools\",\n              @\"enetdown\":@\"Network down\",\n              @\"etimedout\":@\"Timed out\",\n              @\"timeout\":@\"Timed out\",\n              @\"ehostunreach\":@\"Host unreachable\",\n              @\"econnrefused\":@\"Connection refused\",\n              @\"nxdomain\":@\"Invalid hostname\",\n              @\"server_ping_timeout\":@\"PING timeout\",\n              @\"ssl_certificate_error\":@\"SSL certificate error\",\n              @\"ssl_error\":@\"SSL error\",\n              @\"crash\":@\"Connection crashed\",\n              @\"networks\":@\"You've exceeded the connection limit for free accounts.\",\n              @\"passworded_servers\":@\"You can't connect to passworded servers with free accounts.\",\n              @\"unverified\":@\"You can’t connect to external servers until you confirm your email address.\",\n              };\n    if([reason isKindOfClass:[NSString class]] && [reason length]) {\n        if([r objectForKey:reason])\n            return [r objectForKey:reason];\n    }\n    return reason;\n}\n\n+(NSString *)SSLreason:(NSDictionary *)info {\n    static NSDictionary *r;\n    if(!r)\n        r = @{@\"bad_cert\":@{@\"unknown_ca\": @\"Unknown certificate authority\",\n                            @\"selfsigned_peer\": @\"Self signed certificate\",\n                            @\"cert_expired\": @\"Certificate expired\",\n                            @\"invalid_issuer\": @\"Invalid certificate issuer\",\n                            @\"invalid_signature\": @\"Invalid certificate signature\",\n                            @\"name_not_permitted\": @\"Invalid certificate alternative hostname\",\n                            @\"missing_basic_constraint\": @\"Missing certificate basic contraints\",\n                            @\"invalid_key_usage\": @\"Invalid certificate key usage\"},\n              @\"ssl_verify_hostname\":@{@\"unable_to_match_altnames\": @\"Certificate hostname mismatch\",\n                                       @\"unable_to_match_common_name\": @\"Certificate hostname mismatch\",\n                                       @\"unable_to_decode_common_name\": @\"Invalid certificate hostname\"}\n              };\n\n    if([[r objectForKey:[info objectForKey:@\"type\"]] objectForKey:@\"error\"]) {\n        return [[r objectForKey:[info objectForKey:@\"type\"]] objectForKey:@\"error\"];\n    }\n    \n    return [NSString stringWithFormat:@\"%@: %@\", [info objectForKey:@\"type\"], [info objectForKey:@\"error\"]];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/EventsTableView.h",
    "content": "//\n//  EventsTableView.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n#import \"BuffersDataSource.h\"\n#import \"EventsDataSource.h\"\n#import \"CollapsedEvents.h\"\n#import \"NetworkConnection.h\"\n#import \"HighlightsCountView.h\"\n#import \"LinkLabel.h\"\n#import \"URLHandler.h\"\n\n@protocol EventsTableViewDelegate<NSObject>\n-(void)rowSelected:(Event *)event;\n-(void)rowLongPressed:(Event *)event rect:(CGRect)rect link:(NSString *)url;\n-(void)dismissKeyboard;\n-(void)showJoinPrompt:(NSString *)channel server:(Server *)s;\n@end\n\n@interface EventsTableView : UIViewController<LinkLabelDelegate,UIGestureRecognizerDelegate,UIViewControllerPreviewingDelegate,UITableViewDataSource,UITableViewDelegate,UIContextMenuInteractionDelegate> {\n    IBOutlet UITableView *_tableView;\n    IBOutlet UIView *_headerView;\n    IBOutlet UIView *_backlogFailedView;\n    IBOutlet UIButton *_backlogFailedButton;\n    IBOutlet UIView *_topUnreadView;\n    IBOutlet UILabel *_topUnreadArrow;\n    IBOutlet UILabel *_topUnreadLabel;\n    IBOutlet HighlightsCountView *_topHighlightsCountView;\n    IBOutlet UIView *_bottomUnreadView;\n    IBOutlet UILabel *_bottomUnreadArrow;\n    IBOutlet UILabel *_bottomUnreadLabel;\n    IBOutlet HighlightsCountView *_bottomHighlightsCountView;\n    IBOutlet NSLayoutConstraint *_topUnreadLabelXOffsetConstraint;\n    IBOutlet NSLayoutConstraint *_topUnreadDismissXOffsetConstraint;\n    IBOutlet NSLayoutConstraint *_bottomUnreadLabelXOffsetConstraint;\n    IBOutlet NSLayoutConstraint *_stickyAvatarYOffsetConstraint;\n    IBOutlet NSLayoutConstraint *_stickyAvatarXOffsetConstraint;\n    IBOutlet NSLayoutConstraint *_stickyAvatarWidthConstraint;\n    IBOutlet NSLayoutConstraint *_stickyAvatarHeightConstraint;\n    IBOutlet UIImageView *_stickyAvatar;\n    IBOutlet UIButton *_loadMoreBacklog;\n    \n    NSDateFormatter *_formatter;\n    NSMutableArray *_data;\n    NSMutableArray *_unseenHighlightPositions;\n    NSMutableDictionary *_expandedSectionEids;\n    NSMutableDictionary *_msgids;\n    Buffer *_buffer;\n    Server *_server;\n    CollapsedEvents *_collapsedEvents;\n    NetworkConnection *_conn;\n    NSString *_msgid;\n    \n    NSTimeInterval _maxEid, _minEid, _currentCollapsedEid, _earliestEid, _eidToOpen, _lastCollapsedEid;\n    NSInteger _newMsgs, _newHighlights, _lastSeenEidPos, _bottomRow;\n    NSString *_lastCollpasedDay;\n    BOOL _requestingBacklog, _ready, _shouldAutoFetch;\n    NSTimer *_heartbeatTimer;\n    NSTimer *_scrollTimer;\n    NSTimer *_reloadTimer;\n    NSRecursiveLock *_lock;\n    \n    IBOutlet id<EventsTableViewDelegate> _delegate;\n    \n    NSDictionary *_linkAttributes;\n    NSDictionary *_lightLinkAttributes;\n\n    NSString *_groupIndent;\n    id<UIViewControllerPreviewing> __previewer;\n    UILongPressGestureRecognizer *lp;\n    \n    NSUInteger _previewingRow;\n    NSUInteger _hiddenAvatarRow;\n    NSMutableDictionary *_rowCache;\n    NSMutableDictionary *_filePropsCache;\n    NSMutableSet *_closedPreviews;\n    URLHandler *_urlHandler;\n    \n    UINib *_eventsTableCell, *_eventsTableCell_Thumbnail, *_eventsTableCell_File, *_eventsTableCell_ReplyCount;\n}\n@property (readonly) UITableView *tableView;\n@property (readonly) UIView *topUnreadView;\n@property (readonly) UIView *bottomUnreadView;\n@property (readonly) UILabel *topUnreadArrow;\n@property (readonly) UILabel *topUnreadLabel;\n@property (readonly) UILabel *bottomUnreadLabel;\n@property (readonly) UILabel *bottomUnreadArrow;\n@property (assign) NSTimeInterval eidToOpen;\n@property (readonly) UIImageView *stickyAvatar;\n@property Buffer *buffer;\n@property NSString *msgid;\n@property (assign) BOOL shouldAutoFetch;\n-(void)insertEvent:(Event *)event backlog:(BOOL)backlog nextIsGrouped:(BOOL)nextIsGrouped;\n-(IBAction)topUnreadBarClicked:(id)sender;\n-(IBAction)bottomUnreadBarClicked:(id)sender;\n-(IBAction)dismissButtonPressed:(id)sender;\n-(IBAction)loadMoreBacklogButtonPressed:(id)sender;\n-(void)_scrollToBottom;\n-(void)scrollToBottom;\n-(void)clearLastSeenMarker;\n-(void)refresh;\n-(void)clearCachedHeights;\n-(void)clearRowCache;\n-(void)uncacheFile:(NSString *)fileID;\n-(void)closePreview:(Event *)event;\n-(NSString *)YUNoHeartbeat;\n-(CGRect)rectForEvent:(Event *)event;\n-(void)reloadData;\n-(void)viewWillResize;\n-(void)viewDidResize;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/EventsTableView.m",
    "content": "//\n//  EventsTableView.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <AVFoundation/AVFoundation.h>\n#import <AVKit/AVKit.h>\n#import <MediaPlayer/MediaPlayer.h>\n#import \"EventsTableView.h\"\n#import \"NetworkConnection.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"ColorFormatter.h\"\n#import \"AppDelegate.h\"\n#import \"FontAwesome.h\"\n#import \"ImageViewController.h\"\n#import \"PastebinViewController.h\"\n#import \"YouTubeViewController.h\"\n#import \"EditConnectionViewController.h\"\n#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n#import \"IRCCloudSafariViewController.h\"\n#import \"AvatarsDataSource.h\"\n#import \"ImageCache.h\"\n\nint __timestampWidth;\nBOOL __24hrPref = NO;\nBOOL __secondsPref = NO;\nBOOL __timeLeftPref = NO;\nBOOL __nickColorsPref = NO;\nBOOL __hideJoinPartPref = NO;\nBOOL __expandJoinPartPref = NO;\nBOOL __avatarsOffPref = NO;\nBOOL __chatOneLinePref = NO;\nBOOL __norealnamePref = NO;\nBOOL __monospacePref = NO;\nBOOL __disableInlineFilesPref = NO;\nBOOL __inlineMediaPref = NO;\nBOOL __disableBigEmojiPref = NO;\nBOOL __disableCodeSpanPref = NO;\nBOOL __disableCodeBlockPref = NO;\nBOOL __disableQuotePref = NO;\nBOOL __avatarImages = YES;\nBOOL __replyCollapsePref = NO;\nBOOL __colorizeMentionsPref = NO;\nBOOL __notificationsMuted = NO;\nBOOL __noColor = NO;\nBOOL __showDeleted = NO;\nint __smallAvatarHeight;\nint __largeAvatarHeight = 32;\n\nextern BOOL __compact;\nextern UIImage *__socketClosedBackgroundImage;\n\n@interface EventsTableCell : UITableViewCell {\n    IBOutlet UIImageView *_avatar;\n    IBOutlet UILabel *_timestampLeft,*_timestampRight,*_reply,*_datestamp;\n    IBOutlet LinkLabel *_message;\n    IBOutlet LinkLabel *_nickname;\n    IBOutlet UIView *_socketClosedBar;\n    IBOutlet UILabel *_accessory;\n    IBOutlet UIView *_topBorder;\n    IBOutlet UIView *_bottomBorder;\n    IBOutlet UIView *_quoteBorder;\n    IBOutlet UIView *_codeBlockBackground;\n    IBOutlet UIView *_lastSeenEIDBackground;\n    IBOutlet UILabel *_lastSeenEID;\n    IBOutlet UIControl *_replyButton;\n    IBOutlet NSLayoutConstraint *_messageOffsetLeft,*_messageOffsetRight,*_messageOffsetTop,*_messageOffsetBottom,*_timestampWidth,*_avatarOffset,*_nicknameOffset,*_lastSeenEIDOffset,*_avatarWidth,*_avatarHeight,*_replyCenter,*_replyXOffset,*_avatarTop,*_rightTimestampOffset;\n}\n@property (readonly) UILabel *timestampLeft, *timestampRight, *accessory, *lastSeenEID, *reply, *datestamp;\n@property (readonly) LinkLabel *message, *nickname;\n@property (readonly) UIImageView *avatar;\n@property (readonly) UIView *quoteBorder, *codeBlockBackground, *topBorder, *bottomBorder, *lastSeenEIDBackground, *socketClosedBar;\n@property (readonly) NSLayoutConstraint *messageOffsetLeft, *messageOffsetRight, *messageOffsetTop, *messageOffsetBottom, *timestampWidth, *avatarOffset, *nicknameOffset, *lastSeenEIDOffset, *avatarWidth, *avatarHeight, *replyCenter, *replyXOffset, *avatarTop, *rightTimestampOffset;\n@property (readonly) UIControl *replyButton;\n@property (strong) NSURL *largeAvatarURL;\n\n-(IBAction)avatarTapped:(UITapGestureRecognizer *)sender;\n@end\n\n@implementation EventsTableCell\n- (void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n-(IBAction)avatarTapped:(UITapGestureRecognizer *)sender {\n    [(AppDelegate *)[UIApplication sharedApplication].delegate setActiveScene:self.window];\n    [(AppDelegate *)[UIApplication sharedApplication].delegate launchURL:_largeAvatarURL];\n}\n@end\n\n@interface EventsTableCell_Thumbnail : EventsTableCell {\n    IBOutlet UIView *_background;\n    IBOutlet YYAnimatedImageView *_thumbnail;\n    IBOutlet NSLayoutConstraint *_thumbnailWidth, *_thumbnailHeight;\n    IBOutlet UILabel *_filename;\n    IBOutlet UIActivityIndicatorView *_spinner;\n}\n@property (readonly) UIView *background;\n@property (readonly) UILabel *filename;\n@property (readonly) YYAnimatedImageView *thumbnail;\n@property (readonly) NSLayoutConstraint *thumbnailWidth, *thumbnailHeight;\n@property (readonly) UIActivityIndicatorView *spinner;\n\n@end\n\n@implementation EventsTableCell_Thumbnail\n@end\n\n@interface EventsTableCell_File : EventsTableCell {\n    IBOutlet UIView *_background;\n    IBOutlet UILabel *_filename;\n    IBOutlet UILabel *_mimeType;\n    IBOutlet UILabel *_extension;\n}\n@property (readonly) UIView *background;\n@property (readonly) UILabel *filename, *mimeType, *extension;\n@end\n\n@implementation EventsTableCell_File\n@end\n\n@interface EventsTableCell_ReplyCount : EventsTableCell {\n    IBOutlet UILabel *_replyCount;\n}\n@property (readonly) UILabel *replyCount;\n@end\n\n@implementation EventsTableCell_ReplyCount\n@end\n\n@implementation EventsTableView\n\n- (id)init {\n    self = [super init];\n    if (self) {\n        self->_conn = [NetworkConnection sharedInstance];\n        self->_lock = [[NSRecursiveLock alloc] init];\n        self->_ready = NO;\n        self->_formatter = [[NSDateFormatter alloc] init];\n        self->_formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@\"en_US_POSIX\"];\n        self->_data = [[NSMutableArray alloc] init];\n        self->_expandedSectionEids = [[NSMutableDictionary alloc] init];\n        self->_collapsedEvents = [[CollapsedEvents alloc] init];\n        self->_unseenHighlightPositions = [[NSMutableArray alloc] init];\n        self->_filePropsCache = [[NSMutableDictionary alloc] init];\n        self->_closedPreviews = [[NSMutableSet alloc] init];\n        self->_buffer = nil;\n        self->_eidToOpen = -1;\n        self->_urlHandler = [[URLHandler alloc] init];\n#ifdef ENTERPRISE\n        self->_urlHandler.appCallbackURL = [NSURL URLWithString:@\"irccloud-enterprise://\"];\n#else\n        self->_urlHandler.appCallbackURL = [NSURL URLWithString:@\"irccloud://\"];\n#endif\n    }\n    return self;\n}\n\n- (id)initWithCoder:(NSCoder *)aDecoder {\n    self = [super initWithCoder:aDecoder];\n    if (self) {\n        self->_conn = [NetworkConnection sharedInstance];\n        self->_lock = [[NSRecursiveLock alloc] init];\n        self->_ready = NO;\n        self->_formatter = [[NSDateFormatter alloc] init];\n        self->_formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@\"en_US_POSIX\"];\n        self->_data = [[NSMutableArray alloc] init];\n        self->_expandedSectionEids = [[NSMutableDictionary alloc] init];\n        self->_collapsedEvents = [[CollapsedEvents alloc] init];\n        self->_unseenHighlightPositions = [[NSMutableArray alloc] init];\n        self->_filePropsCache = [[NSMutableDictionary alloc] init];\n        self->_closedPreviews = [[NSMutableSet alloc] init];\n        self->_buffer = nil;\n        self->_eidToOpen = -1;\n        self->_urlHandler = [[URLHandler alloc] init];\n    }\n    return self;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;\n\n    self->_rowCache = [[NSMutableDictionary alloc] init];\n    \n    if(!_headerView) {\n        self->_headerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,_tableView.frame.size.width,20)];\n        self->_headerView.autoresizesSubviews = YES;\n        UIActivityIndicatorView *a = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n        a.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;\n        a.center = self->_headerView.center;\n        [a startAnimating];\n        [self->_headerView addSubview:a];\n    }\n    \n    if(!_tableView) {\n        self->_tableView = [[UITableView alloc] initWithFrame:self.view.bounds];\n        self->_tableView.dataSource = self;\n        self->_tableView.delegate = self;\n        [self.view addSubview:self->_tableView];\n    }\n    \n    self->_eventsTableCell = [UINib nibWithNibName:@\"EventsTableCell\" bundle:nil];\n    self->_eventsTableCell_File = [UINib nibWithNibName:@\"EventsTableCell_File\" bundle:nil];\n    self->_eventsTableCell_Thumbnail = [UINib nibWithNibName:@\"EventsTableCell_Thumbnail\" bundle:nil];\n    self->_eventsTableCell_ReplyCount = [UINib nibWithNibName:@\"EventsTableCell_ReplyCount\" bundle:nil];\n    self->_tableView.scrollsToTop = NO;\n    self->_tableView.estimatedRowHeight = 0;\n    self->_tableView.estimatedSectionHeaderHeight = 0;\n    self->_tableView.estimatedSectionFooterHeight = 0;\n    lp = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(_longPress:)];\n    lp.minimumPressDuration = 1.0;\n    lp.cancelsTouchesInView = YES;\n    lp.delegate = self;\n    [self->_tableView addGestureRecognizer:lp];\n\n    if (@available(iOS 13.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp)\n            [self->_tableView addInteraction:[[UIContextMenuInteraction alloc] initWithDelegate:self]];\n    }\n\n    self->_topUnreadView.backgroundColor = [UIColor chatterBarColor];\n    self->_bottomUnreadView.backgroundColor = [UIColor chatterBarColor];\n    [self->_backlogFailedButton setBackgroundImage:[[UIImage imageNamed:@\"sendbg_active\"] resizableImageWithCapInsets:UIEdgeInsetsMake(14, 14, 14, 14)  resizingMode:UIImageResizingModeStretch] forState:UIControlStateNormal];\n    [self->_backlogFailedButton setBackgroundImage:[[UIImage imageNamed:@\"sendbg\"] resizableImageWithCapInsets:UIEdgeInsetsMake(14, 14, 14, 14)  resizingMode:UIImageResizingModeStretch] forState:UIControlStateHighlighted];\n    [self->_backlogFailedButton setTitleColor:[UIColor unreadBlueColor] forState:UIControlStateNormal];\n    [self->_backlogFailedButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateHighlighted];\n    [self->_backlogFailedButton setTitleShadowColor:[UIColor whiteColor] forState:UIControlStateNormal];\n    self->_backlogFailedButton.titleLabel.shadowOffset = CGSizeMake(0, 1);\n    [self->_backlogFailedButton.titleLabel setFont:[UIFont fontWithName:@\"Helvetica-Bold\" size:14.0]];\n    \n    self->_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    self->_tableView.backgroundColor = [UIColor contentBackgroundColor];\n    \n    if([self respondsToSelector:@selector(registerForPreviewingWithDelegate:sourceView:)]) {\n        __previewer = [self registerForPreviewingWithDelegate:self sourceView:self->_tableView];\n        [__previewer.previewingGestureRecognizerForFailureRelationship addTarget:self action:@selector(_3DTouchChanged:)];\n    }\n}\n\n-(void)_3DTouchChanged:(UIGestureRecognizer *)gesture {\n    if(gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateCancelled) {\n        MainViewController *mainViewController = [(AppDelegate *)([UIApplication sharedApplication].delegate) mainViewController];\n        mainViewController.isShowingPreview = NO;\n    }\n}\n\n- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location {\n    if(!_data.count)\n        return nil;\n    MainViewController *mainViewController = [(AppDelegate *)([UIApplication sharedApplication].delegate) mainViewController];\n    EventsTableCell *cell = [self->_tableView cellForRowAtIndexPath:[self->_tableView indexPathForRowAtPoint:location]];\n    self->_previewingRow = [self->_tableView indexPathForRowAtPoint:location].row;\n    Event *e = [self->_data objectAtIndex:self->_previewingRow];\n    \n    NSURL *url;\n    if(e.rowType == ROW_THUMBNAIL || e.rowType == ROW_FILE) {\n        if([e.entities objectForKey:@\"id\"]) {\n            NSString *extension = [e.entities objectForKey:@\"extension\"];\n            if(!extension.length)\n                extension = [@\".\" stringByAppendingString:[[e.entities objectForKey:@\"mime_type\"] substringFromIndex:[[e.entities objectForKey:@\"mime_type\"] rangeOfString:@\"/\"].location + 1]];\n            url = [NSURL URLWithString:[NSString stringWithFormat:@\"%@/%@%@\", [[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":[e.entities objectForKey:@\"id\"]} error:nil], [[e.entities objectForKey:@\"mime_type\"] substringToIndex:5], extension]];\n        } else {\n            url = [e.entities objectForKey:@\"url\"];\n        }\n    } else {\n        NSTextCheckingResult *r = [cell.message linkAtPoint:[self->_tableView convertPoint:location toView:cell.message]];\n        url = r.URL;\n    }\n    mainViewController.isShowingPreview = YES;\n    \n    if([URLHandler isImageURL:url]) {\n        previewingContext.sourceRect = cell.frame;\n        ImageViewController *i = [[ImageViewController alloc] initWithURL:url];\n        i.preferredContentSize = self.view.window.bounds.size;\n        i.previewing = YES;\n        lp.enabled = NO;\n        lp.enabled = YES;\n        return i;\n    } else if([URLHandler isYouTubeURL:url]) {\n        previewingContext.sourceRect = cell.frame;\n        YouTubeViewController *y = [[YouTubeViewController alloc] initWithURL:url];\n        [y loadViewIfNeeded];\n        y.preferredContentSize = y.player.bounds.size;\n        y.toolbar.hidden = YES;\n        lp.enabled = NO;\n        lp.enabled = YES;\n        return y;\n    } else if([url.scheme hasPrefix:@\"irccloud-paste-\"]) {\n        previewingContext.sourceRect = cell.frame;\n        PastebinViewController *pvc = [[UIStoryboard storyboardWithName:@\"MainStoryboard\" bundle:nil] instantiateViewControllerWithIdentifier:@\"PastebinViewController\"];\n        [pvc setUrl:[NSURL URLWithString:[url.absoluteString substringFromIndex:15]]];\n        lp.enabled = NO;\n        lp.enabled = YES;\n        return pvc;\n    } else if([url.pathExtension.lowercaseString isEqualToString:@\"mov\"] || [url.pathExtension.lowercaseString isEqualToString:@\"mp4\"] || [url.pathExtension.lowercaseString isEqualToString:@\"m4v\"] || [url.pathExtension.lowercaseString isEqualToString:@\"3gp\"] || [url.pathExtension.lowercaseString isEqualToString:@\"quicktime\"]) {\n        previewingContext.sourceRect = cell.frame;\n        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];\n        AVPlayerViewController *player = [[AVPlayerViewController alloc] init];\n        player.player = [[AVPlayer alloc] initWithURL:url];\n        player.modalPresentationStyle = UIModalPresentationCurrentContext;\n        player.preferredContentSize = self.view.window.bounds.size;\n        return player;\n    } else if(([SFSafariViewController class] && !((AppDelegate *)([UIApplication sharedApplication].delegate)).isOnVisionOS) && [url.scheme hasPrefix:@\"http\"]) {\n        previewingContext.sourceRect = cell.frame;\n        IRCCloudSafariViewController *s = [[IRCCloudSafariViewController alloc] initWithURL:url];\n        s.modalPresentationStyle = UIModalPresentationCurrentContext;\n        s.preferredContentSize = self.view.window.bounds.size;\n        return s;\n    }\n    \n    self->_previewingRow = -1;\n    mainViewController.isShowingPreview = NO;\n    return nil;\n}\n\n- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit {\n    AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;\n    [appDelegate setActiveScene:self.view.window];\n    MainViewController *mainViewController = [(AppDelegate *)([UIApplication sharedApplication].delegate) mainViewController];\n    mainViewController.isShowingPreview = NO;\n    if([viewControllerToCommit isKindOfClass:[ImageViewController class]]) {\n        appDelegate.mainViewController.ignoreVisibilityChanges = YES;\n        appDelegate.window.backgroundColor = [UIColor blackColor];\n        appDelegate.window.rootViewController = viewControllerToCommit;\n        [appDelegate.window addSubview:viewControllerToCommit.view];\n        appDelegate.slideViewController.view.frame = appDelegate.window.bounds;\n        [appDelegate.window insertSubview:appDelegate.slideViewController.view belowSubview:viewControllerToCommit.view];\n        appDelegate.mainViewController.ignoreVisibilityChanges = NO;\n        [viewControllerToCommit didMoveToParentViewController:nil];\n    } else if([viewControllerToCommit isKindOfClass:[YouTubeViewController class]]) {\n        viewControllerToCommit.modalPresentationStyle = UIModalPresentationCustom;\n        ((YouTubeViewController *)viewControllerToCommit).toolbar.hidden = NO;\n        [self.slidingViewController presentViewController:viewControllerToCommit animated:NO completion:nil];\n    } else if([viewControllerToCommit isKindOfClass:[UINavigationController class]]) {\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:((UINavigationController *)viewControllerToCommit).topViewController];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationFormSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        viewControllerToCommit = nc;\n        [self.slidingViewController presentViewController:viewControllerToCommit animated:YES completion:nil];\n    } else if([viewControllerToCommit isKindOfClass:[PastebinViewController class]]) {\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:viewControllerToCommit];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationFormSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        [self.slidingViewController presentViewController:nc animated:YES completion:nil];\n    } else {\n        [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;\n        [self.slidingViewController presentViewController:viewControllerToCommit animated:YES completion:nil];\n    }\n}\n\n- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {\n    UIPreviewAction *deleteAction = [UIPreviewAction actionWithTitle:@\"Delete\" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n        NSString *title = [self->_buffer.type isEqualToString:@\"console\"]?@\"Delete Connection\":@\"Clear History\";\n        NSString *msg;\n        if([self->_buffer.type isEqualToString:@\"console\"]) {\n            msg = @\"Are you sure you want to remove this connection?\";\n        } else if([self->_buffer.type isEqualToString:@\"channel\"]) {\n            msg = [NSString stringWithFormat:@\"Are you sure you want to clear your history in %@?\", self->_buffer.name];\n        } else {\n            msg = [NSString stringWithFormat:@\"Are you sure you want to clear your history with %@?\", self->_buffer.name];\n        }\n        \n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];\n        \n        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {\n            if([self->_buffer.type isEqualToString:@\"console\"]) {\n                [self->_conn deleteServer:self->_buffer.cid handler:nil];\n            } else {\n                [self->_conn deleteBuffer:self->_buffer.bid cid:self->_buffer.cid handler:nil];\n            }\n        }]];\n        \n        if(((AppDelegate *)([UIApplication sharedApplication].delegate)).mainViewController.presentedViewController)\n            [((AppDelegate *)([UIApplication sharedApplication].delegate)).mainViewController dismissViewControllerAnimated:NO completion:nil];\n        \n        [((AppDelegate *)([UIApplication sharedApplication].delegate)).mainViewController presentViewController:alert animated:YES completion:nil];\n    }];\n    \n    UIPreviewAction *archiveAction = [UIPreviewAction actionWithTitle:@\"Archive\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n        [self->_conn archiveBuffer:self->_buffer.bid cid:self->_buffer.cid handler:nil];\n    }];\n    \n    UIPreviewAction *unarchiveAction = [UIPreviewAction actionWithTitle:@\"Unarchive\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n        [self->_conn unarchiveBuffer:self->_buffer.bid cid:self->_buffer.cid handler:nil];\n    }];\n    \n    NSMutableArray *items = [[NSMutableArray alloc] init];\n    \n    if([self->_buffer.type isEqualToString:@\"console\"]) {\n        if([self->_server.status isEqualToString:@\"disconnected\"]) {\n            [items addObject:[UIPreviewAction actionWithTitle:@\"Reconnect\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                [self->_conn reconnect:self->_buffer.cid handler:nil];\n            }]];\n            [items addObject:deleteAction];\n        } else {\n            [items addObject:[UIPreviewAction actionWithTitle:@\"Disconnect\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                [self->_conn disconnect:self->_buffer.cid msg:nil handler:nil];\n            }]];\n            \n        }\n        [items addObject:[UIPreviewAction actionWithTitle:@\"Edit Connection\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n            EditConnectionViewController *ecv = [[EditConnectionViewController alloc] initWithStyle:UITableViewStyleGrouped];\n            [ecv setServer:self->_buffer.cid];\n            UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:ecv];\n            [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n            if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                nc.modalPresentationStyle = UIModalPresentationPageSheet;\n            else\n                nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n            \n            if(((AppDelegate *)([UIApplication sharedApplication].delegate)).mainViewController.presentedViewController)\n                [((AppDelegate *)([UIApplication sharedApplication].delegate)).mainViewController dismissViewControllerAnimated:NO completion:nil];\n            \n            [((AppDelegate *)([UIApplication sharedApplication].delegate)).mainViewController presentViewController:nc animated:YES completion:nil];\n        }]];\n    } else if([self->_buffer.type isEqualToString:@\"channel\"]) {\n        if([[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid]) {\n            [items addObject:[UIPreviewAction actionWithTitle:@\"Leave\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                [self->_conn part:self->_buffer.name msg:nil cid:self->_buffer.cid handler:nil];\n            }]];\n            [items addObject:[UIPreviewAction actionWithTitle:@\"Invite to Channel\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                [((AppDelegate *)([UIApplication sharedApplication].delegate)).mainViewController _setSelectedBuffer:self->_buffer];\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", self->_server.name, self->_server.hostname, self->_server.port] message:@\"Invite to channel\" preferredStyle:UIAlertControllerStyleAlert];\n                \n                [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Invite\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                    if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n                        [[NetworkConnection sharedInstance] invite:((UITextField *)[alert.textFields objectAtIndex:0]).text chan:self->_buffer.name cid:self->_buffer.cid handler:nil];\n                    }\n                }]];\n                \n                [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n                    textField.placeholder = @\"nickname\";\n                    textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n                }];\n                \n                [self presentViewController:alert animated:YES completion:nil];\n            }]];\n        } else {\n            [items addObject:[UIPreviewAction actionWithTitle:@\"Rejoin\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                [self->_conn join:self->_buffer.name key:nil cid:self->_buffer.cid handler:nil];\n            }]];\n            if(self->_buffer.archived) {\n                [items addObject:unarchiveAction];\n            } else {\n                [items addObject:archiveAction];\n            }\n            [items addObject:deleteAction];\n        }\n    } else {\n        if(self->_buffer.archived) {\n            [items addObject:unarchiveAction];\n        } else {\n            [items addObject:archiveAction];\n        }\n        [items addObject:deleteAction];\n    }\n    \n    return items;\n}\n\n- (void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [self _reloadData];\n    \n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(backlogCompleted:)\n                                                 name:kIRCCloudBacklogCompletedNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(backlogFailed:)\n                                                 name:kIRCCloudBacklogFailedNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(drawerClosed:)\n                                                 name:ECSlidingViewTopDidReset object:nil];\n}\n\n- (void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n    if(self->_data.count && _buffer.scrolledUp) {\n        self->_bottomRow = [[[self->_tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self->_tableView.bounds, _tableView.contentInset)] lastObject] row];\n        if(self->_bottomRow >= self->_data.count)\n            self->_bottomRow = self->_data.count - 1;\n    } else {\n        self->_bottomRow = -1;\n    }\n}\n\n-(void)drawerClosed:(NSNotification *)n {\n    if(self.slidingViewController.underLeftViewController)\n        [self scrollViewDidScroll:self->_tableView];\n}\n\n-(void)viewWillResize {\n    self->_ready = NO;\n    self->_tableView.hidden = YES;\n    self->_stickyAvatar.hidden = YES;\n    if(self->_data.count && self->_buffer.scrolledUp)\n        self->_bottomRow = [[[self->_tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self->_tableView.bounds, self->_tableView.contentInset)] lastObject] row];\n    else\n        self->_bottomRow = -1;\n}\n\n-(void)viewDidResize {\n    self->_ready = YES;\n    [self clearCachedHeights];\n    [self updateUnread];\n    [self scrollViewDidScroll:self->_tableView];\n    self->_tableView.hidden = NO;\n}\n\n-(void)uncacheFile:(NSString *)fileID {\n    @synchronized (self->_filePropsCache) {\n        if(fileID)\n            [self->_filePropsCache removeObjectForKey:fileID];\n    }\n}\n\n-(void)closePreview:(Event *)event {\n    [self->_closedPreviews addObject:@(event.eid)];\n    [self refresh];\n}\n\n-(void)clearRowCache {\n    @synchronized (self->_rowCache) {\n        [self->_rowCache removeAllObjects];\n    }\n}\n\n-(void)clearCachedHeights {\n    if(self->_ready) {\n        if([self->_data count]) {\n            [self->_lock lock];\n            for(Event *e in _data) {\n                e.height = 0;\n            }\n            [self clearRowCache];\n            [self->_lock unlock];\n            self->_ready = NO;\n            [self->_tableView reloadData];\n            if(self->_bottomRow >= 0 && _bottomRow < [self->_tableView numberOfRowsInSection:0]) {\n                [self->_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self->_bottomRow inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];\n                self->_bottomRow = -1;\n            } else {\n                [self _scrollToBottom];\n            }\n            self->_ready = YES;\n        }\n    }\n}\n\n- (IBAction)loadMoreBacklogButtonPressed:(id)sender {\n    if(self->_conn.ready) {\n        self->_requestingBacklog = YES;\n        self->_shouldAutoFetch = NO;\n        [self->_conn cancelPendingBacklogRequests];\n        [self->_conn requestBacklogForBuffer:self->_buffer.bid server:self->_buffer.cid beforeId:self->_earliestEid completion:nil];\n        self->_tableView.tableHeaderView = self->_headerView;\n    }\n}\n\n- (void)backlogFailed:(NSNotification *)notification {\n    if(self->_buffer && [notification.object bid] == self->_buffer.bid) {\n        self->_requestingBacklog = NO;\n        self->_tableView.tableHeaderView = self->_backlogFailedView;\n        UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @\"Unable to download chat history. Please try again shortly.\");\n    }\n}\n\n- (void)backlogCompleted:(NSNotification *)notification {\n    if(self->_buffer && [notification.object bid] == self->_buffer.bid) {\n        if([[EventsDataSource sharedInstance] eventsForBuffer:self->_buffer.bid] == nil) {\n            CLS_LOG(@\"This buffer contains no events, switching to backlog failed header view\");\n            self->_tableView.tableHeaderView = self->_backlogFailedView;\n            return;\n        }\n        UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @\"Download complete.\");\n    }\n    if(notification.object == nil || [notification.object bid] == -1 || (self->_buffer && [notification.object bid] == self->_buffer.bid && _requestingBacklog)) {\n        CLS_LOG(@\"Backlog loaded in current buffer, will find and remove the last seen EID marker\");\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            if(self->_buffer.scrolledUp) {\n                [self->_lock lock];\n                int row = 0;\n                NSInteger toprow = [self->_tableView indexPathForRowAtPoint:CGPointMake(0,self->_buffer.savedScrollOffset)].row;\n                if(self->_tableView.tableHeaderView != nil)\n                    row++;\n                for(Event *event in self->_data) {\n                    if((event.rowType == ROW_LASTSEENEID && [[EventsDataSource sharedInstance] unreadStateForBuffer:self->_buffer.bid lastSeenEid:self->_buffer.last_seen_eid type:self->_buffer.type] == 0) || event.rowType == ROW_BACKLOG) {\n                        if(toprow > row) {\n                            CLS_LOG(@\"Adjusting scroll offset\");\n                            self->_buffer.savedScrollOffset -= 26;\n                        }\n                    }\n                    if(++row > toprow)\n                        break;\n                }\n                [self->_lock unlock];\n                for(Event *event in [[EventsDataSource sharedInstance] eventsForBuffer:self->_buffer.bid]) {\n                    if(event.rowType == ROW_LASTSEENEID) {\n                        CLS_LOG(@\"removing the last seen EID marker\");\n                        [[EventsDataSource sharedInstance] removeEvent:event.eid buffer:event.bid];\n                        CLS_LOG(@\"removed!\");\n                        break;\n                    }\n                }\n            }\n            CLS_LOG(@\"Rebuilding the message table\");\n            [self refresh];\n        }];\n    }\n}\n\n- (void)_sendHeartbeat {\n    if(self->_data.count && _topUnreadView.alpha == 0 && _bottomUnreadView.alpha == 0 && [UIApplication sharedApplication].applicationState == UIApplicationStateActive && ![NetworkConnection sharedInstance].notifier && [self.slidingViewController topViewHasFocus] && !_requestingBacklog && _conn.state == kIRCCloudStateConnected) {\n        NSArray *events = [[EventsDataSource sharedInstance] eventsForBuffer:self->_buffer.bid];\n        NSTimeInterval eid = self->_buffer.scrolledUpFrom;\n        if(eid <= 0) {\n            Event *last;\n            for(NSInteger i = events.count - 1; i >= 0; i--) {\n                last = [events objectAtIndex:i];\n                if(!last.pending && last.rowType != ROW_LASTSEENEID)\n                    break;\n            }\n            if(!last.pending) {\n                eid = last.eid;\n            }\n        }\n        if(eid >= 0 && eid >= self->_buffer.last_seen_eid) {\n            [self->_conn heartbeat:self->_buffer.bid cid:self->_buffer.cid bid:self->_buffer.bid lastSeenEid:eid handler:nil];\n            self->_buffer.last_seen_eid = eid;\n        }\n    }\n    self->_heartbeatTimer = nil;\n}\n\n- (void)sendHeartbeat {\n    if(!_heartbeatTimer)\n        self->_heartbeatTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(_sendHeartbeat) userInfo:nil repeats:NO];\n}\n\n- (void)handleEvent:(NSNotification *)notification {\n    IRCCloudJSONObject *o;\n    Event *e;\n    Buffer *b;\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    switch(event) {\n        case kIRCEventHeartbeatEcho:\n            [self updateUnread];\n            if(self->_maxEid <= self->_buffer.last_seen_eid) {\n                [UIView beginAnimations:nil context:nil];\n                [UIView setAnimationDuration:0.1];\n                self->_topUnreadView.alpha = 0;\n                [UIView commitAnimations];\n            }\n            break;\n        case kIRCEventMakeBuffer:\n            b = notification.object;\n            if(self->_buffer.bid == -1 && b.cid == self->_buffer.cid && [[b.name lowercaseString] isEqualToString:[self->_buffer.name lowercaseString]]) {\n                self->_buffer = b;\n                [self refresh];\n            }\n            break;\n        case kIRCEventChannelTopic:\n        case kIRCEventJoin:\n        case kIRCEventPart:\n        case kIRCEventNickChange:\n        case kIRCEventQuit:\n        case kIRCEventKick:\n        case kIRCEventChannelMode:\n        case kIRCEventUserMode:\n        case kIRCEventUserChannelMode:\n            o = notification.object;\n            if(o.bid == self->_buffer.bid) {\n                e = [[EventsDataSource sharedInstance] event:o.eid buffer:o.bid];\n                if(e)\n                    [self insertEvent:e backlog:NO nextIsGrouped:NO];\n            }\n            break;\n        case kIRCEventSelfDetails:\n        case kIRCEventBufferMsg:\n            e = notification.object;\n            if(e.bid == self->_buffer.bid) {\n                if(((e.from && [[e.from lowercaseString] isEqualToString:[self->_buffer.name lowercaseString]]) || (e.nick && [[e.nick lowercaseString] isEqualToString:[self->_buffer.name lowercaseString]])) && e.reqId == -1) {\n                    [self->_lock lock];\n                    for(int i = 0; i < _data.count; i++) {\n                        e = [self->_data objectAtIndex:i];\n                        if(e.pending) {\n                            if(i > 0) {\n                                Event *p = [self->_data objectAtIndex:i-1];\n                                if(p.rowType == ROW_TIMESTAMP) {\n                                    [self->_data removeObject:p];\n                                    i--;\n                                }\n                            }\n                            [self->_data removeObject:e];\n                            i--;\n                        }\n                    }\n                    [self->_lock unlock];\n                } else if(e.reqId != -1) {\n                    CLS_LOG(@\"Searching for pending message matching reqid %i\", e.reqId);\n                    int reqid = e.reqId;\n                    NSTimeInterval eid = -1;\n                    [self->_lock lock];\n                    for(int i = 0; i < _data.count; i++) {\n                        e = [self->_data objectAtIndex:i];\n                        if(e.reqId == reqid && (e.pending || e.rowType == ROW_FAILED)) {\n                            CLS_LOG(@\"Found at position %i\", i);\n                            eid = e.eid;\n                            if(i>0) {\n                                Event *p = [self->_data objectAtIndex:i-1];\n                                if(p.rowType == ROW_TIMESTAMP) {\n                                    CLS_LOG(@\"Removing timestamp row\");\n                                    [self->_data removeObject:p];\n                                    [self clearRowCache];\n                                    i--;\n                                }\n                            }\n                            CLS_LOG(@\"Removing pending event\");\n                            [self->_data removeObject:e];\n                            [self clearRowCache];\n                            i--;\n                        }\n                        if(e.parent == eid) {\n                            CLS_LOG(@\"Removing child event\");\n                            [self->_data removeObject:e];\n                            [self clearRowCache];\n                            i--;\n                        }\n                    }\n                    [self->_lock unlock];\n                    CLS_LOG(@\"Finished\");\n                }\n                [self insertEvent:notification.object backlog:NO nextIsGrouped:NO];\n            }\n            break;\n        case kIRCEventSetIgnores:\n            [self refresh];\n            break;\n        case kIRCEventUserInfo:\n            [[EventsDataSource sharedInstance] clearFormattingCache];\n            for(Event *e in _data) {\n                e.formatted = nil;\n                e.timestamp = nil;\n                e.formattedNick = nil;\n                e.formattedRealname = nil;\n                e.height = 0;\n            }\n            [self->_rowCache removeAllObjects];\n            [self refresh];\n            break;\n        case kIRCEventMessageChanged:\n            o = notification.object;\n            if(o.bid == self->_buffer.bid) {\n                [[EventsDataSource sharedInstance] clearFormattingCache];\n                for(Event *e in _data) {\n                    e.formatted = nil;\n                    e.timestamp = nil;\n                    e.formattedNick = nil;\n                    e.formattedRealname = nil;\n                    e.height = 0;\n                }\n                [self->_rowCache removeAllObjects];\n                [self refresh];\n            }\n            break;\n        default:\n            break;\n    }\n}\n\n- (void)insertEvent:(Event *)event backlog:(BOOL)backlog nextIsGrouped:(BOOL)nextIsGrouped {\n    @synchronized(self) {\n        BOOL colors = NO;\n        if(!event.isSelf && __nickColorsPref)\n            colors = YES;\n        \n        if(self->_minEid == 0)\n            self->_minEid = event.eid;\n        if(event.eid == self->_buffer.min_eid || (self->_msgid && [self->_msgid isEqualToString:event.msgid])) {\n            self->_tableView.tableHeaderView = nil;\n        }\n        if(event.eid < _earliestEid || _earliestEid == 0)\n            self->_earliestEid = event.eid;\n        \n        if(self->_msgid && !([event.msgid isEqualToString:self->_msgid] || [event.reply isEqualToString:self->_msgid])) {\n            return;\n        }\n        \n        if(!__showDeleted && (event.deleted || event.redacted))\n            return;\n        \n        NSTimeInterval eid = event.eid;\n        NSString *type = event.type;\n        if([type hasPrefix:@\"you_\"]) {\n            type = [type substringFromIndex:4];\n        }\n        NSString *eventmsg = event.msg;\n\n        if([type isEqualToString:@\"joined_channel\"] || [type isEqualToString:@\"parted_channel\"] || [type isEqualToString:@\"nickchange\"] || [type isEqualToString:@\"quit\"] || [type isEqualToString:@\"user_channel_mode\"]|| [type isEqualToString:@\"socket_closed\"] || [type isEqualToString:@\"connecting_failed\"] || [type isEqualToString:@\"connecting_cancelled\"]) {\n            self->_collapsedEvents.showChan = ![self->_buffer.type isEqualToString:@\"channel\"];\n            self->_collapsedEvents.noColor = __noColor;\n            if(__hideJoinPartPref && !event.isSelf && ![type isEqualToString:@\"socket_closed\"] && ![type isEqualToString:@\"connecting_failed\"] && ![type isEqualToString:@\"connecting_cancelled\"]) {\n                [self->_lock lock];\n                for(Event *e in _data) {\n                    if(e.eid == event.eid) {\n                        [self->_data removeObject:e];\n                        break;\n                    }\n                }\n                [self->_lock unlock];\n                if(!backlog)\n                    [self _reloadData];\n                return;\n            }\n            \n            [self->_formatter setDateFormat:@\"DDD\"];\n            NSDate *date = [NSDate dateWithTimeIntervalSince1970:event.time];\n            \n            if(__expandJoinPartPref)\n                [self->_expandedSectionEids removeAllObjects];\n            \n            if([event.type isEqualToString:@\"socket_closed\"] || [event.type isEqualToString:@\"connecting_failed\"] || [event.type isEqualToString:@\"connecting_cancelled\"]) {\n                Event *last = [[EventsDataSource sharedInstance] event:self->_lastCollapsedEid buffer:self->_buffer.bid];\n                if(last) {\n                    if(![last.type isEqualToString:@\"socket_closed\"] && ![last.type isEqualToString:@\"connecting_failed\"] && ![last.type isEqualToString:@\"connecting_cancelled\"])\n                        self->_currentCollapsedEid = -1;\n                }\n            } else {\n                Event *last = [[EventsDataSource sharedInstance] event:self->_lastCollapsedEid buffer:self->_buffer.bid];\n                if(last) {\n                    if([last.type isEqualToString:@\"socket_closed\"] || [last.type isEqualToString:@\"connecting_failed\"] || [last.type isEqualToString:@\"connecting_cancelled\"])\n                        self->_currentCollapsedEid = -1;\n                }\n            }\n            \n            if(self->_currentCollapsedEid == -1 || ![[self->_formatter stringFromDate:date] isEqualToString:self->_lastCollpasedDay] || __expandJoinPartPref || [event.type isEqualToString:@\"you_parted_channel\"]) {\n                [self->_collapsedEvents clear];\n                self->_currentCollapsedEid = eid;\n                self->_lastCollpasedDay = [self->_formatter stringFromDate:date];\n            }\n            \n            if(!_collapsedEvents.showChan)\n                event.chan = self->_buffer.name;\n            \n            if(![self->_collapsedEvents addEvent:event]) {\n                [self->_collapsedEvents clear];\n            }\n            \n            event.color = [UIColor collapsedRowTextColor];\n            event.bgColor = [UIColor contentBackgroundColor];\n            \n            NSString *msg;\n            if([self->_expandedSectionEids objectForKey:@(self->_currentCollapsedEid)]) {\n                CollapsedEvents *c = [[CollapsedEvents alloc] init];\n                c.showChan = self->_collapsedEvents.showChan;\n                c.server = self->_server;\n                [c addEvent:event];\n                if(!nextIsGrouped) {\n                    msg = [c collapse];\n                    NSString *groupMsg = [self->_collapsedEvents collapse];\n                    if(groupMsg == nil && [type isEqualToString:@\"nickchange\"])\n                        groupMsg = [NSString stringWithFormat:@\"%@ → %c%@%c\", event.oldNick, BOLD, [self->_collapsedEvents formatNick:event.nick mode:event.fromMode colorize:NO displayName:nil], BOLD];\n                    if(groupMsg == nil && [type isEqualToString:@\"user_channel_mode\"]) {\n                        if(event.from.length > 0)\n                            groupMsg = [NSString stringWithFormat:@\"%c%@%c was set to: %c%@%c by %c%@%c\", BOLD, event.nick, BOLD, BOLD, event.diff, BOLD, BOLD, [self->_collapsedEvents formatNick:event.from mode:event.fromMode colorize:NO displayName:nil], BOLD];\n                        else\n                            groupMsg = [NSString stringWithFormat:@\"%@ was set to: %c%@%c by the server %c%@%c\", event.nick, BOLD, event.diff, BOLD, BOLD, event.server, BOLD];\n                    }\n                    Event *heading = [[Event alloc] init];\n                    heading.cid = event.cid;\n                    heading.bid = event.bid;\n                    heading.eid = self->_currentCollapsedEid - 1;\n                    heading.groupMsg = [NSString stringWithFormat:@\"%@%@\",_groupIndent,groupMsg];\n                    heading.color = [UIColor timestampColor];\n                    heading.bgColor = [UIColor contentBackgroundColor];\n                    heading.formattedMsg = nil;\n                    heading.formatted = nil;\n                    heading.linkify = NO;\n                    [self _addItem:heading eid:self->_currentCollapsedEid - 1];\n                    if([event.type isEqualToString:@\"socket_closed\"] || [event.type isEqualToString:@\"connecting_failed\"] || [event.type isEqualToString:@\"connecting_cancelled\"]) {\n                        Event *last = [[EventsDataSource sharedInstance] event:self->_lastCollapsedEid buffer:self->_buffer.bid];\n                        if(last) {\n                            if(last.msg.length == 0)\n                                [self->_data removeObject:last];\n                            else\n                                last.rowType = ROW_MESSAGE;\n                        }\n                        event.rowType = ROW_SOCKETCLOSED;\n                    }\n                } else {\n                    msg = @\"\";\n                }\n                event.timestamp = nil;\n                event.collapsed = NO;\n            } else {\n                msg = (nextIsGrouped && _currentCollapsedEid != event.eid)?@\"\":[self->_collapsedEvents collapse];\n                event.collapsed = YES;\n            }\n            if(msg == nil && [type isEqualToString:@\"nickchange\"])\n                msg = [NSString stringWithFormat:@\"%@ → %c%@%c\", event.oldNick, BOLD, [self->_collapsedEvents formatNick:event.nick mode:event.fromMode colorize:NO displayName:nil], BOLD];\n            if(msg == nil && [type isEqualToString:@\"user_channel_mode\"]) {\n                if(event.from.length > 0)\n                    msg = [NSString stringWithFormat:@\"%c%@%c was set to: %c%@%c by %c%@%c\", BOLD, event.nick, BOLD, BOLD, event.diff, BOLD, BOLD, [self->_collapsedEvents formatNick:event.from mode:event.fromMode colorize:NO displayName:nil], BOLD];\n                else\n                    msg = [NSString stringWithFormat:@\"%@ was set to: %c%@%c by the server %c%@%c\", event.nick, BOLD, event.diff, BOLD, BOLD, event.server, BOLD];\n                self->_currentCollapsedEid = eid;\n            }\n            if([self->_expandedSectionEids objectForKey:@(self->_currentCollapsedEid)]) {\n                msg = [NSString stringWithFormat:@\"%@%@\", _groupIndent, msg];\n            } else {\n                if(eid != self->_currentCollapsedEid)\n                    msg = [NSString stringWithFormat:@\"%@%@\", _groupIndent, msg];\n                eid = self->_currentCollapsedEid;\n            }\n            event.groupMsg = msg;\n            event.formattedMsg = nil;\n            event.formatted = nil;\n            event.formattedPrefix = nil;\n            event.linkify = NO;\n            self->_lastCollapsedEid = event.eid;\n            if(([self->_buffer.type isEqualToString:@\"console\"] && ![type isEqualToString:@\"socket_closed\"] && ![type isEqualToString:@\"connecting_failed\"] && ![type isEqualToString:@\"connecting_cancelled\"]) || [event.type isEqualToString:@\"you_parted_channel\"]) {\n                self->_currentCollapsedEid = -1;\n                self->_lastCollapsedEid = -1;\n                [self->_collapsedEvents clear];\n            }\n            EventsTableCell *cell = [self->_rowCache objectForKey:event.UUID];\n            if(cell) {\n                cell.message.text = nil;\n            }\n        } else {\n            self->_currentCollapsedEid = -1;\n            self->_lastCollapsedEid = -1;\n            event.mentionOffset = 0;\n            event.formattedPrefix = nil;\n            [self->_collapsedEvents clear];\n            \n            if(!event.formatted.length || !event.formattedMsg.length) {\n                if((__chatOneLinePref || ![event isMessage]) && [event.from length] && event.rowType != ROW_THUMBNAIL && event.rowType != ROW_FILE) {\n                    event.formattedPrefix = [NSString stringWithFormat:@\"%@\", [self->_collapsedEvents formatNick:event.fromNick mode:event.fromMode colorize:colors defaultColor:[UIColor isDarkTheme]?@\"ffffff\":@\"142b43\" displayName:event.from]];\n                }\n                event.formattedMsg = eventmsg;\n            }\n        }\n        \n        if(event.ignoreMask.length && [event isMessage]) {\n            if((!_buffer || ![self->_buffer.type isEqualToString:@\"conversation\"]) && [self->_server.ignore match:event.ignoreMask]) {\n                if(self->_topUnreadView.alpha == 0 && _bottomUnreadView.alpha == 0)\n                    [self sendHeartbeat];\n                return;\n            }\n        }\n        \n        event.childEventCount = 0;\n        event.hasReplyRow = NO;\n        \n        if(!event.formatted) {\n            if(event.rowType == ROW_THUMBNAIL) {\n                event.formattedMsg = eventmsg;\n            } else if([type isEqualToString:@\"channel_mode\"] && event.nick.length > 0) {\n                if(event.nick.length)\n                    event.formattedMsg = [NSString stringWithFormat:@\"%@ by %@\", event.msg, [self->_collapsedEvents formatNick:event.nick mode:event.fromMode colorize:NO displayName:nil]];\n                else if(event.server.length)\n                    event.formattedMsg = [NSString stringWithFormat:@\"%@ by the server %c%@%c\", event.msg, BOLD, event.server, CLEAR];\n            } else if([type isEqualToString:@\"buffer_me_msg\"]) {\n                NSString *msg = eventmsg;\n                if(!__disableCodeSpanPref)\n                    msg = [msg insertCodeSpans];\n                event.formattedPrefix = [NSString stringWithFormat:@\"— %c%@\", ITALICS, [self->_collapsedEvents formatNick:event.fromNick mode:event.fromMode colorize:colors displayName:event.nick]];\n                event.formattedMsg = [NSString stringWithFormat:@\"%c%@\",ITALICS,msg];\n                event.mentionOffset++;\n                event.rowType = ROW_ME_MESSAGE;\n            } else if([type isEqualToString:@\"notice\"] || [type isEqualToString:@\"buffer_msg\"]) {\n                event.isCodeBlock = NO;\n                if(event.rowType == ROW_FAILED)\n                    event.color = [UIColor networkErrorColor];\n                else if(event.pending)\n                    event.color = [UIColor timestampColor];\n                else\n                    event.color = [UIColor messageTextColor];\n                Server *s = [[ServersDataSource sharedInstance] getServer:event.cid];\n                if([event.targetMode isEqualToString:[s.PREFIX objectForKey:s.MODE_OPER]])\n                    event.formattedPrefix = [NSString stringWithFormat:@\"%c%@%c \",BOLD,[self->_collapsedEvents formatNick:@\"Opers\" mode:s.MODE_OPER colorize:NO displayName:nil],BOLD];\n                else if([event.targetMode isEqualToString:[s.PREFIX objectForKey:s.MODE_OWNER]])\n                    event.formattedPrefix = [NSString stringWithFormat:@\"%c%@%c \",BOLD,[self->_collapsedEvents formatNick:@\"Owners\" mode:s.MODE_OWNER colorize:NO displayName:nil],BOLD];\n                else if([event.targetMode isEqualToString:[s.PREFIX objectForKey:s.MODE_ADMIN]])\n                    event.formattedPrefix = [NSString stringWithFormat:@\"%c%@%c \",BOLD,[self->_collapsedEvents formatNick:@\"Admins\" mode:s.MODE_ADMIN colorize:NO displayName:nil],BOLD];\n                else if([event.targetMode isEqualToString:[s.PREFIX objectForKey:s.MODE_OP]])\n                    event.formattedPrefix = [NSString stringWithFormat:@\"%c%@%c \",BOLD,[self->_collapsedEvents formatNick:@\"Ops\" mode:s.MODE_OP colorize:NO displayName:nil],BOLD];\n                else if([event.targetMode isEqualToString:[s.PREFIX objectForKey:s.MODE_HALFOP]])\n                    event.formattedPrefix = [NSString stringWithFormat:@\"%c%@%c \",BOLD,[self->_collapsedEvents formatNick:@\"Half Ops\" mode:s.MODE_HALFOP colorize:NO displayName:nil],BOLD];\n                else if([event.targetMode isEqualToString:[s.PREFIX objectForKey:s.MODE_VOICED]])\n                    event.formattedPrefix = [NSString stringWithFormat:@\"%c%@%c \",BOLD,[self->_collapsedEvents formatNick:@\"Voiced\" mode:s.MODE_VOICED colorize:NO displayName:nil],BOLD];\n                else\n                    event.formattedPrefix = @\"\";\n                \n                if(event.edited)\n                    eventmsg = [eventmsg stringByAppendingFormat:@\" %c%@(edited)%c\", COLOR_RGB, [UIColor collapsedRowTextColor].toHexString, COLOR_RGB];\n\n                if(event.deleted || event.redacted)\n                    if(event.redactedReason.length)\n                        eventmsg = [NSString stringWithFormat:@\"%c%@(deleted: %@)%c %@\", COLOR_RGB, [UIColor collapsedRowTextColor].toHexString, event.redactedReason, COLOR_RGB, eventmsg];\n                    else\n                        eventmsg = [NSString stringWithFormat:@\"%c%@(deleted)%c %@\", COLOR_RGB, [UIColor collapsedRowTextColor].toHexString, COLOR_RGB, eventmsg];\n\n                if(!__disableCodeBlockPref && eventmsg) {\n                    static NSRegularExpression *_pattern = nil;\n                    if(!_pattern) {\n                        NSString *pattern = @\"```([\\\\s\\\\S]+?)```(?=(?!`)[\\\\W\\\\s\\\\n]|$)\";\n                        _pattern = [NSRegularExpression\n                                    regularExpressionWithPattern:pattern\n                                    options:NSRegularExpressionCaseInsensitive\n                                    error:nil];\n                    }\n                    \n                    NSString *msg = eventmsg;\n                    NSArray *matches = [_pattern matchesInString:msg options:0 range:NSMakeRange(0, msg.length)];\n                    if(matches.count) {\n                        NSUInteger start = 0;\n                        \n                        for(NSTextCheckingResult *result in matches) {\n                            NSString *lastChunk = @\"\";\n                            if(result.range.location)\n                                lastChunk = [msg substringWithRange:NSMakeRange(start, result.range.location - start)];\n                            BOOL strippedSpace = NO;\n                            if(lastChunk.length > 1 && ([lastChunk hasPrefix:@\" \"] || [lastChunk hasPrefix:@\"\\n\"])) {\n                                lastChunk = [lastChunk substringFromIndex:1];\n                                strippedSpace = YES;\n                            }\n                            if([lastChunk hasSuffix:@\" \"] || [lastChunk hasSuffix:@\"\\n\"])\n                                lastChunk = [lastChunk substringToIndex:lastChunk.length - 1];\n                            if(start > 0) {\n                                Event *e = [event copy];\n                                e.eid = event.eid + ++event.childEventCount;\n                                e.msg = e.formattedMsg = lastChunk;\n                                if(!__disableCodeSpanPref)\n                                    e.msg = e.formattedMsg = [e.formattedMsg insertCodeSpans];\n                                e.timestamp = @\"\";\n                                e.parent = event.eid;\n                                e.isHeader = NO;\n                                e.mentionOffset = -start;\n                                if(strippedSpace)\n                                    e.mentionOffset--;\n                                [self _addItem:e eid:e.eid];\n                            } else {\n                                eventmsg = lastChunk;\n                            }\n                            if(result.range.location == 0 && !__chatOneLinePref) {\n                                eventmsg = [msg substringWithRange:NSMakeRange(3, result.range.length - 6)];\n                                if([eventmsg hasPrefix:@\"\\n\"])\n                                    eventmsg = [eventmsg substringFromIndex:1];\n                                if([eventmsg hasSuffix:@\"\\n\"])\n                                    eventmsg = [eventmsg substringToIndex:eventmsg.length - 1];\n                                event.isCodeBlock = YES;\n                                event.color = [UIColor codeSpanForegroundColor];\n                                event.monospace = YES;\n                            } else {\n                                Event *e = [event copy];\n                                e.eid = event.eid + ++event.childEventCount;\n                                NSString *strippedmsg = [msg substringWithRange:NSMakeRange(result.range.location + 3, result.range.length - 6)];\n                                if([strippedmsg hasPrefix:@\"\\n\"])\n                                    strippedmsg = [strippedmsg substringFromIndex:1];\n                                if([strippedmsg hasSuffix:@\"\\n\"])\n                                    strippedmsg = [strippedmsg substringToIndex:strippedmsg.length - 1];\n                                e.msg = e.formattedMsg = strippedmsg;\n                                e.timestamp = @\"\";\n                                e.parent = event.eid;\n                                e.isCodeBlock = YES;\n                                e.isHeader = NO;\n                                e.color = [UIColor codeSpanForegroundColor];\n                                e.monospace = YES;\n                                e.entities = nil;\n                                [self _addItem:e eid:e.eid];\n                            }\n                            start = result.range.location + result.range.length;\n                        }\n                        if(start < msg.length) {\n                            Event *e = [event copy];\n                            e.eid = event.eid + ++event.childEventCount;\n                            e.msg = e.formattedMsg = [msg substringWithRange:NSMakeRange(start, msg.length - start)];\n                            e.mentionOffset = -start;\n                            if(e.formattedMsg.length > 1 && ([e.formattedMsg hasPrefix:@\" \"] || [e.formattedMsg hasPrefix:@\"\\n\"])) {\n                                e.formattedMsg = [e.formattedMsg substringFromIndex:1];\n                                e.mentionOffset--;\n                            }\n                            if(!__disableCodeSpanPref)\n                                e.formattedMsg = [e.formattedMsg insertCodeSpans];\n                            e.timestamp = @\"\";\n                            e.parent = event.eid;\n                            e.isHeader = NO;\n                            if(e.formattedMsg.length)\n                                [self _addItem:e eid:e.eid];\n                        }\n                    }\n                } else {\n                    event.isCodeBlock = NO;\n                }\n                \n                if(!__disableCodeSpanPref)\n                    eventmsg = [eventmsg insertCodeSpans];\n                if([type isEqualToString:@\"notice\"]) {\n                    if([self->_buffer.type isEqualToString:@\"console\"] && event.toChan && event.chan.length) {\n                        event.formattedPrefix = [event.formattedPrefix stringByAppendingFormat:@\"%c%@%c:\", BOLD, event.chan, BOLD];\n                    } else if([self->_buffer.type isEqualToString:@\"console\"] && event.isSelf && event.nick.length) {\n                        event.formattedPrefix = [event.formattedPrefix stringByAppendingFormat:@\"%c%@%c:\", BOLD, event.nick, BOLD];\n                    }\n                }\n                event.formattedMsg = eventmsg;\n                if(event.from.length && __chatOneLinePref && event.rowType != ROW_THUMBNAIL && event.rowType != ROW_FILE) {\n                    if(!__disableQuotePref && event.formattedMsg.length > 0 && [event.formattedMsg isBlockQuote]) {\n                        Event *e1 = event.copy;\n                        e1.eid = event.eid + ++event.childEventCount;\n                        e1.timestamp = @\"\";\n                        e1.formattedMsg = event.formattedMsg;\n                        e1.parent = event.eid;\n                        [self _addItem:e1 eid:e1.eid];\n                        event.formattedPrefix = [self->_collapsedEvents formatNick:event.fromNick mode:event.fromMode colorize:colors displayName:event.from];\n                        event.formattedMsg = @\"\";\n                    } else {\n                        NSString *formattedPrefix = event.formattedPrefix;\n                        formattedPrefix = [NSString stringWithFormat:@\"%@ %@\", [self->_collapsedEvents formatNick:event.fromNick mode:event.fromMode colorize:colors displayName:event.from], formattedPrefix];\n                        event.formattedPrefix = formattedPrefix;\n                    }\n                }\n            } else if([type isEqualToString:@\"kicked_channel\"]) {\n                event.formattedPrefix = [NSString stringWithFormat:@\"%c%@← \", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString];\n                if([event.type hasPrefix:@\"you_\"])\n                    event.formattedPrefix = [event.formattedPrefix stringByAppendingString:@\"You\"];\n                else\n                    event.formattedPrefix = [event.formattedPrefix stringByAppendingFormat:@\"%@%c\", event.oldNick, CLEAR];\n                if([event.type hasPrefix:@\"you_\"])\n                    event.formattedPrefix = [event.formattedPrefix stringByAppendingString:@\" were\"];\n                else\n                    event.formattedPrefix = [event.formattedPrefix stringByAppendingString:@\" was\"];\n                if(event.hostmask && event.hostmask.length)\n                    event.formattedPrefix = [event.formattedPrefix stringByAppendingFormat:@\" kicked by %@\", [self->_collapsedEvents formatNick:event.nick mode:event.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil]];\n                else\n                    event.formattedPrefix = [event.formattedPrefix stringByAppendingFormat:@\" kicked by the server %c%@%@%c\", COLOR_RGB, [UIColor collapsedRowNickColor].toHexString, event.nick, CLEAR];\n                if(event.msg.length > 0 && ![event.msg isEqualToString:event.nick])\n                    event.formattedMsg = [NSString stringWithFormat:@\": %@\", eventmsg];\n                else\n                    event.formattedMsg = @\"\";\n            } else if([type isEqualToString:@\"channel_mode_list_change\"]) {\n                if(event.from.length == 0) {\n                    if(event.nick.length)\n                        event.formattedMsg = [NSString stringWithFormat:@\"%@ %@\", [self->_collapsedEvents formatNick:event.nick mode:event.fromMode colorize:NO displayName:nil], event.msg];\n                    else if(event.server.length)\n                        event.formattedMsg = [NSString stringWithFormat:@\"The server %c%@%c %@\", BOLD, event.server, CLEAR, event.msg];\n                }\n            } else if([type isEqualToString:@\"user_chghost\"]) {\n                event.formattedMsg = [NSString stringWithFormat:@\"%@ %@\", [self->_collapsedEvents formatNick:event.nick mode:event.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString bold:NO displayName:nil], event.msg];\n            } else if([type isEqualToString:@\"channel_name_change\"]) {\n                if(event.from.length) {\n                    event.formattedMsg = [NSString stringWithFormat:@\"%@ %@\", [self->_collapsedEvents formatNick:event.from mode:event.fromMode colorize:NO defaultColor:[UIColor collapsedRowNickColor].toHexString displayName:nil], event.msg];\n                } else {\n                    NSString *from = @\"The server \";\n                    if(event.server.length)\n                        from = [from stringByAppendingFormat:@\"%@ \",event.server];\n                    event.formattedMsg = [NSString stringWithFormat:@\"%@%@\", from, event.msg];\n                }\n            } else if([type isEqualToString:@\"channel_topic\"]) {\n                if([event.msg hasPrefix:@\"set the topic: \"])\n                    event.mentionOffset += 15;\n            }\n        }\n\n        if(event.msgid)\n            [self->_msgids setObject:event forKey:event.msgid];\n        if(event.reply) {\n            Event *parent = [self->_msgids objectForKey:event.reply];\n            parent.replyCount = parent.replyCount + 1;\n            if(!parent.replyNicks)\n                parent.replyNicks = [[NSMutableSet alloc] init];\n            if(event.from)\n                [parent.replyNicks addObject:event.from];\n        }\n        \n        event.isReply = event.reply != nil;\n        if(event.isReply && __replyCollapsePref) {\n            Event *parent = [self->_msgids objectForKey:event.reply];\n            if(parent && !parent.hasReplyRow) {\n                Event *e1 = [self entity:parent eid:parent.eid + ++parent.childEventCount properties:nil];\n                e1.rowType = ROW_REPLY_COUNT;\n                e1.type = TYPE_REPLY_COUNT;\n                e1.msg = e1.formattedMsg = nil;\n                e1.formatted = nil;\n                e1.entities = @{@\"parent\":parent};\n                parent.hasReplyRow = YES;\n                [self insertEvent:e1 backlog:YES nextIsGrouped:NO];\n            }\n            if(!backlog)\n                [self reloadData];\n            return;\n        }\n        [self _addItem:event eid:eid];\n        if(!event.formatted && event.formattedMsg.length > 0 && !backlog) {\n            [self _format:event];\n        }\n        \n        if(!backlog) {\n            [self _reloadData];\n            if(!_buffer.scrolledUp) {\n                [self scrollToBottom];\n                [self _scrollToBottom];\n                if(self->_topUnreadView.alpha == 0)\n                    [self sendHeartbeat];\n            } else if(!event.isSelf && [event isImportant:self->_buffer.type]) {\n                self->_newMsgs++;\n                if(event.isHighlight && !__notificationsMuted)\n                    self->_newHighlights++;\n                [self updateUnread];\n                [self scrollViewDidScroll:self->_tableView];\n            }\n        }\n        \n        if(!__disableInlineFilesPref && event.rowType != ROW_THUMBNAIL) {\n            NSTimeInterval entity_eid = event.eid;\n            for(NSDictionary *entity in [event.entities objectForKey:@\"files\"]) {\n                entity_eid = event.eid + ++event.childEventCount;\n                if([self->_closedPreviews containsObject:@(entity_eid)])\n                    continue;\n                \n                @synchronized (self->_filePropsCache) {\n                    NSDictionary *properties = [self->_filePropsCache objectForKey:[entity objectForKey:@\"id\"]];\n#ifdef DEBUG\n                    if([[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"]) {\n                        NSMutableDictionary *d = entity.mutableCopy;\n                        [d removeObjectForKey:@\"id\"];\n                        [d setObject:[NSURL URLWithString:[NSString stringWithFormat:@\"https://www.irccloud.com/static/test/%@\", [d objectForKey:@\"filename\"]]] forKey:@\"thumb\"];\n                        properties = d;\n                    }\n#endif\n                    if(properties) {\n                        Event *e1 = [self entity:event eid:entity_eid properties:properties];\n                        [self insertEvent:e1 backlog:YES nextIsGrouped:NO];\n                        if(!backlog)\n                            [self reloadForEvent:e1];\n                    } else {\n                        [self->_conn propertiesForFile:[entity objectForKey:@\"id\"] handler:^(IRCCloudJSONObject *properties) {\n                            if(properties) {\n                                [self->_filePropsCache setObject:properties.dictionary forKey:[entity objectForKey:@\"id\"]];\n                                if(self->_buffer.bid == event.bid) {\n                                    Event *e1 = [self entity:event eid:entity_eid properties:properties.dictionary];\n                                    [self insertEvent:e1 backlog:YES nextIsGrouped:NO];\n                                    [self reloadForEvent:e1];\n                                }\n                            }\n                        }];\n                    }\n                }\n            }\n            if(self->_buffer.last_seen_eid == event.eid)\n                self->_buffer.last_seen_eid = entity_eid;\n        }\n        \n        if(__inlineMediaPref && event.linkify && event.msg.length && event.rowType != ROW_THUMBNAIL) {\n            NSTimeInterval entity_eid = event.eid;\n\n            NSArray *results = event.links;\n            for(id r in results) {\n                if([r isKindOfClass:NSTextCheckingResult.class]) {\n                    NSTextCheckingResult *result = r;\n                    BOOL found = NO;\n                    for(NSDictionary *entity in [event.entities objectForKey:@\"files\"]) {\n                        if([result.URL.absoluteString rangeOfString:[entity objectForKey:@\"id\"]].location != NSNotFound) {\n                            found = YES;\n                            break;\n                        }\n                    }\n                    \n                    if(!found) {\n                        entity_eid = event.eid + ++event.childEventCount;\n                        if([self->_closedPreviews containsObject:@(entity_eid)])\n                            continue;\n                        if([URLHandler isImageURL:result.URL] && [[ImageCache sharedInstance] isValidURL:result.URL]) {\n                            if([self->_urlHandler MediaURLs:result.URL]) {\n                                Event *e1 = [self entity:event eid:entity_eid properties:[self->_urlHandler MediaURLs:result.URL]];\n                                if([[ImageCache sharedInstance] isValidURL:[e1.entities objectForKey:@\"url\"]])\n                                    [self insertEvent:e1 backlog:backlog nextIsGrouped:NO];\n                            } else {\n                                [self->_urlHandler fetchMediaURLs:result.URL result:^(BOOL success, NSString *error) {\n                                    if([self->_data containsObject:event] && self->_buffer.bid == event.bid) {\n                                        if(success) {\n                                            Event *e1 = [self entity:event eid:entity_eid properties:[self->_urlHandler MediaURLs:result.URL]];\n                                            if([[ImageCache sharedInstance] isValidURL:[e1.entities objectForKey:@\"url\"]]) {\n                                                [self insertEvent:e1 backlog:YES nextIsGrouped:NO];\n                                                [self reloadForEvent:e1];\n                                            }\n                                        } else {\n                                            CLS_LOG(@\"METADATA FAILED: %@: %@\", result.URL, error);\n                                        }\n                                    }\n                                }];\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n-(Event *)entity:(Event *)parent eid:(NSTimeInterval)eid properties:(NSDictionary *)properties {\n    Event *e1 = [[Event alloc] init];\n    e1.cid = parent.cid;\n    e1.bid = parent.bid;\n    e1.eid = eid;\n    e1.from = parent.from;\n    e1.nick = parent.nick;\n    e1.isSelf = parent.isSelf;\n    e1.fromMode = parent.fromMode;\n    e1.realname = parent.realname;\n    e1.hostmask = parent.hostmask;\n    e1.parent = parent.eid;\n    e1.entities = properties;\n    e1.avatar = parent.avatar;\n    e1.avatarURL = parent.avatarURL;\n    e1.msgid = self->_msgid;\n\n    if([properties objectForKey:@\"id\"]) {\n        if([[properties objectForKey:@\"mime_type\"] hasPrefix:@\"image/\"])\n            e1.rowType = ROW_THUMBNAIL;\n        else\n            e1.rowType = ROW_FILE;\n        int bytes = [[properties objectForKey:@\"size\"] intValue];\n        if(bytes < 1024) {\n            e1.msg = [NSString stringWithFormat:@\"%lu B\", (unsigned long)bytes];\n        } else {\n            int exp = (int)(log(bytes) / log(1024));\n            e1.msg = [NSString stringWithFormat:@\"%.1f %cB\", bytes / pow(1024, exp), [@\"KMGTPE\" characterAtIndex:exp -1]];\n        }\n    } else {\n        e1.rowType = ROW_THUMBNAIL;\n        if([[properties objectForKey:@\"description\"] isKindOfClass:NSString.class]) {\n            e1.msg = [properties objectForKey:@\"description\"];\n            e1.linkify = YES;\n        } else {\n            e1.msg = @\"\";\n        }\n    }\n    e1.color = [UIColor messageTextColor];\n    e1.bgColor = e1.isSelf?[UIColor selfBackgroundColor]:parent.bgColor;\n    if([parent.type isEqualToString:@\"buffer_me_msg\"])\n        e1.type = @\"buffer_msg\";\n    else\n        e1.type = parent.type;\n    e1.formattedMsg = e1.msg;\n    [self _format:e1];\n    return e1;\n}\n\n-(void)updateTopUnread:(NSInteger)firstRow {\n    if(!_topUnreadView)\n        return;\n    int highlights = 0;\n    for(NSNumber *pos in _unseenHighlightPositions) {\n        if([pos intValue] > firstRow)\n            break;\n        highlights++;\n    }\n    NSString *msg = @\"\";\n    if(highlights) {\n        if(highlights == 1)\n            msg = @\"mention and \";\n        else\n            msg = @\"mentions and \";\n        self->_topHighlightsCountView.count = [NSString stringWithFormat:@\"%i\", highlights];\n        self->_topHighlightsCountView.hidden = NO;\n        self->_topUnreadLabelXOffsetConstraint.constant = self->_topHighlightsCountView.intrinsicContentSize.width + 2;\n    } else {\n        self->_topHighlightsCountView.hidden = YES;\n        self->_topUnreadLabelXOffsetConstraint.constant = 0;\n    }\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"tabletMode\"] && [[UIDevice currentDevice] isBigPhone]) {\n        self->_topUnreadDismissXOffsetConstraint.constant = -self.slidingViewController.view.window.safeAreaInsets.left;\n    }\n    if(self->_lastSeenEidPos == 0 && firstRow < _data.count) {\n        int seconds;\n        if(firstRow < 0)\n            seconds = (self->_earliestEid - _buffer.last_seen_eid) / 1000000;\n        else\n            seconds = ([[self->_data objectAtIndex:firstRow] eid] - _buffer.last_seen_eid) / 1000000;\n        if(seconds < 0) {\n            self->_topUnreadView.alpha = 0;\n        } else {\n            int minutes = seconds / 60;\n            int hours = minutes / 60;\n            int days = hours / 24;\n            if(days) {\n                if(days == 1)\n                    self->_topUnreadLabel.text = [msg stringByAppendingFormat:@\"%i day of unread messages\", days];\n                else\n                    self->_topUnreadLabel.text = [msg stringByAppendingFormat:@\"%i days of unread messages\", days];\n            } else if(hours) {\n                if(hours == 1)\n                    self->_topUnreadLabel.text = [msg stringByAppendingFormat:@\"%i hour of unread messages\", hours];\n                else\n                    self->_topUnreadLabel.text = [msg stringByAppendingFormat:@\"%i hours of unread messages\", hours];\n            } else if(minutes) {\n                if(minutes == 1)\n                    self->_topUnreadLabel.text = [msg stringByAppendingFormat:@\"%i minute of unread messages\", minutes];\n                else\n                    self->_topUnreadLabel.text = [msg stringByAppendingFormat:@\"%i minutes of unread messages\", minutes];\n            } else {\n                if(seconds == 1)\n                    self->_topUnreadLabel.text = [msg stringByAppendingFormat:@\"%i second of unread messages\", seconds];\n                else\n                    self->_topUnreadLabel.text = [msg stringByAppendingFormat:@\"%i seconds of unread messages\", seconds];\n            }\n        }\n    } else {\n        if(firstRow - _lastSeenEidPos == 1) {\n            self->_topUnreadLabel.text = [msg stringByAppendingFormat:@\"%li unread message\", (long)(firstRow - _lastSeenEidPos)];\n        } else if(firstRow - _lastSeenEidPos > 0) {\n            self->_topUnreadLabel.text = [msg stringByAppendingFormat:@\"%li unread messages\", (long)(firstRow - _lastSeenEidPos)];\n        } else {\n            self->_topUnreadView.alpha = 0;\n        }\n    }\n}\n\n-(void)updateUnread {\n    if(!_bottomUnreadView)\n        return;\n    NSString *msg = @\"\";\n    if(self->_newHighlights) {\n        if(self->_newHighlights == 1)\n            msg = @\"mention\";\n        else\n            msg = @\"mentions\";\n        self->_bottomHighlightsCountView.count = [NSString stringWithFormat:@\"%li\", (long)_newHighlights];\n        self->_bottomHighlightsCountView.hidden = NO;\n        self->_bottomUnreadLabelXOffsetConstraint.constant = self->_bottomHighlightsCountView.intrinsicContentSize.width + 2;\n    } else {\n        self->_bottomHighlightsCountView.hidden = YES;\n        self->_bottomUnreadLabelXOffsetConstraint.constant = self->_bottomHighlightsCountView.intrinsicContentSize.width + 2;\n    }\n    if(self->_newMsgs - _newHighlights > 0) {\n        if(self->_newHighlights)\n            msg = [msg stringByAppendingString:@\" and \"];\n        if(self->_newMsgs - _newHighlights == 1)\n            msg = [msg stringByAppendingFormat:@\"%li unread message\", (long)(self->_newMsgs - _newHighlights)];\n        else\n            msg = [msg stringByAppendingFormat:@\"%li unread messages\", (long)(self->_newMsgs - _newHighlights)];\n    }\n    if(msg.length) {\n        self->_bottomUnreadLabel.text = msg;\n        [UIView beginAnimations:nil context:nil];\n        [UIView setAnimationDuration:0.1];\n        self->_bottomUnreadView.alpha = 1;\n        [UIView commitAnimations];\n    }\n}\n\n-(void)_addItem:(Event *)e eid:(NSTimeInterval)eid {\n    if(!e)\n        return;\n    @synchronized(self) {\n        [self->_lock lock];\n        e.groupEid = self->_currentCollapsedEid;\n        NSInteger insertPos = -1;\n        NSString *lastDay = nil;\n        NSDate *date = [NSDate dateWithTimeIntervalSince1970:e.time];\n        if(!e.timestamp) {\n            if(__24hrPref) {\n                if(__secondsPref)\n                    [self->_formatter setDateFormat:@\"HH:mm:ss\"];\n                else\n                    [self->_formatter setDateFormat:@\"HH:mm\"];\n            } else if(__secondsPref) {\n                [self->_formatter setDateFormat:@\"h:mm:ss a\"];\n            } else {\n                [self->_formatter setDateFormat:@\"h:mm a\"];\n            }\n            \n            e.timestamp = [self->_formatter stringFromDate:date];\n        }\n        if(!e.day) {\n            [self->_formatter setDateFormat:@\"DDD\"];\n            e.day = [self->_formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:e.time]];\n        }\n        if(e.groupMsg && !e.formattedMsg) {\n            e.formattedMsg = e.groupMsg;\n            e.formatted = nil;\n            e.height = 0;\n        }\n        \n        if(eid > _maxEid || _data.count == 0 || (eid == e.eid && [e compare:[self->_data objectAtIndex:self->_data.count - 1]] == NSOrderedDescending)) {\n            //Message at bottom\n            if(self->_data.count) {\n                lastDay = ((Event *)[self->_data objectAtIndex:self->_data.count - 1]).day;\n            }\n            self->_maxEid = eid;\n            [self->_data addObject:e];\n            insertPos = self->_data.count - 1;\n        } else if(self->_minEid > eid) {\n            //Message on top\n            if(self->_data.count > 1) {\n                lastDay = ((Event *)[self->_data objectAtIndex:1]).day;\n                if(![lastDay isEqualToString:e.day]) {\n                    //Insert above the dateline\n                    [self->_data insertObject:e atIndex:0];\n                    insertPos = 0;\n                } else {\n                    //Insert below the dateline\n                    [self->_data insertObject:e atIndex:1];\n                    insertPos = 1;\n                }\n            } else {\n                [self->_data insertObject:e atIndex:0];\n                insertPos = 0;\n            }\n        } else {\n            int i = 0;\n            for(Event *e1 in _data) {\n                if(e1.rowType != ROW_TIMESTAMP && [e compare:e1] == NSOrderedAscending && e.eid == eid) {\n                    //Insert the message\n                    if(i > 0 && ((Event *)[self->_data objectAtIndex:i - 1]).rowType != ROW_TIMESTAMP) {\n                        lastDay = ((Event *)[self->_data objectAtIndex:i - 1]).day;\n                        [self->_data insertObject:e atIndex:i];\n                        insertPos = i;\n                        break;\n                    } else {\n                        //There was a dateline above our insertion point\n                        lastDay = e1.day;\n                        if(![lastDay isEqualToString:e.day]) {\n                            if(i > 1) {\n                                lastDay = ((Event *)[self->_data objectAtIndex:i - 2]).day;\n                            } else {\n                                //We're above the first dateline, so we'll need to put a new one on top\n                                lastDay = nil;\n                            }\n                            [self->_data insertObject:e atIndex:i-1];\n                            insertPos = i-1;\n                        } else {\n                            //Insert below the dateline\n                            [self->_data insertObject:e atIndex:i];\n                            insertPos = i;\n                        }\n                        break;\n                    }\n                } else if(e1.rowType != ROW_TIMESTAMP && (e1.eid == eid || e1.groupEid == eid)) {\n                    //Replace the message\n                    lastDay = e.day;\n                    [self->_data removeObjectAtIndex:i];\n                    [self->_data insertObject:e atIndex:i];\n                    insertPos = i;\n                    break;\n                }\n                i++;\n            }\n        }\n        \n        if(insertPos == -1) {\n            CLS_LOG(@\"Couldn't insert EID: %f MSG: %@\", eid, e.formattedMsg);\n            [self->_lock unlock];\n            return;\n        }\n        \n        if(eid > _buffer.last_seen_eid && e.isHighlight && !__notificationsMuted) {\n            [self->_unseenHighlightPositions addObject:@(insertPos)];\n            [self->_unseenHighlightPositions sortUsingSelector:@selector(compare:)];\n        }\n        \n        if(eid < _minEid || _minEid == 0)\n            self->_minEid = eid;\n        \n        if(![lastDay isEqualToString:e.day]) {\n            [self->_formatter setDateFormat:@\"EEEE, MMMM dd, yyyy\"];\n            Event *d = [[Event alloc] init];\n            d.type = TYPE_TIMESTMP;\n            d.rowType = ROW_TIMESTAMP;\n            d.eid = eid;\n            d.groupEid = -1;\n            d.timestamp = [self->_formatter stringFromDate:date];\n            d.bgColor = [UIColor timestampBackgroundColor];\n            d.day = e.day;\n            [self->_data insertObject:d atIndex:insertPos++];\n        }\n        \n        if(insertPos < _data.count - 1) {\n            Event *next = [self->_data objectAtIndex:insertPos + 1];\n            if(![e isMessage] && e.rowType != ROW_LASTSEENEID) {\n                next.isHeader = (next.groupEid < 1 && [next isMessage]) && next.rowType != ROW_ME_MESSAGE;\n                next.height = 0;\n                [self->_rowCache removeObjectForKey:@(insertPos + 1)];\n            }\n            if(([next.type isEqualToString:e.type] && [next.from isEqualToString:e.from] && [[next avatar:__largeAvatarHeight].absoluteString isEqualToString:[e avatar:__largeAvatarHeight].absoluteString]) || e.rowType == ROW_ME_MESSAGE) {\n                if(e.isHeader)\n                    e.height = 0;\n                e.isHeader = NO;\n            }\n        }\n        \n        if(insertPos > 0 && e.parent == 0) {\n            Event *prev = [self->_data objectAtIndex:insertPos - 1];\n            if(prev.rowType == ROW_LASTSEENEID)\n                prev = [self->_data objectAtIndex:insertPos - 2];\n            BOOL wasHeader = e.isHeader;\n            NSString *prevAvatar = [prev avatar:__largeAvatarHeight].absoluteString;\n            NSString *avatar = [e avatar:__largeAvatarHeight].absoluteString;\n            BOOL newAvatar = NO;\n            if(prevAvatar || avatar) {\n                newAvatar = ![avatar isEqualToString:prevAvatar];\n            }\n            e.isHeader = !__chatOneLinePref && (e.groupEid < 1 && [e isMessage] && (![prev.type isEqualToString:e.type] || ![prev.from isEqualToString:e.from] || newAvatar)) && e.rowType != ROW_ME_MESSAGE;\n            if(wasHeader != e.isHeader)\n                e.height = 0;\n        }\n        \n        e.row = insertPos;\n        \n        [self->_lock unlock];\n    }\n}\n\n-(Buffer *)buffer {\n    return _buffer;\n}\n\n-(void)setBuffer:(Buffer *)buffer {\n    self->_ready = NO;\n    [self->_heartbeatTimer invalidate];\n    self->_heartbeatTimer = nil;\n    [self->_scrollTimer performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:YES];\n    self->_scrollTimer = nil;\n    self->_requestingBacklog = NO;\n    if(self->_buffer && _buffer.scrolledUp) {\n        [self->_lock lock];\n        int row = 0;\n        NSInteger toprow = [self->_tableView indexPathForRowAtPoint:CGPointMake(0,_buffer.savedScrollOffset)].row;\n        if(self->_tableView.tableHeaderView != nil)\n            row++;\n        for(Event *event in _data) {\n            if((event.rowType == ROW_LASTSEENEID && [[EventsDataSource sharedInstance] unreadStateForBuffer:self->_buffer.bid lastSeenEid:self->_buffer.last_seen_eid type:self->_buffer.type] == 0) || event.rowType == ROW_BACKLOG) {\n                if(toprow > row) {\n                    self->_buffer.savedScrollOffset -= 26;\n                }\n            }\n            if(++row > toprow)\n                break;\n        }\n        [self->_lock unlock];\n    }\n    if(self->_buffer && buffer.bid != self->_buffer.bid) {\n        for(Event *event in [[EventsDataSource sharedInstance] eventsForBuffer:buffer.bid]) {\n            if(event.rowType == ROW_LASTSEENEID) {\n                [[EventsDataSource sharedInstance] removeEvent:event.eid buffer:event.bid];\n                break;\n            }\n            event.formatted = nil;\n            event.timestamp = nil;\n        }\n        self->_topUnreadView.alpha = 0;\n        self->_bottomUnreadView.alpha = 0;\n        @synchronized (self->_rowCache) {\n            [self->_rowCache removeAllObjects];\n        }\n        [self->_expandedSectionEids removeAllObjects];\n        [self->_urlHandler clearFileIDs];\n        self->_bottomRow = -1;\n        [[ImageCache sharedInstance] clear];\n    }\n    self->_buffer = buffer;\n    if(buffer)\n        self->_server = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n    else\n        self->_server = nil;\n    self->_earliestEid = 0;\n    [self refresh];\n}\n\n- (void)_scrollToBottom {\n    @try {\n        [self->_lock lock];\n        [self->_scrollTimer performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:YES];\n        self->_scrollTimer = nil;\n        if(self->_data.count) {\n            [self->_tableView reloadData];\n            [self->_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self->_data.count - 1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];\n            if([UIApplication sharedApplication].applicationState == UIApplicationStateActive)\n                [self scrollViewDidScroll:self->_tableView];\n        }\n        self->_buffer.scrolledUp = NO;\n        self->_buffer.scrolledUpFrom = -1;\n        [self->_lock unlock];\n    } @catch (NSException * e) {\n        CLS_LOG(@\"Failed to scroll down, will retry shortly. Exception: %@\", e);\n        [self performSelectorOnMainThread:@selector(scrollToBottom) withObject:nil waitUntilDone:YES];\n    }\n}\n\n- (void)scrollToBottom {\n    if(![NSThread currentThread].isMainThread) {\n        CLS_LOG(@\"scrollToBottom called on wrong thread\");\n        [self performSelectorOnMainThread:@selector(scrollToBottom) withObject:nil waitUntilDone:YES];\n        return;\n    }\n    [self->_scrollTimer invalidate];\n    \n    self->_scrollTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(_scrollToBottom) userInfo:nil repeats:NO];\n}\n\n- (void)reloadData {\n    @synchronized(self) {\n        [self->_reloadTimer invalidate];\n        \n        self->_reloadTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(_reloadData) userInfo:nil repeats:NO];\n    }\n}\n\n- (void)_reloadData {\n    @synchronized(self) {\n        CGPoint offset = self->_tableView.contentOffset;\n        [self->_tableView reloadData];\n        if(self->_buffer.scrolledUp) {\n            self->_tableView.contentOffset = offset;\n        } else {\n            [self _scrollToBottom];\n        }\n    }\n}\n\n- (void)reloadForEvent:(Event *)e {\n    CGFloat h = self->_tableView.contentSize.height;\n    [self _reloadData];\n    [self->_tableView visibleCells];\n    NSInteger bottom = self->_tableView.indexPathsForVisibleRows.lastObject.row;\n    if(!_buffer.scrolledUp) {\n        [self _scrollToBottom];\n    } else if(e.row < bottom) {\n        self->_tableView.contentOffset = CGPointMake(0, _tableView.contentOffset.y + (self->_tableView.contentSize.height - h));\n    }\n}\n\n- (void)refresh {\n    @synchronized(self) {\n        NSDate *start = [NSDate date];\n        if(self.tableView.bounds.size.width != [EventsDataSource sharedInstance].widthForHeightCache)\n            [[EventsDataSource sharedInstance] clearHeightCache];\n        [EventsDataSource sharedInstance].widthForHeightCache = self.tableView.bounds.size.width;\n        [self->_reloadTimer invalidate];\n        self->_urlHandler.window = self->_tableView.window;\n\n        if([[NSUserDefaults standardUserDefaults] boolForKey:@\"tabletMode\"]) {\n            self->_stickyAvatarXOffsetConstraint.constant = 20;\n        } else {\n            self->_stickyAvatarXOffsetConstraint.constant = 20 + self.slidingViewController.view.window.safeAreaInsets.left;\n        }\n\n        __24hrPref = NO;\n        __secondsPref = NO;\n        __timeLeftPref = NO;\n        __nickColorsPref = NO;\n        __colorizeMentionsPref = NO;\n        __hideJoinPartPref = NO;\n        __expandJoinPartPref = NO;\n        __avatarsOffPref = NO;\n        __chatOneLinePref = NO;\n        __norealnamePref = NO;\n        __monospacePref = NO;\n        __disableInlineFilesPref = NO;\n        __compact = NO;\n        __disableBigEmojiPref = NO;\n        __disableCodeSpanPref = NO;\n        __disableCodeBlockPref = NO;\n        __disableQuotePref = NO;\n        __inlineMediaPref = NO;\n        __avatarImages = YES;\n        __replyCollapsePref = NO;\n        __notificationsMuted = NO;\n        __noColor = NO;\n        NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n        if(prefs) {\n            __monospacePref = [[prefs objectForKey:@\"font\"] isEqualToString:@\"mono\"];\n            __nickColorsPref = [[prefs objectForKey:@\"nick-colors\"] boolValue];\n            __colorizeMentionsPref = [[prefs objectForKey:@\"mention-colors\"] boolValue];\n            __secondsPref = [[prefs objectForKey:@\"time-seconds\"] boolValue];\n            __24hrPref = [[prefs objectForKey:@\"time-24hr\"] boolValue];\n            __timeLeftPref = [[NSUserDefaults standardUserDefaults] boolForKey:@\"time-left\"];\n            __avatarsOffPref = [[NSUserDefaults standardUserDefaults] boolForKey:@\"avatars-off\"];\n            __chatOneLinePref = [[NSUserDefaults standardUserDefaults] boolForKey:@\"chat-oneline\"];\n            if(!__chatOneLinePref && !__avatarsOffPref)\n                __timeLeftPref = NO;\n            __norealnamePref = [[NSUserDefaults standardUserDefaults] boolForKey:@\"chat-norealname\"];\n            __compact = [[prefs objectForKey:@\"ascii-compact\"] boolValue];\n            __disableBigEmojiPref = [[prefs objectForKey:@\"emoji-nobig\"] boolValue];\n            __disableCodeSpanPref = [[prefs objectForKey:@\"chat-nocodespan\"] boolValue];\n            __disableCodeBlockPref = [[prefs objectForKey:@\"chat-nocodeblock\"] boolValue];\n            __disableQuotePref = [[prefs objectForKey:@\"chat-noquote\"] boolValue];\n            __avatarImages = [[NSUserDefaults standardUserDefaults] boolForKey:@\"avatarImages\"];\n            __showDeleted = [[prefs objectForKey:@\"chat-deleted-show\"] boolValue];\n\n            __hideJoinPartPref = [[prefs objectForKey:@\"hideJoinPart\"] boolValue];\n            if(__hideJoinPartPref) {\n                NSDictionary *enableMap;\n                \n                if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                    enableMap = [prefs objectForKey:@\"channel-showJoinPart\"];\n                } else {\n                    enableMap = [prefs objectForKey:@\"buffer-showJoinPart\"];\n                }\n                \n                if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                    __hideJoinPartPref = NO;\n            } else {\n                NSDictionary *disableMap;\n                \n                if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                    disableMap = [prefs objectForKey:@\"channel-hideJoinPart\"];\n                } else {\n                    disableMap = [prefs objectForKey:@\"buffer-hideJoinPart\"];\n                }\n                \n                if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                    __hideJoinPartPref = YES;\n            }\n\n            \n            __expandJoinPartPref = [[prefs objectForKey:@\"expandJoinPart\"] boolValue];\n            if(__expandJoinPartPref) {\n                NSDictionary *collapseMap;\n                \n                if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                    collapseMap = [prefs objectForKey:@\"channel-collapseJoinPart\"];\n                } else {\n                    collapseMap = [prefs objectForKey:@\"buffer-collapseJoinPart\"];\n                }\n                \n                if((collapseMap && [[collapseMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue]))\n                    __expandJoinPartPref = NO;\n            } else {\n                NSDictionary *expandMap;\n                \n                if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                    expandMap = [prefs objectForKey:@\"channel-expandJoinPart\"];\n                } else if([self->_buffer.type isEqualToString:@\"console\"]) {\n                    expandMap = [prefs objectForKey:@\"buffer-expandDisco\"];\n                } else {\n                    expandMap = [prefs objectForKey:@\"buffer-expandJoinPart\"];\n                }\n                \n                if((expandMap && [[expandMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue]))\n                    __expandJoinPartPref = YES;\n            }\n            NSDictionary *disableFilesMap;\n            \n            if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                disableFilesMap = [prefs objectForKey:@\"channel-files-disableinline\"];\n            } else {\n                disableFilesMap = [prefs objectForKey:@\"buffer-files-disableinline\"];\n            }\n            \n            if([[prefs objectForKey:@\"files-disableinline\"] boolValue] || (disableFilesMap && [[disableFilesMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue]))\n                __disableInlineFilesPref = YES;\n\n            __inlineMediaPref = [[prefs objectForKey:@\"inlineimages\"] boolValue];\n            if(__inlineMediaPref) {\n                NSDictionary *disableMap;\n                \n                if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                    disableMap = [prefs objectForKey:@\"channel-inlineimages-disable\"];\n                } else {\n                    disableMap = [prefs objectForKey:@\"buffer-inlineimages-disable\"];\n                }\n                \n                if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                    __inlineMediaPref = NO;\n            } else {\n                NSDictionary *enableMap;\n                \n                if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                    enableMap = [prefs objectForKey:@\"channel-inlineimages\"];\n                } else {\n                    enableMap = [prefs objectForKey:@\"buffer-inlineimages\"];\n                }\n                \n                if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                    __inlineMediaPref = YES;\n            }\n            \n            if([[NSUserDefaults standardUserDefaults] boolForKey:@\"inlineWifiOnly\"] && ![NetworkConnection sharedInstance].isWifi) {\n                __disableInlineFilesPref = YES;\n                __inlineMediaPref = NO;\n            }\n            \n            NSDictionary *replyCollapseMap;\n            \n            if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                replyCollapseMap = [prefs objectForKey:@\"channel-reply-collapse\"];\n            } else {\n                replyCollapseMap = [prefs objectForKey:@\"buffer-reply-collapse\"];\n            }\n            \n            if([[prefs objectForKey:@\"reply-collapse\"] boolValue] || (replyCollapseMap && [[replyCollapseMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])) {\n                __replyCollapsePref = YES;\n            }\n            \n            if(self->_msgid)\n                __replyCollapsePref = NO;\n            \n            __notificationsMuted = [[prefs objectForKey:@\"notifications-mute\"] boolValue];\n            if(__notificationsMuted) {\n                NSDictionary *disableMap;\n                \n                if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                    disableMap = [prefs objectForKey:@\"channel-notifications-mute-disable\"];\n                } else {\n                    disableMap = [prefs objectForKey:@\"buffer-notifications-mute-disable\"];\n                }\n                \n                if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                    __notificationsMuted = NO;\n            } else {\n                NSDictionary *enableMap;\n                \n                if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                    enableMap = [prefs objectForKey:@\"channel-notifications-mute\"];\n                } else {\n                    enableMap = [prefs objectForKey:@\"buffer-notifications-mute\"];\n                }\n                \n                if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                    __notificationsMuted = YES;\n            }\n            \n            __noColor = [[prefs objectForKey:@\"chat-nocolor\"] boolValue];\n            if(__noColor) {\n                NSDictionary *enableMap;\n                \n                if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                    enableMap = [prefs objectForKey:@\"channel-chat-color\"];\n                } else {\n                    enableMap = [prefs objectForKey:@\"buffer-chat-color\"];\n                }\n                \n                if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                    __noColor = NO;\n            } else {\n                NSDictionary *disableMap;\n                \n                if([self->_buffer.type isEqualToString:@\"channel\"]) {\n                    disableMap = [prefs objectForKey:@\"channel-chat-nocolor\"];\n                } else {\n                    disableMap = [prefs objectForKey:@\"buffer-chat-nocolor\"];\n                }\n                \n                if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue])\n                    __noColor = YES;\n            }\n        }\n#ifdef DEBUG\n        if([[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"]) {\n            __24hrPref = NO;\n            __secondsPref = NO;\n            __timeLeftPref = NO;\n            __nickColorsPref = YES;\n            __colorizeMentionsPref = YES;\n            __hideJoinPartPref = NO;\n            __expandJoinPartPref = NO;\n            __avatarsOffPref = NO;\n            __chatOneLinePref = NO;\n            __norealnamePref = NO;\n            __monospacePref = [[NSProcessInfo processInfo].arguments containsObject:@\"-mono\"];\n            __disableInlineFilesPref = NO;\n            __compact = NO;\n            __disableBigEmojiPref = NO;\n            __disableCodeSpanPref = NO;\n            __disableCodeBlockPref = NO;\n            __disableQuotePref = NO;\n            __inlineMediaPref = YES;\n            __avatarImages = YES;\n            __replyCollapsePref = NO;\n        }\n#endif\n        __largeAvatarHeight = MIN(32, roundf(FONT_SIZE * 2) + (__compact ? 1 : 6));\n        if(__monospacePref)\n            self->_groupIndent = @\"  \";\n        else\n            self->_groupIndent = @\"    \";\n        self->_tableView.backgroundColor = [UIColor contentBackgroundColor];\n        self->_headerView.backgroundColor = [UIColor contentBackgroundColor];\n        self->_backlogFailedView.backgroundColor = [UIColor contentBackgroundColor];\n        [self->_loadMoreBacklog setTitleColor:[UIColor isDarkTheme]?[UIColor navBarSubheadingColor]:[UIColor unreadBlueColor] forState:UIControlStateNormal];\n        [self->_loadMoreBacklog setTitleShadowColor:[UIColor contentBackgroundColor] forState:UIControlStateNormal];\n        self->_loadMoreBacklog.backgroundColor = [UIColor contentBackgroundColor];\n        \n        self->_linkAttributes = [UIColor linkAttributes];\n        self->_lightLinkAttributes = [UIColor lightLinkAttributes];\n        \n        __socketClosedBackgroundImage = nil;\n        [UIColor socketClosedBackgroundColor];\n        \n        [self->_lock lock];\n        [self->_scrollTimer performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:YES];\n        self->_scrollTimer = nil;\n        self->_ready = NO;\n        NSInteger oldPosition = (self->_requestingBacklog && _data.count && [self->_tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self->_tableView.bounds, _tableView.contentInset)].count)?[[[self->_tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self->_tableView.bounds, _tableView.contentInset)] objectAtIndex: 0] row]:-1;\n        NSTimeInterval backlogEid = (self->_requestingBacklog && _data.count && oldPosition < _data.count)?[[self->_data objectAtIndex:oldPosition] groupEid]-1:0;\n        if(backlogEid < 1)\n            backlogEid = (self->_requestingBacklog && _data.count && oldPosition < _data.count)?[[self->_data objectAtIndex:oldPosition] eid]-1:0;\n        \n        [self->_data removeAllObjects];\n        self->_minEid = self->_maxEid = self->_earliestEid = self->_newMsgs = self->_newHighlights = 0;\n        self->_lastSeenEidPos = -1;\n        self->_currentCollapsedEid = 0;\n        self->_lastCollpasedDay = @\"\";\n        [self->_collapsedEvents clear];\n        self->_collapsedEvents.server = self->_server;\n        [self->_unseenHighlightPositions removeAllObjects];\n        self->_hiddenAvatarRow = -1;\n        self->_stickyAvatar.hidden = YES;\n        __smallAvatarHeight = roundf(FONT_SIZE) + 2;\n        self->_msgids = [[NSMutableDictionary alloc] init];\n        \n        if(!_buffer) {\n            [self->_lock unlock];\n            self->_tableView.tableHeaderView = nil;\n            [self->_tableView reloadData];\n            return;\n        }\n        \n        if(self->_conn.state == kIRCCloudStateConnected)\n            [[NetworkConnection sharedInstance] cancelIdleTimer]; //This may take a while\n        \n        UIFont *f = __monospacePref?[ColorFormatter monoTimestampFont]:[ColorFormatter timestampFont];\n        __timestampWidth = [@\"88:88\" sizeWithAttributes:@{NSFontAttributeName:f}].width;\n        if(__secondsPref)\n            __timestampWidth += [@\":88\" sizeWithAttributes:@{NSFontAttributeName:f}].width;\n        if(!__24hrPref)\n            __timestampWidth += [@\" AM\" sizeWithAttributes:@{NSFontAttributeName:f}].width;\n        __timestampWidth += 8;\n        \n        NSArray *events = [[EventsDataSource sharedInstance] eventsForBuffer:self->_buffer.bid];\n        _shouldAutoFetch = !_requestingBacklog && events.count < 50;\n        \n        if(events.count) {\n            NSMutableDictionary *uuids = [[NSMutableDictionary alloc] init];\n            for(int i = 0; i < events.count; i++) {\n                Event *e = [events objectAtIndex:i];\n                Event *next = (i < events.count - 1)?[events objectAtIndex:i+1]:nil;\n                if(e.childEventCount) {\n                    e.formatted = nil;\n                    e.formattedMsg = nil;\n                }\n                e.replyCount = 0;\n                NSString *type = next.type;\n                if(next && _currentCollapsedEid != -1 && ![_expandedSectionEids objectForKey:@(_currentCollapsedEid)] &&\n                   ([type isEqualToString:@\"joined_channel\"] || [type isEqualToString:@\"parted_channel\"] || [type isEqualToString:@\"nickchange\"] || [type isEqualToString:@\"quit\"] || [type isEqualToString:@\"user_channel_mode\"])) {\n                    NSDate *date = [NSDate dateWithTimeIntervalSince1970:next.time];\n                    [self insertEvent:e backlog:YES nextIsGrouped:[_lastCollpasedDay isEqualToString:[self->_formatter stringFromDate:date]]];\n                } else {\n                    [self insertEvent:e backlog:YES nextIsGrouped:NO];\n                }\n                [uuids setObject:@(YES) forKey:e.UUID];\n            }\n            for(NSString *uuid in _rowCache.allKeys) {\n                if(![uuids objectForKey:uuid])\n                    [self->_rowCache removeObjectForKey:uuid];\n            }\n            self->_tableView.tableHeaderView = nil;\n        }\n        \n        int row = 0;\n        for(Event *e in _data) {\n            if(e.formattedMsg && !e.formatted) {\n                [self _format:e];\n                [self tableView:self.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0]];\n            }\n            row++;\n        }\n        \n        if(backlogEid > 0) {\n            for(NSInteger i = self->_data.count-1 ; i >= 0; i--) {\n                Event *e = [self->_data objectAtIndex:i];\n                if(e.eid == backlogEid)\n                    backlogEid--;\n            }\n            \n            Event *e = [[Event alloc] init];\n            e.eid = backlogEid;\n            e.type = TYPE_BACKLOG;\n            e.rowType = ROW_BACKLOG;\n            e.formattedMsg = nil;\n            e.bgColor = [UIColor contentBackgroundColor];\n            [self _addItem:e eid:backlogEid];\n            e.timestamp = nil;\n        }\n        \n        if(self->_buffer.last_seen_eid == 0 && _data.count > 1) {\n            self->_lastSeenEidPos = 1;\n        } else if((self->_minEid > 0 && _minEid >= self->_buffer.last_seen_eid) || (self->_data.count == 0 && _buffer.last_seen_eid > 0)) {\n            self->_lastSeenEidPos = 0;\n        } else {\n            Event *e = [[Event alloc] init];\n            e.cid = self->_buffer.cid;\n            e.bid = self->_buffer.bid;\n            e.type = TYPE_LASTSEENEID;\n            e.rowType = ROW_LASTSEENEID;\n            e.formattedMsg = nil;\n            e.bgColor = [UIColor contentBackgroundColor];\n            e.timestamp = @\"New Messages\";\n            self->_lastSeenEidPos = self->_data.count - 1;\n            NSEnumerator *i = [self->_data reverseObjectEnumerator];\n            Event *event = [i nextObject];\n            while(event) {\n                if((event.eid <= self->_buffer.last_seen_eid || (event.parent > 0 && event.parent <= self->_buffer.last_seen_eid)) && event.rowType != ROW_LASTSEENEID)\n                    break;\n                e.eid = event.eid - 1;\n                event = [i nextObject];\n                self->_lastSeenEidPos--;\n            }\n            if(self->_lastSeenEidPos != self->_data.count - 1 && !event.isSelf && !event.pending) {\n                if(self->_lastSeenEidPos > 0 && [[self->_data objectAtIndex:self->_lastSeenEidPos - 1] rowType] == ROW_TIMESTAMP)\n                    self->_lastSeenEidPos--;\n                if(self->_lastSeenEidPos > 0) {\n                    for(Event *event in events) {\n                        if(event.rowType == ROW_LASTSEENEID) {\n                            [[EventsDataSource sharedInstance] removeEvent:event.eid buffer:event.bid];\n                            [self->_data removeObject:event];\n                            break;\n                        }\n                    }\n                    [[EventsDataSource sharedInstance] addEvent:e];\n                    [self _addItem:e eid:e.eid];\n                    e.groupEid = -1;\n                }\n            } else {\n                self->_lastSeenEidPos = -1;\n            }\n        }\n        \n        self->_backlogFailedView.frame = self->_headerView.frame = CGRectMake(0,0,_headerView.frame.size.width, 60);\n        \n        [self->_tableView reloadData];\n        \n        if(events.count)\n            self->_earliestEid = ((Event *)[events objectAtIndex:0]).eid;\n        if(events.count && _earliestEid > _buffer.min_eid && _buffer.min_eid > 0 && _conn.state == kIRCCloudStateConnected && _conn.ready && _tableView.contentSize.height > _tableView.bounds.size.height) {\n            self->_tableView.tableHeaderView = self->_headerView;\n        } else if((!_data.count || _earliestEid > _buffer.min_eid) && _buffer.min_eid > 0 && _conn.state == kIRCCloudStateConnected && _conn.ready && !(self->_msgid && [self->_msgids objectForKey:self->_msgid])) {\n            self->_tableView.tableHeaderView = self->_backlogFailedView;\n        } else {\n            self->_tableView.tableHeaderView = nil;\n        }\n        if(_earliestEid == _buffer.min_eid)\n            self->_shouldAutoFetch = NO;\n        \n        @try {\n            if(self->_requestingBacklog && backlogEid > 0 && _buffer.scrolledUp) {\n                int markerPos = -1;\n                for(Event *e in _data) {\n                    if(e.eid == backlogEid)\n                        break;\n                    markerPos++;\n                }\n                if(markerPos < [self->_tableView numberOfRowsInSection:0])\n                    [self->_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:markerPos inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];\n            } else if(self->_eidToOpen > 0) {\n                if(self->_eidToOpen <= self->_maxEid) {\n                    int i = 0;\n                    for(Event *e in _data) {\n                        if(e.eid == self->_eidToOpen) {\n                            [self->_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:NO];\n                            self->_buffer.scrolledUpFrom = [[self->_data objectAtIndex:[[[self->_tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self->_tableView.bounds, _tableView.contentInset)] lastObject] row]] eid];\n                            break;\n                        }\n                        i++;\n                    }\n                    self->_eidToOpen = -1;\n                } else {\n                    if(!_buffer.scrolledUp)\n                        self->_buffer.scrolledUpFrom = -1;\n                }\n            } else if(self->_buffer.scrolledUp && _buffer.savedScrollOffset > 0) {\n                if((self->_buffer.savedScrollOffset + _tableView.tableHeaderView.bounds.size.height) <= _tableView.contentSize.height - UIEdgeInsetsInsetRect(_tableView.bounds, _tableView.contentInset).size.height) {\n                    self->_tableView.contentOffset = CGPointMake(0, (self->_buffer.savedScrollOffset + _tableView.tableHeaderView.bounds.size.height));\n                } else {\n                    [self _scrollToBottom];\n                    [self scrollToBottom];\n                }\n            } else if(!_buffer.scrolledUp || (self->_data.count && _scrollTimer)) {\n                [self _scrollToBottom];\n                [self scrollToBottom];\n            }\n        } @catch (NSException *e) {\n            CLS_LOG(@\"Unable to set scroll position: %@\", e);\n        }\n        \n        if(self->_data.count == 0 && _buffer.bid != -1 && _buffer.min_eid > 0 && _conn.state == kIRCCloudStateConnected && [UIApplication sharedApplication].applicationState == UIApplicationStateActive && _conn.ready && !_requestingBacklog) {\n            self->_tableView.tableHeaderView = self->_backlogFailedView;\n        }\n        \n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            NSArray *rows = [self->_tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self->_tableView.bounds, self->_tableView.contentInset)];\n            if(self->_data.count && rows.count) {\n                NSInteger firstRow = [[rows objectAtIndex:0] row];\n                NSInteger lastRow = [[rows lastObject] row];\n                Event *e = ((self->_lastSeenEidPos+1) < self->_data.count)?[self->_data objectAtIndex:self->_lastSeenEidPos+1]:nil;\n                if(e && ((self->_lastSeenEidPos > 0 && firstRow > self->_lastSeenEidPos) || self->_lastSeenEidPos == 0) && e.eid >= self->_buffer.last_seen_eid) {\n                    if(self->_topUnreadView.alpha == 0) {\n                        [UIView beginAnimations:nil context:nil];\n                        [UIView setAnimationDuration:0.1];\n                        self->_topUnreadView.alpha = 1;\n                        [UIView commitAnimations];\n                    }\n                    [self updateTopUnread:firstRow];\n                } else if(lastRow < self->_lastSeenEidPos) {\n                    for(Event *e in self->_data) {\n                        if(self->_buffer.last_seen_eid > 0 && e.eid > self->_buffer.last_seen_eid && !e.isSelf && e.rowType != ROW_LASTSEENEID && [e isImportant:self->_buffer.type]) {\n                            self->_newMsgs++;\n                            if(e.isHighlight && !__notificationsMuted)\n                                self->_newHighlights++;\n                        }\n                    }\n                } else {\n                    [UIView beginAnimations:nil context:nil];\n                    [UIView setAnimationDuration:0.1];\n                    self->_topUnreadView.alpha = 0;\n                    [UIView commitAnimations];\n                }\n                self->_requestingBacklog = NO;\n            } else if(self->_earliestEid > self->_buffer.last_seen_eid) {\n                if(self->_topUnreadView.alpha == 0) {\n                    [UIView beginAnimations:nil context:nil];\n                    [UIView setAnimationDuration:0.1];\n                    self->_topUnreadView.alpha = 1;\n                    [UIView commitAnimations];\n                }\n                [self updateTopUnread:-1];\n            }\n            \n            [self updateUnread];\n            self->_ready = YES;\n            [self scrollViewDidScroll:self->_tableView];\n            [self->_tableView flashScrollIndicators];\n            \n            if((self->_buffer.deferred || (self->_shouldAutoFetch && (rows.count == 0 || [[rows objectAtIndex:0] row] == 0))) && self->_conn.state == kIRCCloudStateConnected && self->_conn.ready) {\n                [self loadMoreBacklogButtonPressed:nil];\n            }\n            \n            CLS_LOG(@\"Refresh finished in %f seconds\", [start timeIntervalSinceNow] * -1.0);\n        }];\n    }\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n    @synchronized (self->_rowCache) {\n        [self->_rowCache removeAllObjects];\n    }\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    [self->_lock lock];\n    NSInteger count = self->_data.count;\n    [self->_lock unlock];\n    return count;\n}\n\n- (void)_format:(Event *)e {\n    @synchronized (e) {\n        NSArray *links;\n        [self->_lock lock];\n        if(!__disableBigEmojiPref && ([e.type isEqualToString:@\"buffer_msg\"] || [e.type isEqualToString:@\"notice\"])) {\n            NSMutableString *msg = [[e.msg stripIRCFormatting] mutableCopy];\n            if(msg) {\n                [ColorFormatter emojify:msg];\n                e.isEmojiOnly = [msg isEmojiOnly];\n            }\n        } else {\n            e.isEmojiOnly = NO;\n        }\n        if(e.from.length)\n            e.formattedNick = [ColorFormatter format:[self->_collapsedEvents formatNick:e.fromNick mode:e.fromMode colorize:(__nickColorsPref && !e.isSelf) defaultColor:[UIColor isDarkTheme]?@\"ffffff\":@\"142b43\" displayName:e.from] defaultColor:e.color mono:__monospacePref linkify:NO server:nil links:nil];\n        if([e.realname isKindOfClass:[NSString class]] && e.realname.length) {\n            e.formattedRealname = [ColorFormatter format:e.realname.stripIRCColors defaultColor:[UIColor collapsedRowTextColor] mono:__monospacePref linkify:YES server:self->_server links:&links];\n            e.realnameLinks = links;\n            links = nil;\n        }\n        if(!__disableQuotePref && e.rowType == ROW_MESSAGE && e.formattedMsg.length > 1 && [e.formattedMsg isBlockQuote]) {\n            e.formattedMsg = [e.formattedMsg substringFromIndex:1];\n            e.mentionOffset--;\n            e.isQuoted = YES;\n        } else {\n            e.isQuoted = NO;\n        }\n        NSString *formattedMsg = e.formattedMsg;\n        NSString *formattedPrefix = e.formattedPrefix;\n        if(e.rowType == ROW_FAILED || (e.groupEid < 0 && (e.from.length || e.rowType == ROW_ME_MESSAGE) && !__avatarsOffPref && (__chatOneLinePref || e.rowType == ROW_ME_MESSAGE) && e.rowType != ROW_THUMBNAIL && e.rowType != ROW_FILE && e.parent == 0)) {\n            if(formattedPrefix.length)\n                formattedPrefix = [NSString stringWithFormat:@\"\\u2001\\u2005%@\",formattedPrefix];\n            else\n                formattedMsg = [NSString stringWithFormat:@\"\\u2001\\u2005%@\",formattedMsg];\n        }\n\n        e.formatted = [ColorFormatter format:formattedMsg defaultColor:e.color mono:__monospacePref || e.monospace linkify:e.linkify server:self->_server links:&links largeEmoji:e.isEmojiOnly mentions:[e.entities objectForKey:@\"mentions\"] colorizeMentions:__colorizeMentionsPref mentionOffset:e.mentionOffset + (formattedMsg.length - e.formattedMsg.length) mentionData:[e.entities objectForKey:@\"mention_data\"] stripColors:__noColor];\n        \n        if(formattedPrefix.length) {\n            NSUInteger linksOffset = 0;\n            if(![formattedPrefix hasSuffix:@\" \"])\n                formattedPrefix = [formattedPrefix stringByAppendingString:@\" \"];\n            NSMutableAttributedString *prefix = [ColorFormatter format:formattedPrefix defaultColor:e.color mono:__monospacePref || e.monospace linkify:NO server:nil links:nil].mutableCopy;\n            linksOffset = prefix.length;\n            [prefix appendAttributedString:e.formatted];\n            e.formatted = prefix;\n            \n            if(linksOffset > 0 && links.count > 0) {\n                NSMutableArray *mutableLinks = links.mutableCopy;\n                for(int i = 0; i < mutableLinks.count; i++) {\n                    NSTextCheckingResult *r = [mutableLinks objectAtIndex:i];\n                    if(r.resultType == NSTextCheckingTypeLink) {\n                        r = [NSTextCheckingResult linkCheckingResultWithRange:NSMakeRange(r.range.location + linksOffset, r.range.length) URL:r.URL];\n                        [mutableLinks setObject:r atIndexedSubscript:i];\n                    } else if(r.resultType == NSTextCheckingTypeRegularExpression) {\n                        NSRangePointer ranges = malloc(r.numberOfRanges * sizeof(NSRange));\n                        for(int j = 0; j < r.numberOfRanges; j++) {\n                            NSRange range = [r rangeAtIndex:j];\n                            range.location += linksOffset;\n                            ranges[j] = range;\n                        }\n                        r = [NSTextCheckingResult regularExpressionCheckingResultWithRanges:ranges count:r.numberOfRanges regularExpression:r.regularExpression];\n                        [mutableLinks setObject:r atIndexedSubscript:i];\n                        free(ranges);\n                    }\n                }\n                links = mutableLinks;\n            }\n        }\n\n        if([e.entities objectForKey:@\"files\"] || [e.entities objectForKey:@\"pastes\"]) {\n            NSMutableArray *mutableLinks = links.mutableCopy;\n            for(int i = 0; i < mutableLinks.count; i++) {\n                NSTextCheckingResult *r = [mutableLinks objectAtIndex:i];\n                if(r.resultType == NSTextCheckingTypeLink) {\n                    for(NSDictionary *file in [e.entities objectForKey:@\"files\"]) {\n                        NSString *url = [[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":[file objectForKey:@\"id\"]} error:nil];\n                        if(url && ([r.URL.absoluteString isEqualToString:url] || [r.URL.absoluteString hasPrefix:[url stringByAppendingString:@\"/\"]])) {\n                            [_urlHandler addFileID:[file objectForKey:@\"id\"] URL:r.URL];\n                        }\n                    }\n                    for(NSDictionary *paste in [e.entities objectForKey:@\"pastes\"]) {\n                        NSString *url = [[NetworkConnection sharedInstance].pasteURITemplate relativeStringWithVariables:@{@\"id\":[paste objectForKey:@\"id\"]} error:nil];\n                        if(url && ([r.URL.absoluteString isEqualToString:url] || [r.URL.absoluteString hasPrefix:[url stringByAppendingString:@\"/\"]])) {\n                            r = [NSTextCheckingResult linkCheckingResultWithRange:r.range URL:[NSURL URLWithString:[NSString stringWithFormat:@\"irccloud-paste-%@?id=%@\", url, [paste objectForKey:@\"id\"]]]];\n                            [mutableLinks setObject:r atIndexedSubscript:i];\n                        }\n                    }\n                }\n            }\n            links = mutableLinks;\n        }\n        e.links = links;\n        \n        if(e.from.length && e.msg.length) {\n            e.accessibilityLabel = [NSString stringWithFormat:@\"Message from %@: \", e.from];\n            e.accessibilityValue = [[[ColorFormatter format:e.msg defaultColor:[UIColor blackColor] mono:NO linkify:NO server:nil links:nil] string] stringByAppendingFormat:@\", at %@\", e.timestamp];\n        } else if([e.type isEqualToString:@\"buffer_me_msg\"]) {\n            e.accessibilityLabel = @\"Action: \";\n            e.accessibilityValue = [NSString stringWithFormat:@\"%@ %@, at: %@\", e.nick, [[ColorFormatter format:e.msg defaultColor:[UIColor blackColor] mono:NO linkify:NO server:nil links:nil] string], e.timestamp];\n        } else if(e.rowType == ROW_MESSAGE || e.rowType == ROW_ME_MESSAGE) {\n            NSMutableString *s = [[[ColorFormatter format:e.formattedMsg defaultColor:[UIColor blackColor] mono:NO linkify:NO server:nil links:nil] string] mutableCopy];\n            if(s.length > 1) {\n                [s replaceOccurrencesOfString:@\"→\" withString:@\"\" options:0 range:NSMakeRange(0, 1)];\n                [s replaceOccurrencesOfString:@\"←\" withString:@\"\" options:0 range:NSMakeRange(0, 1)];\n                [s replaceOccurrencesOfString:@\"⇐\" withString:@\"\" options:0 range:NSMakeRange(0, 1)];\n                [s replaceOccurrencesOfString:@\"•\" withString:@\"\" options:0 range:NSMakeRange(0, s.length)];\n                [s replaceOccurrencesOfString:@\"↔\" withString:@\"\" options:0 range:NSMakeRange(0, 1)];\n                \n                if([e.type hasSuffix:@\"nickchange\"])\n                    [s replaceOccurrencesOfString:@\"→\" withString:@\"changed their nickname to\" options:0 range:NSMakeRange(0, s.length)];\n            }\n            [s appendFormat:@\", at: %@\", e.timestamp];\n            e.accessibilityLabel = @\"Status message:\";\n            e.accessibilityValue = s;\n        }\n        \n        if((e.rowType == ROW_MESSAGE || e.rowType == ROW_ME_MESSAGE || e.rowType == ROW_FAILED || e.rowType == ROW_SOCKETCLOSED) && e.groupEid > 0 && (e.groupEid != e.eid || [self->_expandedSectionEids objectForKey:@(e.groupEid)])) {\n            NSMutableString *s = [[[ColorFormatter format:e.formattedMsg defaultColor:[UIColor blackColor] mono:NO linkify:NO server:nil links:nil] string] mutableCopy];\n            [s replaceOccurrencesOfString:@\"→\" withString:@\".\" options:0 range:NSMakeRange(0, s.length)];\n            [s replaceOccurrencesOfString:@\"←\" withString:@\".\" options:0 range:NSMakeRange(0, s.length)];\n            [s replaceOccurrencesOfString:@\"⇐\" withString:@\".\" options:0 range:NSMakeRange(0, s.length)];\n            [s replaceOccurrencesOfString:@\"•\" withString:@\".\" options:0 range:NSMakeRange(0, s.length)];\n            [s replaceOccurrencesOfString:@\"↔\" withString:@\".\" options:0 range:NSMakeRange(0, s.length)];\n            if([s rangeOfString:@\".\"].location != NSNotFound)\n                [s replaceCharactersInRange:[s rangeOfString:@\".\"] withString:@\"\"];\n            e.accessibilityValue = s;\n        }\n        [self->_lock unlock];\n    }\n}\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    [self->_lock lock];\n    if(indexPath.row >= self->_data.count) {\n        [self->_lock unlock];\n        return 0;\n    }\n    Event *e = [self->_data objectAtIndex:indexPath.row];\n    [self->_lock unlock];\n    @synchronized (e) {\n        if(e.rowType == ROW_THUMBNAIL) {\n            float width = self.tableView.bounds.size.width/2;\n            if(![[[e.entities objectForKey:@\"properties\"] objectForKey:@\"width\"] intValue] || ![[[e.entities objectForKey:@\"properties\"] objectForKey:@\"height\"] intValue]) {\n                CGSize size = CGSizeZero;\n                \n                if([e.entities objectForKey:@\"id\"] && [[ImageCache sharedInstance] isLoaded:[e.entities objectForKey:@\"id\"] width:(int)(width * [UIScreen mainScreen].scale)]) {\n                    YYImage *img = [[ImageCache sharedInstance] imageForFileID:[e.entities objectForKey:@\"id\"] width:(int)(width * [UIScreen mainScreen].scale)];\n                    if(img)\n                        size = img.size;\n                } else if([[ImageCache sharedInstance] isLoaded:[e.entities objectForKey:@\"thumb\"]]) {\n                    YYImage *img = [[ImageCache sharedInstance] imageForURL:[e.entities objectForKey:@\"thumb\"]];\n                    if(img)\n                        size = img.size;\n                }\n                if(size.width > 0 && size.height > 0) {\n                    NSMutableDictionary *entities = [e.entities mutableCopy];\n                    if(size.width > width) {\n                        float ratio = width / size.width;\n                        size.width = width;\n                        size.height = size.height * ratio;\n                    } else {\n                        size.width *= [UIScreen mainScreen].scale;\n                        size.height *= [UIScreen mainScreen].scale;\n                    }\n                    [entities setObject:@{@\"width\":@(size.width), @\"height\":@(size.height)} forKey:@\"properties\"];\n                    e.entities = entities;\n                }\n            }\n        }\n        if(e.formattedMsg && !e.formatted)\n            [self _format:e];\n        UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];\n        cell.bounds = CGRectMake(0,0,self.tableView.bounds.size.width,cell.bounds.size.height);\n        [cell setNeedsLayout];\n        [cell layoutIfNeeded];\n        e.height = ceilf([cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height);\n        return e.height;\n    }\n}\n\n-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    [self->_lock lock];\n    if(indexPath.row >= self->_data.count) {\n        [self->_lock unlock];\n        return 0;\n    }\n    Event *e = [self->_data objectAtIndex:indexPath.row];\n    [self->_lock unlock];\n    if(e.height)\n        return e.height;\n    else\n        return ceilf(FONT_SIZE);\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    if([indexPath row] >= self->_data.count) {\n        [self->_lock unlock];\n        return [[self->_eventsTableCell instantiateWithOwner:self options:nil] objectAtIndex:0];\n    }\n\n    [self->_lock lock];\n    Event *e = [self->_data objectAtIndex:indexPath.row];\n    [self->_lock unlock];\n\n    if(e.rowType == ROW_THUMBNAIL) {\n        EventsTableCell_Thumbnail *cell = nil;\n        if([[self->_rowCache objectForKey:[e UUID]] isKindOfClass:EventsTableCell_Thumbnail.class])\n            cell = [self->_rowCache objectForKey:[e UUID]];\n        if(!cell)\n            cell = [[self->_eventsTableCell_Thumbnail instantiateWithOwner:self options:nil] objectAtIndex:0];\n        [self->_rowCache setObject:cell forKey:[e UUID]];\n        \n        cell.filename.textColor = [UIColor linkColor];\n        cell.filename.font = [UIFont boldSystemFontOfSize:FONT_SIZE];\n        cell.filename.text = [e.entities objectForKey:@\"name\"];\n        \n        if([e.entities objectForKey:@\"id\"] || [[e.entities objectForKey:@\"name\"] length] || [[e.entities objectForKey:@\"description\"] length]) {\n            cell.background.backgroundColor = [UIColor navBarColor];\n        } else {\n            cell.background.backgroundColor = [UIColor clearColor];\n        }\n        float width = self.tableView.bounds.size.width/2;\n        if([e.entities objectForKey:@\"id\"]) {\n            cell.thumbnail.image = [[ImageCache sharedInstance] imageForFileID:[e.entities objectForKey:@\"id\"] width:(int)(width * [UIScreen mainScreen].scale)];\n        } else {\n            cell.thumbnail.image = [[ImageCache sharedInstance] imageForURL:[e.entities objectForKey:@\"thumb\"]];\n        }\n        cell.spinner.hidden = YES;\n        cell.spinner.activityIndicatorViewStyle = [UIColor activityIndicatorViewStyle];\n        cell.thumbnail.hidden = !(cell.thumbnail.image != nil);\n        if(cell.thumbnail.image) {\n            if(![[[e.entities objectForKey:@\"properties\"] objectForKey:@\"height\"] intValue]) {\n                cell.thumbnail.image = nil;\n                cell.spinner.hidden = NO;\n                [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                    CLS_LOG(@\"Image dimensions were missing, reloading table\");\n                    e.height = 0;\n                    [self reloadForEvent:e];\n                }];\n            } else {\n                if(width > [[[e.entities objectForKey:@\"properties\"] objectForKey:@\"width\"] floatValue])\n                    width = [[[e.entities objectForKey:@\"properties\"] objectForKey:@\"width\"] floatValue];\n                float ratio = width / [[[e.entities objectForKey:@\"properties\"] objectForKey:@\"width\"] floatValue];\n                CGFloat thumbWidth = ceilf([[[e.entities objectForKey:@\"properties\"] objectForKey:@\"width\"] floatValue] * ratio);\n                if(thumbWidth == 0 || thumbWidth > self.tableView.bounds.size.width) {\n                    CLS_LOG(@\"invalid thumbnail width: %f ratio: %f\", width, ratio);\n                    @synchronized(self->_data) {\n                        [self->_data removeObject:e];\n                    }\n                    cell.thumbnailWidth.constant = FONT_SIZE * 2;\n                    cell.thumbnailHeight.constant = FONT_SIZE * 2;\n                    [self.tableView reloadData];\n                } else {\n                    cell.thumbnailWidth.constant = thumbWidth;\n                    cell.thumbnailHeight.constant = ceilf([[[e.entities objectForKey:@\"properties\"] objectForKey:@\"height\"] floatValue] * ratio);\n                    if(e.height > 0 && e.height < cell.thumbnailHeight.constant) {\n                        e.height = 0;\n                        [self reloadForEvent:e];\n                    }\n                    [cell.thumbnail layoutIfNeeded];\n                }\n            }\n        } else {\n            cell.thumbnailWidth.constant = FONT_SIZE * 2;\n            cell.thumbnailHeight.constant = FONT_SIZE * 2;\n            if([e.entities objectForKey:@\"id\"]) {\n                if(![[NSFileManager defaultManager] fileExistsAtPath:[[ImageCache sharedInstance] pathForFileID:[e.entities objectForKey:@\"id\"] width:(int)(width * [UIScreen mainScreen].scale)].path]) {\n                    cell.spinner.hidden = NO;\n                    [[ImageCache sharedInstance] fetchFileID:[e.entities objectForKey:@\"id\"] width:(int)(width * [UIScreen mainScreen].scale) completionHandler:^(BOOL success) {\n                        if(!success) {\n                            e.rowType = ROW_FILE;\n                        }\n                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                            cell.spinner.hidden = YES;\n                            e.height = 0;\n                            [self reloadForEvent:e];\n                        }];\n                    }];\n                } else {\n                    e.rowType = ROW_FILE;\n                    cell.spinner.hidden = YES;\n                }\n            } else {\n                if(![[NSFileManager defaultManager] fileExistsAtPath:[[ImageCache sharedInstance] pathForURL:[e.entities objectForKey:@\"thumb\"]].path]) {\n                    cell.spinner.hidden = NO;\n                    [[ImageCache sharedInstance] fetchURL:[e.entities objectForKey:@\"thumb\"] completionHandler:^(BOOL success) {\n                        if(!success) {\n                            @synchronized(self->_data) {\n                                [self->_data removeObject:e];\n                            }\n                        }\n                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                            e.height = 0;\n                            cell.spinner.hidden = YES;\n                            [self reloadForEvent:e];\n                        }];\n                    }];\n                } else {\n                    cell.spinner.hidden = YES;\n                    @synchronized(self->_data) {\n                        [self->_data removeObject:e];\n                    }\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        [self reloadData];\n                    }];\n                }\n            }\n        }\n    }\n\n    if(e.rowType == ROW_FILE) {\n        EventsTableCell_File *cell = nil;\n        if([[self->_rowCache objectForKey:[e UUID]] isKindOfClass:EventsTableCell_File.class])\n            cell = [self->_rowCache objectForKey:[e UUID]];\n        if(!cell)\n            cell = [[self->_eventsTableCell_File instantiateWithOwner:self options:nil] objectAtIndex:0];\n        [self->_rowCache setObject:cell forKey:[e UUID]];\n        \n        NSString *extension = [e.entities objectForKey:@\"extension\"];\n        if(extension.length)\n            extension = [extension substringFromIndex:1];\n        else\n            extension = [[e.entities objectForKey:@\"mime_type\"] substringFromIndex:[[e.entities objectForKey:@\"mime_type\"] rangeOfString:@\"/\"].location + 1];\n        \n        cell.extension.font = [UIFont boldSystemFontOfSize:FONT_SIZE * 1.5];\n        cell.extension.text = extension.uppercaseString;\n        \n        cell.filename.textColor = [UIColor linkColor];\n        cell.filename.font = [UIFont boldSystemFontOfSize:FONT_SIZE];\n        cell.filename.text = [e.entities objectForKey:@\"name\"];\n\n        cell.mimeType.textColor = [UIColor messageTextColor];\n        cell.mimeType.font = [UIFont systemFontOfSize:FONT_SIZE];\n        cell.mimeType.text = [e.entities objectForKey:@\"mime_type\"];\n        cell.mimeType.numberOfLines = 1;\n        cell.mimeType.lineBreakMode = NSLineBreakByTruncatingTail;\n        \n        cell.background.backgroundColor = [UIColor connectionBarColor];\n    }\n    \n    if(e.rowType == ROW_REPLY_COUNT) {\n        EventsTableCell_ReplyCount *cell = nil;\n        if([[self->_rowCache objectForKey:[e UUID]] isKindOfClass:EventsTableCell_File.class])\n            cell = [self->_rowCache objectForKey:[e UUID]];\n        if(!cell)\n            cell = [[self->_eventsTableCell_ReplyCount instantiateWithOwner:self options:nil] objectAtIndex:0];\n        [self->_rowCache setObject:cell forKey:[e UUID]];\n        \n        Event *parent = [e.entities objectForKey:@\"parent\"];\n        cell.reply.font = [ColorFormatter awesomeFont];\n        cell.reply.textColor = [UIColor colorFromHexString:[UIColor colorForNick:parent.msgid]];\n        cell.reply.text = FA_COMMENTS;\n        cell.reply.hidden = NO;\n        cell.replyButton.hidden = NO;\n        cell.reply.alpha = 0.4;\n        cell.replyCount.font = [ColorFormatter messageFont:__monospacePref];\n        cell.replyCount.textColor = [UIColor messageTextColor];\n        cell.replyCount.text = [NSString stringWithFormat:@\"%i %@\", parent.replyCount, parent.replyCount == 1 ? @\"reply\" : @\"replies\"];\n        if(parent.replyNicks.count)\n            cell.replyCount.text = [NSString stringWithFormat:@\"%@: %@\", cell.replyCount.text, [parent.replyNicks.allObjects componentsJoinedByString:@\", \"]];\n        cell.replyCount.alpha = 0.4;\n        cell.replyCount.preferredMaxLayoutWidth = self.tableView.bounds.size.width / 2;\n    }\n\n    EventsTableCell *cell = [self->_rowCache objectForKey:[e UUID]];\n    if(!cell)\n        cell = [[self->_eventsTableCell instantiateWithOwner:self options:nil] objectAtIndex:0];\n    [self->_rowCache setObject:cell forKey:[e UUID]];\n\n    cell.backgroundView = nil;\n    cell.backgroundColor = nil;\n    cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;\n    cell.contentView.backgroundColor = e.bgColor;\n    if(e.isHeader && !__chatOneLinePref) {\n        if(!cell.nickname.text.length) {\n            NSMutableAttributedString *s = [[NSMutableAttributedString alloc] initWithAttributedString:e.formattedNick];\n            if(e.formattedRealname && ([e.realname isKindOfClass:[NSString class]] && ![e.realname.lowercaseString isEqualToString:e.from.lowercaseString]) && !__norealnamePref) {\n                [s appendAttributedString:[[NSAttributedString alloc] initWithString:@\" \"]];\n                [s appendAttributedString:e.formattedRealname];\n            }\n            cell.nickname.attributedText = s;\n            cell.nickname.lineBreakMode = NSLineBreakByTruncatingTail;\n        }\n        cell.avatar.hidden = __avatarsOffPref || (indexPath.row == self->_hiddenAvatarRow);\n    } else {\n        cell.nickname.text = nil;\n        cell.avatar.hidden = !((__chatOneLinePref || e.rowType == ROW_ME_MESSAGE) && !__avatarsOffPref && e.parent == 0 && e.groupEid < 1);\n    }\n    float avatarHeight = __avatarsOffPref?0:((__chatOneLinePref || e.rowType == ROW_ME_MESSAGE)?__smallAvatarHeight:__largeAvatarHeight);\n\n    cell.avatarTop.constant = (avatarHeight > __smallAvatarHeight || !__compact)?2:0;\n    if(__chatOneLinePref && e.isEmojiOnly)\n        cell.avatarTop.constant += FONT_SIZE;\n    cell.avatarWidth.constant = cell.avatarHeight.constant = avatarHeight;\n    \n    cell.replyXOffset.constant = __timeLeftPref ? -__timestampWidth : 0;\n    \n    if(__avatarsOffPref) {\n        cell.avatar.image = nil;\n        cell.replyXOffset.constant += 4;\n    } else {\n        cell.replyXOffset.constant -= 4;\n        if(__avatarImages) {\n            NSURL *avatarURL = [e avatar:avatarHeight * [UIScreen mainScreen].scale];\n            if(avatarURL) {\n                BOOL needsRefresh = NO;\n                if(![[ImageCache sharedInstance] isLoaded:avatarURL])\n                    needsRefresh = [[ImageCache sharedInstance] ageOfCache:avatarURL] >= 600;\n                \n                if(needsRefresh) {\n                    CLS_LOG(@\"Avatar needs refresh: %@\", avatarURL);\n                }\n                \n                UIImage *image = [[ImageCache sharedInstance] imageForURL:avatarURL];\n                if(image) {\n                    cell.avatar.image = image;\n                    cell.avatar.layer.cornerRadius = 5.0;\n                    cell.avatar.layer.masksToBounds = YES;\n                    cell.avatar.userInteractionEnabled = YES;\n                    cell.largeAvatarURL = [e avatar:[UIScreen mainScreen].bounds.size.width * [UIScreen mainScreen].scale];\n                } else {\n                    cell.avatar.userInteractionEnabled = NO;\n                    cell.largeAvatarURL = nil;\n                }\n                \n                if(![[NSFileManager defaultManager] fileExistsAtPath:[[ImageCache sharedInstance] pathForURL:avatarURL].path] || needsRefresh) {\n                    [[ImageCache sharedInstance] fetchURL:avatarURL completionHandler:^(BOOL success) {\n                        if(success || [[ImageCache sharedInstance] isValidURL:[e avatar:avatarHeight * [UIScreen mainScreen].scale]])\n                            [self reloadForEvent:e];\n                    }];\n                }\n            }\n        }\n        if(!cell.avatar.image) {\n            cell.avatar.layer.cornerRadius = 0;\n            if(e.from.length) {\n                cell.avatar.image = [[[AvatarsDataSource sharedInstance] getAvatar:e.from nick:e.fromNick bid:e.bid] getImage:avatarHeight isSelf:e.isSelf];\n            } else if(e.rowType == ROW_ME_MESSAGE && e.nick.length) {\n                cell.avatar.image = [[[AvatarsDataSource sharedInstance] getAvatar:e.nick nick:e.fromNick bid:e.bid] getImage:__smallAvatarHeight isSelf:e.isSelf];\n            } else {\n                cell.avatar.image = nil;\n            }\n        }\n    }\n    cell.timestampLeft.font = cell.timestampRight.font = cell.lastSeenEID.font = __monospacePref?[ColorFormatter monoTimestampFont]:[ColorFormatter timestampFont];\n    cell.message.linkDelegate = self;\n    cell.nickname.linkDelegate = self;\n    cell.accessory.font = [ColorFormatter awesomeFont];\n    cell.accessory.textColor = [UIColor expandCollapseIndicatorColor];\n    cell.accessibilityLabel = e.accessibilityLabel;\n    cell.accessibilityValue = e.accessibilityValue;\n    cell.accessibilityHint = nil;\n    cell.accessibilityElementsHidden = NO;\n\n    cell.messageOffsetTop.constant = __compact ? -2 : 0;\n    cell.messageOffsetLeft.constant = (__timeLeftPref ? __timestampWidth : 6) + (__compact ? 6 : 10) + 10;\n    cell.messageOffsetRight.constant = __timeLeftPref ? 6 : (__timestampWidth + 16);\n    cell.messageOffsetBottom.constant = __compact ? 0 : 4;\n    \n    if (@available(iOS 13.0, *)) {\n        cell.rightTimestampOffset.constant = [NSProcessInfo processInfo].macCatalystApp ? 24 : 8;\n    }\n\n    cell.quoteBorder.hidden = !e.isQuoted;\n    cell.quoteBorder.backgroundColor = [UIColor quoteBorderColor];\n    if(e.isQuoted) {\n        cell.messageOffsetLeft.constant += 8;\n        cell.avatarOffset.constant = __compact ? -14 : -18;\n        cell.nicknameOffset.constant = -8;\n    } else {\n        cell.avatarOffset.constant = __compact ? -6 : -10;\n        cell.nicknameOffset.constant = 0;\n    }\n    if(avatarHeight > 0) {\n        if(__chatOneLinePref || e.rowType == ROW_ME_MESSAGE)\n            cell.avatarOffset.constant = avatarHeight;\n        if(!__chatOneLinePref)\n            cell.messageOffsetLeft.constant += __largeAvatarHeight + 4;\n    }\n    if(__avatarsOffPref)\n        cell.nicknameOffset.constant -= 6;\n    cell.nickname.preferredMaxLayoutWidth = cell.message.preferredMaxLayoutWidth = self.tableView.bounds.size.width - cell.messageOffsetLeft.constant - cell.messageOffsetRight.constant;\n\n    if(e.rowType == ROW_TIMESTAMP || e.rowType == ROW_LASTSEENEID) {\n        cell.message.text = @\"\";\n    } else if(!cell.message.text.length || e.rowType == ROW_FAILED) {\n        cell.message.attributedText = e.formatted;\n        \n        if((e.rowType == ROW_MESSAGE || e.rowType == ROW_ME_MESSAGE || e.rowType == ROW_FAILED || e.rowType == ROW_SOCKETCLOSED) && e.groupEid > 0 && (e.groupEid != e.eid || [self->_expandedSectionEids objectForKey:@(e.groupEid)])) {\n            if([self->_expandedSectionEids objectForKey:@(e.groupEid)]) {\n                if(e.groupEid == e.eid + 1) {\n                    cell.accessory.text = FA_MINUS_SQUARE_O;\n                    cell.contentView.backgroundColor = [UIColor collapsedHeadingBackgroundColor];\n                    cell.accessibilityLabel = [NSString stringWithFormat:@\"Expanded status messages heading. at %@\", e.timestamp];\n                    cell.accessibilityHint = @\"Collapses this group\";\n                } else {\n                    cell.accessory.text = FA_ANGLE_RIGHT;\n                    cell.contentView.backgroundColor = [UIColor contentBackgroundColor];\n                    cell.accessibilityLabel = [NSString stringWithFormat:@\"Expanded status message. at %@\", e.timestamp];\n                    cell.accessibilityHint = @\"Collapses this group\";\n                }\n            } else {\n                cell.accessory.text = FA_PLUS_SQUARE_O;\n                cell.accessibilityLabel = [NSString stringWithFormat:@\"Collapsed status messages. at %@\", e.timestamp];\n                cell.accessibilityHint = @\"Expands this group\";\n            }\n            cell.accessory.hidden = NO;\n        } else if(e.rowType == ROW_FAILED) {\n            cell.accessory.hidden = NO;\n            cell.accessory.text = FA_EXCLAMATION_TRIANGLE;\n            cell.accessory.textColor = [UIColor networkErrorColor];\n        } else {\n            cell.accessory.hidden = YES;\n        }\n        \n        if(e.links.count) {\n            if(e.pending || [e.color isEqual:[UIColor timestampColor]])\n                cell.message.linkAttributes = self->_lightLinkAttributes;\n            else\n                cell.message.linkAttributes = self->_linkAttributes;\n            @try {\n                for(NSTextCheckingResult *result in e.links) {\n                    if(result.resultType == NSTextCheckingTypeLink) {\n                        if(result.URL)\n                            [cell.message addLinkWithTextCheckingResult:result];\n                    } else {\n                        NSString *url = [[e.formatted attributedSubstringFromRange:result.range] string];\n                        if(![url hasPrefix:@\"irc\"]) {\n                            url = [NSString stringWithFormat:@\"irc://%i/%@\", _server.cid, [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]];\n                        }\n                        NSURL *u = [NSURL URLWithString:url];\n                        if(u)\n                            [cell.message addLinkToURL:u withRange:result.range];\n                    }\n                }\n            }\n            @catch (NSException *exception) {\n                CLS_LOG(@\"An exception occured while setting the links, the table is probably being reloaded: %@\", exception);\n            }\n        }\n        if(cell.nickname.text.length && e.realnameLinks.count) {\n            cell.nickname.linkAttributes = self->_lightLinkAttributes;\n            @try {\n                for(NSTextCheckingResult *result in e.realnameLinks) {\n                    if(result.resultType == NSTextCheckingTypeLink) {\n                        if(result.URL)\n                            [cell.nickname addLinkToURL:result.URL withRange:NSMakeRange(result.range.location + e.formattedNick.length + 1, result.range.length)];\n                    } else {\n                        NSString *url = [[e.formattedRealname attributedSubstringFromRange:result.range] string];\n                        if(![url hasPrefix:@\"irc\"]) {\n                            url = [NSString stringWithFormat:@\"irc://%i/%@\", _server.cid, [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]];\n                        }\n                        NSURL *u = [NSURL URLWithString:[url stringByReplacingOccurrencesOfString:@\"#\" withString:@\"%23\"]];\n                        if(u)\n                            [cell.nickname addLinkToURL:u withRange:NSMakeRange(result.range.location + e.formattedNick.length + 1, result.range.length)];\n                    }\n                }\n            }\n            @catch (NSException *exception) {\n                CLS_LOG(@\"An exception occured while setting the links, the table is probably being reloaded: %@\", exception);\n            }\n        }\n    }\n    cell.timestampLeft.hidden = !__timeLeftPref;\n    cell.timestampRight.hidden = __timeLeftPref;\n    cell.datestamp.hidden = YES;\n    UILabel *timestamp = __timeLeftPref ? cell.timestampLeft : cell.timestampRight;\n    if(e.rowType == ROW_LASTSEENEID) {\n        timestamp.hidden = YES;\n        cell.lastSeenEIDBackground.backgroundColor = [UIColor timestampColor];\n        cell.lastSeenEIDBackground.hidden = NO;\n        cell.lastSeenEID.textColor = [UIColor timestampColor];\n        cell.lastSeenEID.superview.backgroundColor = [UIColor contentBackgroundColor];\n        cell.lastSeenEID.superview.hidden = NO;\n        cell.lastSeenEIDOffset.constant = __avatarsOffPref ? 0 : cell.messageOffsetLeft.constant;\n    } else {\n        cell.lastSeenEIDBackground.hidden = YES;\n        cell.lastSeenEID.superview.hidden = YES;\n        timestamp.text = e.timestamp;\n        cell.timestampWidth.constant = __timestampWidth - 8;\n        cell.lastSeenEIDOffset.constant = 0;\n    }\n    if(e.rowType == ROW_TIMESTAMP) {\n        timestamp.hidden = YES;\n        timestamp = cell.datestamp;\n        timestamp.hidden = NO;\n        timestamp.text = e.timestamp;\n        timestamp.font = [ColorFormatter messageFont:__monospacePref];\n        timestamp.textColor = [UIColor messageTextColor];\n    } else if(e.isHighlight && !e.isSelf) {\n        timestamp.textColor = [UIColor highlightTimestampColor];\n    } else if(e.rowType == ROW_FAILED || [e.bgColor isEqual:[UIColor errorBackgroundColor]]) {\n        timestamp.textColor = [UIColor networkErrorColor];\n    } else {\n        timestamp.textColor = [UIColor timestampColor];\n    }\n    if(e.rowType == ROW_BACKLOG) {\n        timestamp.hidden = YES;\n        cell.lastSeenEIDBackground.backgroundColor = [UIColor backlogDividerColor];\n        cell.lastSeenEIDBackground.hidden = NO;\n        cell.accessibilityElementsHidden = YES;\n    } else if(e.rowType == ROW_LASTSEENEID) {\n        timestamp.backgroundColor = [UIColor contentBackgroundColor];\n    } else {\n        timestamp.backgroundColor = [UIColor clearColor];\n    }\n    if(e.rowType == ROW_TIMESTAMP) {\n        cell.topBorder.backgroundColor = [UIColor timestampTopBorderColor];\n        cell.topBorder.hidden = NO;\n        \n        cell.bottomBorder.backgroundColor = [UIColor timestampBottomBorderColor];\n        cell.bottomBorder.hidden = NO;\n        cell.messageOffsetBottom.constant = 4;\n    } else {\n        cell.topBorder.hidden = cell.bottomBorder.hidden = YES;\n    }\n    cell.codeBlockBackground.backgroundColor = [UIColor codeSpanBackgroundColor];\n    cell.codeBlockBackground.hidden = !e.isCodeBlock;\n    if(e.isCodeBlock) {\n        cell.messageOffsetTop.constant += 6;\n        cell.messageOffsetLeft.constant += 6;\n        cell.messageOffsetBottom.constant += 6;\n        cell.messageOffsetRight.constant += 6;\n    }\n\n    if(e.rowType == ROW_SOCKETCLOSED) {\n        cell.socketClosedBar.backgroundColor = [UIColor socketClosedBackgroundColor];\n        cell.socketClosedBar.hidden = NO;\n        if(!e.msg.length && !e.groupMsg.length) {\n            cell.message.text = nil;\n            cell.timestampLeft.text = nil;\n            cell.timestampRight.text = nil;\n        }\n        cell.messageOffsetBottom.constant = FONT_SIZE;\n    } else {\n        cell.socketClosedBar.hidden = YES;\n    }\n    \n    if(!__replyCollapsePref) {\n        if(e.isReply || e.replyCount) {\n            cell.reply.font = [ColorFormatter replyThreadFont];\n            cell.reply.textColor = [UIColor colorFromHexString:[UIColor colorForNick:e.isReply ? e.reply : e.msgid]];\n            cell.reply.text = e.isReply ? FA_COMMENTS : FA_COMMENT;\n            cell.reply.hidden = NO;\n            cell.replyButton.hidden = NO;\n            cell.replyButton.userInteractionEnabled = YES;\n            cell.reply.alpha = 0.4;\n            cell.replyCenter.priority = (e.isHeader && !__avatarsOffPref && !__chatOneLinePref) ? 999 : 1;\n        } else {\n            cell.reply.hidden = YES;\n            cell.replyButton.hidden = YES;\n            cell.replyButton.userInteractionEnabled = NO;\n        }\n    } else if(e.rowType != ROW_REPLY_COUNT) {\n        cell.reply.hidden = YES;\n        cell.replyButton.hidden = YES;\n        cell.replyButton.userInteractionEnabled = NO;\n    }\n\n    if(cell.replyButton && !cell.replyButton.hidden) {\n        [cell.replyButton addTarget:self action:@selector(_replyButtonPressed:) forControlEvents:UIControlEventTouchUpInside];\n        cell.replyButton.tag = indexPath.row;\n    } else {\n        [cell.replyButton removeTarget:self action:@selector(_replyButtonPressed:) forControlEvents:UIControlEventTouchUpInside];\n    }\n    \n    if(e.rowType == ROW_FILE) {\n        cell.message.textColor = [UIColor messageTextColor];\n        cell.message.font = [UIFont systemFontOfSize:FONT_SIZE];\n        cell.messageOffsetTop.constant += FONT_SIZE + 4;\n        cell.messageOffsetBottom.constant += FONT_SIZE + 8;\n        cell.messageOffsetLeft.constant += 60;\n        cell.messageOffsetRight.constant += 4;\n    }\n\n    if(e.rowType == ROW_THUMBNAIL) {\n        if([e.entities objectForKey:@\"id\"]) {\n            cell.message.text = [NSString stringWithFormat:@\"%@ • %@\", [e.entities objectForKey:@\"mime_type\"], e.msg];\n            cell.message.numberOfLines = 1;\n            cell.message.lineBreakMode = NSLineBreakByTruncatingTail;\n            cell.message.textColor = [UIColor messageTextColor];\n            cell.message.font = [UIFont systemFontOfSize:FONT_SIZE];\n        }\n        cell.messageOffsetLeft.constant += 4;\n        cell.messageOffsetRight.constant += 4;\n    }\n\n    return cell;\n}\n\n- (void)LinkLabel:(LinkLabel *)label didSelectLinkWithTextCheckingResult:(NSTextCheckingResult *)result {\n    [_urlHandler launchURL:result.URL];\n}\n\n-(IBAction)dismissButtonPressed:(id)sender {\n    if(self->_topUnreadView.alpha) {\n        [UIView beginAnimations:nil context:nil];\n        [UIView setAnimationDuration:0.1];\n        self->_topUnreadView.alpha = 0;\n        [UIView commitAnimations];\n        [self sendHeartbeat];\n    }\n}\n\n-(IBAction)topUnreadBarClicked:(id)sender {\n    if(self->_topUnreadView.alpha) {\n        if(!_buffer.scrolledUp) {\n            self->_buffer.scrolledUpFrom = [[self->_data lastObject] eid];\n            self->_buffer.scrolledUp = YES;\n        }\n        if(self->_lastSeenEidPos > 0) {\n            [UIView beginAnimations:nil context:nil];\n            [UIView setAnimationDuration:0.1];\n            self->_topUnreadView.alpha = 0;\n            [UIView commitAnimations];\n            [self->_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self->_lastSeenEidPos+1 inSection:0] atScrollPosition: UITableViewScrollPositionTop animated: YES];\n            [self scrollViewDidScroll:self->_tableView];\n            [self sendHeartbeat];\n        } else {\n            if(self->_tableView.tableHeaderView == self->_backlogFailedView)\n                [self loadMoreBacklogButtonPressed:nil];\n            [self->_tableView setContentOffset:CGPointMake(0,0) animated:YES];\n        }\n    }\n}\n\n-(IBAction)bottomUnreadBarClicked:(id)sender {\n    if(self->_bottomUnreadView.alpha) {\n        [UIView beginAnimations:nil context:nil];\n        [UIView setAnimationDuration:0.1];\n        self->_bottomUnreadView.alpha = 0;\n        [UIView commitAnimations];\n        if(self->_data.count) {\n            [self->_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self->_data.count - 1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];\n        }\n        self->_buffer.scrolledUp = NO;\n        self->_buffer.scrolledUpFrom = -1;\n    }\n}\n\n#pragma mark - Table view delegate\n\n-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {\n    [self->_delegate dismissKeyboard];\n}\n\n-(void)scrollViewDidScroll:(UIScrollView *)scrollView {\n    if(!_ready || !_buffer || _requestingBacklog || [UIApplication sharedApplication].applicationState != UIApplicationStateActive) {\n        self->_stickyAvatar.hidden = YES;\n        if(self->_data.count && _hiddenAvatarRow != -1) {\n            Event *e = [self->_data objectAtIndex:self->_hiddenAvatarRow];\n            EventsTableCell *cell = [self->_rowCache objectForKey:[e UUID]];\n            cell.avatar.hidden = !e.isHeader;\n            self->_hiddenAvatarRow = -1;\n        }\n        return;\n    }\n    \n    if(self->_previewingRow) {\n        EventsTableCell *cell = [self->_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:self->_previewingRow inSection:0]];\n        __previewer.sourceRect = cell.frame;\n    }\n    \n    UITableView *tableView = self->_tableView;\n    NSInteger firstRow = -1;\n    NSInteger lastRow = -1;\n    if(@available(iOS 13, *)) {\n        //visibleCells resets the scroll position on iOS 13\n    } else {\n        [tableView visibleCells];\n    }\n    NSArray *rows = [tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(tableView.bounds, tableView.contentInset)];\n    if(rows.count) {\n        firstRow = [[rows objectAtIndex:0] row];\n        lastRow = [[rows lastObject] row];\n    } else {\n        self->_stickyAvatar.hidden = YES;\n        if(self->_hiddenAvatarRow != -1) {\n            Event *e = [self->_data objectAtIndex:self->_hiddenAvatarRow];\n            EventsTableCell *cell = [self->_rowCache objectForKey:[e UUID]];\n            cell.avatar.hidden = !e.isHeader;\n            self->_hiddenAvatarRow = -1;\n        }\n    }\n    \n    if(tableView.tableHeaderView == self->_headerView && _minEid > 0 && _buffer && _buffer.bid != -1 && (self->_buffer.scrolledUp || !_data.count || (self->_data.count && firstRow == 0 && lastRow == self->_data.count - 1))) {\n        if(self->_conn.state == kIRCCloudStateConnected && scrollView.contentOffset.y < _headerView.frame.size.height && _conn.ready) {\n            CLS_LOG(@\"The table scrolled and the loading header became visible, requesting more backlog\");\n            self->_requestingBacklog = YES;\n            [self->_conn cancelPendingBacklogRequests];\n            [self->_conn requestBacklogForBuffer:self->_buffer.bid server:self->_buffer.cid beforeId:self->_earliestEid completion:nil];\n            UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @\"Downloading more chat history\");\n            self->_stickyAvatar.hidden = YES;\n            if(self->_hiddenAvatarRow != -1) {\n                Event *e = [self->_data objectAtIndex:self->_hiddenAvatarRow];\n                EventsTableCell *cell = [self->_rowCache objectForKey:[e UUID]];\n                cell.avatar.hidden = !e.isHeader;\n                self->_hiddenAvatarRow = -1;\n            }\n            return;\n        }\n    }\n    \n    if(rows.count && _topUnreadView) {\n        if(self->_data.count) {\n            if(lastRow < _data.count)\n                self->_buffer.savedScrollOffset = floorf(tableView.contentOffset.y - tableView.tableHeaderView.bounds.size.height);\n            \n            CGRect frame = [tableView convertRect:[tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:self->_data.count - 1 inSection:0]] toView:tableView.superview];\n            \n            if(frame.origin.y + frame.size.height <= tableView.frame.origin.y + tableView.frame.size.height - tableView.contentInset.bottom + 4 + (FONT_SIZE / 2)) {\n                [UIView beginAnimations:nil context:nil];\n                [UIView setAnimationDuration:0.1];\n                self->_bottomUnreadView.alpha = 0;\n                [UIView commitAnimations];\n                self->_newMsgs = 0;\n                self->_newHighlights = 0;\n                self->_buffer.scrolledUp = NO;\n                self->_buffer.scrolledUpFrom = -1;\n                self->_buffer.savedScrollOffset = -1;\n                [self sendHeartbeat];\n            } else if (!_buffer.scrolledUp && lastRow < (_data.count - 1)) {\n                self->_buffer.scrolledUpFrom = [[self->_data objectAtIndex:lastRow] eid];\n                self->_buffer.scrolledUp = YES;\n                [self->_scrollTimer performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:YES];\n                self->_scrollTimer = nil;\n            }\n            \n            if(self->_lastSeenEidPos >= 0) {\n                if(self->_lastSeenEidPos > 0 && firstRow < _lastSeenEidPos + 1) {\n                    [UIView beginAnimations:nil context:nil];\n                    [UIView setAnimationDuration:0.1];\n                    self->_topUnreadView.alpha = 0;\n                    [UIView commitAnimations];\n                    [self sendHeartbeat];\n                } else {\n                    [self updateTopUnread:firstRow];\n                }\n            }\n            \n            if(tableView.tableHeaderView != self->_headerView && _earliestEid > _buffer.min_eid && _buffer.min_eid > 0 && firstRow > 0 && lastRow < _data.count && _conn.state == kIRCCloudStateConnected && !(self->_msgid && [self->_msgids objectForKey:self->_msgid]))\n                tableView.tableHeaderView = self->_headerView;\n        }\n    }\n    \n    if(rows.count && !__chatOneLinePref && !__avatarsOffPref && scrollView.contentOffset.y > _headerView.frame.size.height) {\n        int offset = ((self->_topUnreadView.alpha == 0)?0:self->_topUnreadView.bounds.size.height);\n        NSUInteger i = firstRow;\n        CGRect rect;\n        NSIndexPath *topIndexPath;\n        do {\n            topIndexPath = [NSIndexPath indexPathForRow:i++ inSection:0];\n            rect = [self->_tableView convertRect:[self->_tableView rectForRowAtIndexPath:topIndexPath] toView:self->_tableView.superview];\n        } while(i < _data.count && rect.origin.y + rect.size.height <= offset - 1);\n        Event *e = [self->_data objectAtIndex:firstRow];\n        if((e.groupEid < 1 && e.from.length && [e isMessage]) || e.rowType == ROW_LASTSEENEID) {\n            float groupHeight = rect.size.height;\n            for(i = firstRow; i < _data.count - 1 && i < firstRow + 4; i++) {\n                e = [self->_data objectAtIndex:i];\n                if(e.rowType == ROW_LASTSEENEID)\n                    e = [self->_data objectAtIndex:i-1];\n                NSUInteger next = i+1;\n                Event *e1 = [self->_data objectAtIndex:next];\n                if(e1.rowType == ROW_LASTSEENEID) {\n                    next++;\n                    e1 = [self->_data objectAtIndex:next];\n                }\n                if([e.from isEqualToString:e1.from] && e1.groupEid < 1 && !e1.isHeader) {\n                    rect = [self->_tableView convertRect:[self->_tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:next inSection:0]] toView:self->_tableView.superview];\n                    groupHeight += rect.size.height;\n                } else {\n                    break;\n                }\n            }\n            if(e.from.length && !(((Event *)[self->_data objectAtIndex:firstRow]).rowType == ROW_LASTSEENEID && groupHeight == 26) && (!e.isHeader || groupHeight > __largeAvatarHeight + 14)) {\n                self->_stickyAvatarYOffsetConstraint.constant = rect.origin.y + rect.size.height - (__largeAvatarHeight + 4);\n                if(self->_stickyAvatarYOffsetConstraint.constant >= offset + 4)\n                    self->_stickyAvatarYOffsetConstraint.constant = offset + 4;\n                self->_stickyAvatarWidthConstraint.constant = self->_stickyAvatarHeightConstraint.constant = __largeAvatarHeight;\n                if(self->_hiddenAvatarRow != topIndexPath.row) {\n                    self->_stickyAvatar.image = nil;\n                    if(__avatarImages) {\n                        NSURL *avatarURL = [e avatar:__largeAvatarHeight * [UIScreen mainScreen].scale];\n                        if(avatarURL) {\n                            UIImage *image = [[ImageCache sharedInstance] imageForURL:avatarURL];\n                            if(image) {\n                                self->_stickyAvatar.image = image;\n                                self->_stickyAvatar.layer.cornerRadius = 5.0;\n                                self->_stickyAvatar.layer.masksToBounds = YES;\n                            } else {\n                                [[ImageCache sharedInstance] fetchURL:avatarURL completionHandler:^(BOOL success) {\n                                    if(success)\n                                        [self scrollViewDidScroll:self.tableView];\n                                }];\n                            }\n                        }\n                    }\n                    if(!_stickyAvatar.image) {\n                        self->_stickyAvatar.image = [[[AvatarsDataSource sharedInstance] getAvatar:e.from nick:e.fromNick bid:e.bid] getImage:__largeAvatarHeight isSelf:e.isSelf];\n                        self->_stickyAvatar.layer.cornerRadius = 0;\n                    }\n                    self->_stickyAvatar.hidden = NO;\n                    if(self->_hiddenAvatarRow != -1 && _hiddenAvatarRow < _data.count) {\n                        Event *e = [self->_data objectAtIndex:self->_hiddenAvatarRow];\n                        EventsTableCell *cell = [self->_rowCache objectForKey:[e UUID]];\n                        cell.avatar.hidden = !e.isHeader;\n                    }\n                    if(topIndexPath.row < self->_data.count) {\n                        EventsTableCell *cell = [self->_rowCache objectForKey:[[self->_data objectAtIndex: topIndexPath.row] UUID]];\n                        cell.avatar.hidden = YES;\n                        self->_hiddenAvatarRow = topIndexPath.row;\n                    }\n                }\n            } else {\n                self->_stickyAvatar.hidden = YES;\n                if(self->_hiddenAvatarRow != -1) {\n                    if(self->_hiddenAvatarRow < self->_data.count) {\n                        Event *e = [self->_data objectAtIndex:self->_hiddenAvatarRow];\n                        EventsTableCell *cell = [self->_rowCache objectForKey:[e UUID]];\n                        cell.avatar.hidden = !e.isHeader;\n                    }\n                    self->_hiddenAvatarRow = -1;\n                }\n            }\n        } else {\n            self->_stickyAvatar.hidden = YES;\n            if(self->_hiddenAvatarRow != -1) {\n                if(self->_hiddenAvatarRow < self->_data.count) {\n                    Event *e = [self->_data objectAtIndex:self->_hiddenAvatarRow];\n                    EventsTableCell *cell = [self->_rowCache objectForKey:[e UUID]];\n                    cell.avatar.hidden = !e.isHeader;\n                }\n                self->_hiddenAvatarRow = -1;\n            }\n        }\n    } else {\n        self->_stickyAvatar.hidden = YES;\n        if(self->_hiddenAvatarRow != -1) {\n            if(self->_hiddenAvatarRow < self->_data.count) {\n                Event *e = [self->_data objectAtIndex:self->_hiddenAvatarRow];\n                EventsTableCell *cell = [self->_rowCache objectForKey:[e UUID]];\n                cell.avatar.hidden = !e.isHeader;\n            }\n            self->_hiddenAvatarRow = -1;\n        }\n    }\n#ifdef DEBUG\n    if([[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"]) {\n        self->_tableView.tableHeaderView = nil;\n    }\n#endif\n}\n\n-(void)_replyButtonPressed:(UIControl *)sender {\n    [self->_lock lock];\n    Event *e = [self->_data objectAtIndex:sender.tag];\n    [self->_lock unlock];\n\n    if(self->_msgid) {\n        self->_eidToOpen = e.eid;\n        [(MainViewController *)_delegate setMsgId:nil];\n    } else if(e.reply) {\n        [(MainViewController *)_delegate setMsgId:e.reply];\n    } else {\n        [(MainViewController *)_delegate setMsgId:e.msgid];\n    }\n}\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [tableView deselectRowAtIndexPath:indexPath animated:NO];\n    \n    if(indexPath.row < _data.count) {\n        NSTimeInterval group = ((Event *)[self->_data objectAtIndex:indexPath.row]).groupEid;\n        if(group > 0) {\n            int count = 0;\n            for(Event *e in _data) {\n                if(e.groupEid == group)\n                    count++;\n            }\n            if(count > 1 || [((Event *)[self->_data objectAtIndex:indexPath.row]).groupMsg hasPrefix:self->_groupIndent]) {\n                if([self->_expandedSectionEids objectForKey:@(group)])\n                    [self->_expandedSectionEids removeObjectForKey:@(group)];\n                else if(((Event *)[self->_data objectAtIndex:indexPath.row]).eid != group)\n                    [self->_expandedSectionEids setObject:@(YES) forKey:@(group)];\n                for(Event *e in _data) {\n                    e.timestamp = nil;\n                    e.formatted = nil;\n                }\n                if(!_buffer.scrolledUp) {\n                    self->_buffer.scrolledUpFrom = [[self->_data lastObject] eid];\n                    self->_buffer.scrolledUp = YES;\n                }\n                self->_buffer.savedScrollOffset = floorf(self->_tableView.contentOffset.y - _tableView.tableHeaderView.bounds.size.height);\n                [self refresh];\n            }\n        } else if(indexPath.row < _data.count) {\n            Event *e = [self->_data objectAtIndex:indexPath.row];\n            if([e.type isEqualToString:@\"channel_invite\"])\n                [self->_delegate showJoinPrompt:e.oldNick server:[[ServersDataSource sharedInstance] getServer:e.cid]];\n            else if([e.type isEqualToString:@\"callerid\"])\n                [self->_conn say:[NSString stringWithFormat:@\"/accept %@\", e.nick] to:nil cid:e.cid handler:nil];\n            else if(e.rowType == ROW_THUMBNAIL || e.rowType == ROW_FILE) {\n                if([e.entities objectForKey:@\"id\"]) {\n                    NSString *extension = [e.entities objectForKey:@\"extension\"];\n                    if(!extension.length)\n                        extension = [@\".\" stringByAppendingString:[[e.entities objectForKey:@\"mime_type\"] substringFromIndex:[[e.entities objectForKey:@\"mime_type\"] rangeOfString:@\"/\"].location + 1]];\n                    if([[[e.entities objectForKey:@\"name\"] lowercaseString] hasSuffix:extension.lowercaseString]) {\n                        [_urlHandler launchURL:[NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":[e.entities objectForKey:@\"id\"], @\"name\":[[e.entities objectForKey:@\"name\"] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLPathAllowedCharacterSet]} error:nil]]];\n                    } else {\n                        [_urlHandler launchURL:[NSURL URLWithString:[NSString stringWithFormat:@\"%@/%@%@\", [[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":[e.entities objectForKey:@\"id\"]} error:nil], [e.entities objectForKey:@\"id\"], extension]]];\n                    }\n                } else {\n                    [_urlHandler launchURL:[e.entities objectForKey:@\"url\"]];\n                }\n            } else\n                [self->_delegate rowSelected:e];\n        }\n    }\n}\n\n-(void)clearLastSeenMarker {\n    [self->_lock lock];\n    for(Event *event in [[EventsDataSource sharedInstance] eventsForBuffer:self->_buffer.bid]) {\n        if(event.rowType == ROW_LASTSEENEID) {\n            [[EventsDataSource sharedInstance] removeEvent:event.eid buffer:event.bid];\n            break;\n        }\n    }\n    for(Event *event in _data) {\n        if(event.rowType == ROW_LASTSEENEID) {\n            [self->_data removeObject:event];\n            break;\n        }\n    }\n    [self->_lock unlock];\n    [self _reloadData];\n}\n\n-(void)_showLongPressMenu:(CGPoint)location {\n    NSIndexPath *indexPath = [self->_tableView indexPathForRowAtPoint:location];\n    if(indexPath) {\n        if(indexPath.row < _data.count) {\n            Event *e = [self->_data objectAtIndex:indexPath.row];\n            EventsTableCell *c = (EventsTableCell *)[self->_tableView cellForRowAtIndexPath:indexPath];\n            NSURL *url;\n            if(e.rowType == ROW_THUMBNAIL || e.rowType == ROW_FILE)\n                url = [e.entities objectForKey:@\"id\"]?[NSURL URLWithString:[e.entities objectForKey:@\"url\"]]:[e.entities objectForKey:@\"url\"];\n            else\n                url = [c.message linkAtPoint:[self->_tableView convertPoint:location toView:c.message]].URL;\n            if(url) {\n                if([url.scheme hasPrefix:@\"irc\"] && [url.host intValue] > 0 && url.path && url.path.length > 1) {\n                    Server *s = [[ServersDataSource sharedInstance] getServer:[url.host intValue]];\n                    if(s != nil) {\n                        if(s.ssl > 0)\n                            url = [NSURL URLWithString:[NSString stringWithFormat:@\"ircs://%@%@\", s.hostname, [url.path stringByReplacingOccurrencesOfString:@\"#\" withString:@\"%23\"]]];\n                        else\n                            url = [NSURL URLWithString:[NSString stringWithFormat:@\"irc://%@%@\", s.hostname, [url.path stringByReplacingOccurrencesOfString:@\"#\" withString:@\"%23\"]]];\n                    }\n                } else if([url.scheme hasPrefix:@\"irccloud-paste-\"]) {\n                    url = [NSURL URLWithString:[NSString stringWithFormat:@\"%@://%@%@\", [url.scheme substringFromIndex:15], url.host, url.path]];\n                }\n            }\n            [self->_delegate rowLongPressed:[self->_data objectAtIndex:indexPath.row] rect:[self->_tableView rectForRowAtIndexPath:indexPath] link:url.absoluteString];\n        }\n    }\n}\n\n-(void)_longPress:(UILongPressGestureRecognizer *)gestureRecognizer {\n    @synchronized(self->_data) {\n        if(gestureRecognizer.state == UIGestureRecognizerStateBegan) {\n            [self _showLongPressMenu:[gestureRecognizer locationInView:self->_tableView]];\n        }\n    }\n}\n\n- (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction\n                        configurationForMenuAtLocation:(CGPoint)location API_AVAILABLE(ios(13.0)) {\n    [self _showLongPressMenu:location];\n    return nil;\n}\n\n\n-(NSString *)YUNoHeartbeat {\n    if(!_ready)\n        return @\"Events table view not ready\";\n    if(!_buffer)\n        return @\"No buffer\";\n    if(self->_requestingBacklog)\n        return @\"Currently requesting backlog\";\n    if([UIApplication sharedApplication].applicationState != UIApplicationStateActive)\n        return @\"Application state not active\";\n    if(!_topUnreadView)\n        return @\"Can't find top chatter bar\";\n    if(self->_topUnreadView.alpha != 0)\n        return @\"Top chatter bar is visible\";\n    if(self->_bottomUnreadView.alpha != 0)\n        return @\"Bottom chatter bar is visible\";\n    if([NetworkConnection sharedInstance].notifier)\n        return @\"Connected as a notifier socket\";\n    if(![self.slidingViewController topViewHasFocus])\n        return @\"A drawer is open\";\n    if(self->_conn.state != kIRCCloudStateConnected)\n        return @\"Websocket not in Connected state\";\n    if(self->_lastSeenEidPos == 0)\n        return @\"New Messages marker is above the loaded backlog\";\n    UITableView *tableView = self->_tableView;\n    NSInteger firstRow = -1;\n    NSArray *rows = [tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(tableView.bounds, tableView.contentInset)];\n    if(rows.count) {\n        firstRow = [[rows objectAtIndex:0] row];\n    } else {\n        return @\"Empty table view\";\n    }\n    if(self->_lastSeenEidPos > 0 && firstRow >= self->_lastSeenEidPos)\n        return @\"New Messages marker is above the current visible range\";\n    NSArray *events = [[EventsDataSource sharedInstance] eventsForBuffer:self->_buffer.bid];\n    NSTimeInterval eid = self->_buffer.scrolledUpFrom;\n    if(eid <= 0) {\n        Event *last;\n        for(NSInteger i = events.count - 1; i >= 0; i--) {\n            last = [events objectAtIndex:i];\n            if(!last.pending && last.rowType != ROW_LASTSEENEID)\n                break;\n        }\n        if(!last.pending) {\n            eid = last.eid;\n        }\n    }\n    if(eid < 0 || eid < _buffer.last_seen_eid)\n        return @\"eid <= last_seen_eid\";\n    if(floorf(tableView.contentOffset.y) >= floorf(tableView.contentSize.height - (tableView.bounds.size.height - tableView.contentInset.top - tableView.contentInset.bottom)))\n        return @\"This channel should be marked as read\";\n    else\n        return @\"Table view is not scrolled to the bottom\";\n}\n\n-(CGRect)rectForEvent:(Event *)event {\n    int i = 0;\n    for(Event *e in _data) {\n        if(event == e)\n            break;\n        i++;\n    }\n    if(i < _data.count) {\n        return [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];\n    } else {\n        return CGRectZero;\n    }\n}\n@end\n\n"
  },
  {
    "path": "IRCCloud/Classes/FileMetadataViewController.h",
    "content": "//\n//  FileMetadataViewController.h\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"FileUploader.h\"\n\n@interface FileMetadataViewController : UITableViewController<UITextFieldDelegate,UITextViewDelegate,FileUploaderMetadataDelegate> {\n    UITextField *_filename;\n    UITextView *_msg;\n    NSString *_metadata;\n    FileUploader *_uploader;\n    UIImageView *_imageView;\n    CGFloat _imageHeight;\n    BOOL _done;\n    NSString *_url;\n}\n@property (readonly) UITextView *msg;\n- (id)initWithUploader:(FileUploader *)uploader;\n- (void)setURL:(NSString *)url;\n- (void)setImage:(UIImage *)image;\n- (void)setFilename:(NSString *)filename metadata:(NSString *)metadata;\n- (void)showCancelButton;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/FileMetadataViewController.m",
    "content": "//\n//  FileMetadataViewController.m\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import \"FileMetadataViewController.h\"\n#import \"ImageViewController.h\"\n#import \"AppDelegate.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@implementation FileMetadataViewController\n\n- (id)initWithUploader:(FileUploader *)uploader {\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        uploader.metadatadelegate = self;\n        self->_uploader = uploader;\n        self.navigationItem.title = @\"Upload a File\";\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@\"Send\" style:UIBarButtonItemStyleDone target:self action:@selector(saveButtonPressed:)];\n    }\n    return self;\n}\n\n-(void)fileUploadWillUpload:(NSUInteger)bytes mimeType:(NSString *)mimeType {\n    if(bytes < 1024) {\n        self->_metadata = [NSString stringWithFormat:@\"%lu B • %@\", (unsigned long)bytes, mimeType];\n    } else {\n        int exp = (int)(log(bytes) / log(1024));\n        self->_metadata = [NSString stringWithFormat:@\"%.1f %cB • %@\", bytes / pow(1024, exp), [@\"KMGTPE\" characterAtIndex:exp -1], mimeType];\n    }\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        [self.tableView reloadData];\n    }];\n}\n\n-(void)saveButtonPressed:(id)sender {\n    self->_done = YES;\n    [self.tableView endEditing:YES];\n    [self->_uploader setFilename:self->_filename.text message:self->_msg.text];\n    [((AppDelegate *)[UIApplication sharedApplication].delegate).mainViewController clearText];\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)didMoveToParentViewController:(UIViewController *)parent {\n    if(!parent && !_done)\n        [self->_uploader cancel];\n}\n\n-(void)cancelButtonPressed:(id)sender {\n    [self.tableView endEditing:YES];\n    [self->_uploader cancel];\n    \n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)showCancelButton {\n    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    if(self->_uploader) {\n        if(self.navigationController.viewControllers.count == 1) {\n            self.navigationController.navigationBar.clipsToBounds = YES;\n            \n            self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];\n        } else {\n            self.navigationController.navigationBar.clipsToBounds = NO;\n            [self.navigationController setNavigationBarHidden:NO animated:NO];\n        }\n    }\n    \n    if(!self->_filename.text.length)\n        self->_filename.text = self->_uploader.originalFilename;\n    if(!_metadata) {\n        if(self->_uploader.mimeType.length)\n            self->_metadata = [NSString stringWithFormat:@\"Calculating size… • %@\", _uploader.mimeType];\n        else\n            self->_metadata = @\"Calculating size…\";\n    }\n    [self.tableView reloadData];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n\n    self->_filename = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width / 3, 22)];\n    self->_filename.textAlignment = NSTextAlignmentRight;\n    self->_filename.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_filename.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    self->_filename.autocorrectionType = UITextAutocorrectionTypeNo;\n    self->_filename.keyboardType = UIKeyboardTypeDefault;\n    self->_filename.adjustsFontSizeToFitWidth = YES;\n    self->_filename.returnKeyType = UIReturnKeyDone;\n    self->_filename.delegate = self;\n    \n    self->_msg = [[UITextView alloc] initWithFrame:CGRectZero];\n    self->_msg.text = @\"\";\n    self->_msg.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_msg.backgroundColor = [UIColor clearColor];\n    self->_msg.returnKeyType = UIReturnKeyDone;\n    self->_msg.delegate = self;\n    self->_msg.font = self->_filename.font;\n    self->_msg.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    self->_msg.keyboardAppearance = [UITextField appearance].keyboardAppearance;\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"autoCaps\"]) {\n        self->_msg.autocapitalizationType = UITextAutocapitalizationTypeSentences;\n    } else {\n        self->_msg.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    }\n    self->_msg.text = ((AppDelegate *)[UIApplication sharedApplication].delegate).mainViewController.buffer.draft;\n    \n    self->_imageView = [[UIImageView alloc] initWithFrame:CGRectZero];\n    self->_imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    self->_imageView.contentMode = UIViewContentModeScaleAspectFit;\n    self->_imageView.accessibilityIgnoresInvertColors = YES;\n\n    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    if(!self.view.backgroundColor)\n        self.view.backgroundColor = self.tableView.backgroundColor = [UIColor colorWithRed:0.937255 green:0.937255 blue:0.956863 alpha:1];\n}\n\n- (void)setURL:(NSString *)url {\n    self->_url = url;\n}\n\n- (void)setFilename:(NSString *)filename metadata:(NSString *)metadata {\n    self->_filename.text = filename;\n    self->_filename.enabled = NO;\n    self->_metadata = metadata;\n    [self.tableView reloadData];\n}\n\n-(void)setImage:(UIImage *)image {\n    CGFloat width = image.size.width, height = image.size.height;\n    \n    if(width > self.tableView.frame.size.width) {\n        height *= self.tableView.frame.size.width / width;\n    }\n    \n    if(height > 240) {\n        height = 240;\n    }\n    \n    self->_imageView.image = image;\n    self->_imageHeight = height;\n    \n    [self.tableView reloadData];\n}\n\n- (void)textViewDidBeginEditing:(UITextView *)textView {\n    if(self->_imageView)\n        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:2] atScrollPosition:UITableViewScrollPositionTop animated:YES];\n    else\n        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];\n}\n\n- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {\n    if([text isEqualToString:@\"\\n\"]) {\n        [self.tableView endEditing:YES];\n        return NO;\n    }\n    return YES;\n}\n\n-(void)textFieldDidBeginEditing:(UITextField *)textField {\n    if(self->_imageView)\n        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];\n    else\n        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];\n\n    if(textField.text.length) {\n        textField.selectedTextRange = [textField textRangeFromPosition:textField.beginningOfDocument\n                                                            toPosition:([textField.text rangeOfString:@\".\"].location != NSNotFound)?[textField positionFromPosition:textField.beginningOfDocument offset:[textField.text rangeOfString:@\".\" options:NSBackwardsSearch].location]:textField.endOfDocument];\n    }\n}\n\n- (BOOL)textFieldShouldReturn:(UITextField *)textField {\n    [self.tableView endEditing:YES];\n    return NO;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSInteger section = indexPath.section;\n    if(!_imageView)\n        section++;\n    \n    if(section == 0)\n        return _imageHeight;\n    else if(section == 2)\n        return ([UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody].pointSize * 2) + 32;\n    else\n        return UITableViewAutomaticDimension;\n}\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return (self->_imageView)?3:2;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return 1;\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {\n    if(self->_imageView && section > 0)\n        section--;\n    \n    switch (section) {\n        case 1:\n            return @\"Message (optional)\";\n    }\n    return nil;\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {\n    if(section == ((self->_imageView)?1:0))\n        return _metadata;\n    else\n        return nil;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSInteger section = indexPath.section;\n    if(!_imageView)\n        section++;\n\n    NSString *identifier = [NSString stringWithFormat:@\"uploadcell-%li-%li\", (long)indexPath.section, (long)indexPath.row];\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];\n    \n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    cell.accessoryView = nil;\n    cell.accessoryType = UITableViewCellAccessoryNone;\n    cell.detailTextLabel.text = nil;\n    cell.backgroundView = nil;\n    cell.backgroundColor = [UITableViewCell appearance].backgroundColor;\n    \n    switch(section) {\n        case 0:\n            cell.backgroundView = self->_imageView;\n            cell.backgroundColor = [UIColor clearColor];\n            break;\n        case 1:\n            cell.textLabel.text = @\"Filename\";\n            self->_filename.frame = CGRectMake(0, 0, self.tableView.frame.size.width / 3, 22);\n            cell.accessoryView = self->_filename;\n            break;\n        case 2:\n            cell.textLabel.text = nil;\n            [self->_msg removeFromSuperview];\n            self->_msg.frame = CGRectInset(cell.contentView.bounds, 4, 4);\n            [cell.contentView addSubview:self->_msg];\n            break;\n    }\n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [self.tableView deselectRowAtIndexPath:indexPath animated:NO];\n    [self.tableView endEditing:YES];\n    \n    if(self->_imageView && _url && indexPath.section == 0) {\n        ImageViewController *ivc = [[ImageViewController alloc] initWithURL:[NSURL URLWithString:self->_url]];\n        AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;\n        appDelegate.window.backgroundColor = [UIColor blackColor];\n        appDelegate.window.rootViewController = ivc;\n        [appDelegate.window insertSubview:appDelegate.slideViewController.view belowSubview:ivc.view];\n        ivc.view.alpha = 0;\n        [UIView animateWithDuration:0.5f animations:^{\n            ivc.view.alpha = 1;\n        } completion:^(BOOL finished){\n            [UIApplication sharedApplication].statusBarHidden = YES;\n        }];\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/FileUploader.h",
    "content": "//\n//  FileUploader.h\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import <Foundation/Foundation.h>\n\n@protocol FileUploaderDelegate<NSObject>\n-(void)fileUploadProgress:(float)progress;\n-(void)fileUploadDidFail:(NSString *)reason;\n-(void)fileUploadDidFinish;\n-(void)fileUploadWasCancelled;\n-(void)fileUploadTooLarge;\n@end\n\n@protocol FileUploaderMetadataDelegate<NSObject>\n-(void)fileUploadWillUpload:(NSUInteger)bytes mimeType:(NSString *)mimeType;\n@end\n\n@interface FileUploader : NSObject<NSURLSessionDataDelegate,NSURLSessionDownloadDelegate> {\n    NSURLSessionTask *_task;\n    NSMutableData *_response;\n    NSObject<FileUploaderDelegate> *_delegate;\n    NSObject<FileUploaderMetadataDelegate> *_metadatadelegate;\n    int _cid;\n    BOOL _filenameSet;\n    BOOL _finished;\n    BOOL _cancelled;\n    BOOL _avatar;\n    int _orgId;\n    NSString *_id;\n    NSString *_msg;\n    NSMutableData *_body;\n    NSString *_originalFilename;\n    NSString *_filename;\n    NSString *_mimeType;\n    NSString *_backgroundID;\n    NSString *_boundary;\n    NSString *_msgid;\n    NSArray *_to;\n    void (^completionHandler)(void);\n}\n@property NSObject<FileUploaderDelegate> *delegate;\n@property NSObject<FileUploaderMetadataDelegate> *metadatadelegate;\n@property int orgId, cid;\n@property NSString *originalFilename, *mimeType, *msgid;\n@property BOOL finished, avatar;\n@property NSArray *to;\n-(id)initWithTask:(NSDictionary *)task response:(NSData *)response completion:(void (^)(void))completionHandler;\n-(void)uploadVideo:(NSURL *)file;\n-(void)uploadFile:(NSURL *)file;\n-(void)uploadFile:(NSString *)filename UTI:(NSString *)UTI data:(NSData *)data;\n-(void)uploadImage:(UIImage *)image;\n-(void)uploadPNG:(UIImage *)image;\n-(void)setFilename:(NSString *)filename message:(NSString *)message;\n-(void)cancel;\n+(UIImage *)image:(UIImage *)image scaledCopyOfSize:(CGSize)newSize;\n-(void)connectionDidFinishLoading;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/FileUploader.m",
    "content": "//\n//  FileUplaoder.m\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import <AVFoundation/AVFoundation.h>\n#import <MobileCoreServices/MobileCoreServices.h>\n#import \"FileUploader.h\"\n#import \"NSData+Base64.h\"\n#import \"config.h\"\n#import \"NetworkConnection.h\"\n#import \"SSZipArchive.h\"\n\n@implementation FileUploader\n\n-(id)initWithTask:(NSDictionary *)task response:(NSData *)response completion:(void (^)(void))completionHandler {\n    self = [super init];\n    \n    if(self) {\n        _originalFilename = [task objectForKey:@\"original_filename\"];\n        _msg = [task objectForKey:@\"msg\"];\n        _filename = [task objectForKey:@\"filename\"];\n        _avatar = [[task objectForKey:@\"avatar\"] intValue];\n        _orgId = [[task objectForKey:@\"orgId\"] intValue];\n        _cid = [[task objectForKey:@\"cid\"] intValue];\n        _msgid = [task objectForKey:@\"msgid\"];\n        _to = [task objectForKey:@\"to\"];\n        _response = response.mutableCopy;\n        self->completionHandler = completionHandler;\n    }\n    \n    return self;\n}\n\n-(void)setFilename:(NSString *)filename message:(NSString *)message {\n    self->_filename = filename;\n    self->_msg = message;\n    self->_filenameSet = YES;\n    if(self->_finished && _id.length) {\n        [[NetworkConnection sharedInstance] finalizeUpload:self->_id filename:self->_filename originalFilename:self->_originalFilename avatar:self->_avatar orgId:self->_orgId cid:self->_cid handler:^(IRCCloudJSONObject *result) {\n            [self handleResult:result.dictionary];\n        }];\n    } else {\n        if(self->_backgroundID)\n            [self _updateBackgroundUploadMetadata];\n    }\n}\n\n-(void)cancel {\n#ifndef EXTENSION\n    [[UIApplication sharedApplication] performSelectorOnMainThread:@selector(setNetworkActivityIndicatorVisible:) withObject:@(NO) waitUntilDone:YES];\n#endif\n    CLS_LOG(@\"File upload cancelled\");\n    self->_cancelled = YES;\n    self->_msg = self->_filename = self->_originalFilename = self->_mimeType = nil;\n    [self->_task cancel];\n    if(self->_delegate)\n        [self->_delegate fileUploadWasCancelled];\n}\n\n- (void)handleResult:(NSDictionary *)result {\n    if([[result objectForKey:@\"success\"] intValue] == 1 && [[result objectForKey:@\"file\"] objectForKey:@\"url\"]) {\n        CLS_LOG(@\"Finalize success: %@\", result);\n        if(self->_avatar) {\n            [self->_delegate fileUploadDidFinish];\n        } else {\n            if(self->_msg.length) {\n                if(![self->_msg hasSuffix:@\" \"])\n                    self->_msg = [self->_msg stringByAppendingString:@\" \"];\n            } else {\n                self->_msg = @\"\";\n            }\n            self->_msg = [self->_msg stringByAppendingFormat:@\"%@\", [[result objectForKey:@\"file\"] objectForKey:@\"url\"]];\n            \n            for(NSDictionary *d in self->_to) {\n                if(self->_msgid.length > 0)\n                    [[NetworkConnection sharedInstance] POSTreply:self->_msg to:[d objectForKey:@\"to\"] cid:[[d objectForKey:@\"cid\"] intValue] msgid:self->_msgid handler:nil];\n                else\n                    [[NetworkConnection sharedInstance] POSTsay:self->_msg to:[d objectForKey:@\"to\"] cid:[[d objectForKey:@\"cid\"] intValue] handler:nil];\n            }\n            [self->_delegate fileUploadDidFinish];\n        }\n    } else {\n        CLS_LOG(@\"Finalize failed: %@\", result);\n        [self->_delegate fileUploadDidFail:[result objectForKey:@\"message\"]];\n    }\n    if(self->completionHandler)\n        self->completionHandler();\n}\n\n//From http://stackoverflow.com/a/23862326\n- (BOOL)encodeVideo:(NSURL *)videoURL\n{\n    CFUUIDRef  uuid;\n    NSString  *uuidStr;\n    \n    uuid = CFUUIDCreate(NULL);\n    assert(uuid != NULL);\n    \n    uuidStr = CFBridgingRelease(CFUUIDCreateString(NULL, uuid));\n    assert(uuidStr != NULL);\n    \n    CFRelease(uuid);\n    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];\n    \n    // Create the composition and tracks\n    AVMutableComposition *composition = [AVMutableComposition composition];\n    AVMutableCompositionTrack *videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];\n    NSArray *assetVideoTracks = [asset tracksWithMediaType:AVMediaTypeVideo];\n    if (assetVideoTracks.count <= 0)\n    {\n        CLS_LOG(@\"Error reading the transformed video track\");\n        return NO;\n    }\n\n    if(!_originalFilename)\n        self->_originalFilename = [[videoURL lastPathComponent] stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@\".%@\", [videoURL pathExtension]] withString:@\".mp4\"];\n\n    // Insert the tracks in the composition's tracks\n    AVAssetTrack *assetVideoTrack = [assetVideoTracks firstObject];\n    [videoTrack insertTimeRange:assetVideoTrack.timeRange ofTrack:assetVideoTrack atTime:CMTimeMake(0, 1) error:nil];\n    [videoTrack setPreferredTransform:assetVideoTrack.preferredTransform];\n    \n    // Only add an audio track if the source video contains one\n    NSArray *assetAudioTracks = [asset tracksWithMediaType:AVMediaTypeAudio];\n    if(assetAudioTracks.count) {\n        AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];\n        AVAssetTrack *assetAudioTrack = [assetAudioTracks firstObject];\n        [audioTrack insertTimeRange:assetAudioTrack.timeRange ofTrack:assetAudioTrack atTime:CMTimeMake(0, 1) error:nil];\n    }\n    \n    // Export to mp4\n    NSString *exportPath = [NSString stringWithFormat:@\"%@/%@.mp4\", NSTemporaryDirectory(), uuidStr];\n    \n    NSURL *exportUrl = [NSURL fileURLWithPath:exportPath];\n    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];\n    exportSession.outputURL = exportUrl;\n    CMTime start = CMTimeMakeWithSeconds(0.0, 0);\n    CMTimeRange range = CMTimeRangeMake(start, [asset duration]);\n    exportSession.timeRange = range;\n    exportSession.outputFileType = AVFileTypeMPEG4;\n    [exportSession exportAsynchronouslyWithCompletionHandler:^{\n        switch ([exportSession status])\n        {\n            case AVAssetExportSessionStatusCompleted:\n                CLS_LOG(@\"MP4 Successful!\");\n                [self uploadFile:exportUrl];\n                break;\n            case AVAssetExportSessionStatusFailed:\n                CLS_LOG(@\"Export failed: %@\", [[exportSession error] localizedDescription]);\n                [self->_delegate fileUploadDidFail:[[exportSession error] localizedDescription]];\n                break;\n            case AVAssetExportSessionStatusCancelled:\n                CLS_LOG(@\"Export canceled\");\n                [self->_delegate fileUploadDidFail:@\"Export cancelled\"];\n                break;\n            default:\n                break;\n        }\n        [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];\n    }];\n    \n    return YES;\n}\n\n-(void)uploadVideo:(NSURL *)file {\n    if(![self encodeVideo:file])\n        [self uploadFile:file];\n}\n\n-(void)uploadFile:(NSURL *)file {\n    CLS_LOG(@\"Uploading file: %@\", file);\n    NSFileWrapper *wrapper = [[NSFileWrapper alloc] initWithURL:file options:0 error:nil];\n    \n    if(wrapper.regularFile) {\n        if(!_mimeType) {\n            CFStringRef extension = (__bridge CFStringRef)[file pathExtension];\n            CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL);\n            self->_mimeType = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType));\n            if(!_mimeType)\n                self->_mimeType = @\"application/octet-stream\";\n            CFRelease(UTI);\n        }\n        \n        if(!_originalFilename)\n            self->_originalFilename = wrapper.filename;\n    \n        [self performSelectorInBackground:@selector(_upload:) withObject:wrapper.regularFileContents];\n    } else {\n        CLS_LOG(@\"Uploading a bundle requires zipping first\");\n        NSString *tempFile = [[NSTemporaryDirectory() stringByAppendingPathComponent:wrapper.filename] stringByAppendingString:@\".zip\"];\n        CLS_LOG(@\"Creating %@\", tempFile);\n        \n        [SSZipArchive createZipFileAtPath:tempFile withContentsOfDirectory:file.path keepParentDirectory:YES];\n        self->_mimeType = @\"application/zip\";\n\n        if(!_originalFilename)\n            self->_originalFilename = wrapper.filename;\n        \n        self->_originalFilename = [self->_originalFilename stringByAppendingString:@\".zip\"];\n        NSData *data = [NSData dataWithContentsOfFile:tempFile];\n        [self performSelectorInBackground:@selector(_upload:) withObject:data];\n        \n        [[NSFileManager defaultManager] removeItemAtPath:tempFile error:nil];\n    }\n}\n\n-(void)uploadFile:(NSString *)filename UTI:(NSString *)UTI data:(NSData *)data {\n    CLS_LOG(@\"Uploading data with filename: %@\", filename);\n    self->_originalFilename = filename;\n    self->_mimeType = UTI;\n    [self performSelectorInBackground:@selector(_upload:) withObject:data];\n}\n\n\n-(void)uploadImage:(UIImage *)img {\n    CLS_LOG(@\"Uploading UIImage\");\n    self->_mimeType = @\"image/jpeg\";\n    if(self->_originalFilename) {\n        if([self->_originalFilename rangeOfString:@\".\" options:NSBackwardsSearch].location != NSNotFound) {\n            self->_originalFilename = [NSString stringWithFormat:@\"%@.JPG\", [self->_originalFilename substringToIndex:[self->_originalFilename rangeOfString:@\".\" options:NSBackwardsSearch].location]];\n        } else {\n            self->_originalFilename = [self->_originalFilename stringByAppendingString:@\".JPG\"];\n        }\n    } else {\n        self->_originalFilename = [NSString stringWithFormat:@\"%li.JPG\", time(NULL)];\n    }\n    [self performSelectorInBackground:@selector(_uploadImage:) withObject:img];\n}\n\n-(void)_uploadImage:(UIImage *)img {\n    NSUserDefaults *d;\n#ifdef ENTERPRISE\n    d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n    d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n    int size = [[d objectForKey:@\"photoSize\"] intValue];\n    if(size == -1 && (img.size.width * img.size.height > 15000000)) {\n        CLS_LOG(@\"Image dimensions too large, scaling down to 3872x3872\");\n        size = 3872;\n    }\n    if(size > 0) {\n        img = [FileUploader image:img scaledCopyOfSize:CGSizeMake(size,size)];\n    }\n\n    NSData *file = UIImageJPEGRepresentation(img, 0.8);\n    [self _upload:file];\n}\n\n-(void)uploadPNG:(UIImage *)img {\n    CLS_LOG(@\"Uploading UIImage\");\n    self->_mimeType = @\"image/png\";\n    if(self->_originalFilename) {\n        if([self->_originalFilename rangeOfString:@\".\" options:NSBackwardsSearch].location != NSNotFound) {\n            self->_originalFilename = [NSString stringWithFormat:@\"%@.PNG\", [self->_originalFilename substringToIndex:[self->_originalFilename rangeOfString:@\".\" options:NSBackwardsSearch].location]];\n        } else {\n            self->_originalFilename = [self->_originalFilename stringByAppendingString:@\".PNG\"];\n        }\n    } else {\n        self->_originalFilename = [NSString stringWithFormat:@\"%li.PNG\", time(NULL)];\n    }\n    [self performSelectorInBackground:@selector(_uploadPNG:) withObject:img];\n}\n\n-(void)_uploadPNG:(UIImage *)img {\n    NSUserDefaults *d;\n#ifdef ENTERPRISE\n    d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n    d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n    int size = [[d objectForKey:@\"photoSize\"] intValue];\n    if(size == -1 && (img.size.width * img.size.height > 15000000)) {\n        CLS_LOG(@\"Image dimensions too large, scaling down to 3872x3872\");\n        size = 3872;\n    }\n    if(size > 0) {\n        img = [FileUploader image:img scaledCopyOfSize:CGSizeMake(size,size)];\n    }\n    \n    NSData *file = UIImagePNGRepresentation(img);\n    [self _upload:file];\n}\n\n//http://stackoverflow.com/a/19697172\n+ (UIImage *)image:(UIImage *)image scaledCopyOfSize:(CGSize)newSize {\n    if(image.size.width <= newSize.width && image.size.height <= newSize.height)\n        return image;\n\n    CGImageRef imgRef = image.CGImage;\n    \n    CGFloat width = CGImageGetWidth(imgRef);\n    CGFloat height = CGImageGetHeight(imgRef);\n    \n    CGAffineTransform transform = CGAffineTransformIdentity;\n    CGRect bounds = CGRectMake(0, 0, width, height);\n    if (width > newSize.width || height > newSize.height) {\n        CGFloat ratio = width/height;\n        if (ratio > 1) {\n            bounds.size.width = newSize.width;\n            bounds.size.height = bounds.size.width / ratio;\n        }\n        else {\n            bounds.size.height = newSize.height;\n            bounds.size.width = bounds.size.height * ratio;\n        }\n    }\n    \n    CGFloat scaleRatio = bounds.size.width / width;\n    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));\n    CGFloat boundHeight;\n    UIImageOrientation orient = image.imageOrientation;\n    switch(orient) {\n        case UIImageOrientationUp: //EXIF = 1\n            transform = CGAffineTransformIdentity;\n            break;\n            \n        case UIImageOrientationUpMirrored: //EXIF = 2\n            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);\n            transform = CGAffineTransformScale(transform, -1.0, 1.0);\n            break;\n            \n        case UIImageOrientationDown: //EXIF = 3\n            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);\n            transform = CGAffineTransformRotate(transform, M_PI);\n            break;\n            \n        case UIImageOrientationDownMirrored: //EXIF = 4\n            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);\n            transform = CGAffineTransformScale(transform, 1.0, -1.0);\n            break;\n            \n        case UIImageOrientationLeftMirrored: //EXIF = 5\n            boundHeight = bounds.size.height;\n            bounds.size.height = bounds.size.width;\n            bounds.size.width = boundHeight;\n            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);\n            transform = CGAffineTransformScale(transform, -1.0, 1.0);\n            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);\n            break;\n            \n        case UIImageOrientationLeft: //EXIF = 6\n            boundHeight = bounds.size.height;\n            bounds.size.height = bounds.size.width;\n            bounds.size.width = boundHeight;\n            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);\n            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);\n            break;\n            \n        case UIImageOrientationRightMirrored: //EXIF = 7\n            boundHeight = bounds.size.height;\n            bounds.size.height = bounds.size.width;\n            bounds.size.width = boundHeight;\n            transform = CGAffineTransformMakeScale(-1.0, 1.0);\n            transform = CGAffineTransformRotate(transform, M_PI / 2.0);\n            break;\n            \n        case UIImageOrientationRight: //EXIF = 8\n            boundHeight = bounds.size.height;\n            bounds.size.height = bounds.size.width;\n            bounds.size.width = boundHeight;\n            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);\n            transform = CGAffineTransformRotate(transform, M_PI / 2.0);\n            break;\n            \n        default:\n            [NSException raise:NSInternalInconsistencyException format:@\"Invalid image orientation\"];\n            \n    }\n    \n    UIGraphicsBeginImageContext(bounds.size);\n    \n    CGContextRef context = UIGraphicsGetCurrentContext();\n    \n    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {\n        CGContextScaleCTM(context, -scaleRatio, scaleRatio);\n        CGContextTranslateCTM(context, -height, 0);\n    }\n    else {\n        CGContextScaleCTM(context, scaleRatio, -scaleRatio);\n        CGContextTranslateCTM(context, 0, -height);\n    }\n    \n    CGContextConcatCTM(context, transform);\n    \n    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);\n    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();\n    UIGraphicsEndImageContext();\n    \n    return imageCopy;\n}\n\n- (NSString *)boundaryString\n{\n    // generate boundary string\n    //\n    // adapted from http://developer.apple.com/library/ios/#samplecode/SimpleURLConnections\n    \n    CFUUIDRef  uuid;\n    NSString  *uuidStr;\n    \n    uuid = CFUUIDCreate(NULL);\n    assert(uuid != NULL);\n    \n    uuidStr = CFBridgingRelease(CFUUIDCreateString(NULL, uuid));\n    assert(uuidStr != NULL);\n    \n    CFRelease(uuid);\n    \n    return [NSString stringWithFormat:@\"Boundary-%@\", uuidStr];\n}\n\n-(void)_upload:(NSData *)file {\n    if(file.length > 15000000) {\n        CLS_LOG(@\"File exceeds 15M\");\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self->_delegate fileUploadTooLarge];\n        }];\n        return;\n    }\n    if(self->_delegate)\n        [self->_delegate fileUploadProgress:0.0f];\n    if(!_originalFilename)\n        self->_originalFilename = [NSString stringWithFormat:@\"%li\", time(NULL)];\n    self->_boundary = [self boundaryString];\n    self->_response = [[NSMutableData alloc] init];\n    self->_body = [[NSMutableData alloc] init];\n    \n    [self->_body appendData:[[NSString stringWithFormat:@\"--%@\\r\\n\", _boundary] dataUsingEncoding:NSUTF8StringEncoding]];\n    [self->_body appendData:[[NSString stringWithFormat:@\"Content-Disposition: form-data; name=\\\"file\\\"; filename=\\\"%@\\\"\\r\\n\", _originalFilename] dataUsingEncoding:NSUTF8StringEncoding]];\n    [self->_body appendData:[[NSString stringWithFormat:@\"Content-Type: %@\\r\\n\", _mimeType] dataUsingEncoding:NSUTF8StringEncoding]];\n    [self->_body appendData:[@\"\\r\\n\" dataUsingEncoding:NSUTF8StringEncoding]];\n    [self->_body appendData:file];\n    [self->_body appendData:[@\"\\r\\n\" dataUsingEncoding:NSUTF8StringEncoding]];\n    [self->_body appendData:[[NSString stringWithFormat:@\"--%@--\\r\\n\", _boundary] dataUsingEncoding:NSUTF8StringEncoding]];\n\n    CLS_LOG(@\"Uploading %@ with boundary %@ (%lu bytes)\", _originalFilename, _boundary, (unsigned long)_body.length);\n    \n#ifndef EXTENSION\n    [[UIApplication sharedApplication] performSelectorOnMainThread:@selector(setNetworkActivityIndicatorVisible:) withObject:@(YES) waitUntilDone:YES];\n#endif\n    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@\"https://%@/chat/%@\", IRCCLOUD_HOST, _avatar?@\"upload-avatar\":@\"upload\"]] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];\n    [request setHTTPShouldHandleCookies:NO];\n    [request setValue:[NSString stringWithFormat:@\"multipart/form-data; boundary=%@\", _boundary] forHTTPHeaderField:@\"Content-Type\"];\n    [request setValue:[NSString stringWithFormat:@\"session=%@\",[NetworkConnection sharedInstance].session] forHTTPHeaderField:@\"Cookie\"];\n    [request setValue:[NetworkConnection sharedInstance].session forHTTPHeaderField:@\"x-irccloud-session\"];\n    [request setHTTPMethod:@\"POST\"];\n    [request setHTTPBody:self->_body];\n    \n    if(self->_metadatadelegate)\n        [self->_metadatadelegate fileUploadWillUpload:file.length mimeType:self->_mimeType];\n    \n    NSURLSession *session;\n    NSURLSessionConfiguration *config;\n    config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:[NSString stringWithFormat:@\"com.irccloud.share.image.%li\", time(NULL)]];\n#ifdef ENTERPRISE\n    config.sharedContainerIdentifier = @\"group.com.irccloud.enterprise.share\";\n#else\n    config.sharedContainerIdentifier = @\"group.com.irccloud.share\";\n#endif\n    config.HTTPCookieStorage = nil;\n    config.URLCache = nil;\n    config.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;\n    config.discretionary = NO;\n    session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];\n    _task = [session downloadTaskWithRequest:request];\n    \n    if(session.configuration.identifier) {\n        self->_backgroundID = session.configuration.identifier;\n        [self _updateBackgroundUploadMetadata];\n    }\n\n    [_task resume];\n}\n\n-(void)_updateBackgroundUploadMetadata {\n    NSUserDefaults *d;\n#ifdef ENTERPRISE\n    d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n    d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n    NSMutableDictionary *tasks = [[d dictionaryForKey:@\"uploadtasks\"] mutableCopy];\n    if(!tasks)\n        tasks = [[NSMutableDictionary alloc] init];\n    \n    [tasks setObject:@{@\"service\":@\"irccloud\", @\"original_filename\":self->_originalFilename?_originalFilename:@\"\", @\"msg\":self->_msg?self->_msg:@\"\", @\"filename\":self->_filename?_filename:@\"\", @\"avatar\":@(self->_avatar), @\"orgId\":@(self->_orgId), @\"cid\":@(self->_cid), @\"msgid\":self->_msgid?self->_msgid:@\"\", @\"to\":self->_to?self->_to:@[]} forKey:self->_backgroundID];\n    \n    [d setObject:tasks forKey:@\"uploadtasks\"];\n    \n    CLS_LOG(@\"Upload tasks: %@\", tasks);\n    \n    [d synchronize];\n}\n\n-(void)connectionDidFinishLoading {\n#ifndef EXTENSION\n    [[UIApplication sharedApplication] performSelectorOnMainThread:@selector(setNetworkActivityIndicatorVisible:) withObject:@(NO) waitUntilDone:YES];\n#endif\n    if(self->_cancelled) {\n        CLS_LOG(@\"Upload finished but it was cancelled\");\n        return;\n    }\n    NSDictionary *d = [NSJSONSerialization JSONObjectWithData:self->_response options:kNilOptions error:nil];\n    if(d) {\n        if([[d objectForKey:@\"success\"] intValue] == 1) {\n            self->_id = [d objectForKey:@\"id\"];\n            self->_finished = YES;\n            if(self->_filenameSet || _avatar) {\n                [[NetworkConnection sharedInstance] finalizeUpload:self->_id filename:self->_filename?_filename:@\"\" originalFilename:self->_originalFilename?_originalFilename:@\"\" avatar:self->_avatar orgId:self->_orgId cid:self->_cid handler:^(IRCCloudJSONObject *result) {\n                    [self handleResult:result.dictionary];\n                }];\n            }\n        } else {\n            CLS_LOG(@\"Upload failed: %@\", d);\n            [self->_delegate fileUploadDidFail:[d objectForKey:@\"message\"]];\n        }\n    } else {\n        CLS_LOG(@\"UPLOAD: Invalid JSON response: %@\", [[NSString alloc] initWithData:self->_response encoding:NSUTF8StringEncoding]);\n        [self->_delegate fileUploadDidFail:nil];\n    }\n}\n\n- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {\n    CLS_LOG(@\"Sent body data: %lli / %lli\", totalBytesSent, totalBytesExpectedToSend);\n    _response = nil;\n    if(self->_delegate && !_cancelled)\n        [self->_delegate fileUploadProgress:(float)totalBytesSent / (float)_body.length];\n}\n\n- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler {\n    CLS_LOG(@\"Got HTTP redirect to: %@ %@\", request.URL, response);\n    completionHandler(request);\n}\n\n- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {\n    self->_response = [NSData dataWithContentsOfURL:location].mutableCopy;\n    CLS_LOG(@\"Did finish downloading to URL: %@\", location);\n    [[NSFileManager defaultManager] removeItemAtURL:location error:nil];\n    NSUserDefaults *d;\n#ifdef ENTERPRISE\n    d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n    d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n    NSMutableDictionary *uploadtasks = [[d dictionaryForKey:@\"uploadtasks\"] mutableCopy];\n    [uploadtasks removeObjectForKey:session.configuration.identifier];\n    [d setObject:uploadtasks forKey:@\"uploadtasks\"];\n    [d synchronize];\n}\n\n-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {\n    if(!self->_response)\n        self->_response = data.mutableCopy;\n    else\n        [self->_response appendData:data];\n}\n\n- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {\n    if(session.configuration.identifier) {\n        NSUserDefaults *d;\n#ifdef ENTERPRISE\n        d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n        d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n        NSMutableDictionary *uploadtasks = [[d dictionaryForKey:@\"uploadtasks\"] mutableCopy];\n        [uploadtasks removeObjectForKey:session.configuration.identifier];\n        [d setObject:uploadtasks forKey:@\"uploadtasks\"];\n        [d synchronize];\n    }\n\n    CLS_LOG(@\"HTTP request completed with status code %i\", (int)((NSHTTPURLResponse *)task.response).statusCode);\n    \n    if(error) {\n#ifndef EXTENSION\n        if([error.domain isEqualToString:NSURLErrorDomain]) {\n            if(error.code == NSURLErrorUnknown || error.code == NSURLErrorBackgroundSessionWasDisconnected) {\n                CLS_LOG(@\"Lost connection to background upload service, retrying in-process\");\n                NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@\"https://%@/chat/upload\", IRCCLOUD_HOST]] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];\n                [request setHTTPShouldHandleCookies:NO];\n                [request setValue:[NSString stringWithFormat:@\"multipart/form-data; boundary=%@\", _boundary] forHTTPHeaderField:@\"Content-Type\"];\n                [request setValue:[NSString stringWithFormat:@\"session=%@\",[NetworkConnection sharedInstance].session] forHTTPHeaderField:@\"Cookie\"];\n                [request setValue:[NetworkConnection sharedInstance].session forHTTPHeaderField:@\"x-irccloud-session\"];\n                [request setHTTPMethod:@\"POST\"];\n                [request setHTTPBody:self->_body];\n                \n                [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                    NSURLSession *session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration delegate:self delegateQueue:NSOperationQueue.mainQueue];\n                    self->_task = [session dataTaskWithRequest:request];\n                    [self->_task resume];\n                    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;\n                }];\n                return;\n            }\n        }\n#endif\n        CLS_LOG(@\"Upload error: %@\", error);\n        \n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self->_delegate fileUploadDidFail:error.localizedDescription];\n        }];\n    } else {\n        [self connectionDidFinishLoading];\n    }\n    [session finishTasksAndInvalidate];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/FilesTableViewController.h",
    "content": "//\n//  FilesTableViewController.h\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n\n@protocol FilesTableViewDelegate<NSObject>\n-(void)filesTableViewControllerDidSelectFile:(NSDictionary *)file message:(NSString *)message;\n@end\n\n@interface FilesTableViewController : UITableViewController {\n    int _pages;\n    NSArray *_files;\n    NSMutableDictionary *_imageViews;\n    NSMutableDictionary *_spinners;\n    NSMutableDictionary *_extensions;\n    NSDateFormatter *_formatter;\n    BOOL _canLoadMore;\n    id<FilesTableViewDelegate> _delegate;\n    UIView *_footerView;\n    NSDictionary *_selectedFile;\n}\n@property id<FilesTableViewDelegate> delegate;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/FilesTableViewController.m",
    "content": "//\n//  FilesTableViewController.m\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import \"FilesTableViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"ColorFormatter.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"FileMetadataViewController.h\"\n#import \"ImageCache.h\"\n\n@interface FilesTableCell : UITableViewCell {\n    UILabel *_date;\n    UILabel *_name;\n    UILabel *_metadata;\n    UILabel *_extension;\n    YYAnimatedImageView *_thumbnail;\n    UIActivityIndicatorView *_spinner;\n}\n@property (readonly) UILabel *date,*name,*metadata,*extension;\n@property (readonly) YYAnimatedImageView *thumbnail;\n@property (readonly) UIActivityIndicatorView *spinner;\n@end\n\n@implementation FilesTableCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self->_date = [[UILabel alloc] init];\n        self->_date.textColor = [UITableViewCell appearance].detailTextLabelColor;\n        self->_date.font = [UIFont systemFontOfSize:[UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleCaption1].pointSize];\n        [self.contentView addSubview:self->_date];\n\n        self->_name = [[UILabel alloc] init];\n        self->_name.textColor = [UITableViewCell appearance].textLabelColor;\n        self->_name.font = [UIFont boldSystemFontOfSize:[UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleCaption1].pointSize];\n        [self.contentView addSubview:self->_name];\n        \n        self->_metadata = [[UILabel alloc] init];\n        self->_metadata.textColor = [UITableViewCell appearance].detailTextLabelColor;\n        self->_metadata.font = [UIFont systemFontOfSize:[UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleCaption1].pointSize];\n        [self.contentView addSubview:self->_metadata];\n        \n        self->_extension = [[UILabel alloc] init];\n        self->_extension.textColor = [UIColor whiteColor];\n        self->_extension.backgroundColor = [UIColor unreadBlueColor];\n        self->_extension.font = [UIFont boldSystemFontOfSize:[UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleCaption1].pointSize];\n        self->_extension.textAlignment = NSTextAlignmentCenter;\n        self->_extension.hidden = YES;\n        [self.contentView addSubview:self->_extension];\n\n        self->_thumbnail = [[YYAnimatedImageView alloc] init];\n        self->_thumbnail.contentMode = UIViewContentModeScaleAspectFit;\n        self->_thumbnail.accessibilityIgnoresInvertColors = YES;\n        [self.contentView addSubview:self->_thumbnail];\n        \n        self->_spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n        [self.contentView addSubview:self->_spinner];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n    [super layoutSubviews];\n    \n    CGRect frame = [self.contentView bounds];\n    frame.origin.x = 4;\n    frame.origin.y = 4;\n    frame.size.width -= 8;\n    frame.size.height -= 8;\n    \n    self->_extension.frame = self->_spinner.frame = self->_thumbnail.frame = CGRectMake(frame.origin.x, frame.origin.y, 64, frame.size.height);\n    self->_date.frame = CGRectMake(frame.origin.x + 64, frame.origin.y, frame.size.width - 64, frame.size.height / 3);\n    self->_name.frame = CGRectMake(frame.origin.x + 64, _date.frame.origin.y + _date.frame.size.height, frame.size.width - 64, frame.size.height / 3);\n    self->_metadata.frame = CGRectMake(frame.origin.x + 64, _name.frame.origin.y + _name.frame.size.height, frame.size.width - 64, frame.size.height / 3);\n}\n\n-(void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n@end\n\n@implementation FilesTableViewController\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.tableView.backgroundColor = [[UITableViewCell appearance] backgroundColor];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.navigationItem.title = @\"File Uploads\";\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)];\n    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editButtonPressed:)];\n    self->_formatter = [[NSDateFormatter alloc] init];\n    self->_formatter.dateStyle = NSDateFormatterLongStyle;\n    self->_formatter.timeStyle = NSDateFormatterMediumStyle;\n    self->_imageViews = [[NSMutableDictionary alloc] init];\n    self->_spinners = [[NSMutableDictionary alloc] init];\n    self->_extensions = [[NSMutableDictionary alloc] init];\n    \n    self->_footerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,64,64)];\n    self->_footerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n    UIActivityIndicatorView *a = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n    a.center = self->_footerView.center;\n    a.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;\n    [a startAnimating];\n    [self->_footerView addSubview:a];\n    \n    self.tableView.tableFooterView = self->_footerView;\n    self->_pages = 0;\n    self->_files = nil;\n    self->_canLoadMore = YES;\n    [self _loadMore];\n}\n\n-(void)editButtonPressed:(id)sender {\n    [self.tableView setEditing:!self.tableView.isEditing animated:YES];\n    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:self.tableView.isEditing?UIBarButtonSystemItemCancel:UIBarButtonSystemItemEdit target:self action:@selector(editButtonPressed:)];\n}\n\n-(void)doneButtonPressed:(id)sender {\n    [self.tableView endEditing:YES];\n    [self dismissViewControllerAnimated:YES completion:nil];\n    self->_files = nil;\n    self->_canLoadMore = NO;\n    [[ImageCache sharedInstance] clear];\n}\n\n-(void)_loadMore {\n    [[NetworkConnection sharedInstance] getFiles:++_pages handler:^(IRCCloudJSONObject *d) {\n        if([[d objectForKey:@\"success\"] boolValue]) {\n            CLS_LOG(@\"Loaded file list for page %i\", self->_pages);\n            if(self->_files)\n                self->_files = [self->_files arrayByAddingObjectsFromArray:[d objectForKey:@\"files\"]];\n            else\n                self->_files = [d objectForKey:@\"files\"];\n            self->_canLoadMore = self->_files.count < [[d objectForKey:@\"total\"] intValue];\n            self.tableView.tableFooterView = self->_canLoadMore?self->_footerView:nil;\n            if(!self->_files.count) {\n                CLS_LOG(@\"File list is empty\");\n                UILabel *fail = [[UILabel alloc] init];\n                fail.text = @\"\\nYou haven't uploaded any files yet.\\n\";\n                fail.numberOfLines = 3;\n                fail.textAlignment = NSTextAlignmentCenter;\n                fail.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n                [fail sizeToFit];\n                self.tableView.tableFooterView = fail;\n            }\n        } else {\n            CLS_LOG(@\"Failed to load file list for page %i: %@\", self->_pages, d);\n            self->_canLoadMore = NO;\n            UILabel *fail = [[UILabel alloc] init];\n            fail.text = @\"\\nUnable to load files.\\nPlease try again later.\\n\";\n            fail.numberOfLines = 4;\n            fail.textAlignment = NSTextAlignmentCenter;\n            fail.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n            [fail sizeToFit];\n            self.tableView.tableFooterView = fail;\n            return;\n        }\n        [self.tableView reloadData];\n    }];\n}\n\n-(void)_refreshFileID:(NSString *)fileID {\n    [[self->_spinners objectForKey:fileID] stopAnimating];\n    [[self->_spinners objectForKey:fileID] setHidden:YES];\n    YYImage *image = [[ImageCache sharedInstance] imageForFileID:fileID width:(self.view.frame.size.width/2) * [UIScreen mainScreen].scale];\n    if(image) {\n        [[self->_imageViews objectForKey:fileID] setImage:image];\n        [[self->_imageViews objectForKey:fileID] setHidden:NO];\n        [[self->_extensions objectForKey:fileID] setHidden:YES];\n    } else {\n        [[self->_extensions objectForKey:fileID] setHidden:NO];\n    }\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return _files.count;\n}\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    return ([UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleCaption1].pointSize * 3) + 32;\n}\n\n-(void)scrollViewDidScroll:(UIScrollView *)scrollView {\n    if(self->_files.count && _canLoadMore) {\n        NSArray *rows = [self.tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self.tableView.bounds, self.tableView.contentInset)];\n        \n        if([[rows lastObject] row] >= self->_files.count - 5) {\n            self->_canLoadMore = NO;\n            [self _loadMore];\n        }\n    }\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    FilesTableCell *cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:@\"filecell-%li-%li\", (long)indexPath.section, (long)indexPath.row]];\n    if(!cell)\n        cell = [[FilesTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[NSString stringWithFormat:@\"filecell-%li-%li\", (long)indexPath.section, (long)indexPath.row]];\n\n    NSDictionary *file = [self->_files objectAtIndex:indexPath.row];\n    \n    cell.date.text = [self->_formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:[[file objectForKey:@\"date\"] intValue]]];\n    cell.name.text = [file objectForKey:@\"name\"];\n    int bytes = [[file objectForKey:@\"size\"] intValue];\n    if(bytes < 1024) {\n        cell.metadata.text = [NSString stringWithFormat:@\"%i B • %@\", bytes, [file objectForKey:@\"mime_type\"]];\n    } else {\n        int exp = (int)(log(bytes) / log(1024));\n        cell.metadata.text = [NSString stringWithFormat:@\"%.1f %cB • %@\", bytes / pow(1024, exp), [@\"KMGTPE\" characterAtIndex:exp -1], [file objectForKey:@\"mime_type\"]];\n    }\n    \n    NSString *e = [file objectForKey:@\"extension\"];\n    if(!e.length && [[file objectForKey:@\"mime_type\"] rangeOfString:@\"/\"].location != NSNotFound)\n        e = [[file objectForKey:@\"mime_type\"] substringFromIndex:[[file objectForKey:@\"mime_type\"] rangeOfString:@\"/\"].location + 1];\n    if([e hasPrefix:@\".\"])\n        e = [e substringFromIndex:1];\n    cell.extension.text = [e uppercaseString];\n\n    if([[file objectForKey:@\"mime_type\"] hasPrefix:@\"image/\"]) {\n        [self->_spinners setObject:cell.spinner forKey:[file objectForKey:@\"id\"]];\n        [self->_imageViews setObject:cell.thumbnail forKey:[file objectForKey:@\"id\"]];\n        [self->_extensions setObject:cell.extension forKey:[file objectForKey:@\"id\"]];\n        YYImage *image = [[ImageCache sharedInstance] imageForFileID:[file objectForKey:@\"id\"] width:(self.view.frame.size.width/2) * [UIScreen mainScreen].scale];\n        if(image) {\n            [cell.thumbnail setImage:image];\n            cell.thumbnail.hidden = NO;\n            cell.extension.hidden = YES;\n            cell.spinner.hidden = YES;\n            [cell.spinner stopAnimating];\n        } else if(cell.extension.hidden) {\n            cell.thumbnail.hidden = YES;\n            cell.spinner.hidden = NO;\n            if(![cell.spinner isAnimating])\n                [cell.spinner startAnimating];\n            [[ImageCache sharedInstance] fetchFileID:[file objectForKey:@\"id\"] width:(self.view.frame.size.width/2) * [UIScreen mainScreen].scale completionHandler:^(BOOL success) {\n                [self _refreshFileID:[file objectForKey:@\"id\"]];\n            }];\n        }\n    } else {\n        cell.extension.hidden = NO;\n        cell.thumbnail.hidden = YES;\n        cell.spinner.hidden = YES;\n        [cell.spinner stopAnimating];\n    }\n    return cell;\n}\n\n- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {\n    return YES;\n}\n\n- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized (self) {\n        if (editingStyle == UITableViewCellEditingStyleDelete) {\n            [[NetworkConnection sharedInstance] deleteFile:[[self->_files objectAtIndex:indexPath.row] objectForKey:@\"id\"] handler:^(IRCCloudJSONObject *result) {\n                if([[result objectForKey:@\"success\"] boolValue]) {\n                    CLS_LOG(@\"File deleted successfully\");\n                } else {\n                    CLS_LOG(@\"Error deleting file: %@\", result);\n                    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to delete file, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                    [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                    [self presentViewController:alert animated:YES completion:nil];\n\n                    self->_pages = 0;\n                    self->_files = nil;\n                    self->_canLoadMore = YES;\n                    [self _loadMore];\n                }\n            }];\n            NSMutableArray *a = self->_files.mutableCopy;\n            [a removeObjectAtIndex:indexPath.row];\n            self->_files = [NSArray arrayWithArray:a];\n            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];\n            if(!_files.count) {\n                UILabel *fail = [[UILabel alloc] init];\n                fail.text = @\"\\nYou haven't uploaded any files yet.\\n\";\n                fail.numberOfLines = 3;\n                fail.textAlignment = NSTextAlignmentCenter;\n                fail.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n                [fail sizeToFit];\n                self.tableView.tableFooterView = fail;\n            }\n            [self scrollViewDidScroll:self.tableView];\n        }\n    }\n}\n\n-(void)saveButtonPressed:(id)sender {\n    if(self->_delegate)\n        [self->_delegate filesTableViewControllerDidSelectFile:self->_selectedFile message:((FileMetadataViewController *)self.navigationController.topViewController).msg.text];\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    self->_selectedFile = [self->_files objectAtIndex:indexPath.row];\n    if(self->_selectedFile) {\n        FileMetadataViewController *c = [[FileMetadataViewController alloc] initWithUploader:nil];\n        c.navigationItem.title = @\"Share a File\";\n        c.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@\"Send\" style:UIBarButtonItemStyleDone target:self action:@selector(saveButtonPressed:)];\n        [c loadView];\n        [c viewDidLoad];\n        int bytes = [[self->_selectedFile objectForKey:@\"size\"] intValue];\n        int exp = (int)(log(bytes) / log(1024));\n        [c setFilename:[self->_selectedFile objectForKey:@\"name\"] metadata:[NSString stringWithFormat:@\"%.1f %cB • %@\", bytes / pow(1024, exp), [@\"KMGTPE\" characterAtIndex:exp -1], [self->_selectedFile objectForKey:@\"mime_type\"]]];\n        [c setImage:[[ImageCache sharedInstance] imageForFileID:[self->_selectedFile objectForKey:@\"id\"] width:(self.view.frame.size.width/2) * [UIScreen mainScreen].scale]];\n        [c setURL:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:self->_selectedFile error:nil]];\n        [self.navigationController pushViewController:c animated:YES];\n    }\n    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/FontAwesome.h",
    "content": "//\n//  FontAwesome.h\n//  IRCCloud\n//\n//  Created by Sam Steele on 9/16/15.\n//  Copyright (c) 2015 IRCCloud, Ltd. All rights reserved.\n//\n\n#ifndef IRCCloud_FontAwesome_h\n#define IRCCloud_FontAwesome_h\n\n#define FA_500PX @\"\\uf26E\"\n#define FA_ADJUST @\"\\uf042\"\n#define FA_ADN @\"\\uf170\"\n#define FA_ALIGN_CENTER @\"\\uf037\"\n#define FA_ALIGN_JUSTIFY @\"\\uf039\"\n#define FA_ALIGN_LEFT @\"\\uf036\"\n#define FA_ALIGN_RIGHT @\"\\uf038\"\n#define FA_AMAZON @\"\\uf270\"\n#define FA_AMBULANCE @\"\\uf0F9\"\n#define FA_ANCHOR @\"\\uf13D\"\n#define FA_ANDROID @\"\\uf17B\"\n#define FA_ANGELLIST @\"\\uf209\"\n#define FA_ANGLE_DOUBLE_DOWN @\"\\uf103\"\n#define FA_ANGLE_DOUBLE_LEFT @\"\\uf100\"\n#define FA_ANGLE_DOUBLE_RIGHT @\"\\uf101\"\n#define FA_ANGLE_DOUBLE_UP @\"\\uf102\"\n#define FA_ANGLE_DOWN @\"\\uf107\"\n#define FA_ANGLE_LEFT @\"\\uf104\"\n#define FA_ANGLE_RIGHT @\"\\uf105\"\n#define FA_ANGLE_UP @\"\\uf106\"\n#define FA_APPLE @\"\\uf179\"\n#define FA_ARCHIVE @\"\\uf187\"\n#define FA_AREA_CHART @\"\\uf1FE\"\n#define FA_ARROW_CIRCLE_DOWN @\"\\uf0AB\"\n#define FA_ARROW_CIRCLE_LEFT @\"\\uf0A8\"\n#define FA_ARROW_CIRCLE_O_DOWN @\"\\uf01A\"\n#define FA_ARROW_CIRCLE_O_LEFT @\"\\uf190\"\n#define FA_ARROW_CIRCLE_O_RIGHT @\"\\uf18E\"\n#define FA_ARROW_CIRCLE_O_UP @\"\\uf01B\"\n#define FA_ARROW_CIRCLE_RIGHT @\"\\uf0A9\"\n#define FA_ARROW_CIRCLE_UP @\"\\uf0AA\"\n#define FA_ARROW_DOWN @\"\\uf063\"\n#define FA_ARROW_LEFT @\"\\uf060\"\n#define FA_ARROW_RIGHT @\"\\uf061\"\n#define FA_ARROW_UP @\"\\uf062\"\n#define FA_ARROWS @\"\\uf047\"\n#define FA_ARROWS_ALT @\"\\uf0B2\"\n#define FA_ARROWS_H @\"\\uf07E\"\n#define FA_ARROWS_V @\"\\uf07D\"\n#define FA_ASTERISK @\"\\uf069\"\n#define FA_AT @\"\\uf1FA\"\n#define FA_AUTOMOBILE @\"\\uf1B9\"\n#define FA_BACKWARD @\"\\uf04A\"\n#define FA_BALANCE_SCALE @\"\\uf24E\"\n#define FA_BAN @\"\\uf05E\"\n#define FA_BANK @\"\\uf19C\"\n#define FA_BAR_CHART @\"\\uf080\"\n#define FA_BAR_CHART_O @\"\\uf080\"\n#define FA_BARCODE @\"\\uf02A\"\n#define FA_BARS @\"\\uf0C9\"\n#define FA_BATTERY_0 @\"\\uf244\"\n#define FA_BATTERY_1 @\"\\uf243\"\n#define FA_BATTERY_2 @\"\\uf242\"\n#define FA_BATTERY_3 @\"\\uf241\"\n#define FA_BATTERY_4 @\"\\uf240\"\n#define FA_BATTERY_EMPTY @\"\\uf244\"\n#define FA_BATTERY_FULL @\"\\uf240\"\n#define FA_BATTERY_HALF @\"\\uf242\"\n#define FA_BATTERY_QUARTER @\"\\uf243\"\n#define FA_BATTERY_THREE_QUARTERS @\"\\uf241\"\n#define FA_BED @\"\\uf236\"\n#define FA_BEER @\"\\uf0FC\"\n#define FA_BEHANCE @\"\\uf1B4\"\n#define FA_BEHANCE_SQUARE @\"\\uf1B5\"\n#define FA_BELL @\"\\uf0F3\"\n#define FA_BELL_O @\"\\uf0A2\"\n#define FA_BELL_SLASH @\"\\uf1F6\"\n#define FA_BELL_SLASH_O @\"\\uf1F7\"\n#define FA_BICYCLE @\"\\uf206\"\n#define FA_BINOCULARS @\"\\uf1E5\"\n#define FA_BIRTHDAY_CAKE @\"\\uf1FD\"\n#define FA_BITBUCKET @\"\\uf171\"\n#define FA_BITBUCKET_SQUARE @\"\\uf172\"\n#define FA_BITCOIN @\"\\uf15A\"\n#define FA_BLACK_TIE @\"\\uf27E\"\n#define FA_BOLD @\"\\uf032\"\n#define FA_BOLT @\"\\uf0E7\"\n#define FA_BOMB @\"\\uf1E2\"\n#define FA_BOOK @\"\\uf02D\"\n#define FA_BOOKMARK @\"\\uf02E\"\n#define FA_BOOKMARK_O @\"\\uf097\"\n#define FA_BRIEFCASE @\"\\uf0B1\"\n#define FA_BTC @\"\\uf15A\"\n#define FA_BUG @\"\\uf188\"\n#define FA_BUILDING @\"\\uf1AD\"\n#define FA_BUILDING_O @\"\\uf0F7\"\n#define FA_BULLHORN @\"\\uf0A1\"\n#define FA_BULLSEYE @\"\\uf140\"\n#define FA_BUS @\"\\uf207\"\n#define FA_BUYSELLADS @\"\\uf20D\"\n#define FA_CAB @\"\\uf1BA\"\n#define FA_CALCULATOR @\"\\uf1EC\"\n#define FA_CALENDAR @\"\\uf073\"\n#define FA_CALENDAR_CHECK_O @\"\\uf274\"\n#define FA_CALENDAR_MINUS_O @\"\\uf272\"\n#define FA_CALENDAR_O @\"\\uf133\"\n#define FA_CALENDAR_PLUS_O @\"\\uf271\"\n#define FA_CALENDAR_TIMES_O @\"\\uf273\"\n#define FA_CAMERA @\"\\uf030\"\n#define FA_CAMERA_RETRO @\"\\uf083\"\n#define FA_CAR @\"\\uf1B9\"\n#define FA_CARET_DOWN @\"\\uf0D7\"\n#define FA_CARET_LEFT @\"\\uf0D9\"\n#define FA_CARET_RIGHT @\"\\uf0DA\"\n#define FA_CARET_SQUARE_O_DOWN @\"\\uf150\"\n#define FA_CARET_SQUARE_O_LEFT @\"\\uf191\"\n#define FA_CARET_SQUARE_O_RIGHT @\"\\uf152\"\n#define FA_CARET_SQUARE_O_UP @\"\\uf151\"\n#define FA_CARET_UP @\"\\uf0D8\"\n#define FA_CART_ARROW_DOWN @\"\\uf218\"\n#define FA_CART_PLUS @\"\\uf217\"\n#define FA_CC @\"\\uf20A\"\n#define FA_CC_AMEX @\"\\uf1F3\"\n#define FA_CC_DINERS_CLUB @\"\\uf24C\"\n#define FA_CC_DISCOVER @\"\\uf1F2\"\n#define FA_CC_JCB @\"\\uf24B\"\n#define FA_CC_MASTERCARD @\"\\uf1F1\"\n#define FA_CC_PAYPAL @\"\\uf1F4\"\n#define FA_CC_STRIPE @\"\\uf1F5\"\n#define FA_CC_VISA @\"\\uf1F0\"\n#define FA_CERTIFICATE @\"\\uf0A3\"\n#define FA_CHAIN @\"\\uf0C1\"\n#define FA_CHAIN_BROKEN @\"\\uf127\"\n#define FA_CHECK @\"\\uf00C\"\n#define FA_CHECK_CIRCLE @\"\\uf058\"\n#define FA_CHECK_CIRCLE_O @\"\\uf05D\"\n#define FA_CHECK_SQUARE @\"\\uf14A\"\n#define FA_CHECK_SQUARE_O @\"\\uf046\"\n#define FA_CHEVRON_CIRCLE_DOWN @\"\\uf13A\"\n#define FA_CHEVRON_CIRCLE_LEFT @\"\\uf137\"\n#define FA_CHEVRON_CIRCLE_RIGHT @\"\\uf138\"\n#define FA_CHEVRON_CIRCLE_UP @\"\\uf139\"\n#define FA_CHEVRON_DOWN @\"\\uf078\"\n#define FA_CHEVRON_LEFT @\"\\uf053\"\n#define FA_CHEVRON_RIGHT @\"\\uf054\"\n#define FA_CHEVRON_UP @\"\\uf077\"\n#define FA_CHILD @\"\\uf1AE\"\n#define FA_CHROME @\"\\uf268\"\n#define FA_CIRCLE @\"\\uf111\"\n#define FA_CIRCLE_O @\"\\uf10C\"\n#define FA_CIRCLE_O_NOTCH @\"\\uf1CE\"\n#define FA_CIRCLE_THIN @\"\\uf1DB\"\n#define FA_CLIPBOARD @\"\\uf0EA\"\n#define FA_CLOCK_O @\"\\uf017\"\n#define FA_CLONE @\"\\uf24D\"\n#define FA_CLOSE @\"\\uf00D\"\n#define FA_CLOUD @\"\\uf0C2\"\n#define FA_CLOUD_DOWNLOAD @\"\\uf0ED\"\n#define FA_CLOUD_UPLOAD @\"\\uf0EE\"\n#define FA_CNY @\"\\uf157\"\n#define FA_CODE @\"\\uf121\"\n#define FA_CODE_FORK @\"\\uf126\"\n#define FA_CODEPEN @\"\\uf1CB\"\n#define FA_COFFEE @\"\\uf0F4\"\n#define FA_COG @\"\\uf013\"\n#define FA_COGS @\"\\uf085\"\n#define FA_COLUMNS @\"\\uf0DB\"\n#define FA_COMMENT @\"\\uf075\"\n#define FA_COMMENT_O @\"\\uf0E5\"\n#define FA_COMMENTING @\"\\uf27A\"\n#define FA_COMMENTING_O @\"\\uf27B\"\n#define FA_COMMENTS @\"\\uf086\"\n#define FA_COMMENTS_O @\"\\uf0E6\"\n#define FA_COMPASS @\"\\uf14E\"\n#define FA_COMPRESS @\"\\uf066\"\n#define FA_CONNECTDEVELOP @\"\\uf20E\"\n#define FA_CONTAO @\"\\uf26D\"\n#define FA_COPY @\"\\uf0C5\"\n#define FA_COPYRIGHT @\"\\uf1F9\"\n#define FA_CREATIVE_COMMONS @\"\\uf25E\"\n#define FA_CREDIT_CARD @\"\\uf09D\"\n#define FA_CROP @\"\\uf125\"\n#define FA_CROSSHAIRS @\"\\uf05B\"\n#define FA_CSS3 @\"\\uf13C\"\n#define FA_CUBE @\"\\uf1B2\"\n#define FA_CUBES @\"\\uf1B3\"\n#define FA_CUT @\"\\uf0C4\"\n#define FA_CUTLERY @\"\\uf0F5\"\n#define FA_DASHBOARD @\"\\uf0E4\"\n#define FA_DASHCUBE @\"\\uf210\"\n#define FA_DATABASE @\"\\uf1C0\"\n#define FA_DEDENT @\"\\uf03B\"\n#define FA_DELICIOUS @\"\\uf1A5\"\n#define FA_DESKTOP @\"\\uf108\"\n#define FA_DEVIANTART @\"\\uf1BD\"\n#define FA_DIAMOND @\"\\uf219\"\n#define FA_DIGG @\"\\uf1A6\"\n#define FA_DOLLAR @\"\\uf155\"\n#define FA_DOT_CIRCLE_O @\"\\uf192\"\n#define FA_DOWNLOAD @\"\\uf019\"\n#define FA_DRIBBBLE @\"\\uf17D\"\n#define FA_DROPBOX @\"\\uf16B\"\n#define FA_DRUPAL @\"\\uf1A9\"\n#define FA_EDIT @\"\\uf044\"\n#define FA_EJECT @\"\\uf052\"\n#define FA_ELLIPSIS_H @\"\\uf141\"\n#define FA_ELLIPSIS_V @\"\\uf142\"\n#define FA_EMPIRE @\"\\uf1D1\"\n#define FA_ENVELOPE @\"\\uf0E0\"\n#define FA_ENVELOPE_O @\"\\uf003\"\n#define FA_ENVELOPE_SQUARE @\"\\uf199\"\n#define FA_ERASER @\"\\uf12D\"\n#define FA_EUR @\"\\uf153\"\n#define FA_EURO @\"\\uf153\"\n#define FA_EXCHANGE @\"\\uf0EC\"\n#define FA_EXCLAMATION @\"\\uf12A\"\n#define FA_EXCLAMATION_CIRCLE @\"\\uf06A\"\n#define FA_EXCLAMATION_TRIANGLE @\"\\uf071\"\n#define FA_EXPAND @\"\\uf065\"\n#define FA_EXPEDITEDSSL @\"\\uf23E\"\n#define FA_EXTERNAL_LINK @\"\\uf08E\"\n#define FA_EXTERNAL_LINK_SQUARE @\"\\uf14C\"\n#define FA_EYE @\"\\uf06E\"\n#define FA_EYE_SLASH @\"\\uf070\"\n#define FA_EYEDROPPER @\"\\uf1FB\"\n#define FA_FACEBOOK @\"\\uf09A\"\n#define FA_FACEBOOK_F @\"\\uf09A\"\n#define FA_FACEBOOK_OFFICIAL @\"\\uf230\"\n#define FA_FACEBOOK_SQUARE @\"\\uf082\"\n#define FA_FAST_BACKWARD @\"\\uf049\"\n#define FA_FAST_FORWARD @\"\\uf050\"\n#define FA_FAX @\"\\uf1AC\"\n#define FA_FEED @\"\\uf09E\"\n#define FA_FEMALE @\"\\uf182\"\n#define FA_FIGHTER_JET @\"\\uf0FB\"\n#define FA_FILE @\"\\uf15B\"\n#define FA_FILE_ARCHIVE_O @\"\\uf1C6\"\n#define FA_FILE_AUDIO_O @\"\\uf1C7\"\n#define FA_FILE_CODE_O @\"\\uf1C9\"\n#define FA_FILE_EXCEL_O @\"\\uf1C3\"\n#define FA_FILE_IMAGE_O @\"\\uf1C5\"\n#define FA_FILE_MOVIE_O @\"\\uf1C8\"\n#define FA_FILE_O @\"\\uf016\"\n#define FA_FILE_PDF_O @\"\\uf1C1\"\n#define FA_FILE_PHOTO_O @\"\\uf1C5\"\n#define FA_FILE_PICTURE_O @\"\\uf1C5\"\n#define FA_FILE_POWERPOINT_O @\"\\uf1C4\"\n#define FA_FILE_SOUND_O @\"\\uf1C7\"\n#define FA_FILE_TEXT @\"\\uf15C\"\n#define FA_FILE_TEXT_O @\"\\uf0F6\"\n#define FA_FILE_VIDEO_O @\"\\uf1C8\"\n#define FA_FILE_WORD_O @\"\\uf1C2\"\n#define FA_FILE_ZIP_O @\"\\uf1C6\"\n#define FA_FILES_O @\"\\uf0C5\"\n#define FA_FILM @\"\\uf008\"\n#define FA_FILTER @\"\\uf0B0\"\n#define FA_FIRE @\"\\uf06D\"\n#define FA_FIRE_EXTINGUISHER @\"\\uf134\"\n#define FA_FIREFOX @\"\\uf269\"\n#define FA_FLAG @\"\\uf024\"\n#define FA_FLAG_CHECKERED @\"\\uf11E\"\n#define FA_FLAG_O @\"\\uf11D\"\n#define FA_FLASH @\"\\uf0E7\"\n#define FA_FLASK @\"\\uf0C3\"\n#define FA_FLICKR @\"\\uf16E\"\n#define FA_FLOPPY_O @\"\\uf0C7\"\n#define FA_FOLDER @\"\\uf07B\"\n#define FA_FOLDER_O @\"\\uf114\"\n#define FA_FOLDER_OPEN @\"\\uf07C\"\n#define FA_FOLDER_OPEN_O @\"\\uf115\"\n#define FA_FONT @\"\\uf031\"\n#define FA_FONTICONS @\"\\uf280\"\n#define FA_FORUMBEE @\"\\uf211\"\n#define FA_FORWARD @\"\\uf04E\"\n#define FA_FOURSQUARE @\"\\uf180\"\n#define FA_FROWN_O @\"\\uf119\"\n#define FA_FUTBOL_O @\"\\uf1E3\"\n#define FA_GAMEPAD @\"\\uf11B\"\n#define FA_GAVEL @\"\\uf0E3\"\n#define FA_GBP @\"\\uf154\"\n#define FA_GE @\"\\uf1D1\"\n#define FA_GEAR @\"\\uf013\"\n#define FA_GEARS @\"\\uf085\"\n#define FA_GENDERLESS @\"\\uf22D\"\n#define FA_GET_POCKET @\"\\uf265\"\n#define FA_GG @\"\\uf260\"\n#define FA_GG_CIRCLE @\"\\uf261\"\n#define FA_GIFT @\"\\uf06B\"\n#define FA_GIT @\"\\uf1D3\"\n#define FA_GIT_SQUARE @\"\\uf1D2\"\n#define FA_GITHUB @\"\\uf09B\"\n#define FA_GITHUB_ALT @\"\\uf113\"\n#define FA_GITHUB_SQUARE @\"\\uf092\"\n#define FA_GITTIP @\"\\uf184\"\n#define FA_GLASS @\"\\uf000\"\n#define FA_GLOBE @\"\\uf0AC\"\n#define FA_GOOGLE @\"\\uf1A0\"\n#define FA_GOOGLE_PLUS @\"\\uf0D5\"\n#define FA_GOOGLE_PLUS_SQUARE @\"\\uf0D4\"\n#define FA_GOOGLE_WALLET @\"\\uf1EE\"\n#define FA_GRADUATION_CAP @\"\\uf19D\"\n#define FA_GRATIPAY @\"\\uf184\"\n#define FA_GROUP @\"\\uf0C0\"\n#define FA_H_SQUARE @\"\\uf0FD\"\n#define FA_HACKER_NEWS @\"\\uf1D4\"\n#define FA_HAND_GRAB_O @\"\\uf255\"\n#define FA_HAND_LIZARD_O @\"\\uf258\"\n#define FA_HAND_O_DOWN @\"\\uf0A7\"\n#define FA_HAND_O_LEFT @\"\\uf0A5\"\n#define FA_HAND_O_RIGHT @\"\\uf0A4\"\n#define FA_HAND_O_UP @\"\\uf0A6\"\n#define FA_HAND_PAPER_O @\"\\uf256\"\n#define FA_HAND_PEACE_O @\"\\uf25B\"\n#define FA_HAND_POINTER_O @\"\\uf25A\"\n#define FA_HAND_ROCK_O @\"\\uf255\"\n#define FA_HAND_SCISSORS_O @\"\\uf257\"\n#define FA_HAND_SPOCK_O @\"\\uf259\"\n#define FA_HAND_STOP_O @\"\\uf256\"\n#define FA_HDD_O @\"\\uf0A0\"\n#define FA_HEADER @\"\\uf1DC\"\n#define FA_HEADPHONES @\"\\uf025\"\n#define FA_HEART @\"\\uf004\"\n#define FA_HEART_O @\"\\uf08A\"\n#define FA_HEARTBEAT @\"\\uf21E\"\n#define FA_HISTORY @\"\\uf1DA\"\n#define FA_HOME @\"\\uf015\"\n#define FA_HOSPITAL_O @\"\\uf0F8\"\n#define FA_HOTEL @\"\\uf236\"\n#define FA_HOURGLASS @\"\\uf254\"\n#define FA_HOURGLASS_1 @\"\\uf251\"\n#define FA_HOURGLASS_2 @\"\\uf252\"\n#define FA_HOURGLASS_3 @\"\\uf253\"\n#define FA_HOURGLASS_END @\"\\uf253\"\n#define FA_HOURGLASS_HALF @\"\\uf252\"\n#define FA_HOURGLASS_O @\"\\uf250\"\n#define FA_HOURGLASS_START @\"\\uf251\"\n#define FA_HOUZZ @\"\\uf27C\"\n#define FA_HTML5 @\"\\uf13B\"\n#define FA_I_CURSOR @\"\\uf246\"\n#define FA_ILS @\"\\uf20B\"\n#define FA_IMAGE @\"\\uf03E\"\n#define FA_INBOX @\"\\uf01C\"\n#define FA_INDENT @\"\\uf03C\"\n#define FA_INDUSTRY @\"\\uf275\"\n#define FA_INFO @\"\\uf129\"\n#define FA_INFO_CIRCLE @\"\\uf05A\"\n#define FA_INR @\"\\uf156\"\n#define FA_INSTAGRAM @\"\\uf16D\"\n#define FA_INSTITUTION @\"\\uf19C\"\n#define FA_INTERNET_EXPLORER @\"\\uf26B\"\n#define FA_INTERSEX @\"\\uf224\"\n#define FA_IOXHOST @\"\\uf208\"\n#define FA_ITALIC @\"\\uf033\"\n#define FA_JOOMLA @\"\\uf1AA\"\n#define FA_JPY @\"\\uf157\"\n#define FA_JSFIDDLE @\"\\uf1CC\"\n#define FA_KEY @\"\\uf084\"\n#define FA_KEYBOARD_O @\"\\uf11C\"\n#define FA_KRW @\"\\uf159\"\n#define FA_LANGUAGE @\"\\uf1AB\"\n#define FA_LAPTOP @\"\\uf109\"\n#define FA_LASTFM @\"\\uf202\"\n#define FA_LASTFM_SQUARE @\"\\uf203\"\n#define FA_LEAF @\"\\uf06C\"\n#define FA_LEANPUB @\"\\uf212\"\n#define FA_LEGAL @\"\\uf0E3\"\n#define FA_LEMON_O @\"\\uf094\"\n#define FA_LEVEL_DOWN @\"\\uf149\"\n#define FA_LEVEL_UP @\"\\uf148\"\n#define FA_LIFE_BOUY @\"\\uf1CD\"\n#define FA_LIFE_BUOY @\"\\uf1CD\"\n#define FA_LIFE_RING @\"\\uf1CD\"\n#define FA_LIFE_SAVER @\"\\uf1CD\"\n#define FA_LIGHTBULB_O @\"\\uf0EB\"\n#define FA_LINE_CHART @\"\\uf201\"\n#define FA_LINK @\"\\uf0C1\"\n#define FA_LINKEDIN @\"\\uf0E1\"\n#define FA_LINKEDIN_SQUARE @\"\\uf08C\"\n#define FA_LINUX @\"\\uf17C\"\n#define FA_LIST @\"\\uf03A\"\n#define FA_LIST_ALT @\"\\uf022\"\n#define FA_LIST_OL @\"\\uf0CB\"\n#define FA_LIST_UL @\"\\uf0CA\"\n#define FA_LOCATION_ARROW @\"\\uf124\"\n#define FA_LOCK @\"\\uf023\"\n#define FA_LONG_ARROW_DOWN @\"\\uf175\"\n#define FA_LONG_ARROW_LEFT @\"\\uf177\"\n#define FA_LONG_ARROW_RIGHT @\"\\uf178\"\n#define FA_LONG_ARROW_UP @\"\\uf176\"\n#define FA_MAGIC @\"\\uf0D0\"\n#define FA_MAGNET @\"\\uf076\"\n#define FA_MAIL_FORWARD @\"\\uf064\"\n#define FA_MAIL_REPLY @\"\\uf112\"\n#define FA_MAIL_REPLY_ALL @\"\\uf122\"\n#define FA_MALE @\"\\uf183\"\n#define FA_MAP @\"\\uf279\"\n#define FA_MAP_MARKER @\"\\uf041\"\n#define FA_MAP_O @\"\\uf278\"\n#define FA_MAP_PIN @\"\\uf276\"\n#define FA_MAP_SIGNS @\"\\uf277\"\n#define FA_MARS @\"\\uf222\"\n#define FA_MARS_DOUBLE @\"\\uf227\"\n#define FA_MARS_STROKE @\"\\uf229\"\n#define FA_MARS_STROKE_H @\"\\uf22B\"\n#define FA_MARS_STROKE_V @\"\\uf22A\"\n#define FA_MAXCDN @\"\\uf136\"\n#define FA_MEANPATH @\"\\uf20C\"\n#define FA_MEDIUM @\"\\uf23A\"\n#define FA_MEDKIT @\"\\uf0FA\"\n#define FA_MEH_O @\"\\uf11A\"\n#define FA_MERCURY @\"\\uf223\"\n#define FA_MICROPHONE @\"\\uf130\"\n#define FA_MICROPHONE_SLASH @\"\\uf131\"\n#define FA_MINUS @\"\\uf068\"\n#define FA_MINUS_CIRCLE @\"\\uf056\"\n#define FA_MINUS_SQUARE @\"\\uf146\"\n#define FA_MINUS_SQUARE_O @\"\\uf147\"\n#define FA_MOBILE @\"\\uf10B\"\n#define FA_MOBILE_PHONE @\"\\uf10B\"\n#define FA_MONEY @\"\\uf0D6\"\n#define FA_MOON_O @\"\\uf186\"\n#define FA_MORTAR_BOARD @\"\\uf19D\"\n#define FA_MOTORCYCLE @\"\\uf21C\"\n#define FA_MOUSE_POINTER @\"\\uf245\"\n#define FA_MUSIC @\"\\uf001\"\n#define FA_NAVICON @\"\\uf0C9\"\n#define FA_NEUTER @\"\\uf22C\"\n#define FA_NEWSPAPER_O @\"\\uf1EA\"\n#define FA_OBJECT_GROUP @\"\\uf247\"\n#define FA_OBJECT_UNGROUP @\"\\uf248\"\n#define FA_ODNOKLASSNIKI @\"\\uf263\"\n#define FA_ODNOKLASSNIKI_SQUARE @\"\\uf264\"\n#define FA_OPENCART @\"\\uf23D\"\n#define FA_OPENID @\"\\uf19B\"\n#define FA_OPERA @\"\\uf26A\"\n#define FA_OPTIN_MONSTER @\"\\uf23C\"\n#define FA_OUTDENT @\"\\uf03B\"\n#define FA_PAGELINES @\"\\uf18C\"\n#define FA_PAINT_BRUSH @\"\\uf1FC\"\n#define FA_PAPER_PLANE @\"\\uf1D8\"\n#define FA_PAPER_PLANE_O @\"\\uf1D9\"\n#define FA_PAPERCLIP @\"\\uf0C6\"\n#define FA_PARAGRAPH @\"\\uf1DD\"\n#define FA_PASTE @\"\\uf0EA\"\n#define FA_PAUSE @\"\\uf04C\"\n#define FA_PAW @\"\\uf1B0\"\n#define FA_PAYPAL @\"\\uf1ED\"\n#define FA_PENCIL @\"\\uf040\"\n#define FA_PENCIL_SQUARE @\"\\uf14B\"\n#define FA_PENCIL_SQUARE_O @\"\\uf044\"\n#define FA_PHONE @\"\\uf095\"\n#define FA_PHONE_SQUARE @\"\\uf098\"\n#define FA_PHOTO @\"\\uf03E\"\n#define FA_PICTURE_O @\"\\uf03E\"\n#define FA_PIE_CHART @\"\\uf200\"\n#define FA_PIED_PIPER @\"\\uf1A7\"\n#define FA_PIED_PIPER_ALT @\"\\uf1A8\"\n#define FA_PINTEREST @\"\\uf0D2\"\n#define FA_PINTEREST_P @\"\\uf231\"\n#define FA_PINTEREST_SQUARE @\"\\uf0D3\"\n#define FA_PLANE @\"\\uf072\"\n#define FA_PLAY @\"\\uf04B\"\n#define FA_PLAY_CIRCLE @\"\\uf144\"\n#define FA_PLAY_CIRCLE_O @\"\\uf01D\"\n#define FA_PLUG @\"\\uf1E6\"\n#define FA_PLUS @\"\\uf067\"\n#define FA_PLUS_CIRCLE @\"\\uf055\"\n#define FA_PLUS_SQUARE @\"\\uf0FE\"\n#define FA_PLUS_SQUARE_O @\"\\uf196\"\n#define FA_POWER_OFF @\"\\uf011\"\n#define FA_PRINT @\"\\uf02F\"\n#define FA_PUZZLE_PIECE @\"\\uf12E\"\n#define FA_QQ @\"\\uf1D6\"\n#define FA_QRCODE @\"\\uf029\"\n#define FA_QUESTION @\"\\uf128\"\n#define FA_QUESTION_CIRCLE @\"\\uf059\"\n#define FA_QUOTE_LEFT @\"\\uf10D\"\n#define FA_QUOTE_RIGHT @\"\\uf10E\"\n#define FA_RA @\"\\uf1D0\"\n#define FA_RANDOM @\"\\uf074\"\n#define FA_REBEL @\"\\uf1D0\"\n#define FA_RECYCLE @\"\\uf1B8\"\n#define FA_REDDIT @\"\\uf1A1\"\n#define FA_REDDIT_SQUARE @\"\\uf1A2\"\n#define FA_REFRESH @\"\\uf021\"\n#define FA_REGISTERED @\"\\uf25D\"\n#define FA_REMOVE @\"\\uf00D\"\n#define FA_RENREN @\"\\uf18B\"\n#define FA_REORDER @\"\\uf0C9\"\n#define FA_REPEAT @\"\\uf01E\"\n#define FA_REPLY @\"\\uf112\"\n#define FA_REPLY_ALL @\"\\uf122\"\n#define FA_RETWEET @\"\\uf079\"\n#define FA_RMB @\"\\uf157\"\n#define FA_ROAD @\"\\uf018\"\n#define FA_ROCKET @\"\\uf135\"\n#define FA_ROTATE_LEFT @\"\\uf0E2\"\n#define FA_ROTATE_RIGHT @\"\\uf01E\"\n#define FA_ROUBLE @\"\\uf158\"\n#define FA_RSS @\"\\uf09E\"\n#define FA_RSS_SQUARE @\"\\uf143\"\n#define FA_RUB @\"\\uf158\"\n#define FA_RUBLE @\"\\uf158\"\n#define FA_RUPEE @\"\\uf156\"\n#define FA_SAFARI @\"\\uf267\"\n#define FA_SAVE @\"\\uf0C7\"\n#define FA_SCISSORS @\"\\uf0C4\"\n#define FA_SEARCH @\"\\uf002\"\n#define FA_SEARCH_MINUS @\"\\uf010\"\n#define FA_SEARCH_PLUS @\"\\uf00E\"\n#define FA_SELLSY @\"\\uf213\"\n#define FA_SEND @\"\\uf1D8\"\n#define FA_SEND_O @\"\\uf1D9\"\n#define FA_SERVER @\"\\uf233\"\n#define FA_SHARE @\"\\uf064\"\n#define FA_SHARE_ALT @\"\\uf1E0\"\n#define FA_SHARE_ALT_SQUARE @\"\\uf1E1\"\n#define FA_SHARE_SQUARE @\"\\uf14D\"\n#define FA_SHARE_SQUARE_O @\"\\uf045\"\n#define FA_SHEKEL @\"\\uf20B\"\n#define FA_SHEQEL @\"\\uf20B\"\n#define FA_SHIELD @\"\\uf132\"\n#define FA_SHIP @\"\\uf21A\"\n#define FA_SHIRTSINBULK @\"\\uf214\"\n#define FA_SHOPPING_CART @\"\\uf07A\"\n#define FA_SIGN_IN @\"\\uf090\"\n#define FA_SIGN_OUT @\"\\uf08B\"\n#define FA_SIGNAL @\"\\uf012\"\n#define FA_SIMPLYBUILT @\"\\uf215\"\n#define FA_SITEMAP @\"\\uf0E8\"\n#define FA_SKYATLAS @\"\\uf216\"\n#define FA_SKYPE @\"\\uf17E\"\n#define FA_SLACK @\"\\uf198\"\n#define FA_SLIDERS @\"\\uf1DE\"\n#define FA_SLIDESHARE @\"\\uf1E7\"\n#define FA_SMILE_O @\"\\uf118\"\n#define FA_SOCCER_BALL_O @\"\\uf1E3\"\n#define FA_SORT @\"\\uf0DC\"\n#define FA_SORT_ALPHA_ASC @\"\\uf15D\"\n#define FA_SORT_ALPHA_DESC @\"\\uf15E\"\n#define FA_SORT_AMOUNT_ASC @\"\\uf160\"\n#define FA_SORT_AMOUNT_DESC @\"\\uf161\"\n#define FA_SORT_ASC @\"\\uf0DE\"\n#define FA_SORT_DESC @\"\\uf0DD\"\n#define FA_SORT_DOWN @\"\\uf0DD\"\n#define FA_SORT_NUMERIC_ASC @\"\\uf162\"\n#define FA_SORT_NUMERIC_DESC @\"\\uf163\"\n#define FA_SORT_UP @\"\\uf0DE\"\n#define FA_SOUNDCLOUD @\"\\uf1BE\"\n#define FA_SPACE_SHUTTLE @\"\\uf197\"\n#define FA_SPINNER @\"\\uf110\"\n#define FA_SPOON @\"\\uf1B1\"\n#define FA_SPOTIFY @\"\\uf1BC\"\n#define FA_SQUARE @\"\\uf0C8\"\n#define FA_SQUARE_O @\"\\uf096\"\n#define FA_STACK_EXCHANGE @\"\\uf18D\"\n#define FA_STACK_OVERFLOW @\"\\uf16C\"\n#define FA_STAR @\"\\uf005\"\n#define FA_STAR_HALF @\"\\uf089\"\n#define FA_STAR_HALF_EMPTY @\"\\uf123\"\n#define FA_STAR_HALF_FULL @\"\\uf123\"\n#define FA_STAR_HALF_O @\"\\uf123\"\n#define FA_STAR_O @\"\\uf006\"\n#define FA_STEAM @\"\\uf1B6\"\n#define FA_STEAM_SQUARE @\"\\uf1B7\"\n#define FA_STEP_BACKWARD @\"\\uf048\"\n#define FA_STEP_FORWARD @\"\\uf051\"\n#define FA_STETHOSCOPE @\"\\uf0F1\"\n#define FA_STICKY_NOTE @\"\\uf249\"\n#define FA_STICKY_NOTE_O @\"\\uf24A\"\n#define FA_STOP @\"\\uf04D\"\n#define FA_STREET_VIEW @\"\\uf21D\"\n#define FA_STRIKETHROUGH @\"\\uf0CC\"\n#define FA_STUMBLEUPON @\"\\uf1A4\"\n#define FA_STUMBLEUPON_CIRCLE @\"\\uf1A3\"\n#define FA_SUBSCRIPT @\"\\uf12C\"\n#define FA_SUBWAY @\"\\uf239\"\n#define FA_SUITCASE @\"\\uf0F2\"\n#define FA_SUN_O @\"\\uf185\"\n#define FA_SUPERSCRIPT @\"\\uf12B\"\n#define FA_SUPPORT @\"\\uf1CD\"\n#define FA_TABLE @\"\\uf0CE\"\n#define FA_TABLET @\"\\uf10A\"\n#define FA_TACHOMETER @\"\\uf0E4\"\n#define FA_TAG @\"\\uf02B\"\n#define FA_TAGS @\"\\uf02C\"\n#define FA_TASKS @\"\\uf0AE\"\n#define FA_TAXI @\"\\uf1BA\"\n#define FA_TELEVISION @\"\\uf26C\"\n#define FA_TENCENT_WEIBO @\"\\uf1D5\"\n#define FA_TERMINAL @\"\\uf120\"\n#define FA_TEXT_HEIGHT @\"\\uf034\"\n#define FA_TEXT_WIDTH @\"\\uf035\"\n#define FA_TH @\"\\uf00A\"\n#define FA_TH_LARGE @\"\\uf009\"\n#define FA_TH_LIST @\"\\uf00B\"\n#define FA_THUMB_TACK @\"\\uf08D\"\n#define FA_THUMBS_DOWN @\"\\uf165\"\n#define FA_THUMBS_O_DOWN @\"\\uf088\"\n#define FA_THUMBS_O_UP @\"\\uf087\"\n#define FA_THUMBS_UP @\"\\uf164\"\n#define FA_TICKET @\"\\uf145\"\n#define FA_TIMES @\"\\uf00D\"\n#define FA_TIMES_CIRCLE @\"\\uf057\"\n#define FA_TIMES_CIRCLE_O @\"\\uf05C\"\n#define FA_TINT @\"\\uf043\"\n#define FA_TOGGLE_DOWN @\"\\uf150\"\n#define FA_TOGGLE_LEFT @\"\\uf191\"\n#define FA_TOGGLE_OFF @\"\\uf204\"\n#define FA_TOGGLE_ON @\"\\uf205\"\n#define FA_TOGGLE_RIGHT @\"\\uf152\"\n#define FA_TOGGLE_UP @\"\\uf151\"\n#define FA_TRADEMARK @\"\\uf25C\"\n#define FA_TRAIN @\"\\uf238\"\n#define FA_TRANSGENDER @\"\\uf224\"\n#define FA_TRANSGENDER_ALT @\"\\uf225\"\n#define FA_TRASH @\"\\uf1F8\"\n#define FA_TRASH_O @\"\\uf014\"\n#define FA_TREE @\"\\uf1BB\"\n#define FA_TRELLO @\"\\uf181\"\n#define FA_TRIPADVISOR @\"\\uf262\"\n#define FA_TROPHY @\"\\uf091\"\n#define FA_TRUCK @\"\\uf0D1\"\n#define FA_TRY @\"\\uf195\"\n#define FA_TTY @\"\\uf1E4\"\n#define FA_TUMBLR @\"\\uf173\"\n#define FA_TUMBLR_SQUARE @\"\\uf174\"\n#define FA_TURKISH_LIRA @\"\\uf195\"\n#define FA_TV @\"\\uf26C\"\n#define FA_TWITCH @\"\\uf1E8\"\n#define FA_TWITTER @\"\\uf099\"\n#define FA_TWITTER_SQUARE @\"\\uf081\"\n#define FA_UMBRELLA @\"\\uf0E9\"\n#define FA_UNDERLINE @\"\\uf0CD\"\n#define FA_UNDO @\"\\uf0E2\"\n#define FA_UNIVERSITY @\"\\uf19C\"\n#define FA_UNLINK @\"\\uf127\"\n#define FA_UNLOCK @\"\\uf09C\"\n#define FA_UNLOCK_ALT @\"\\uf13E\"\n#define FA_UNSORTED @\"\\uf0DC\"\n#define FA_UPLOAD @\"\\uf093\"\n#define FA_USD @\"\\uf155\"\n#define FA_USER @\"\\uf007\"\n#define FA_USER_MD @\"\\uf0F0\"\n#define FA_USER_PLUS @\"\\uf234\"\n#define FA_USER_SECRET @\"\\uf21B\"\n#define FA_USER_TIMES @\"\\uf235\"\n#define FA_USERS @\"\\uf0C0\"\n#define FA_VENUS @\"\\uf221\"\n#define FA_VENUS_DOUBLE @\"\\uf226\"\n#define FA_VENUS_MARS @\"\\uf228\"\n#define FA_VIACOIN @\"\\uf237\"\n#define FA_VIDEO_CAMERA @\"\\uf03D\"\n#define FA_VIMEO @\"\\uf27D\"\n#define FA_VIMEO_SQUARE @\"\\uf194\"\n#define FA_VINE @\"\\uf1CA\"\n#define FA_VK @\"\\uf189\"\n#define FA_VOLUME_DOWN @\"\\uf027\"\n#define FA_VOLUME_OFF @\"\\uf026\"\n#define FA_VOLUME_UP @\"\\uf028\"\n#define FA_WARNING @\"\\uf071\"\n#define FA_WECHAT @\"\\uf1D7\"\n#define FA_WEIBO @\"\\uf18A\"\n#define FA_WEIXIN @\"\\uf1D7\"\n#define FA_WHATSAPP @\"\\uf232\"\n#define FA_WHEELCHAIR @\"\\uf193\"\n#define FA_WIFI @\"\\uf1EB\"\n#define FA_WIKIPEDIA_W @\"\\uf266\"\n#define FA_WINDOWS @\"\\uf17A\"\n#define FA_WON @\"\\uf159\"\n#define FA_WORDPRESS @\"\\uf19A\"\n#define FA_WRENCH @\"\\uf0AD\"\n#define FA_XING @\"\\uf168\"\n#define FA_XING_SQUARE @\"\\uf169\"\n#define FA_Y_COMBINATOR @\"\\uf23B\"\n#define FA_Y_COMBINATOR_SQUARE @\"\\uf1D4\"\n#define FA_YAHOO @\"\\uf19E\"\n#define FA_YC @\"\\uf23B\"\n#define FA_YC_SQUARE @\"\\uf1D4\"\n#define FA_YELP @\"\\uf1E9\"\n#define FA_YEN @\"\\uf157\"\n#define FA_YOUTUBE @\"\\uf167\"\n#define FA_YOUTUBE_PLAY @\"\\uf16A\"\n#define FA_YOUTUBE_SQUARE @\"\\uf166\"\n\n#endif\n"
  },
  {
    "path": "IRCCloud/Classes/HighlightsCountView.h",
    "content": "//\n//  HighlightsCountView.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n\n@interface HighlightsCountView : UIView {\n    NSString *_count;\n    UIFont *_font;\n}\n@property NSString *count;\n@property UIFont *font;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/HighlightsCountView.m",
    "content": "//\n//  HighlightsCountView.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"HighlightsCountView.h\"\n\n@implementation HighlightsCountView\n\n- (id)initWithCoder:(NSCoder *)aDecoder {\n    self = [super initWithCoder:aDecoder];\n    if (self) {\n        self->_font = [UIFont boldSystemFontOfSize:14];\n        self.backgroundColor = [UIColor clearColor];\n    }\n    return self;\n}\n\n-(id)initWithFrame:(CGRect)frame {\n    self = [super initWithFrame:frame];\n    if (self) {\n        self->_font = [UIFont boldSystemFontOfSize:14];\n        self.backgroundColor = [UIColor clearColor];\n    }\n    return self;\n}\n\n-(void)setCount:(NSString *)count {\n    self->_count = count;\n    [self invalidateIntrinsicContentSize];\n    [self setNeedsDisplay];\n}\n\n-(NSString *)count {\n    return _count;\n}\n\n- (void)drawRect:(CGRect)rect {\n    CGContextRef ctx = UIGraphicsGetCurrentContext();\n    CGContextSaveGState(ctx);\n    CGContextAddEllipseInRect(ctx, rect);\n    CGContextSetFillColorWithColor(ctx, [[UIColor redColor] CGColor]);\n    CGContextFillPath(ctx);\n    CGContextRestoreGState(ctx);\n    CGContextSaveGState(ctx);\n    [[UIColor whiteColor] set];\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n    CGSize size = [self->_count sizeWithFont:self->_font forWidth:rect.size.width lineBreakMode:NSLineBreakByClipping];\n    [self->_count drawInRect:CGRectMake(rect.origin.x + ((rect.size.width - size.width) / 2), rect.origin.y + ((rect.size.height - size.height) / 2), size.width, size.height)\n              withFont:self->_font];\n#pragma GCC diagnostic pop\n    CGContextRestoreGState(ctx);\n}\n\n-(CGSize)intrinsicContentSize {\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n    CGSize size = [self->_count sizeWithFont:self->_font forWidth:INT_MAX lineBreakMode:NSLineBreakByClipping];\n#pragma GCC diagnostic pop\n    size.width += 6;\n    size.height += 6;\n    if(size.width < size.height)\n        size.width = size.height;\n    return size;\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/IRCCloudJSONObject.h",
    "content": "//\n//  IRCCloudJSONObject.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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@interface IRCCloudJSONObject : NSObject {\n    NSDictionary *_dict;\n    NSString *_type;\n    int _cid;\n    int _bid;\n    NSTimeInterval _eid;\n}\n-(id)initWithDictionary:(NSDictionary *)dict;\n-(NSString *)type;\n-(int)cid;\n-(int)bid;\n-(NSTimeInterval)eid;\n-(id)objectForKey:(NSString *)key;\n-(NSDictionary *)dictionary;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/IRCCloudJSONObject.m",
    "content": "//\n//  IRCCloudJSONObject.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"IRCCloudJSONObject.h\"\n\n@implementation IRCCloudJSONObject\n-(id)initWithDictionary:(NSDictionary *)dict {\n    self = [super init];\n    if(self) {\n        self->_dict = dict;\n        self->_type = [self->_dict objectForKey:@\"type\"];\n        if([self->_dict objectForKey:@\"cid\"])\n            self->_cid = [[self->_dict objectForKey:@\"cid\"] intValue];\n        else\n            self->_cid = -1;\n        if([self->_dict objectForKey:@\"bid\"])\n            self->_bid = [[self->_dict objectForKey:@\"bid\"] intValue];\n        else\n            self->_bid = -1;\n        if([self->_dict objectForKey:@\"eid\"])\n            self->_eid = [[self->_dict objectForKey:@\"eid\"] doubleValue];\n        else\n            self->_eid = -1;\n    }\n    return self;\n}\n-(NSString *)type {\n    return _type;\n}\n-(int)cid {\n    return _cid;\n}\n-(int)bid {\n    return _bid;\n}\n-(NSTimeInterval)eid {\n    return _eid;\n}\n-(id)objectForKey:(NSString *)key {\n    id obj = [self->_dict objectForKey:key];\n    if(obj)\n        return obj;\n    if([key isEqualToString:@\"success\"])\n        return @YES;\n    return nil;\n}\n-(NSString *)description {\n    return [self->_dict description];\n}\n-(NSDictionary *)dictionary {\n    return _dict;\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/IRCCloudSafariViewController.h",
    "content": "//\n//  IRCCloudSafariViewController.h\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import <SafariServices/SafariServices.h>\n\n@interface IRCCloudSafariViewController : SFSafariViewController {\n    NSURL *_url;\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/IRCCloudSafariViewController.m",
    "content": "//\n//  IRCCloudSafariViewController.m\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import <MobileCoreServices/UTCoreTypes.h>\n#import <SafariServices/SafariServices.h>\n#import \"OpenInChromeController.h\"\n#import \"OpenInFirefoxControllerObjC.h\"\n#import \"IRCCloudSafariViewController.h\"\n#import \"ARChromeActivity.h\"\n#import \"TUSafariActivity.h\"\n#import \"AppDelegate.h\"\n#import \"MainViewController.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@implementation IRCCloudSafariViewController\n\n- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {\n    NSMutableArray *items = @[\n             [UIPreviewAction actionWithTitle:@\"Copy URL\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                 UIPasteboard *pb = [UIPasteboard generalPasteboard];\n                 [pb setValue:self->_url.absoluteString forPasteboardType:(NSString *)kUTTypeUTF8PlainText];\n             }],\n             [UIPreviewAction actionWithTitle:@\"Share\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                 UIApplication *app = [UIApplication sharedApplication];\n                 AppDelegate *appDelegate = (AppDelegate *)app.delegate;\n                 MainViewController *mainViewController = [appDelegate mainViewController];\n\n                 [UIColor clearTheme];\n                 UIActivityViewController *activityController = [URLHandler activityControllerForItems:@[self->_url] type:@\"URL\"];\n                 activityController.popoverPresentationController.sourceView = mainViewController.slidingViewController.view;\n                 [mainViewController.slidingViewController presentViewController:activityController animated:YES completion:nil];\n             }]\n     ].mutableCopy;\n    \n    [items addObject:[UIPreviewAction actionWithTitle:@\"Open in Browser\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n        if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Chrome\"] && [[OpenInChromeController sharedInstance] openInChrome:self->_url\n                                              withCallbackURL:[NSURL URLWithString:\n#ifdef ENTERPRISE\n                                                               @\"irccloud-enterprise://\"\n#else\n                                                               @\"irccloud://\"\n#endif\n                                                               ]\n                                                 createNewTab:NO])\n            return;\n        else if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Firefox\"] && [[OpenInFirefoxControllerObjC sharedInstance] openInFirefox:self->_url])\n            return;\n        else\n            [[UIApplication sharedApplication] openURL:self->_url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n    }]\n];\n    \n    return items;\n}\n\n-(instancetype)initWithURL:(NSURL *)URL {\n    self = [super initWithURL:URL];\n    if(self) {\n        self->_url = URL;\n    }\n    return self;\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/IRCColorPickerView.h",
    "content": "//\n//  IRCColorPickerView.h\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n\n@protocol IRCColorPickerViewDelegate<NSObject>\n-(void)foregroundColorPicked:(UIColor *)color;\n-(void)backgroundColorPicked:(UIColor *)color;\n-(void)closeColorPicker;\n@end\n\n@interface IRCColorPickerView : UIControl {\n    UIButton *_fg[16];\n    UIButton *_bg[16];\n}\n@property (assign) id<IRCColorPickerViewDelegate> delegate;\n-(void)updateButtonColors:(BOOL)background;\n@end\n\n"
  },
  {
    "path": "IRCCloud/Classes/IRCColorPickerView.m",
    "content": "//\n//  IRCColorPickerView.m\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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#import \"IRCColorPickerView.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@implementation IRCColorPickerView\n\n-(instancetype)initWithFrame:(CGRect)frame {\n    self = [super initWithFrame:frame];\n    if (self) {\n        for(int i = 0; i < 16; i++) {\n            self->_fg[i] = [UIButton buttonWithType:UIButtonTypeCustom];\n            self->_fg[i].layer.borderColor = [UIColor blackColor].CGColor;\n            self->_fg[i].layer.borderWidth = 1;\n            [self->_fg[i] addTarget:self action:@selector(fgButtonPressed:) forControlEvents:UIControlEventTouchUpInside];\n            [self addSubview:self->_fg[i]];\n            self->_bg[i] = [UIButton buttonWithType:UIButtonTypeCustom];\n            self->_bg[i].layer.borderColor = [UIColor blackColor].CGColor;\n            self->_bg[i].layer.borderWidth = 1;\n            [self->_bg[i] addTarget:self action:@selector(bgButtonPressed:) forControlEvents:UIControlEventTouchUpInside];\n            [self addSubview:self->_bg[i]];\n        }\n        self.layer.masksToBounds = YES;\n        self.layer.cornerRadius = 4;\n    }\n    return self;\n}\n\n-(void)fgButtonPressed:(UIButton *)sender {\n    [self->_delegate foregroundColorPicked:sender.backgroundColor];\n}\n\n-(void)bgButtonPressed:(UIButton *)sender {\n    [self->_delegate backgroundColorPicked:sender.backgroundColor];\n}\n\n-(void)close:(id)sender {\n    [self->_delegate closeColorPicker];\n}\n\n-(CGSize)intrinsicContentSize {\n    return CGSizeMake(304, 73);\n}\n\n-(void)layoutSubviews {\n    CGFloat bw = self.bounds.size.width / 8;\n\n    for(int i = 0; i < 8; i++) {\n        self->_fg[i].frame = CGRectMake(i*bw + 3, 3, bw - 6, bw - 6);\n        self->_fg[i].layer.cornerRadius = (bw - 6) / 2;\n        self->_bg[i].frame = CGRectMake(i*bw + 3, 3, bw - 6, bw - 6);\n        self->_bg[i].layer.cornerRadius = (bw - 6) / 2;\n    }\n\n    for(int i = 0; i < 8; i++) {\n        self->_fg[i+8].frame = CGRectMake(i*bw + 3, 38, bw - 6, bw - 6);\n        self->_fg[i+8].layer.cornerRadius = (bw - 6) / 2;\n        self->_bg[i+8].frame = CGRectMake(i*bw + 3, 38, bw - 6, bw - 6);\n        self->_bg[i+8].layer.cornerRadius = (bw - 6) / 2;\n    }\n}\n\n-(void)updateButtonColors:(BOOL)background {\n    self.backgroundColor = [UIColor bufferBackgroundColor];\n    //self.layer.borderWidth = 1;\n    //self.layer.borderColor = [UIColor bufferBorderColor].CGColor;\n\n    for(int i = 0; i < 16; i++)\n        self->_fg[i].backgroundColor = [UIColor mIRCColor:i background:NO];\n\n    for(int i = 0; i < 16; i++)\n        self->_bg[i].backgroundColor = [UIColor mIRCColor:i background:YES];\n    \n    if(background) {\n        for(int i = 0; i < 16; i++)\n            self->_fg[i].hidden = YES;\n        for(int i = 0; i < 16; i++)\n            self->_bg[i].hidden = NO;\n    } else {\n        for(int i = 0; i < 16; i++)\n            self->_fg[i].hidden = NO;\n        for(int i = 0; i < 16; i++)\n            self->_bg[i].hidden = YES;\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/Ignore.h",
    "content": "//\n//  Ignore.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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@interface Ignore : NSObject {\n    NSMutableArray *_ignores;\n    NSMutableDictionary *_ignoreCache;\n}\n-(void)addMask:(NSString *)mask;\n-(void)setIgnores:(NSArray *)ignores;\n-(BOOL)match:(NSString *)usermask;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/Ignore.m",
    "content": "//\n//  Ignore.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"Ignore.h\"\n\n@implementation Ignore\n-(void)addMask:(NSString *)mask {\n    @synchronized(self) {\n        if(!_ignores)\n            self->_ignores = [[NSMutableArray alloc] init];\n        if(!_ignoreCache)\n            self->_ignoreCache = [[NSMutableDictionary alloc] init];\n        [self->_ignores addObject:mask];\n        [self->_ignoreCache removeAllObjects];\n    }\n}\n\n-(void)setIgnores:(NSArray *)ignores {\n    @synchronized(self) {\n        if(!_ignores)\n            self->_ignores = [[NSMutableArray alloc] init];\n        if(!_ignoreCache)\n            self->_ignoreCache = [[NSMutableDictionary alloc] init];\n        [self->_ignores removeAllObjects];\n        [self->_ignoreCache removeAllObjects];\n    }\n    for(NSString *ignore in ignores) {\n        NSString *mask = [ignore lowercaseString];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"\\\\\" withString:@\"\\\\\\\\\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"(\" withString:@\"\\\\(\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\")\" withString:@\"\\\\)\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"[\" withString:@\"\\\\[\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"]\" withString:@\"\\\\]\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"{\" withString:@\"\\\\{\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"}\" withString:@\"\\\\}\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"-\" withString:@\"\\\\-\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"^\" withString:@\"\\\\^\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"$\" withString:@\"\\\\$\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"+\" withString:@\"\\\\+\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"?\" withString:@\"\\\\?\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\".\" withString:@\"\\\\.\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\",\" withString:@\"\\\\,\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"#\" withString:@\"\\\\#\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"|\" withString:@\"\\\\|\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"*\" withString:@\".*\"];\n        mask = [mask stringByReplacingOccurrencesOfString:@\"!~\" withString:@\"!\"];\n        if([mask rangeOfString:@\"!\"].location == NSNotFound) {\n            if([mask rangeOfString:@\"@\"].location == NSNotFound) {\n                mask = [mask stringByAppendingString:@\"!.*\"];\n            } else {\n                mask = [NSString stringWithFormat:@\".*!%@\", mask];\n            }\n        }\n        if([mask rangeOfString:@\"@\"].location == NSNotFound) {\n            if([mask rangeOfString:@\"!\"].location == NSNotFound) {\n                mask = [mask stringByAppendingString:@\"@.*\"];\n            } else {\n                mask = [mask stringByReplacingOccurrencesOfString:@\"!\" withString:@\"!.*@\"];\n            }\n        }\n        if([mask isEqualToString:@\".*!.*@.*\"])\n            continue;\n        @synchronized(self) {\n            [self->_ignores addObject:mask];\n        }\n    }\n}\n\n-(BOOL)match:(NSString *)usermask {\n    @synchronized(self) {\n        if(usermask && [self->_ignoreCache objectForKey:usermask])\n            return [[self->_ignoreCache objectForKey:usermask] boolValue];\n        if(usermask && _ignores.count) {\n            for(NSString *ignore in _ignores) {\n                if(ignore) {\n                    usermask = [[usermask stringByReplacingOccurrencesOfString:@\"!~\" withString:@\"!\"] lowercaseString];\n                    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@\"^%@$\",ignore] options:0 error:NULL];\n                    if([regex rangeOfFirstMatchInString:usermask options:0 range:NSMakeRange(0, [usermask length])].location != NSNotFound) {\n                        [self->_ignoreCache setObject:@(YES) forKey:usermask];\n                        return YES;\n                    }\n                }\n            }\n            [self->_ignoreCache setObject:@(NO) forKey:usermask];\n        }\n        return NO;\n    }\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/IgnoresTableViewController.h",
    "content": "//\n//  IgnoresTableViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"IRCCloudJSONObject.h\"\n\n@interface IgnoresTableViewController : UITableViewController {\n    NSArray *_ignores;\n    UIBarButtonItem *_addButton;\n    int _cid;\n    UILabel *_placeholder;\n}\n@property (strong) NSArray *ignores;\n@property int cid;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/IgnoresTableViewController.m",
    "content": "//\n//  IgnoresTableViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"IgnoresTableViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"ColorFormatter.h\"\n\n@implementation IgnoresTableViewController\n\n-(id)initWithStyle:(UITableViewStyle)style {\n    self = [super initWithStyle:style];\n    if (self) {\n        self->_addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonPressed)];\n        self->_placeholder = [[UILabel alloc] initWithFrame:CGRectZero];\n        self->_placeholder.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n        self->_placeholder.numberOfLines = 0;\n        self->_placeholder.text = @\"You're not ignoring anyone at the moment.\\n\\nYou can ignore someone by tapping their nickname in the user list, long-pressing a message, or by using `/ignore`.\\n\";\n        self->_placeholder.attributedText = [ColorFormatter format:[self->_placeholder.text insertCodeSpans] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil];\n        self->_placeholder.textAlignment = NSTextAlignmentCenter;\n    }\n    return self;\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.navigationItem.leftBarButtonItem = self->_addButton;\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed)];\n    self.tableView.backgroundColor = [[UITableViewCell appearance] backgroundColor];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    self->_placeholder.frame = CGRectInset(self.tableView.frame, 12, 0);\n    if(self->_ignores.count)\n        [self->_placeholder removeFromSuperview];\n    else\n        [self.tableView.superview addSubview:self->_placeholder];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    Server *s = nil;\n    \n    switch(event) {\n        case kIRCEventSetIgnores:\n            s = [[ServersDataSource sharedInstance] getServer:self->_cid];\n            self->_ignores = s.ignores;\n            if(self->_ignores.count)\n                [self->_placeholder removeFromSuperview];\n            else\n                [self.tableView.superview addSubview:self->_placeholder];\n            [self.tableView reloadData];\n            break;\n        default:\n            break;\n    }\n}\n\n-(void)doneButtonPressed {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)addButtonPressed {\n    [self.view endEditing:YES];\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_cid];\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Ignore this hostmask\" preferredStyle:UIAlertControllerStyleAlert];\n    \n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Ignore\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n        if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n            [[NetworkConnection sharedInstance] ignore:((UITextField *)[alert.textFields objectAtIndex:0]).text cid:self->_cid handler:nil];\n        }\n    }]];\n    \n    [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n        textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n    }];\n    \n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n#pragma mark - Table view data source\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    return [[self->_ignores objectAtIndex:indexPath.row] boundingRectWithSize:CGSizeMake(self.tableView.frame.size.width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:18]} context:nil].size.height + 16;\n}\n\n-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    if([self->_ignores count])\n        self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;\n    else\n        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    @synchronized(self->_ignores) {\n        return [self->_ignores count];\n    }\n}\n\n-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized(self->_ignores) {\n        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"ignorescell\"];\n        if(!cell)\n            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"ignorescell\"];\n        cell.textLabel.text = [self->_ignores objectAtIndex:[indexPath row]];\n        cell.textLabel.font = [UIFont boldSystemFontOfSize:18];\n        cell.textLabel.numberOfLines = 0;\n        cell.textLabel.lineBreakMode = NSLineBreakByCharWrapping;\n        return cell;\n    }\n}\n\n-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {\n    return YES;\n}\n\n-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {\n    if (editingStyle == UITableViewCellEditingStyleDelete && indexPath.row < _ignores.count) {\n        NSString *mask = [self->_ignores objectAtIndex:indexPath.row];\n        [[NetworkConnection sharedInstance] unignore:mask cid:self->_cid handler:nil];\n    }\n}\n\n#pragma mark - Table view delegate\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [tableView deselectRowAtIndexPath:indexPath animated:NO];\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ImageCache.h",
    "content": "//\n//  ImageCache.h\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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#import <Foundation/Foundation.h>\n#import \"YYImage.h\"\n\ntypedef void (^imageCompletionHandler)(BOOL);\n\n@interface ImageCache : NSObject {\n    NSURL *_cachePath;\n    NSURLSession *_session;\n    NSMutableDictionary *_tasks;\n    NSMutableDictionary *_images;\n    NSMutableDictionary *_failures;\n}\n\n+(ImageCache *)sharedInstance;\n+(NSString *)md5:(NSString *)string;\n-(void)prune;\n-(void)clear;\n-(void)clearFailedURLs;\n-(void)purge;\n-(BOOL)isValidURL:(NSURL *)url;\n-(BOOL)isValidFileID:(NSString *)url;\n-(BOOL)isValidFileID:(NSString *)url width:(int)width;\n-(BOOL)isLoaded:(NSURL *)url;\n-(BOOL)isLoaded:(NSString *)fileID width:(int)width;\n-(NSURL *)pathForURL:(NSURL *)url;\n-(NSURL *)pathForFileID:(NSString *)fileID;\n-(NSURL *)pathForFileID:(NSString *)fileID width:(int)width;\n-(YYImage *)imageForURL:(NSURL *)url;\n-(YYImage *)imageForFileID:(NSString *)fileID;\n-(YYImage *)imageForFileID:(NSString *)fileID width:(int)width;\n-(void)fetchURL:(NSURL *)url completionHandler:(imageCompletionHandler)handler;\n-(void)fetchFileID:(NSString *)fileID completionHandler:(imageCompletionHandler)handler;\n-(void)fetchFileID:(NSString *)fileID width:(int)width completionHandler:(imageCompletionHandler)handler;\n-(NSTimeInterval)ageOfCache:(NSURL *)url;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ImageCache.m",
    "content": "//  ImageCache.h\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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#import <CommonCrypto/CommonDigest.h>\n#import \"ImageCache.h\"\n#import \"NetworkConnection.h\"\n\n@implementation ImageCache\n\n+(ImageCache *)sharedInstance {\n    static ImageCache *sharedInstance;\n    \n    @synchronized(self) {\n        if(!sharedInstance)\n            sharedInstance = [[ImageCache alloc] init];\n        \n        return sharedInstance;\n    }\n    return nil;\n}\n\n-(id)init {\n    self = [super init];\n    if(self) {\n#ifdef ENTERPRISE\n        NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.enterprise.share\"];\n#else\n        NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.share\"];\n#endif\n        int memoryCacheSize = 1024*1024*16; //16MB\n        int diskCacheSize = 1024*1024*500; //500MB\n        NSURLCache *httpCache = [[NSURLCache alloc] initWithMemoryCapacity:memoryCacheSize diskCapacity:diskCacheSize diskPath:@\"httpCache\"];\n        [NSURLCache setSharedURLCache:httpCache];\n        self->_cachePath = [sharedcontainer URLByAppendingPathComponent:@\"imagecache\"];\n\n        NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration];\n        config.timeoutIntervalForRequest = 30;\n        config.URLCache = httpCache;\n        config.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;\n        config.waitsForConnectivity = NO;\n        self->_session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:NSOperationQueue.mainQueue];\n        self->_tasks = [[NSMutableDictionary alloc] init];\n        self->_images = [[NSMutableDictionary alloc] init];\n        self->_failures = [[NSMutableDictionary alloc] init];\n        [self clear];\n    }\n    return self;\n}\n\n-(void)prune {\n    __block BOOL __interrupt = NO;\n#ifndef EXTENSION\n    UIBackgroundTaskIdentifier background_task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^ {\n        CLS_LOG(@\"ImageCache prune task expired\");\n        __interrupt = YES;\n    }];\n#endif\n    @synchronized (self) {\n        CLS_LOG(@\"Pruning image cache directory: %@\", _cachePath.path);\n        \n        NSDirectoryEnumerator *directoryEnumerator = [[NSFileManager defaultManager] enumeratorAtURL:self->_cachePath includingPropertiesForKeys:@[NSURLContentModificationDateKey] options:0 errorHandler:nil];\n        \n        NSDate *lastWeek = [NSDate dateWithTimeIntervalSinceNow:(-60*60*24*7)];\n        \n        for (NSURL *fileURL in directoryEnumerator) {\n            NSDate *modificationDate = nil;\n            [fileURL getResourceValue:&modificationDate forKey:NSURLContentModificationDateKey error:nil];\n            \n            if([lastWeek compare:modificationDate] == NSOrderedDescending) {\n                CLS_LOG(@\"Removing stale image cache file: %@\", fileURL.path);\n                [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];\n            }\n            \n            if(__interrupt)\n                break;\n        }\n    }\n#ifndef EXTENSION\n    [[UIApplication sharedApplication] endBackgroundTask: background_task];\n#endif\n}\n\n-(void)clear {\n    @synchronized(self->_tasks) {\n        [self->_tasks.allValues makeObjectsPerformSelector:@selector(cancel)];\n        [self->_tasks removeAllObjects];\n    }\n    @synchronized(self->_images) {\n        [self->_images removeAllObjects];\n    }\n}\n\n-(void)clearFailedURLs {\n    @synchronized(self->_failures) {\n        [self->_failures removeAllObjects];\n    }\n}\n\n-(void)purge {\n    [[NSFileManager defaultManager] removeItemAtURL:self->_cachePath error:nil];\n    [self clear];\n}\n\n+ (NSString *)md5:(NSString *)string {\n    const char *cstr = [string UTF8String];\n    unsigned char result[16];\n    CC_MD5(cstr, (unsigned int)strlen(cstr), result);\n    \n    return [NSString stringWithFormat:\n            @\"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\",\n            result[0], result[1], result[2], result[3],\n            result[4], result[5], result[6], result[7],\n            result[8], result[9], result[10], result[11],\n            result[12], result[13], result[14], result[15]\n            ];  \n}\n\n-(BOOL)isValidURL:(NSURL *)url {\n    @synchronized(self->_failures) {\n        return url != nil && [self->_failures objectForKey:url.absoluteString] == nil;\n    }\n}\n\n-(BOOL)isValidFileID:(NSString *)fileID {\n    return [self isValidURL:[NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":fileID} error:nil]]];\n}\n\n-(BOOL)isValidFileID:(NSString *)fileID width:(int)width {\n    return [self isValidURL:[NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":fileID, @\"modifiers\":[NSString stringWithFormat:@\"w%i\", width]} error:nil]]];\n}\n\n-(BOOL)isLoaded:(NSURL *)url {\n    @synchronized(self->_images) {\n        return [self->_images objectForKey:url.absoluteString] != nil || [self->_failures objectForKey:url.absoluteString] != nil;\n    }\n}\n\n-(BOOL)isLoaded:(NSString *)fileID width:(int)width {\n    return [self isLoaded:[NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":fileID, @\"modifiers\":[NSString stringWithFormat:@\"w%i\", width]} error:nil]]];\n}\n\n-(UIImage *)imageForURL:(NSURL *)url {\n    @synchronized(self->_failures) {\n        if([self->_failures objectForKey:url.absoluteString])\n            return nil;\n    }\n    YYImage *img;\n    @synchronized(self->_images) {\n        img = [self->_images objectForKey:url.absoluteString];\n    }\n    if(!img) {\n        NSURL *cache = [self pathForURL:url];\n        if([[NSFileManager defaultManager] fileExistsAtPath:cache.path]) {\n            NSData *data = [NSData dataWithContentsOfURL:cache];\n            if(data.length) {\n                img = [YYImage imageWithData:data scale:[UIScreen mainScreen].scale];\n                if(img.size.width) {\n                    @synchronized(self->_images) {\n                        [self->_images setObject:img forKey:url.absoluteString];\n                    }\n                } else {\n                    CLS_LOG(@\"Unable to load %@ from cache\", url);\n                    @synchronized(self->_failures) {\n                        [self->_failures setObject:@(YES) forKey:url.absoluteString];\n                    }\n                }\n            } else {\n                [[NSFileManager defaultManager] removeItemAtPath:cache.path error:nil];\n            }\n        }\n    }\n    if([img isKindOfClass:UIImage.class])\n        return img;\n    else\n        return nil;\n}\n\n-(UIImage *)imageForFileID:(NSString *)fileID {\n    return [self imageForURL:[NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":fileID} error:nil]]];\n}\n\n-(UIImage *)imageForFileID:(NSString *)fileID width:(int)width {\n    return [self imageForURL:[NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":fileID, @\"modifiers\":[NSString stringWithFormat:@\"w%i\", width]} error:nil]]];\n}\n\n-(void)fetchURL:(NSURL *)url completionHandler:(imageCompletionHandler)handler {\n    @synchronized (self->_tasks) {\n        if(url == nil || [self->_tasks objectForKey:url] || [self->_failures objectForKey:url]) {\n            return;\n        }\n        \n        NSURLSessionDownloadTask *task = [self->_session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {\n            [self->_tasks removeObjectForKey:url];\n            if(error) {\n                CLS_LOG(@\"Download failed: %@\", error);\n                @synchronized(self->_failures) {\n                    [self->_failures setObject:@(YES) forKey:url.absoluteString];\n                }\n            } else if(location) {\n                NSURL *cache = [self pathForURL:url];\n                [[NSFileManager defaultManager] createDirectoryAtURL:self->_cachePath withIntermediateDirectories:YES attributes:nil error:nil];\n                [[NSFileManager defaultManager] copyItemAtURL:location toURL:cache error:nil];\n                NSData *data = [NSData dataWithContentsOfURL:cache];\n                if(data.length) {\n                    YYImage *img = [YYImage imageWithData:data scale:[UIScreen mainScreen].scale];\n                    if(img.size.width) {\n                        @synchronized(self->_images) {\n                            [self->_images setObject:img forKey:url.absoluteString];\n                        }\n                    } else {\n                        @synchronized(self->_failures) {\n                            [self->_failures setObject:@(YES) forKey:url.absoluteString];\n                        }\n                    }\n                } else {\n                    [[NSFileManager defaultManager] removeItemAtURL:cache error:nil];\n                    @synchronized(self->_failures) {\n                        [self->_failures setObject:@(YES) forKey:url.absoluteString];\n                    }\n                }\n            }\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                handler([self->_images objectForKey:url.absoluteString] != nil);\n            }];\n        }];\n        [self->_tasks setObject:task forKey:url];\n        [task resume];\n    }\n}\n\n-(void)fetchFileID:(NSString *)fileID completionHandler:(imageCompletionHandler)handler {\n    return [self fetchURL:[NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":fileID} error:nil]] completionHandler:handler];\n}\n\n-(void)fetchFileID:(NSString *)fileID width:(int)width completionHandler:(imageCompletionHandler)handler {\n    return [self fetchURL:[NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":fileID, @\"modifiers\":[NSString stringWithFormat:@\"w%i\", width]} error:nil]] completionHandler:handler];\n}\n\n-(NSURL *)pathForURL:(NSURL *)url {\n    if(url)\n        return [self->_cachePath URLByAppendingPathComponent:[ImageCache md5:url.absoluteString]];\n    else\n        return nil;\n}\n\n-(NSURL *)pathForFileID:(NSString *)fileID {\n    return [self pathForURL:[NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":fileID} error:nil]]];\n}\n\n-(NSURL *)pathForFileID:(NSString *)fileID width:(int)width {\n    return [self pathForURL:[NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":fileID, @\"modifiers\":[NSString stringWithFormat:@\"w%i\", width]} error:nil]]];\n}\n\n-(NSTimeInterval)ageOfCache:(NSURL *)url {\n    NSString *path = [self pathForURL:url].path;\n    if([[NSFileManager defaultManager] fileExistsAtPath:path]) {\n        return fabs([[[[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil] fileCreationDate] timeIntervalSinceNow]);\n    }\n    return -1;\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ImageViewController.h",
    "content": "//\n//  ImageViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import <AVKit/AVKit.h>\n#import \"OpenInChromeController.h\"\n#import \"YYAnimatedImageView.h\"\n#import \"URLHandler.h\"\n\n@interface ImageViewController : UIViewController<UIScrollViewDelegate,NSURLSessionDataDelegate,UIPopoverPresentationControllerDelegate,UIGestureRecognizerDelegate> {\n    IBOutlet YYAnimatedImageView *_imageView;\n    IBOutlet UIScrollView *_scrollView;\n    AVPlayerViewController *_movieController;\n    __weak IBOutlet UIProgressView *_progressView;\n    IBOutlet UIToolbar *_toolbar;\n    NSURL *_url;\n    NSTimer *_hideTimer;\n    OpenInChromeController *_chrome;\n    NSURLSessionDataTask *_imageTask;\n    BOOL _previewing;\n    UIPanGestureRecognizer *_panGesture;\n    URLHandler *_urlHandler;\n}\n@property BOOL previewing;\n-(id)initWithURL:(NSURL *)url;\n-(IBAction)viewTapped:(id)sender;\n-(IBAction)doneButtonPressed:(id)sender;\n-(IBAction)shareButtonPressed:(id)sender;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ImageViewController.m",
    "content": "//\n//  ImageViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <AVFoundation/AVFoundation.h>\n#import <MobileCoreServices/UTCoreTypes.h>\n#import <Twitter/Twitter.h>\n#import <SafariServices/SafariServices.h>\n#import \"ImageViewController.h\"\n#import \"AppDelegate.h\"\n#import \"OpenInFirefoxControllerObjC.h\"\n#import \"config.h\"\n#import \"ImageCache.h\"\n#import \"UIColor+IRCCloud.h\"\n@import Firebase;\n\n#define HIDE_DURATION 3\n\n@implementation ImageViewController\n{\n    NSMutableData *_imageData;\n    long long _bytesExpected;\n    long long _totalBytesReceived;\n}\n\n- (id)initWithURL:(NSURL *)url {\n    self = [super initWithNibName:@\"ImageViewController\" bundle:nil];\n    if (self) {\n        self->_url = url;\n        self->_chrome = [[OpenInChromeController alloc] init];\n        self->_urlHandler = [[URLHandler alloc] init];\n    }\n    return self;\n}\n\n-(void)dealloc {\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {\n    return @[\n             [UIPreviewAction actionWithTitle:@\"Copy URL\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                 UIPasteboard *pb = [UIPasteboard generalPasteboard];\n                 [pb setValue:self->_url.absoluteString forPasteboardType:(NSString *)kUTTypeUTF8PlainText];\n             }],\n             [UIPreviewAction actionWithTitle:@\"Share\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                 [UIColor clearTheme];\n                 UIApplication *app = [UIApplication sharedApplication];\n                 AppDelegate *appDelegate = (AppDelegate *)app.delegate;\n                 MainViewController *mainViewController = [appDelegate mainViewController];\n                 \n                 UIActivityViewController *activityController = [URLHandler activityControllerForItems:self->_imageView.image?@[self->_url,self->_imageView.image]:@[self->_url] type:self->_movieController?@\"Animation\":@\"Image\"];\n\n                 activityController.popoverPresentationController.sourceView = mainViewController.slidingViewController.view;\n\n                 [mainViewController.slidingViewController presentViewController:activityController animated:YES completion:nil];\n             }],\n             [UIPreviewAction actionWithTitle:@\"Open in Browser\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                 if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Chrome\"] && [[OpenInChromeController sharedInstance] openInChrome:self->_url\n                                                                                                                                                         withCallbackURL:[NSURL URLWithString:\n#ifdef ENTERPRISE\n                                                                                                                                                                          @\"irccloud-enterprise://\"\n#else\n                                                                                                                                                                          @\"irccloud://\"\n#endif\n                                                                                                                                                                          ]\n                                                                                                                                                            createNewTab:NO])\n                     return;\n                 else if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Firefox\"] && [[OpenInFirefoxControllerObjC sharedInstance] openInFirefox:self->_url])\n                     return;\n                 else\n                     [[UIApplication sharedApplication] openURL:self->_url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n             }]\n             ];\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(UIView *)viewForZoomingInScrollView:(UIScrollView *)inScroll {\n    return _imageView;\n}\n\n-(void)transitionToSize:(CGSize)size {\n    self->_scrollView.frame = CGRectMake(0,0,size.width,size.height);\n    if(self->_imageView.image) {\n        [self->_imageView sizeToFit];\n        CGRect frame = self->_imageView.frame;\n        frame.origin.x = 0;\n        frame.origin.y = 0;\n        self->_imageView.frame = frame;\n        self->_scrollView.contentSize = self->_imageView.frame.size;\n    }\n    [self scrollViewDidZoom:self->_scrollView];\n    \n    self->_progressView.center = CGPointMake(self.view.bounds.size.width / 2.0,self.view.bounds.size.height/2.0);\n    \n    if(self->_movieController)\n        self->_movieController.view.frame = self->_scrollView.bounds;\n}\n\n-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {\n    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];\n    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n        [self transitionToSize:size];\n    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n    }];\n}\n\n//Some centering magic from: http://stackoverflow.com/a/2189336/1406639\n-(void)scrollViewDidZoom:(UIScrollView *)pScrollView {\n    if(self->_movieController)\n        return;\n    \n    CGRect innerFrame = self->_imageView.frame;\n    CGRect scrollerBounds = pScrollView.bounds;\n    \n    if ((innerFrame.size.width < scrollerBounds.size.width) || (innerFrame.size.height < scrollerBounds.size.height)) {\n        CGFloat tempx = self->_imageView.center.x - (scrollerBounds.size.width / 2);\n        CGFloat tempy = self->_imageView.center.y - (scrollerBounds.size.height / 2);\n        CGPoint myScrollViewOffset = CGPointMake(tempx, tempy);\n        \n        pScrollView.contentOffset = myScrollViewOffset;\n        \n    }\n    \n    UIEdgeInsets anEdgeInset = { 0, 0, 0, 0};\n    if(scrollerBounds.size.width > innerFrame.size.width) {\n        anEdgeInset.left = (scrollerBounds.size.width - innerFrame.size.width) / 2;\n        anEdgeInset.right = -anEdgeInset.left;\n    }\n    if(scrollerBounds.size.height > innerFrame.size.height) {\n        anEdgeInset.top = (scrollerBounds.size.height - innerFrame.size.height) / 2;\n        anEdgeInset.bottom = -anEdgeInset.top;\n    }\n    pScrollView.contentInset = anEdgeInset;\n    \n    if(self->_toolbar.hidden && !_previewing)\n        [self _showToolbar];\n    [self->_hideTimer invalidate];\n    self->_hideTimer = [NSTimer scheduledTimerWithTimeInterval:HIDE_DURATION target:self selector:@selector(_hideToolbar) userInfo:nil repeats:NO];\n    \n    pScrollView.alwaysBounceHorizontal = (pScrollView.zoomScale > pScrollView.minimumZoomScale);\n    pScrollView.alwaysBounceVertical = (pScrollView.zoomScale > pScrollView.minimumZoomScale);\n}\n\n-(void)_showToolbar {\n    [self->_hideTimer invalidate];\n    self->_hideTimer = nil;\n    [UIView animateWithDuration:0.5 animations:^{\n        self->_toolbar.hidden = NO;\n        self->_toolbar.alpha = 1;\n    } completion:nil];\n}\n\n-(void)_hideToolbar {\n    [self->_hideTimer invalidate];\n    self->_hideTimer = nil;\n    if(self->_imageView.image != nil || _movieController != nil) {\n        [UIView animateWithDuration:0.5 animations:^{\n            self->_toolbar.alpha = 0;\n        } completion:^(BOOL finished){\n            self->_toolbar.hidden = YES;\n        }];\n    }\n}\n\n-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {\n    if(!_previewing)\n        [self _showToolbar];\n}\n\n-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {\n    self->_hideTimer = [NSTimer scheduledTimerWithTimeInterval:HIDE_DURATION target:self selector:@selector(_hideToolbar) userInfo:nil repeats:NO];\n}\n\n-(void)fail:(NSString *)error {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        [self->_progressView removeFromSuperview];\n\n        if(self->_previewing || self.view.window.rootViewController != self) {\n            CLS_LOG(@\"Not launching fallback URL as we're not the root view controller\");\n            return;\n        }\n        \n        if([[NSUserDefaults standardUserDefaults] boolForKey:@\"warnBeforeLaunchingBrowser\"]) {\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Unable To Load Image\" message:error preferredStyle:UIAlertControllerStyleAlert];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Open in Browser\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [self _openInBrowser];\n            }]];\n            \n            [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:^(UIAlertAction *alert) {\n                [self doneButtonPressed:alert];\n            }]];\n            [self presentViewController:alert animated:YES completion:nil];\n            [self _showToolbar];\n        } else {\n            [self _openInBrowser];\n        }\n    }];\n}\n\n-(void)_openInBrowser {\n    if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Chrome\"] && [[OpenInChromeController sharedInstance] isChromeInstalled]) {\n        if([[OpenInChromeController sharedInstance] openInChrome:self->_url withCallbackURL:[NSURL URLWithString:\n#ifdef ENTERPRISE\n                                                                                       @\"irccloud-enterprise://\"\n#else\n                                                                                       @\"irccloud://\"\n#endif\n                                                                                       ] createNewTab:NO])\n            return;\n    }\n    if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Firefox\"] && [[OpenInFirefoxControllerObjC sharedInstance] isFirefoxInstalled]) {\n        if([[OpenInFirefoxControllerObjC sharedInstance] openInFirefox:self->_url])\n            return;\n    }\n    if(![[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Safari\"] && ([SFSafariViewController class] && !((AppDelegate *)([UIApplication sharedApplication].delegate)).isOnVisionOS) && [self->_url.scheme hasPrefix:@\"http\"]) {\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            UIApplication *app = [UIApplication sharedApplication];\n            AppDelegate *appDelegate = (AppDelegate *)app.delegate;\n            MainViewController *mainViewController = [appDelegate mainViewController];\n            \n            [((AppDelegate *)[UIApplication sharedApplication].delegate) showMainView:NO];\n            \n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;\n                [UIApplication sharedApplication].statusBarHidden = NO;\n                \n                [mainViewController.slidingViewController presentViewController:[[SFSafariViewController alloc] initWithURL:self->_url] animated:YES completion:nil];\n            }];\n        }];\n    } else {\n        [[UIApplication sharedApplication] openURL:self->_url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n    }\n}\n\n-(void)_fetchVideo:(NSURL *)url {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];\n        self->_movieController = [[AVPlayerViewController alloc] init];\n        self->_movieController.player = [[AVPlayer alloc] initWithURL:url];\n        self->_movieController.showsPlaybackControls = NO;\n        self->_movieController.view.userInteractionEnabled = NO;\n        self->_movieController.view.frame = self->_scrollView.bounds;\n        self->_movieController.view.backgroundColor = [UIColor clearColor];\n        [self->_scrollView addSubview:self->_movieController.view];\n        self->_scrollView.userInteractionEnabled = NO;\n        [self->_scrollView removeGestureRecognizer:self->_panGesture];\n        [self.view addGestureRecognizer:self->_panGesture];\n        [self->_progressView removeFromSuperview];\n        [self->_movieController.player play];\n        \n        [self scrollViewDidZoom:self->_scrollView];\n    }];\n}\n\n- (void)playerItemDidReachEnd:(NSNotification *)notification {\n    AVPlayerItem *p = [notification object];\n    [p seekToTime:kCMTimeZero completionHandler:nil];\n}\n\n-(void)load {\n#ifdef DEBUG\n    [[NSURLCache sharedURLCache] removeAllCachedResponses];\n#endif\n    \n    NSDictionary *d = [self->_urlHandler MediaURLs:self->_url];\n    if(d) {\n        if([d objectForKey:@\"mp4_loop\"]) {\n            [self _fetchVideo:[d objectForKey:@\"mp4_loop\"]];\n            self->_movieController.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;\n            [[NSNotificationCenter defaultCenter] addObserver:self\n                                                       selector:@selector(playerItemDidReachEnd:)\n                                                           name:AVPlayerItemDidPlayToEndTimeNotification\n                                                         object:[self->_movieController.player currentItem]];\n        } else if([d objectForKey:@\"mp4\"]) {\n            [self _fetchVideo:[d objectForKey:@\"mp4\"]];\n        } else if([d objectForKey:@\"image\"]) {\n            [self _fetchImage:[d objectForKey:@\"image\"]];\n        } else {\n            [self fail:@\"Unsupported media type\"];\n        }\n    } else {\n        [self->_urlHandler fetchMediaURLs:self->_url result:^(BOOL success, NSString *error) {\n            if(success)\n                [self load];\n            else\n                [self fail:error];\n        }];\n    }\n}\n\n- (void)_fetchImage:(NSURL *)url {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        NSString *cacheFile = [[ImageCache sharedInstance] pathForURL:url].path;\n        if([[NSFileManager defaultManager] fileExistsAtPath:cacheFile]) {\n            self->_imageData = [[NSData alloc] initWithContentsOfFile:cacheFile].mutableCopy;\n            [self _parseImageData:self->_imageData];\n        } else {\n            NSURLSession *session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration delegate:self delegateQueue:NSOperationQueue.mainQueue];\n            self->_imageTask = [session dataTaskWithURL:url];\n            [self->_imageTask resume];\n        }\n    }];\n}\n\n-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {\n    self->_bytesExpected = [response expectedContentLength];\n    self->_imageData = [[NSMutableData alloc] initWithCapacity:(NSUInteger)(self->_bytesExpected + 32)]; // Just in case? Unsure if the extra 32 bytes are necessary\n    if(((NSHTTPURLResponse *)response).statusCode != 200) {\n        [self fail:[NSString stringWithFormat:@\"HTTP error %ld: %@\", (long)((NSHTTPURLResponse *)response).statusCode, [NSHTTPURLResponse localizedStringForStatusCode:((NSHTTPURLResponse *)response).statusCode]]];\n        completionHandler(NSURLSessionResponseCancel);\n        return;\n    }\n    if(response.MIMEType.length && ![response.MIMEType.lowercaseString hasPrefix:@\"image/\"] && ![response.MIMEType.lowercaseString isEqualToString:@\"binary/octet-stream\"]) {\n        [self fail:[NSString stringWithFormat:@\"Invalid MIME type: %@\", response.MIMEType]];\n        completionHandler(NSURLSessionResponseCancel);\n        return;\n    }\n    completionHandler(NSURLSessionResponseAllow);\n}\n\n-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {\n    NSInteger receivedDataLength = data.length;\n    self->_totalBytesReceived += receivedDataLength;\n    [self->_imageData appendData:data];\n\n    if(self->_bytesExpected != NSURLResponseUnknownLength) {\n        float progress = (((self->_totalBytesReceived/(float)_bytesExpected) * 100.f) / 100.f);\n        if(self->_progressView.progress < progress)\n            self->_progressView.progress = progress;\n    }\n}\n\n-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {\n    if(task == self->_imageTask) {\n        if(error) {\n            CLS_LOG(@\"Couldn't download image. Error code %li: %@\", (long)error.code, error.localizedDescription);\n            [self fail:error.localizedDescription];\n        } else {\n            if(self->_imageData) {\n                NSString *cacheFile = [[ImageCache sharedInstance] pathForURL:task.originalRequest.URL].path;\n                [self->_imageData writeToFile:cacheFile atomically:YES];\n                [self performSelectorInBackground:@selector(_parseImageData:) withObject:self->_imageData];\n            } else {\n                [self fail:@\"No image data recieved\"];\n            }\n        }\n        self->_imageTask = nil;\n    }\n}\n\n- (void)_parseImageData:(NSData *)data {\n    YYImage *img = [YYImage imageWithData:data scale:[UIScreen mainScreen].scale];\n    if(img) {\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            self->_progressView.progress = 1.f;\n            [self->_scrollView removeGestureRecognizer:self->_panGesture];\n            [self.view addGestureRecognizer:self->_panGesture];\n            CGSize size;\n            size = img.size;\n            self->_imageView.image = img;\n            self->_imageView.frame = CGRectMake(0,0,size.width,size.height);\n            CGFloat xScale = self->_scrollView.bounds.size.width / self->_imageView.frame.size.width;\n            CGFloat yScale = self->_scrollView.bounds.size.height / self->_imageView.frame.size.height;\n            CGFloat minScale = MIN(xScale, yScale);\n            \n            CGFloat maxScale = 4;\n            \n            if (minScale > maxScale) {\n                minScale = maxScale;\n            }\n            \n            self->_scrollView.minimumZoomScale = minScale;\n            self->_scrollView.maximumZoomScale = maxScale;\n            self->_scrollView.contentSize = self->_imageView.frame.size;\n            self->_scrollView.zoomScale = minScale;\n            [self scrollViewDidZoom:self->_scrollView];\n            \n            [self->_progressView removeFromSuperview];\n            [UIView beginAnimations:nil context:nil];\n            [UIView setAnimationDuration:0.25];\n            self->_imageView.alpha = 1;\n            [UIView commitAnimations];\n        }];\n    } else {\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self fail:@\"Unable to display image\"];\n        }];\n    }\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n\n    self->_imageView.accessibilityIgnoresInvertColors = YES;\n\n    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap:)];\n    [doubleTap setNumberOfTapsRequired:2];\n    [self->_scrollView addGestureRecognizer:doubleTap];\n    \n    self->_panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panned:)];\n    [self->_scrollView addGestureRecognizer:self->_panGesture];\n    \n    [self transitionToSize:self.view.bounds.size];\n    [self performSelector:@selector(load) withObject:nil afterDelay:0.5]; //Let the fade animation finish\n    \n    if(self->_previewing)\n        self->_toolbar.hidden = YES;\n}\n\n-(UIStatusBarStyle)preferredStatusBarStyle {\n    return UIStatusBarStyleLightContent;\n}\n\n-(BOOL)prefersStatusBarHidden {\n    return YES;\n}\n\n- (void)didMoveToParentViewController:(UIViewController *)parent {\n    self->_previewing = NO;\n    self->_toolbar.hidden = NO;\n    [self _showToolbar];\n}\n\n//From: http://stackoverflow.com/a/19146512\n- (void)doubleTap:(UITapGestureRecognizer*)recognizer {\n    if (self->_scrollView.zoomScale > _scrollView.minimumZoomScale) {\n        [self->_scrollView setZoomScale:self->_scrollView.minimumZoomScale animated:YES];\n    } else {\n        CGPoint touch = [recognizer locationInView:self->_imageView];\n        \n        CGFloat w = self->_imageView.bounds.size.width / _scrollView.maximumZoomScale;\n        CGFloat h = self->_imageView.bounds.size.height / _scrollView.maximumZoomScale;\n        CGFloat x = touch.x-(w/2.0);\n        CGFloat y = touch.y-(h/2.0);\n        \n        CGRect rectTozoom=CGRectMake(x, y, w, h);\n        [self->_scrollView zoomToRect:rectTozoom animated:YES];\n    }\n}\n\n- (void)panned:(UIPanGestureRecognizer *)recognizer {\n    if(self->_previewing)\n        return;\n    \n    if (self->_scrollView.zoomScale <= self->_scrollView.minimumZoomScale || _movieController || !_imageView.image) {\n        CGRect frame = self->_scrollView.frame;\n        \n        switch(recognizer.state) {\n            case UIGestureRecognizerStateBegan:\n                if(fabs([recognizer velocityInView:self.view].y) > fabs([recognizer velocityInView:self.view].x)) {\n                    [self _hideToolbar];\n                }\n                break;\n            case UIGestureRecognizerStateCancelled: {\n                frame.origin.y = 0;\n                [UIView animateWithDuration:0.25 animations:^{\n                    self->_scrollView.frame = frame;\n                    self->_progressView.center = self->_scrollView.center;\n                    self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:1];\n                }];\n                [self _showToolbar];\n                self->_hideTimer = [NSTimer scheduledTimerWithTimeInterval:HIDE_DURATION target:self selector:@selector(_hideToolbar) userInfo:nil repeats:NO];\n                break;\n            }\n            case UIGestureRecognizerStateChanged:\n                frame.origin.y = [recognizer translationInView:self.view].y;\n                self->_scrollView.frame = frame;\n                if(self->_movieController)\n                    self->_movieController.view.frame = self->_scrollView.bounds;\n                self->_progressView.center = self->_scrollView.center;\n                self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:1-(fabs([recognizer translationInView:self.view].y) / self.view.frame.size.height / 2)];\n                break;\n            case UIGestureRecognizerStateEnded:\n            {\n                if(fabs([recognizer translationInView:self.view].y) > 100 || fabs([recognizer velocityInView:self.view].y) > 1000) {\n                    frame.origin.y = ([recognizer translationInView:self.view].y > 0)?frame.size.height:-frame.size.height;\n                    [self->_hideTimer invalidate];\n                    self->_hideTimer = nil;\n                    [self->_imageTask cancel];\n                    self->_imageTask = nil;\n                    [UIView animateWithDuration:0.25 animations:^{\n                        self->_scrollView.frame = frame;\n                        self->_progressView.center = self->_scrollView.center;\n                        self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0];\n                    } completion:^(BOOL finished) {\n                        [((AppDelegate *)[UIApplication sharedApplication].delegate) showMainView:NO];\n                    }];\n                } else {\n                    frame.origin.y = 0;\n                    [self _showToolbar];\n                    self->_hideTimer = [NSTimer scheduledTimerWithTimeInterval:HIDE_DURATION target:self selector:@selector(_hideToolbar) userInfo:nil repeats:NO];\n                    [UIView animateWithDuration:0.25 animations:^{\n                        self->_scrollView.frame = frame;\n                        self->_progressView.center = self->_scrollView.center;\n                        self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:1];\n                    }];\n                }\n                break;\n            }\n            default:\n                break;\n        }\n    }\n}\n\n- (void)viewDidAppear:(BOOL)animated {\n    [super viewDidAppear:animated];\n    [self transitionToSize:self.view.bounds.size];\n    self->_hideTimer = [NSTimer scheduledTimerWithTimeInterval:HIDE_DURATION target:self selector:@selector(_hideToolbar) userInfo:nil repeats:NO];\n    NSUserActivity *activity = [self userActivity];\n    [activity invalidate];\n    activity = [[NSUserActivity alloc] initWithActivityType:NSUserActivityTypeBrowsingWeb];\n    activity.webpageURL = [NSURL URLWithString:[self->_url.absoluteString stringByReplacingCharactersInRange:NSMakeRange(0, _url.scheme.length) withString:self->_url.scheme.lowercaseString]];\n    [self setUserActivity:activity];\n    [activity becomeCurrent];\n    if(self->_movieController)\n        [self->_movieController.player play];\n}\n\n- (void)viewDidDisappear:(BOOL)animated {\n    [super viewDidDisappear:animated];\n    if(self->_movieController)\n        [self->_movieController.player pause];\n    [self->_hideTimer invalidate];\n    self->_hideTimer = nil;\n}\n\n-(IBAction)viewTapped:(id)sender {\n    if(self->_toolbar.hidden && !_previewing) {\n        [self _showToolbar];\n    } else {\n        [self _hideToolbar];\n    }\n}\n\n-(void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController {\n    self->_hideTimer = [NSTimer scheduledTimerWithTimeInterval:HIDE_DURATION target:self selector:@selector(_hideToolbar) userInfo:nil repeats:NO];\n}\n\n-(IBAction)shareButtonPressed:(id)sender {\n    [UIColor clearTheme];\n    UIActivityViewController *activityController = [URLHandler activityControllerForItems:self->_imageView.image?@[self->_url,_imageView.image]:@[self->_url] type:self->_movieController?@\"Animation\":@\"Image\"];\n\n    activityController.popoverPresentationController.delegate = self;\n    activityController.popoverPresentationController.barButtonItem = sender;\n    [self presentViewController:activityController animated:YES completion:nil];\n    [self->_hideTimer invalidate];\n    self->_hideTimer = nil;\n}\n\n-(IBAction)doneButtonPressed:(id)sender {\n    [self->_hideTimer invalidate];\n    self->_hideTimer = nil;\n    [self->_imageTask cancel];\n    self->_imageTask = nil;\n    [((AppDelegate *)[UIApplication sharedApplication].delegate) setActiveScene:self.view.window];\n    [((AppDelegate *)[UIApplication sharedApplication].delegate) showMainView:YES];\n}\n\n-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {\n    if(!_toolbar.hidden && CGRectContainsPoint(self->_toolbar.frame, [touch locationInView:self.view]))\n        return NO;\n    return YES;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ImageViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"24123.1\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" colorMatched=\"YES\">\n    <device id=\"retina4_7\" orientation=\"portrait\" appearance=\"light\"/>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"24062\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\" customClass=\"ImageViewController\">\n            <connections>\n                <outlet property=\"_imageView\" destination=\"4\" id=\"7\"/>\n                <outlet property=\"_progressView\" destination=\"xZt-U7-FdQ\" id=\"MVA-MK-PlZ\"/>\n                <outlet property=\"_scrollView\" destination=\"5\" id=\"8\"/>\n                <outlet property=\"_toolbar\" destination=\"16\" id=\"23\"/>\n                <outlet property=\"view\" destination=\"6\" id=\"9\"/>\n            </connections>\n        </placeholder>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <view contentMode=\"scaleToFill\" id=\"6\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"667\"/>\n            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n            <subviews>\n                <progressView opaque=\"NO\" contentMode=\"scaleToFill\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"xZt-U7-FdQ\">\n                    <rect key=\"frame\" x=\"23\" y=\"333\" width=\"328\" height=\"2\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMinX=\"YES\" widthSizable=\"YES\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\" flexibleMaxY=\"YES\"/>\n                    <color key=\"progressTintColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                    <color key=\"trackTintColor\" red=\"0.33333333333333331\" green=\"0.33333333333333331\" blue=\"0.33333333333333331\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                </progressView>\n                <scrollView autoresizesSubviews=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"scaleToFill\" fixedFrame=\"YES\" showsHorizontalScrollIndicator=\"NO\" showsVerticalScrollIndicator=\"NO\" minimumZoomScale=\"0.0\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"5\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"667\"/>\n                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                    <subviews>\n                        <imageView userInteractionEnabled=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4\" customClass=\"YYAnimatedImageView\">\n                            <rect key=\"frame\" x=\"40\" y=\"230\" width=\"240\" height=\"128\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMinX=\"YES\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\" flexibleMaxY=\"YES\"/>\n                            <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                            <gestureRecognizers/>\n                        </imageView>\n                    </subviews>\n                    <gestureRecognizers/>\n                    <connections>\n                        <outlet property=\"delegate\" destination=\"-1\" id=\"10\"/>\n                    </connections>\n                </scrollView>\n                <toolbar opaque=\"NO\" clearsContextBeforeDrawing=\"NO\" contentMode=\"scaleToFill\" fixedFrame=\"YES\" barStyle=\"black\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"16\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"623\" width=\"375\" height=\"44\"/>\n                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                    <items>\n                        <barButtonItem systemItem=\"action\" id=\"27\">\n                            <connections>\n                                <action selector=\"shareButtonPressed:\" destination=\"-1\" id=\"28\"/>\n                            </connections>\n                        </barButtonItem>\n                        <barButtonItem style=\"plain\" systemItem=\"flexibleSpace\" id=\"19\"/>\n                        <barButtonItem style=\"done\" systemItem=\"done\" id=\"20\">\n                            <connections>\n                                <action selector=\"doneButtonPressed:\" destination=\"-1\" id=\"26\"/>\n                            </connections>\n                        </barButtonItem>\n                    </items>\n                </toolbar>\n            </subviews>\n            <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n            <gestureRecognizers/>\n            <connections>\n                <outletCollection property=\"gestureRecognizers\" destination=\"13\" appends=\"YES\" id=\"8FE-Nb-pl9\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"140\" y=\"154\"/>\n        </view>\n        <tapGestureRecognizer id=\"13\">\n            <connections>\n                <action selector=\"viewTapped:\" destination=\"-1\" id=\"15\"/>\n                <outlet property=\"delegate\" destination=\"-1\" id=\"Vhm-05-fGj\"/>\n            </connections>\n        </tapGestureRecognizer>\n    </objects>\n</document>\n"
  },
  {
    "path": "IRCCloud/Classes/LicenseViewController.h",
    "content": "//\n//  LicenseViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n\n@interface LicenseViewController : UIViewController\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LicenseViewController.m",
    "content": "//\n//  LicenseViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"LicenseViewController.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@implementation LicenseViewController\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationItem.title = @\"Licenses\";\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    UITextView *tv = [[UITextView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height)];\n    tv.textColor = [UIColor messageTextColor];\n    tv.backgroundColor = [UIColor contentBackgroundColor];\n    tv.text = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@\"licenses\" ofType:@\"txt\"] encoding:NSUTF8StringEncoding error:nil];\n    tv.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    tv.editable = NO;\n    [self.view addSubview:tv];\n\n    if(self.navigationController.viewControllers.count == 1) {\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed)];\n    }\n}\n\n-(void)doneButtonPressed {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LinkLabel.h",
    "content": "//\n//  LinkLabel.h\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n\n@protocol LinkLabelDelegate;\n\n@interface LinkLabel : UILabel<UIGestureRecognizerDelegate> {\n    UITapGestureRecognizer *_tapGesture;\n    NSMutableArray *_links;\n}\n@property (unsafe_unretained) id <LinkLabelDelegate> linkDelegate;\n@property (strong) NSDictionary *linkAttributes;\n\n- (void)addLinkToURL:(NSURL *)url withRange:(NSRange)range;\n- (void)addLinkWithTextCheckingResult:(NSTextCheckingResult *)result;\n- (NSTextCheckingResult *)linkAtPoint:(CGPoint)p;\n\n+(CGFloat)heightOfString:(NSAttributedString *)text constrainedToWidth:(CGFloat)width;\n@end\n\n@protocol LinkLabelDelegate\n- (void)LinkLabel:(LinkLabel *)label didSelectLinkWithTextCheckingResult:(NSTextCheckingResult *)result;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LinkLabel.m",
    "content": "//\n//  LinkLabel.m\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import <CoreText/CoreText.h>\n#import \"LinkLabel.h\"\n\n@implementation LinkLabel\n\n- (void)viewTapped:(UITapGestureRecognizer *)sender {\n    if(sender.state == UIGestureRecognizerStateEnded) {\n        NSTextCheckingResult *r = [self linkAtPoint:[sender locationInView:self]];\n        if(r && _linkDelegate) {\n            [self->_linkDelegate LinkLabel:self didSelectLinkWithTextCheckingResult:r];\n        } else {\n            UIView *obj = self;\n            \n            do {\n                obj = obj.superview;\n            } while (obj && ![obj isKindOfClass:[UITableViewCell class]]);\n            if(obj) {\n                UITableViewCell *cell = (UITableViewCell*)obj;\n                \n                do {\n                    obj = obj.superview;\n                } while (![obj isKindOfClass:[UITableView class]]);\n                UITableView *tableView = (UITableView*)obj;\n                \n                NSIndexPath *indePath = [tableView indexPathForCell:cell];\n                [[tableView delegate] tableView:tableView didSelectRowAtIndexPath:indePath];\n            }\n        }\n    }\n}\n\n-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {\n    NSTextCheckingResult *r = [self linkAtPoint:[touch locationInView:self]];\n    return (r && _linkDelegate);\n}\n\n-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {\n    return YES;\n}\n\n-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {\n    return NO;\n}\n\n-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {\n    return YES;\n}\n\n- (void)addLinkToURL:(NSURL *)url withRange:(NSRange)range {\n    [self addLinkWithTextCheckingResult:[NSTextCheckingResult linkCheckingResultWithRange:range URL:url]];\n}\n\n- (void)addLinkWithTextCheckingResult:(NSTextCheckingResult *)result {\n    if(!_links) {\n        self->_links = [[NSMutableArray alloc] init];\n    }\n    if(!_tapGesture) {\n        self->_tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewTapped:)];\n        self->_tapGesture.delegate = self;\n        [self addGestureRecognizer:self->_tapGesture];\n    }\n    NSMutableAttributedString *s = self.attributedText.mutableCopy;\n    [s addAttributes:self.linkAttributes range:result.range];\n    [super setAttributedText:s];\n    [self->_links addObject:result];\n}\n\n-(void)setText:(NSString *)text {\n    [self->_links removeAllObjects];\n    [super setText:text];\n}\n\n-(void)setAttributedText:(NSAttributedString *)attributedText {\n    [self->_links removeAllObjects];\n    [super setAttributedText:attributedText];\n}\n\n- (NSTextCheckingResult *)linkAtPoint:(CGPoint)p {\n    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:self.attributedText];\n    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];\n    [textStorage addLayoutManager:layoutManager];\n    \n    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)];\n    textContainer.lineFragmentPadding  = 0;\n    textContainer.maximumNumberOfLines = self.numberOfLines;\n    textContainer.lineBreakMode        = self.lineBreakMode;\n    \n    [layoutManager addTextContainer:textContainer];\n    \n    NSUInteger start = [layoutManager characterIndexForPoint:p inTextContainer:textContainer fractionOfDistanceBetweenInsertionPoints:NULL];\n    if(start == self.attributedText.length - 1) {\n        NSRange glyphRange;\n        [layoutManager characterRangeForGlyphRange:NSMakeRange(start, 1) actualGlyphRange:&glyphRange];\n        CGRect rect = [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];\n        if(!CGRectContainsPoint(rect, p))\n            return nil;\n    }\n    \n    for(NSTextCheckingResult *r in _links) {\n        if(NSLocationInRange(start, r.range))\n            return r;\n    }\n    return nil;\n}\n\n+(CGFloat)heightOfString:(NSAttributedString *)text constrainedToWidth:(CGFloat)width {\n    if(text) {\n        CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)text);\n        CFRange fitRange;\n        CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(width, CGFLOAT_MAX), &fitRange);\n        \n        CFRelease(framesetter);\n        \n        return frameSize.height;\n    } else {\n        return 0;\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LinkTextView.h",
    "content": "//\n//  LinkTextView.h\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n\n@protocol LinkTextViewDelegate;\n\n@interface LinkTextView : UITextView<UIGestureRecognizerDelegate> {\n    UITapGestureRecognizer *_tapGesture;\n    NSMutableArray *_links;\n}\n@property (unsafe_unretained) id <LinkTextViewDelegate> linkDelegate;\n@property (strong) NSDictionary *linkAttributes;\n\n- (void)addLinkToURL:(NSURL *)url withRange:(NSRange)range;\n- (void)addLinkWithTextCheckingResult:(NSTextCheckingResult *)result;\n- (NSTextCheckingResult *)linkAtPoint:(CGPoint)p;\n\n+(CGFloat)heightOfString:(NSAttributedString *)text constrainedToWidth:(CGFloat)width;\n@end\n\n@protocol LinkTextViewDelegate\n- (void)LinkTextView:(LinkTextView *)label didSelectLinkWithTextCheckingResult:(NSTextCheckingResult *)result;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LinkTextView.m",
    "content": "//\n//  LinkTextView.m\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import \"LinkTextView.h\"\n\nNSTextStorage *__LinkTextViewTextStorage;\nNSTextContainer *__LinkTextViewTextContainer;\nNSLayoutManager *__LinkTextViewLayoutManager;\n\n@implementation LinkTextView\n\n- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {\n    NSTextCheckingResult *r = [self linkAtPoint:[touch locationInView:self]];\n    return (r && _linkDelegate);\n}\n\n-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {\n    return NO;\n}\n\n-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {\n    return NO;\n}\n\n-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {\n    return YES;\n}\n\n- (void)viewTapped:(UITapGestureRecognizer *)sender {\n    if(sender.state == UIGestureRecognizerStateEnded) {\n        NSTextCheckingResult *r = [self linkAtPoint:[sender locationInView:self]];\n        if(r && _linkDelegate) {\n            [self->_linkDelegate LinkTextView:self didSelectLinkWithTextCheckingResult:r];\n        } else {\n            UIView *obj = self;\n            \n            do {\n                obj = obj.superview;\n            } while (obj && ![obj isKindOfClass:[UITableViewCell class]]);\n            if([obj isKindOfClass:[UITableViewCell class]]) {\n                UITableViewCell *cell = (UITableViewCell*)obj;\n                \n                do {\n                    obj = obj.superview;\n                } while (![obj isKindOfClass:[UITableView class]]);\n                if([obj isKindOfClass:[UITableView class]]) {\n                    UITableView *tableView = (UITableView*)obj;\n                    if([tableView.delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) {\n                        NSIndexPath *indePath = [tableView indexPathForCell:cell];\n                        [[tableView delegate] tableView:tableView didSelectRowAtIndexPath:indePath];\n                    }\n                }\n            }\n        }\n    }\n}\n\n- (void)addLinkToURL:(NSURL *)url withRange:(NSRange)range {\n    [self addLinkWithTextCheckingResult:[NSTextCheckingResult linkCheckingResultWithRange:range URL:url]];\n}\n\n- (void)addLinkWithTextCheckingResult:(NSTextCheckingResult *)result {\n    if(!_links) {\n        self->_links = [[NSMutableArray alloc] init];\n    }\n    if(!_tapGesture) {\n        self->_tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewTapped:)];\n        self->_tapGesture.delegate = self;\n        [self addGestureRecognizer:self->_tapGesture];\n    }\n    [self->_links addObject:result];\n    [self.textStorage addAttributes:self.linkAttributes range:result.range];\n}\n\n- (NSTextCheckingResult *)linkAtPoint:(CGPoint)p {\n    UITextRange *textRange = [self characterRangeAtPoint:p];\n    NSUInteger start = [self offsetFromPosition:self.beginningOfDocument toPosition:textRange.start];\n    \n    for(NSTextCheckingResult *r in _links) {\n        if(start >= r.range.location && start < r.range.location + r.range.length)\n            return r;\n    }\n    return nil;\n}\n\n-(void)setText:(NSString *)text {\n    [self->_links removeAllObjects];\n    [super setText:text];\n}\n\n-(void)setAttributedText:(NSAttributedString *)attributedText {\n    [self->_links removeAllObjects];\n    [super setAttributedText:attributedText];\n}\n\n+(CGFloat)heightOfString:(NSAttributedString *)text constrainedToWidth:(CGFloat)width {\n    if(!__LinkTextViewTextStorage) {\n        __LinkTextViewTextStorage = [[NSTextStorage alloc] init];\n        __LinkTextViewLayoutManager = [[NSLayoutManager alloc] init];\n        [__LinkTextViewTextStorage addLayoutManager:__LinkTextViewLayoutManager];\n        __LinkTextViewTextContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];\n        __LinkTextViewTextContainer.lineFragmentPadding = 0;\n        __LinkTextViewTextContainer.lineBreakMode = NSLineBreakByWordWrapping;\n        [__LinkTextViewLayoutManager addTextContainer:__LinkTextViewTextContainer];\n    }\n    @synchronized (__LinkTextViewTextStorage) {\n        __LinkTextViewTextContainer.size = CGSizeMake(width, CGFLOAT_MAX);\n        [__LinkTextViewTextStorage setAttributedString:text];\n        (void) [__LinkTextViewLayoutManager glyphRangeForTextContainer:__LinkTextViewTextContainer];\n        return [__LinkTextViewLayoutManager usedRectForTextContainer:__LinkTextViewTextContainer].size.height;\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LinksListTableViewController.h",
    "content": "//\n//  LinksListTableViewController.h\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"IRCCloudJSONObject.h\"\n\n@interface LinksListTableViewController : UITableViewController {\n    IRCCloudJSONObject *_event;\n    NSArray *_data;\n}\n@property (strong) IRCCloudJSONObject *event;\n-(void)refresh;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LinksListTableViewController.m",
    "content": "//\n//  LinksListTableViewController.m\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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#import \"LinksListTableViewController.h\"\n#import \"LinkTextView.h\"\n#import \"ColorFormatter.h\"\n#import \"NetworkConnection.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@interface LinkTableCell : UITableViewCell {\n    LinkTextView *_info;\n}\n@property (readonly) LinkTextView *info;\n@end\n\n@implementation LinkTableCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        \n        self->_info = [[LinkTextView alloc] init];\n        self->_info.font = [UIFont systemFontOfSize:FONT_SIZE];\n        self->_info.editable = NO;\n        self->_info.scrollEnabled = NO;\n        self->_info.textContainerInset = UIEdgeInsetsZero;\n        self->_info.backgroundColor = [UIColor clearColor];\n        self->_info.textColor = [UIColor messageTextColor];\n        [self.contentView addSubview:self->_info];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n\t[super layoutSubviews];\n\t\n\tCGRect frame = [self.contentView bounds];\n    frame.origin.x = 6;\n    frame.size.width -= 12;\n    \n    self->_info.frame = frame;\n}\n\n-(void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n@end\n\n@implementation LinksListTableViewController\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed)];\n    self.tableView.backgroundColor = [[UITableViewCell appearance] backgroundColor];\n    [self refresh];\n}\n\n-(void)refresh {\n    NSMutableArray *data = [[NSMutableArray alloc] init];\n    \n    for(NSDictionary *link in [self->_event objectForKey:@\"links\"]) {\n        NSMutableDictionary *d = [[NSMutableDictionary alloc] init];\n        NSAttributedString *formatted = [ColorFormatter format:[NSString stringWithFormat:@\"%c%@%c\\n%@\\nHops: %@\", BOLD, [link objectForKey:@\"server\"], CLEAR, [link objectForKey:@\"info\"], [link objectForKey:@\"hopcount\"]] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil];\n        [d setObject:formatted forKey:@\"formatted\"];\n        [d setObject:@([LinkTextView heightOfString:formatted constrainedToWidth:self.tableView.bounds.size.width - 6 - 12] + 16) forKey:@\"height\"];\n        [data addObject:d];\n    }\n    \n    self->_data = data;\n    [self.tableView reloadData];\n}\n\n-(void)doneButtonPressed {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)addButtonPressed {\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n#pragma mark - Table view data source\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    return [[row objectForKey:@\"height\"] floatValue];\n}\n\n-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return [self->_data count];\n}\n\n-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    LinkTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"linkcell\"];\n    if(!cell)\n        cell = [[LinkTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"linkcell\"];\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    cell.info.attributedText = [row objectForKey:@\"formatted\"];\n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [tableView deselectRowAtIndexPath:indexPath animated:NO];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LogExportsTableViewController.h",
    "content": "//\n//  LogExportsTableViewController.h\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n#import \"BuffersDataSource.h\"\n#import \"ServersDataSource.h\"\n\n@interface LogExportsTableViewController : UITableViewController<NSURLSessionDownloadDelegate,UIDocumentInteractionControllerDelegate> {\n    NSMutableArray *_downloaded;\n    NSArray *_available;\n    NSArray *_inprogress;\n    NSMutableDictionary *_downloadingURLs;\n    NSMutableDictionary *_fileSizes;\n    UIDocumentInteractionController *_interactionController;\n    UISwitch *_iCloudLogs;\n    \n    Buffer *_buffer;\n    Server *_server;\n    \n    NSInteger _pendingExport;\n}\n\n@property Buffer *buffer;\n@property Server *server;\n@property (copy) void (^completionHandler)(void);\n\n-(void)download:(NSURL *)url;\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LogExportsTableViewController.m",
    "content": "//\n//  LogExportsTableViewController.h\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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#import \"LogExportsTableViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"UIColor+IRCCloud.h\"\n@import Firebase;\n\n@interface LogExportsCell : UITableViewCell {\n    UIProgressView *_progress;\n}\n\n@property (readonly) UIProgressView *progress;\n@end\n\n@implementation LogExportsCell\n\n-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        \n        self->_progress = [[UIProgressView alloc] initWithFrame:CGRectZero];\n        self->_progress.tintColor = UITableViewCell.appearance.detailTextLabelColor;\n        self->_progress.trackTintColor = UITableViewCell.appearance.backgroundColor;\n        [self.contentView addSubview:self->_progress];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n    [super layoutSubviews];\n    [self->_progress sizeToFit];\n    CGRect frame = self->_progress.frame;\n    frame.origin.x = 0;\n    frame.origin.y = self.contentView.bounds.size.height - frame.size.height;\n    frame.size.width = self.contentView.bounds.size.width;\n    self->_progress.frame = frame;\n}\n@end\n\n@implementation LogExportsTableViewController\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self->_fileSizes = [[NSMutableDictionary alloc] init];\n    self->_downloadingURLs = [[NSMutableDictionary alloc] init];\n    self->_iCloudLogs = [[UISwitch alloc] init];\n    self->_pendingExport = -1;\n    [self->_iCloudLogs addTarget:self action:@selector(iCloudLogsChanged:) forControlEvents:UIControlEventValueChanged];\n    self.navigationItem.title = @\"Download Logs\";\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)];\n}\n\n-(void)doneButtonPressed:(id)sender {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)iCloudLogsChanged:(id)sender {\n    BOOL on = self->_iCloudLogs.on;\n    \n    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n        @synchronized(self) {\n            [[NSUserDefaults standardUserDefaults] setBool:on forKey:@\"iCloudLogs\"];\n            \n            NSFileManager *fm = [NSFileManager defaultManager];\n            NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];\n            NSURL *iCloudPath = [[fm URLForUbiquityContainerIdentifier:nil] URLByAppendingPathComponent:@\"Documents\"];\n            NSURL *localPath = [[fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0];\n            \n            NSURL *source,*dest;\n            \n            if(on) {\n                source = localPath;\n                dest = iCloudPath;\n            } else {\n                source = iCloudPath;\n                dest = localPath;\n            }\n            \n            for(NSURL *file in [fm contentsOfDirectoryAtURL:source includingPropertiesForKeys:nil options:0 error:nil]) {\n                [coordinator coordinateReadingItemAtURL:file options:0 writingItemAtURL:[dest URLByAppendingPathComponent:file.lastPathComponent] options:NSFileCoordinatorWritingForReplacing error:nil byAccessor:^(NSURL *newReadingURL, NSURL *newWritingURL) {\n                    CLS_LOG(@\"Moving %@ to %@\", newReadingURL, newWritingURL);\n                    NSError *error;\n                    [fm removeItemAtURL:[dest URLByAppendingPathComponent:file.lastPathComponent] error:nil];\n                    [fm setUbiquitous:on itemAtURL:newReadingURL destinationURL:newWritingURL error:&error];\n                    if(error)\n                        CLS_LOG(@\"Error moving file: %@\", error);\n                }];\n            }\n        }\n    });\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n-(void)documentInteractionControllerWillPresentOpenInMenu:(UIDocumentInteractionController *)controller {\n    [UIColor clearTheme];\n}\n\n-(void)documentInteractionControllerDidDismissOpenInMenu:(UIDocumentInteractionController *)controller {\n    [UIColor setTheme];\n}\n\n-(void)cacheFileSize:(NSDictionary *)d {\n    NSUInteger bytes = [[[[NSFileManager defaultManager] attributesOfItemAtPath:[[self downloadsPath] URLByAppendingPathComponent:[d objectForKey:@\"file_name\"]].path error:nil] objectForKey:NSFileSize] intValue];\n    if(bytes < 1024) {\n        [self->_fileSizes setObject:[NSString stringWithFormat:@\"%li B\", (long)bytes] forKey:[d objectForKey:@\"file_name\"]];\n    } else {\n        int exp = (int)(log(bytes) / log(1024));\n        [self->_fileSizes setObject:[NSString stringWithFormat:@\"%.1f %cB\", bytes / pow(1024, exp), [@\"KMGTPE\" characterAtIndex:exp-1]] forKey:[d objectForKey:@\"file_name\"]];\n    }\n}\n\n-(void)refresh:(NSDictionary *)logs {\n    self->_inprogress = [logs objectForKey:@\"inprogress\"];\n    NSMutableArray *available = [[logs objectForKey:@\"available\"] mutableCopy];\n    NSMutableArray *expired = [[logs objectForKey:@\"expired\"] mutableCopy];\n    NSMutableArray *downloaded = [[NSMutableArray alloc] init];\n    NSMutableSet *filenames = [[NSMutableSet alloc] init];\n    \n    for(int i = 0; i < available.count; i++) {\n        NSDictionary *d = [available objectAtIndex:i];\n        if([self downloadExists:d]) {\n            [self cacheFileSize:d];\n            [downloaded addObject:d];\n            [available removeObject:d];\n            [filenames addObject:[d objectForKey:@\"file_name\"]];\n            i--;\n        }\n    }\n    \n    for(int i = 0; i < expired.count; i++) {\n        NSDictionary *d = [expired objectAtIndex:i];\n        if([self downloadExists:d]) {\n            [self cacheFileSize:d];\n            [downloaded addObject:d];\n            [expired removeObject:d];\n            [filenames addObject:[d objectForKey:@\"file_name\"]];\n            i--;\n        }\n    }\n    \n    for(NSURL *file in [[NSFileManager defaultManager] contentsOfDirectoryAtURL:[self downloadsPath] includingPropertiesForKeys:@[NSURLCreationDateKey] options:0 error:nil]) {\n        if(![filenames containsObject:file.lastPathComponent]) {\n            NSDate *creationDate;\n            [file getResourceValue:&creationDate forKey:NSURLCreationDateKey error:nil];\n            NSDictionary *d = @{@\"file_name\": file.lastPathComponent, @\"startdate\": @(creationDate.timeIntervalSince1970)};\n            [self cacheFileSize:d];\n            [downloaded addObject:d];\n        }\n    }\n    \n    @synchronized (self.tableView) {\n        self->_available = available;\n        self->_downloaded = downloaded;\n        \n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self.tableView reloadData];\n        }];\n    }\n}\n\n-(void)refresh {\n    [[NetworkConnection sharedInstance] getLogExportsWithHandler:^(IRCCloudJSONObject *result) {\n        NSMutableDictionary *logs = result.dictionary.mutableCopy;\n        [logs removeObjectForKey:@\"timezones\"];\n        NSError *error = nil;\n        [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:logs requiringSecureCoding:YES error:&error] forKey:@\"logs_cache\"];\n        if(error)\n            CLS_LOG(@\"Error: %@\", error);\n        \n        [self refresh:logs];\n    }];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [UIColor setTheme];\n    [super viewWillAppear:animated];\n    self->_iCloudLogs.on = [[NSUserDefaults standardUserDefaults] boolForKey:@\"iCloudLogs\"];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"logs_cache\"]) {\n        NSError *error = nil;\n        [self refresh:[NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:NSDictionary.class, NSArray.class, NSNull.class,NSString.class,NSNumber.class, nil] fromData:[[NSUserDefaults standardUserDefaults] objectForKey:@\"logs_cache\"] error:&error]];\n        if(error)\n            CLS_LOG(@\"Error: %@\", error);\n    }\n    [self refresh];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    \n    switch(event) {\n        case kIRCEventLogExportFinished:\n            [self refresh];\n            break;\n        default:\n            break;\n    }\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    @synchronized (self.tableView) {\n        return 1 + (self->_inprogress.count > 0) + (self->_downloaded.count > 0) + (self->_available.count > 0);\n    }\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    @synchronized (self.tableView) {\n        if(section > 0 && _inprogress.count == 0)\n            section++;\n        \n        if(section > 1 && _downloaded.count == 0)\n            section++;\n\n        if(section > 2 && _available.count == 0)\n            section++;\n        \n        switch(section) {\n            case 0:\n                if (@available(iOS 14.0, *)) {\n                    if([NSProcessInfo processInfo].macCatalystApp) {\n                        return 3;\n                    }\n                }\n                return [[NSFileManager defaultManager] ubiquityIdentityToken]?4:3;\n            case 1:\n                return _inprogress.count;\n            case 2:\n                return _downloaded.count;\n            case 3:\n                return _available.count;\n        }\n        return 0;\n    }\n}\n\n-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {\n    @synchronized (self.tableView) {\n        if(section > 0 && _inprogress.count == 0)\n            section++;\n        \n        if(section > 1 && _downloaded.count == 0)\n            section++;\n\n        if(section > 2 && _available.count == 0)\n            section++;\n        \n        switch(section) {\n            case 0:\n                return @\"Export Logs\";\n            case 1:\n                return @\"Pending\";\n            case 2:\n                return @\"Downloaded\";\n            case 3:\n                return @\"Available\";\n        }\n        return nil;\n    }\n}\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized (self.tableView) {\n        if(indexPath.section == 0)\n            return 44;\n        else\n            return 64;\n    }\n}\n\n- (NSString *)relativeTime:(double)seconds {\n    NSString *date = nil;\n    seconds = fabs(seconds);\n    double minutes = fabs(seconds) / 60.0;\n    double hours = minutes / 60.0;\n    double days = hours / 24.0;\n    double months = days / 31.0;\n    double years = months / 12.0;\n    \n    if(years >= 1) {\n        if(years - (int)years > 0.5)\n            years++;\n        \n        if((int)years == 1)\n            date = [NSString stringWithFormat:@\"%i year\", (int)years];\n        else\n            date = [NSString stringWithFormat:@\"%i years\", (int)years];\n    } else if(months >= 1) {\n        if(months - (int)months > 0.5)\n            months++;\n        \n        if((int)months == 1)\n            date = [NSString stringWithFormat:@\"%i month\", (int)months];\n        else\n            date = [NSString stringWithFormat:@\"%i months\", (int)months];\n    } else if(days >= 1) {\n        if(days - (int)days > 0.5)\n            days++;\n        \n        if((int)days == 1)\n            date = [NSString stringWithFormat:@\"%i day\", (int)days];\n        else\n            date = [NSString stringWithFormat:@\"%i days\", (int)days];\n    } else if(hours >= 1) {\n        if(hours - (int)hours > 0.5)\n            hours++;\n        \n        if((int)hours < 2)\n            date = [NSString stringWithFormat:@\"%i hour\", (int)hours];\n        else\n            date = [NSString stringWithFormat:@\"%i hours\", (int)hours];\n    } else if(minutes >= 1) {\n        if(minutes - (int)minutes > 0.5)\n            minutes++;\n        \n        if((int)minutes == 1)\n            date = [NSString stringWithFormat:@\"%i minute\", (int)minutes];\n        else\n            date = [NSString stringWithFormat:@\"%i minutes\", (int)minutes];\n    } else {\n        date = @\"less than a minute\";\n    }\n    return date;\n}\n\n- (BOOL)downloadExists:(NSDictionary *)row {\n    if([row objectForKey:@\"file_name\"] && ![[row objectForKey:@\"file_name\"] isKindOfClass:[NSNull class]]) {\n        return ([[NSFileManager defaultManager] fileExistsAtPath:[[self downloadsPath] URLByAppendingPathComponent:[row objectForKey:@\"file_name\"]].path]);\n    } else {\n        return NO;\n    }\n}\n\n- (NSURL *)fileForDownload:(NSDictionary *)row {\n    return [[self downloadsPath] URLByAppendingPathComponent:[row objectForKey:@\"file_name\"]];\n}\n\n- (NSURL *)downloadsPath {\n    NSFileManager *fm = [NSFileManager defaultManager];\n    if([fm ubiquityIdentityToken] && [[NSUserDefaults standardUserDefaults] boolForKey:@\"iCloudLogs\"])\n        return [[fm URLForUbiquityContainerIdentifier:nil] URLByAppendingPathComponent:@\"Documents\"];\n    else\n        return [[fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized (self.tableView) {\n        UIActivityIndicatorView *spinner;\n        LogExportsCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"LogExport\"];\n        if(!cell)\n            cell = [[LogExportsCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@\"LogExport\"];\n        \n        cell.accessoryView = nil;\n        cell.progress.hidden = YES;\n        \n        if(indexPath.section == 0) {\n            switch(indexPath.row) {\n                case 0:\n                    cell.textLabel.text = @\"This Network\";\n                    cell.detailTextLabel.text = self->_server.name.length ? _server.name : _server.hostname;\n                    break;\n                case 1:\n                    if([self->_buffer.type isEqualToString:@\"channel\"])\n                        cell.textLabel.text = @\"This Channel\";\n                    else if([self->_buffer.type isEqualToString:@\"console\"])\n                        cell.textLabel.text = @\"This Network Console\";\n                    else\n                        cell.textLabel.text = @\"This Conversation\";\n                    if([self->_buffer.type isEqualToString:@\"console\"])\n                        cell.detailTextLabel.text = self->_server.name.length ? _server.name : _server.hostname;\n                    else\n                        cell.detailTextLabel.text = self->_buffer.name;\n                    break;\n                case 2:\n                    cell.textLabel.text = @\"All Networks\";\n                    cell.detailTextLabel.text = [NSString stringWithFormat:@\"%lu networks\", (unsigned long)[ServersDataSource sharedInstance].count];\n                    break;\n                case 3:\n                    cell.textLabel.text = @\"iCloud Drive Sync\";\n                    cell.detailTextLabel.text = nil;\n                    cell.accessoryView = self->_iCloudLogs;\n                    break;\n            }\n            if(self->_pendingExport == indexPath.row) {\n                spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n                [spinner sizeToFit];\n                [spinner startAnimating];\n                cell.accessoryView = spinner;\n            } else {\n                cell.accessoryType = UITableViewCellAccessoryNone;\n            }\n        } else {\n            NSInteger section = indexPath.section;\n            \n            if(section > 0 && _inprogress.count == 0)\n                section++;\n            \n            if(section > 1 && _downloaded.count == 0)\n                section++;\n\n            if(section > 2 && _available.count == 0)\n                section++;\n            \n            NSDictionary *row = nil;\n            switch(section) {\n                case 1:\n                    if(indexPath.row < _inprogress.count) {\n                        row = [self->_inprogress objectAtIndex:indexPath.row];\n                    }\n                    break;\n                case 2:\n                    if(indexPath.row < _downloaded.count) {\n                        row = [self->_downloaded objectAtIndex:indexPath.row];\n                    }\n                    break;\n                case 3:\n                    if(indexPath.row < _available.count) {\n                        row = [self->_available objectAtIndex:indexPath.row];\n                    }\n                    break;\n            }\n            \n            if(row) {\n                Server *s = ![[row objectForKey:@\"cid\"] isKindOfClass:[NSNull class]] ? [[ServersDataSource sharedInstance] getServer:[[row objectForKey:@\"cid\"] intValue]] : nil;\n                Buffer *b = ![[row objectForKey:@\"bid\"] isKindOfClass:[NSNull class]] ? [[BuffersDataSource sharedInstance] getBuffer:[[row objectForKey:@\"bid\"] intValue]] : nil;\n                \n                NSString *serverName = s ? (s.name.length ? s.name : s.hostname) : [NSString stringWithFormat:@\"Unknown Network (%@)\", [row objectForKey:@\"cid\"]];\n                NSString *bufferName = b ? b.name : [NSString stringWithFormat:@\"Unknown Log (%@)\", [row objectForKey:@\"bid\"]];\n                \n                if(![row objectForKey:@\"bid\"] && ![row objectForKey:@\"cid\"])\n                    cell.textLabel.text = [row objectForKey:@\"file_name\"];\n                else if(![[row objectForKey:@\"bid\"] isKindOfClass:[NSNull class]])\n                    cell.textLabel.text = [NSString stringWithFormat:@\"%@: %@\", serverName, bufferName];\n                else if(![[row objectForKey:@\"cid\"] isKindOfClass:[NSNull class]])\n                    cell.textLabel.text = serverName;\n                else\n                    cell.textLabel.text = @\"All Networks\";\n\n                if(section > 1) {\n                    if(section == 2 || [[row objectForKey:@\"expirydate\"] isKindOfClass:[NSNull class]]) {\n                        if([self->_fileSizes objectForKey:[row objectForKey:@\"file_name\"]])\n                            cell.detailTextLabel.text = [NSString stringWithFormat:@\"Exported %@ ago\\n%@\", [self relativeTime:[NSDate date].timeIntervalSince1970 - [[row objectForKey:@\"startdate\"] doubleValue]], [self->_fileSizes objectForKey:[row objectForKey:@\"file_name\"]]];\n                        else\n                            cell.detailTextLabel.text = [NSString stringWithFormat:@\"Exported %@ ago\", [self relativeTime:[NSDate date].timeIntervalSince1970 - [[row objectForKey:@\"startdate\"] doubleValue]]];\n                    } else {\n                        cell.detailTextLabel.text = [NSString stringWithFormat:([NSDate date].timeIntervalSince1970 - [[row objectForKey:@\"expirydate\"] doubleValue] < 0)?@\"Exported %@ ago\\nExpires in %@\":@\"Exported %@ ago\\nExpired %@ ago\", [self relativeTime:[NSDate date].timeIntervalSince1970 - [[row objectForKey:@\"startdate\"] doubleValue]], [self relativeTime:[NSDate date].timeIntervalSince1970 - [[row objectForKey:@\"expirydate\"] doubleValue]]];\n                    }\n                } else {\n                    cell.detailTextLabel.text = [NSString stringWithFormat:@\"Started %@ ago\", [self relativeTime:[NSDate date].timeIntervalSince1970 - [[row objectForKey:@\"startdate\"] doubleValue]]];\n                }\n                cell.detailTextLabel.numberOfLines = 0;\n                \n                if(section == 1 || [self->_downloadingURLs objectForKey:[row objectForKey:@\"redirect_url\"]]) {\n                    cell.accessoryType = UITableViewCellAccessoryNone;\n                    [cell.progress setProgress:[[self->_downloadingURLs objectForKey:[row objectForKey:@\"redirect_url\"]] floatValue] animated:YES];\n                    if(cell.progress.progress > 0) {\n                        cell.progress.hidden = NO;\n                    } else {\n                        spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n                        [spinner sizeToFit];\n                        [spinner startAnimating];\n                        cell.accessoryView = spinner;\n                    }\n                } else {\n                    cell.accessoryType = UITableViewCellAccessoryNone;\n                }\n            } else {\n                CLS_LOG(@\"Requested row %li not found for section %li, reloading table\", (long)indexPath.row, (long)indexPath.section);\n                [self.tableView reloadData];\n            }\n        }\n        \n        return cell;\n    }\n}\n\n#pragma mark - Table view delegate\n\n-(void)requestExport:(int)cid bid:(int)bid {\n    for(NSDictionary *d in _inprogress) {\n        int e_cid = -1;\n        int e_bid = -1;\n        if(![[d objectForKey:@\"cid\"] isKindOfClass:[NSNull class]])\n            e_cid = [[d objectForKey:@\"cid\"] intValue];\n        if(![[d objectForKey:@\"bid\"] isKindOfClass:[NSNull class]])\n            e_bid = [[d objectForKey:@\"bid\"] intValue];\n        \n        if(cid == e_cid && bid == e_bid) {\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Export In Progress\" message:@\"This export is already in progress.  We'll email you when it's ready.\" preferredStyle:UIAlertControllerStyleAlert];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n            [self presentViewController:alert animated:YES completion:nil];\n            self->_pendingExport = -1;\n            return;\n        }\n    }\n    \n    [[NetworkConnection sharedInstance] exportLog:[NSTimeZone localTimeZone].name cid:cid bid:bid handler:^(IRCCloudJSONObject *result) {\n        @synchronized (self.tableView) {\n            if([[result objectForKey:@\"success\"] boolValue]) {\n                NSMutableArray *inprogress = self->_inprogress.mutableCopy;\n                [inprogress insertObject:[result objectForKey:@\"export\"] atIndex:0];\n                self->_inprogress = inprogress;\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Exporting\" message:@\"Your log export is in progress.  We'll email you when it's ready.\" preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n            } else {\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Export Failed\" message:[NSString stringWithFormat:@\"Unable to export log: %@.  Please try again shortly.\", [result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n            }\n            self->_pendingExport = -1;\n            [self.tableView reloadData];\n        }\n    }];\n}\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    @synchronized (self.tableView) {\n        [tableView deselectRowAtIndexPath:indexPath animated:NO];\n        \n        NSInteger section = indexPath.section;\n        \n        if(section > 0 && _inprogress.count == 0)\n            section++;\n        \n        if(section > 1 && _downloaded.count == 0)\n            section++;\n        \n        if(section > 2 && _available.count == 0)\n            section++;\n        \n        switch(section) {\n            case 0:\n                if(indexPath.row < 3) {\n                    if(self->_pendingExport != -1)\n                        break;\n                    self->_pendingExport = indexPath.row;\n                    [self.tableView reloadData];\n                }\n                switch(indexPath.row) {\n                    case 0:\n                        [self requestExport:self->_server.cid bid:-1];\n                        break;\n                    case 1:\n                        [self requestExport:self->_server.cid bid:self->_buffer.bid];\n                        break;\n                    case 2:\n                        [self requestExport:-1 bid:-1];\n                        break;\n                }\n                break;\n            case 1:\n            {\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Preparing Download\" message:@\"This export is being prepared.  You will recieve a notification when it is ready for download.\" preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n                break;\n            }\n            case 2:\n            {\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];\n                NSURL *file = [self fileForDownload:[self->_downloaded objectAtIndex:indexPath.row]];\n                NSURL *url = [[self->_downloaded objectAtIndex:indexPath.row] objectForKey:@\"redirect_url\"];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Open\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        self->_interactionController = [UIDocumentInteractionController interactionControllerWithURL:file];\n                        self->_interactionController.delegate = self;\n                        [self->_interactionController presentOpenInMenuFromRect:[self.view convertRect:[self.tableView rectForRowAtIndexPath:indexPath] fromView:self.tableView] inView:self.view animated:YES];\n                    }];\n                }]];\n                \n                [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {\n                    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Delete Download\" message:[[NSUserDefaults standardUserDefaults] boolForKey:@\"iCloudLogs\"]?@\"Are you sure you want to delete this download?  It will be removed from your device and all other devices that are syncing with iCloud Drive.\":@\"Are you sure you want to delete this download from your device?\" preferredStyle:UIAlertControllerStyleAlert];\n                    \n                    [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {\n                        if(url)\n                            [self->_downloadingURLs setObject:@(0) forKey:url];\n                        [self.tableView reloadData];\n                        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n                            NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];\n                            [coordinator coordinateWritingItemAtURL:file options:NSFileCoordinatorWritingForDeleting error:nil byAccessor:^(NSURL *writingURL) {\n                                NSError *error;\n                                [[NSFileManager defaultManager] removeItemAtPath:writingURL.path error:NULL];\n                                if(error)\n                                    CLS_LOG(@\"Error: %@\", error);\n                                [self refresh:[NSKeyedUnarchiver unarchivedObjectOfClass:NSDictionary.class fromData:[[NSUserDefaults standardUserDefaults] objectForKey:@\"logs_cache\"] error:&error]];\n                                if(error)\n                                    CLS_LOG(@\"Error: %@\", error);\n                                if(url)\n                                    [self->_downloadingURLs removeObjectForKey:url];\n                                [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];\n                                [self performSelectorOnMainThread:@selector(refresh) withObject:nil waitUntilDone:YES];\n                            }];\n                        });\n                    }]];\n                    \n                    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n                    alert.popoverPresentationController.sourceRect = [self.tableView rectForRowAtIndexPath:indexPath];\n                    alert.popoverPresentationController.sourceView = self.tableView;\n                    [self presentViewController:alert animated:YES completion:nil];\n                }]];\n\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n                alert.popoverPresentationController.sourceRect = [self.tableView rectForRowAtIndexPath:indexPath];\n                alert.popoverPresentationController.sourceView = self.tableView;\n                [self presentViewController:alert animated:YES completion:nil];\n                break;\n            }\n            case 3:\n                [self download:[NSURL URLWithString:[[self->_available objectAtIndex:indexPath.row] objectForKey:@\"redirect_url\"]]];\n                break;\n        }\n    }\n}\n\n-(void)download:(NSURL *)url {\n    if (@available(iOS 14.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp) {\n            [[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n            return;\n        }\n    }\n    \n    if([self->_downloadingURLs objectForKey:url.absoluteString]) {\n        CLS_LOG(@\"Ignoring duplicate download request for %@\", url);\n        return;\n    }\n    NSURLSession *session;\n    NSURLSessionConfiguration *config;\n    config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:[NSString stringWithFormat:@\"com.irccloud.logs.%li\", time(NULL)]];\n#ifdef ENTERPRISE\n    config.sharedContainerIdentifier = @\"group.com.irccloud.enterprise.share\";\n#else\n    config.sharedContainerIdentifier = @\"group.com.irccloud.share\";\n#endif\n    config.HTTPCookieStorage = nil;\n    config.URLCache = nil;\n    config.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;\n    config.discretionary = NO;\n    session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];\n    \n    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];\n    [request setHTTPShouldHandleCookies:NO];\n    [request setValue:[NSString stringWithFormat:@\"session=%@\",[NetworkConnection sharedInstance].session] forHTTPHeaderField:@\"Cookie\"];\n    \n    [[session downloadTaskWithRequest:request] resume];\n\n    @synchronized (self.tableView) {\n        [self->_downloadingURLs setObject:@(0) forKey:url.absoluteString];\n    }\n    [self.tableView reloadData];\n}\n\n-(void)URLSession:(NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {\n    [self->_downloadingURLs setObject:@((float)totalBytesWritten / (float)totalBytesExpectedToWrite) forKey:downloadTask.originalRequest.URL.absoluteString];\n    [self.tableView reloadData];\n}\n\n-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {\n    [self->_downloadingURLs removeObjectForKey:task.originalRequest.URL.absoluteString];\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        [self.tableView reloadData];\n        if(error) {\n            [[NotificationsDataSource sharedInstance] alert:[NSString stringWithFormat:@\"Unable to download logs: %@\", error.description] title:@\"Download Failed\" category:nil userInfo:nil];\n        } else {\n            [[NotificationsDataSource sharedInstance] alert:@\"Logs are now available\" title:@\"Download Complete\" category:@\"view_logs\" userInfo:@{@\"view_logs\":@(YES)}];\n        }\n        if(self.completionHandler)\n            self.completionHandler();\n    }];\n}\n\n-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {\n    NSError *error;\n    NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];\n    NSFileManager *fm = [NSFileManager defaultManager];\n    \n    NSURL *dest = [self downloadsPath];\n    [coordinator coordinateWritingItemAtURL:dest options:0 error:&error byAccessor:^(NSURL *newURL) {\n        [fm createDirectoryAtURL:dest withIntermediateDirectories:YES attributes:nil error:NULL];\n    }];\n    \n    dest = [dest URLByAppendingPathComponent:downloadTask.originalRequest.URL.lastPathComponent];\n    \n    [coordinator coordinateReadingItemAtURL:location options:0 writingItemAtURL:dest options:NSFileCoordinatorWritingForReplacing error:&error byAccessor:^(NSURL *newReadingURL, NSURL *newWritingURL) {\n        NSError *error;\n        [fm removeItemAtPath:newWritingURL.path error:NULL];\n        [fm copyItemAtPath:newReadingURL.path toPath:newWritingURL.path error:&error];\n        NSUInteger bytes = [[[[NSFileManager defaultManager] attributesOfItemAtPath:newWritingURL.path error:nil] objectForKey:NSFileSize] intValue];\n        if(bytes < 1024) {\n            [self->_fileSizes setObject:[NSString stringWithFormat:@\"%li B\", (long)bytes] forKey:downloadTask.originalRequest.URL.lastPathComponent];\n        } else {\n            int exp = (int)(log(bytes) / log(1024));\n            [self->_fileSizes setObject:[NSString stringWithFormat:@\"%.1f %cB\", bytes / pow(1024, exp), [@\"KMGTPE\" characterAtIndex:exp-1]] forKey:downloadTask.originalRequest.URL.lastPathComponent];\n        }\n        if(error)\n            CLS_LOG(@\"Error: %@\", error);\n    }];\n    \n    [self->_downloadingURLs removeObjectForKey:downloadTask.originalRequest.URL];\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        @synchronized (self.tableView) {\n            NSMutableArray *available = self->_available.mutableCopy;\n            \n            for(int i = 0; i < available.count; i++) {\n                if([[[available objectAtIndex:i] objectForKey:@\"redirect_url\"] isEqualToString:downloadTask.originalRequest.URL.absoluteString]) {\n                    [self->_downloaded addObject:[available objectAtIndex:i]];\n                    [available removeObjectAtIndex:i];\n                    break;\n                }\n            }\n            \n            self->_available = available;\n        }\n        [self.tableView reloadData];\n        if(self.completionHandler)\n            self.completionHandler();\n    }];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LoginSplashViewController.h",
    "content": "//\n//  LoginSplashViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import <MessageUI/MFMailComposeViewController.h>\n\n@interface LoginSplashViewController : UIViewController<UITextFieldDelegate, UIGestureRecognizerDelegate, MFMailComposeViewControllerDelegate> {\n    IBOutlet UIImageView *logo;\n    IBOutlet UILabel *IRC;\n    IBOutlet UILabel *Cloud;\n    IBOutlet UILabel *version;\n    \n    IBOutlet UIView *loginView;\n    IBOutlet NSLayoutConstraint *loginViewYOffset;\n    IBOutlet UITextField *name;\n    IBOutlet UITextField *username;\n    IBOutlet NSLayoutConstraint *usernameYOffset;\n    IBOutlet UITextField *password;\n    IBOutlet NSLayoutConstraint *passwordYOffset;\n    IBOutlet UITextField *host;\n    IBOutlet NSLayoutConstraint *hostYOffset;\n    IBOutlet UIButton *login;\n    IBOutlet NSLayoutConstraint *loginYOffset;\n    IBOutlet UIButton *signup;\n    IBOutlet NSLayoutConstraint *signupYOffset;\n    IBOutlet UIButton *next;\n    IBOutlet NSLayoutConstraint *nextYOffset;\n    IBOutlet UIButton *sendAccessLink;\n    IBOutlet NSLayoutConstraint *sendAccessLinkYOffset;\n    \n    IBOutlet UIView *loadingView;\n    IBOutlet NSLayoutConstraint *loadingViewYOffset;\n    IBOutlet UILabel *status;\n    IBOutlet UIActivityIndicatorView *activity;\n    \n    IBOutlet UIControl *signupHint;\n    IBOutlet UIControl *loginHint;\n    IBOutlet UIControl *forgotPasswordHint;\n    IBOutlet UIControl *resetPasswordHint;\n    IBOutlet UIControl *TOSHint;\n    IBOutlet UIControl *enterpriseLearnMore;\n    IBOutlet UIControl *forgotPasswordLogin;\n    IBOutlet UIControl *forgotPasswordSignup;\n    \n    IBOutlet UILabel *enterpriseHint;\n    IBOutlet UILabel *hostHint;\n    IBOutlet UILabel *enterEmailAddressHint;\n    IBOutlet UIView *notAProblem;\n    \n    IBOutlet UIButton *OnePassword;\n    \n    CGSize _kbSize;\n    NSURL *_accessLink;\n    BOOL _gotCredentialsFromPasswordManager;\n    BOOL _requestingReset;\n    NSString *_authURL;\n}\n@property NSURL *accessLink;\n-(IBAction)loginButtonPressed:(id)sender;\n-(IBAction)signupButtonPressed:(id)sender;\n-(IBAction)textFieldChanged:(id)sender;\n-(IBAction)loginHintPressed:(id)sender;\n-(IBAction)signupHintPressed:(id)sender;\n-(IBAction)forgotPasswordHintPressed:(id)sender;\n-(IBAction)resetPasswordHintPressed:(id)sender;\n-(IBAction)TOSHintPressed:(id)sender;\n-(IBAction)nextButtonPressed:(id)sender;\n-(IBAction)enterpriseLearnMorePressed:(id)sender;\n-(IBAction)sendAccessLinkButtonPressed:(id)sender;\n-(IBAction)hideKeyboard:(id)sender;\n-(void)hideLoginView;\n-(UIImageView *)logo;\n-(IBAction)onePasswordButtonPressed:(id)sender;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/LoginSplashViewController.m",
    "content": "//\n//  LoginSplashViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <QuartzCore/QuartzCore.h>\n#import \"LoginSplashViewController.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"AppDelegate.h\"\n#import \"OnePasswordExtension.h\"\n#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n#import \"SamlLoginViewController.h\"\n@import Firebase;\n\n@implementation LoginSplashViewController\n\n- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {\n    return ![touch.view isKindOfClass:[UIControl class]];\n}\n\n-(UIStatusBarStyle)preferredStatusBarStyle {\n    return UIStatusBarStyleLightContent;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    \n    if (@available(iOS 13, *)) {\n        self.view.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;\n    }\n    self->_kbSize = CGSizeZero;\n\n    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard:)];\n    tap.delegate = self;\n    tap.cancelsTouchesInView = NO;\n    [self.view addGestureRecognizer:tap];\n    \n    UISwipeGestureRecognizer *swipe =[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard:)];\n    swipe.direction = UISwipeGestureRecognizerDirectionDown;\n    [self.view addGestureRecognizer:swipe];\n    \n    UIFont *sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-Regular\" size:38];\n    IRC.font = sourceSansPro;\n    [IRC sizeToFit];\n    Cloud.font = sourceSansPro;\n    [Cloud sizeToFit];\n#ifdef ENTERPRISE\n    Cloud.textColor = IRC.textColor;\n    IRC.textColor = [UIColor whiteColor];\n#endif\n    \n    sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-Regular\" size:16];\n    enterpriseHint.font = sourceSansPro;\n    \n    for(UILabel *l in signupHint.subviews) {\n        l.font = sourceSansPro;\n        [l sizeToFit];\n        sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-Regular\" size:18];\n    }\n\n    sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-Regular\" size:16];\n    for(UILabel *l in loginHint.subviews) {\n        l.font = sourceSansPro;\n        [l sizeToFit];\n        sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-Regular\" size:18];\n    }\n    \n    ((UILabel *)(forgotPasswordLogin.subviews.firstObject)).font = sourceSansPro;\n    ((UILabel *)(forgotPasswordSignup.subviews.firstObject)).font = sourceSansPro;\n    sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-Regular\" size:15];\n    ((UILabel *)(notAProblem.subviews.firstObject)).font = sourceSansPro;\n    sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-LightIt\" size:15];\n    ((UILabel *)(notAProblem.subviews.lastObject)).font = sourceSansPro;\n    sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-Regular\" size:13];\n    enterEmailAddressHint.font = sourceSansPro;\n    \n    sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-Regular\" size:14];\n    for(UILabel *l in forgotPasswordHint.subviews) {\n        l.font = sourceSansPro;\n        [l sizeToFit];\n    }\n\n    for(UILabel *l in resetPasswordHint.subviews) {\n        l.font = sourceSansPro;\n        [l sizeToFit];\n    }\n\n    for(UILabel *l in TOSHint.subviews) {\n        l.font = sourceSansPro;\n        [l sizeToFit];\n    }\n\n    for(UILabel *l in enterpriseLearnMore.subviews) {\n        l.font = sourceSansPro;\n        [l sizeToFit];\n    }\n    \n    sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-LightIt\" size:13];\n    hostHint.font = sourceSansPro;\n    \n    sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-Regular\" size:16];\n    \n    self.view.frame = [UIScreen mainScreen].bounds;\n    username.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 9, username.frame.size.height)];\n    username.leftViewMode = UITextFieldViewModeAlways;\n    username.rightView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 9, username.frame.size.height)];\n    username.rightViewMode = UITextFieldViewModeAlways;\n    username.font = sourceSansPro;\n#ifdef ENTERPRISE\n    username.placeholder = @\"Email or Username\";\n#endif\n    password.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 9, password.frame.size.height)];\n    password.leftViewMode = UITextFieldViewModeAlways;\n    password.rightView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 9, password.frame.size.height)];\n    password.rightViewMode = UITextFieldViewModeAlways;\n    password.font = sourceSansPro;\n    host.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 9, host.frame.size.height)];\n    host.leftViewMode = UITextFieldViewModeAlways;\n    host.rightView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 9, host.frame.size.height)];\n    host.rightViewMode = UITextFieldViewModeAlways;\n    host.font = sourceSansPro;\n    name.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 9, name.frame.size.height)];\n    name.leftViewMode = UITextFieldViewModeAlways;\n    name.rightView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 9, name.frame.size.height)];\n    name.rightViewMode = UITextFieldViewModeAlways;\n    name.font = sourceSansPro;\n    \n    sourceSansPro = [UIFont fontWithName:@\"SourceSansPro-Regular\" size:17];\n    login.titleLabel.font = sourceSansPro;\n    login.enabled = NO;\n    signup.titleLabel.font = sourceSansPro;\n    signup.enabled = NO;\n    next.titleLabel.font = sourceSansPro;\n    next.enabled = NO;\n    sendAccessLink.titleLabel.font = sourceSansPro;\n    sendAccessLink.enabled = NO;\n#ifdef BRAND_NAME\n    [version setText:[NSString stringWithFormat:@\"Version %@-%@\",[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"], @BRAND_NAME]];\n#else\n    [version setText:[NSString stringWithFormat:@\"Version %@\",[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"]]];\n#endif\n    host.text = [[NSUserDefaults standardUserDefaults] objectForKey:@\"host\"];\n#ifdef ENTERPRISE\n    if([host.text isEqualToString:@\"api.irccloud.com\"] || [host.text isEqualToString:@\"www.irccloud.com\"])\n        host.text = nil;\n#else\n    host.hidden = YES;\n#endif\n    name.background = [UIImage imageNamed:@\"login_top_input\"];\n    username.background = [UIImage imageNamed:@\"login_top_input\"];\n    password.background = [UIImage imageNamed:@\"login_bottom_input\"];\n    host.background = [UIImage imageNamed:@\"login_only_input\"];\n\n    [self transitionToSize:self.view.bounds.size];\n}\n\n-(void)hideLoginView {\n    loginView.alpha = 0;\n    loadingView.alpha = 1;\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(keyboardWillShow:)\n                                                 name:UIKeyboardWillShowNotification object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(keyboardWillBeHidden:)\n                                                 name:UIKeyboardWillHideNotification object:nil];\n    \n    password.text = @\"\";\n    loadingView.alpha = 0;\n    loginView.alpha = 1;\n    if(sendAccessLink.alpha) {\n        [self forgotPasswordHintPressed:nil];\n    } else if(username.text.length && !name.text.length) {\n        [self loginHintPressed:nil];\n    } else {\n        [self signupHintPressed:nil];\n    }\n#ifdef ENTERPRISE\n    host.alpha = 1;\n    username.alpha = 0;\n    password.alpha = 0;\n    name.alpha = 0;\n    enterpriseHint.alpha = 1;\n    enterpriseHint.text = @\"Enterprise Edition\";\n    loginHint.alpha = 0;\n    signupHint.alpha = 0;\n    login.alpha = 0;\n    signup.alpha = 0;\n    next.alpha = 1;\n    TOSHint.alpha = 0;\n    forgotPasswordHint.alpha = 0;\n    enterpriseLearnMore.alpha = 1;\n    hostHint.alpha = 1;\n#endif\n    [self transitionToSize:self.view.bounds.size];\n    if(self->_accessLink && IRCCLOUD_HOST.length) {\n        self->_gotCredentialsFromPasswordManager = YES;\n        [self _loginWithAccessLink];\n#ifndef ENTERPRISE\n    } else {\n        [self performSelector:@selector(_promptForSWC) withObject:nil afterDelay:0.1];\n#endif\n    }\n}\n\n-(void)_promptForSWC {\n#if !TARGET_OS_MACCATALYST\n    if (@available(macCatalyst 14.0, *)) {\n        if(username.text.length == 0 && !_gotCredentialsFromPasswordManager && !_accessLink) {\n            SecRequestSharedWebCredential(NULL, NULL, ^(CFArrayRef credentials, CFErrorRef error) {\n                if (error != NULL) {\n                    CLS_LOG(@\"Unable to request shared web credentials: %@\", error);\n                    return;\n                }\n                \n                if (CFArrayGetCount(credentials) > 0) {\n                    self->_gotCredentialsFromPasswordManager = YES;\n                    NSDictionary *credentialsDict = CFArrayGetValueAtIndex(credentials, 0);\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        [self->username setText:[credentialsDict objectForKey:(__bridge id)(kSecAttrAccount)]];\n                        [self->password setText:[credentialsDict objectForKey:(__bridge id)(kSecSharedPassword)]];\n                        [self loginHintPressed:nil];\n                        [self loginButtonPressed:nil];\n                    }];\n                }\n            });\n        }\n    }\n#endif\n}\n\n-(void)_loginWithAccessLink {\n    if([self->_accessLink.scheme hasPrefix:@\"irccloud\"] && [self->_accessLink.host isEqualToString:@\"chat\"] && [self->_accessLink.path isEqualToString:@\"/access-link\"])\n                self->_accessLink = [NSURL URLWithString:[NSString stringWithFormat:@\"https://%@/%@%@?%@&format=json\", IRCCLOUD_HOST, _accessLink.host, _accessLink.path, _accessLink.query]];\n\n    loginView.alpha = 0;\n    loadingView.alpha = 1;\n    [status setText:@\"Signing in\"];\n    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, status.text);\n    [activity startAnimating];\n    activity.hidden = NO;\n    [[NetworkConnection sharedInstance] login:self->_accessLink handler:^(IRCCloudJSONObject *result) {\n        self->_accessLink = nil;\n        if([[result objectForKey:@\"success\"] intValue] == 1) {\n            if([result objectForKey:@\"websocket_path\"])\n                IRCCLOUD_PATH = [result objectForKey:@\"websocket_path\"];\n            [NetworkConnection sharedInstance].session = [result objectForKey:@\"session\"];\n            [[NSUserDefaults standardUserDefaults] setObject:IRCCLOUD_PATH forKey:@\"path\"];\n            [[NSUserDefaults standardUserDefaults] synchronize];\n            if([result objectForKey:@\"api_host\"])\n                [[NetworkConnection sharedInstance] updateAPIHost:[result objectForKey:@\"api_host\"]];\n#ifdef ENTERPRISE\n            NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n            NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n            [d setObject:IRCCLOUD_HOST forKey:@\"host\"];\n            [d setObject:IRCCLOUD_PATH forKey:@\"path\"];\n            [d synchronize];\n            self->loginHint.alpha = 0;\n            self->signupHint.alpha = 0;\n            self->enterpriseHint.alpha = 0;\n            self->forgotPasswordLogin.alpha = 0;\n            self->forgotPasswordSignup.alpha = 0;\n            [((AppDelegate *)([UIApplication sharedApplication].delegate)) showMainView:YES];\n        } else {\n            [UIView beginAnimations:nil context:nil];\n            self->loginView.alpha = 1;\n            self->loadingView.alpha = 0;\n            [UIView commitAnimations];\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Login Failed\" message:@\"Invalid access link\" preferredStyle:UIAlertControllerStyleAlert];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n            [self presentViewController:alert animated:YES completion:nil];\n        }\n    }];\n}\n\n-(void)viewDidAppear:(BOOL)animated {\n    [super viewDidAppear:animated];\n    [self transitionToSize:self.view.bounds.size];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [username resignFirstResponder];\n    [password resignFirstResponder];\n    [host resignFirstResponder];\n}\n\n-(void)viewDidDisappear:(BOOL)animated {\n    [super viewDidDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)_updateFieldPositions {\n    int offset = 0;\n    if(name.alpha)\n        offset = 1;\n    \n    if(self->_authURL)\n        offset = -2;\n    \n    if(name.alpha > 0)\n        username.background = [UIImage imageNamed:@\"login_mid_input\"];\n    else if(sendAccessLink.alpha > 0)\n        username.background = [UIImage imageNamed:@\"login_only_input\"];\n    else\n        username.background = [UIImage imageNamed:@\"login_top_input\"];\n\n    if(sendAccessLink.alpha) {\n        usernameYOffset.constant = 16 + 26;\n    } else {\n        usernameYOffset.constant = 16 + (offset * 39);\n    }\n\n    passwordYOffset.constant = 16 + ((offset + 1) * 39);\n    nextYOffset.constant = 16 + 39 + 32;\n    loginYOffset.constant = signupYOffset.constant = 16 + ((offset + 2) * 39) + 15;\n    sendAccessLinkYOffset.constant = 16 + 81;\n    \n    OnePassword.hidden = self->_authURL || (login.alpha != 1 && signup.alpha != 1) || ![[OnePasswordExtension sharedExtension] isAppExtensionAvailable];\n}\n\n-(UIImageView *)logo {\n    return logo;\n}\n\n-(void)transitionToSize:(CGSize)size {\n    if(self->_kbSize.height && [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {\n        self.view.window.backgroundColor = [UIColor colorWithRed:68.0/255.0 green:128.0/255.0 blue:250.0/255.0 alpha:1];\n        loadingViewYOffset.constant = loginViewYOffset.constant = logo.frame.origin.y + logo.frame.size.height + 16;\n    } else {\n        self.view.window.backgroundColor = [UIColor colorWithRed:11.0/255.0 green:46.0/255.0 blue:96.0/255.0 alpha:1];\n        loginViewYOffset.constant = 160;\n        loadingViewYOffset.constant = 120;\n        loginViewYOffset.constant += self.view.window.safeAreaInsets.top;\n        loadingViewYOffset.constant += self.view.window.safeAreaInsets.top;\n    }\n    \n    [self _updateFieldPositions];\n}\n\n-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {\n    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];\n    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n        [self transitionToSize:size];\n        [self.view layoutIfNeeded];\n    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n    }];\n}\n\n-(void)keyboardWillShow:(NSNotification*)notification {\n    if (@available(iOS 13.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp) {\n            return;\n        }\n    }\n    [UIView beginAnimations:nil context:NULL];\n    [UIView setAnimationBeginsFromCurrentState:YES];\n    [UIView setAnimationCurve:[[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];\n    [UIView setAnimationDuration:[[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];\n    self->_kbSize = [self.view convertRect:[[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] toView:nil].size;\n    [self transitionToSize:self.view.bounds.size];\n    [self.view layoutIfNeeded];\n    [UIView commitAnimations];\n}\n\n-(void)keyboardWillBeHidden:(NSNotification*)notification {\n    [UIView beginAnimations:nil context:NULL];\n    [UIView setAnimationBeginsFromCurrentState:YES];\n    [UIView setAnimationCurve:[[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];\n    [UIView setAnimationDuration:[[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];\n    self->_kbSize = CGSizeZero;\n    [self transitionToSize:self.view.bounds.size];\n    [self.view layoutIfNeeded];\n    [UIView commitAnimations];\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n-(IBAction)signupButtonPressed:(id)sender {\n    [self loginButtonPressed:sender];\n}\n\n-(IBAction)loginHintPressed:(id)sender {\n    if(sender)\n        [UIView beginAnimations:nil context:NULL];\n    name.alpha = 0;\n    login.alpha = 1;\n    password.alpha = 1;\n    signup.alpha = 0;\n    loginHint.alpha = 0;\n    if(signupHint.enabled)\n        signupHint.alpha = 1;\n    else\n        enterpriseHint.alpha = 1;\n    forgotPasswordHint.alpha = 1;\n    resetPasswordHint.alpha = 1;\n    TOSHint.alpha = 0;\n    forgotPasswordLogin.alpha = 0;\n    forgotPasswordSignup.alpha = 0;\n    notAProblem.alpha = 0;\n    sendAccessLink.alpha = 0;\n    enterEmailAddressHint.alpha = 0;\n    [self transitionToSize:self.view.bounds.size];\n    if(sender)\n        [UIView commitAnimations];\n    [self textFieldChanged:name];\n}\n\n-(IBAction)signupHintPressed:(id)sender {\n    if(sender)\n        [UIView beginAnimations:nil context:NULL];\n    name.alpha = 1;\n    password.alpha = 1;\n    login.alpha = 0;\n    signup.alpha = 1;\n    loginHint.alpha = 1;\n    signupHint.alpha = 0;\n    forgotPasswordHint.alpha = 0;\n    resetPasswordHint.alpha = 0;\n    TOSHint.alpha = 1;\n    forgotPasswordLogin.alpha = 0;\n    forgotPasswordSignup.alpha = 0;\n    notAProblem.alpha = 0;\n    sendAccessLink.alpha = 0;\n    enterEmailAddressHint.alpha = 0;\n    [self transitionToSize:self.view.bounds.size];\n    if(sender)\n        [UIView commitAnimations];\n    [self textFieldChanged:username];\n}\n\n-(IBAction)forgotPasswordHintPressed:(id)sender {\n    if(sender)\n        [UIView beginAnimations:nil context:NULL];\n    login.alpha = 0;\n    password.alpha = 0;\n    signupHint.alpha = 0;\n    forgotPasswordHint.alpha = 0;\n    resetPasswordHint.alpha = 0;\n    enterpriseHint.alpha = 0;\n    \n    forgotPasswordLogin.alpha = 1;\n    if(signupHint.enabled)\n        forgotPasswordSignup.alpha = 1;\n    notAProblem.alpha = 1;\n    sendAccessLink.alpha = 1;\n    enterEmailAddressHint.alpha = 1;\n    if(sender)\n        [UIView commitAnimations];\n    [self _updateFieldPositions];\n    _requestingReset = NO;\n    [sendAccessLink setTitle:@\"Request access link\" forState:UIControlStateNormal];\n    [enterEmailAddressHint setText:@\"Just enter the email address you signed up with and we'll send you a link to log straight in.\"];\n}\n\n-(void)resetPasswordHintPressed:(id)sender {\n    [self forgotPasswordHintPressed:sender];\n    _requestingReset = YES;\n    [sendAccessLink setTitle:@\"Request password reset\" forState:UIControlStateNormal];\n    [enterEmailAddressHint setText:@\"Just enter the email address you signed up with and we'll send you a link to reset your password.\"];\n}\n\n-(void)_accessLinkRequestFailed {\n    [UIView beginAnimations:nil context:nil];\n    self->loginView.alpha = 1;\n    self->loadingView.alpha = 0;\n    [UIView commitAnimations];\n    [self->activity stopAnimating];\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Request Failed\" message:self->_requestingReset?@\"Unable to request a password reset.  Please try again later.\":@\"Unable to request an access link.  Please try again later.\" preferredStyle:UIAlertControllerStyleAlert];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(IBAction)sendAccessLinkButtonPressed:(id)sender {\n    [username resignFirstResponder];\n    [UIView beginAnimations:nil context:nil];\n    loginView.alpha = 0;\n    loadingView.alpha = 1;\n    [UIView commitAnimations];\n    [status setText:self->_requestingReset?@\"Requesting Password Reset\":@\"Requesting Access Link\"];\n    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, status.text);\n    [activity startAnimating];\n    activity.hidden = NO;\n    NSString *user = [username.text stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet];\n    [[NetworkConnection sharedInstance] requestAuthTokenWithHandler:^(IRCCloudJSONObject *result) {\n        if([[result objectForKey:@\"success\"] intValue] == 1) {\n            if(self->_requestingReset) {\n                [[NetworkConnection sharedInstance] requestPasswordReset:user token:[result objectForKey:@\"token\"] handler:^(IRCCloudJSONObject *result) {\n                    if([[result objectForKey:@\"success\"] intValue] == 1) {\n                        [UIView beginAnimations:nil context:nil];\n                        self->loginView.alpha = 1;\n                        self->loadingView.alpha = 0;\n                        [UIView commitAnimations];\n                        [self->activity stopAnimating];\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Email Sent\" message:@\"We've sent you a password reset link.  Check your email and follow the instructions to sign in.\" preferredStyle:UIAlertControllerStyleAlert];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                        [self presentViewController:alert animated:YES completion:nil];\n                        [self loginHintPressed:nil];\n                    } else {\n                        [self _accessLinkRequestFailed];\n                    }\n                }];\n            } else {\n                [[NetworkConnection sharedInstance] requestAccessLink:user token:[result objectForKey:@\"token\"] handler:^(IRCCloudJSONObject *result) {\n                    if([[result objectForKey:@\"success\"] intValue] == 1) {\n                        [UIView beginAnimations:nil context:nil];\n                        self->loginView.alpha = 1;\n                        self->loadingView.alpha = 0;\n                        [UIView commitAnimations];\n                        [self->activity stopAnimating];\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Email Sent\" message:@\"We've sent you an access link.  Check your email and follow the instructions to sign in.\" preferredStyle:UIAlertControllerStyleAlert];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                        [self presentViewController:alert animated:YES completion:nil];\n                        [self loginHintPressed:nil];\n                    } else {\n                        [self _accessLinkRequestFailed];\n                    }\n                }];\n            }\n        } else {\n            [self _accessLinkRequestFailed];\n        }\n    }];\n}\n\n-(IBAction)onePasswordButtonPressed:(id)sender {\n    self->_gotCredentialsFromPasswordManager = YES;\n    dispatch_async(dispatch_get_main_queue(), ^{\n        if(self->login.alpha) {\n#ifdef ENTERPRISE\n            NSString *url = [NSString stringWithFormat:@\"https://%@\", host.text];\n#else\n            NSString *url = @\"https://www.irccloud.com\";\n#endif\n            [[OnePasswordExtension sharedExtension] findLoginForURLString:url forViewController:self sender:sender completion:^(NSDictionary *loginDict, NSError *error) {\n                if (!loginDict) {\n                    if (error.code != AppExtensionErrorCodeCancelledByUser) {\n                        CLS_LOG(@\"Error invoking 1Password App Extension for find login: %@\", error);\n                    }\n                    return;\n                }\n                \n                self->loginView.alpha = 0;\n                if([loginDict[AppExtensionUsernameKey] length])\n                    self->username.text = loginDict[AppExtensionUsernameKey];\n                self->password.text = loginDict[AppExtensionPasswordKey];\n                self->enterpriseHint.alpha = 0;\n                self->host.alpha = 0;\n                self->hostHint.alpha = 0;\n                self->next.alpha = 0;\n                self->enterpriseLearnMore.alpha = 0;\n                self->username.alpha = 1;\n                [self loginHintPressed:nil];\n                [self loginButtonPressed:nil];\n            }];\n        } else {\n#ifdef ENTERPRISE\n            NSString *url = [NSString stringWithFormat:@\"https://%@\", host.text];\n#else\n            NSString *url = @\"https://www.irccloud.com\";\n#endif\n            NSDictionary *newLoginDetails = @{\n                                              AppExtensionTitleKey: @\"IRCCloud\",\n                                              AppExtensionUsernameKey: self->username.text ? : @\"\",\n                                              AppExtensionPasswordKey: self->password.text ? : @\"\",\n                                              AppExtensionSectionTitleKey: @\"IRCCloud\",\n                                              AppExtensionFieldsKey: @{\n                                                      @\"Name\" : self->name.text ? : @\"\"\n                                                      }\n                                              };\n            \n            [[OnePasswordExtension sharedExtension] storeLoginForURLString:url loginDetails:newLoginDetails passwordGenerationOptions:nil forViewController:self sender:sender completion:^(NSDictionary *loginDict, NSError *error) {\n                \n                if (!loginDict) {\n                    if (error.code != AppExtensionErrorCodeCancelledByUser) {\n                        CLS_LOG(@\"Failed to use 1Password App Extension to save a new Login: %@\", error);\n                    }\n                    return;\n                }\n                if(((NSString *)loginDict[AppExtensionReturnedFieldsKey][@\"Name\"]).length)\n                    self->name.text = (NSString *)(loginDict[AppExtensionReturnedFieldsKey][@\"Name\"]);\n                if([loginDict[AppExtensionUsernameKey] length])\n                    self->username.text = loginDict[AppExtensionUsernameKey];\n                self->password.text = loginDict[AppExtensionPasswordKey] ? : @\"\";\n                \n                self->enterpriseHint.alpha = 0;\n                self->host.alpha = 0;\n                self->hostHint.alpha = 0;\n                self->next.alpha = 0;\n                self->enterpriseLearnMore.alpha = 0;\n                self->username.alpha = 1;\n                [self signupHintPressed:nil];\n            }];\n        }\n    });\n}\n\n-(IBAction)TOSHintPressed:(id)sender {\n#ifndef EXTENSION\n    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@\"https://www.irccloud.com/terms\"] options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n#endif\n}\n\n-(void)_stripIRCCloudHost {\n    if([IRCCLOUD_HOST hasPrefix:@\"http://\"])\n        IRCCLOUD_HOST = [IRCCLOUD_HOST substringFromIndex:7];\n    if([IRCCLOUD_HOST hasPrefix:@\"https://\"])\n        IRCCLOUD_HOST = [IRCCLOUD_HOST substringFromIndex:8];\n    if([IRCCLOUD_HOST hasSuffix:@\"/\"])\n        IRCCLOUD_HOST = [IRCCLOUD_HOST substringToIndex:IRCCLOUD_HOST.length - 1];\n}\n\n-(IBAction)nextButtonPressed:(id)sender {\n    IRCCLOUD_HOST = host.text;\n    [self _stripIRCCloudHost];\n    \n    status.text = @\"Connecting\";\n    [activity startAnimating];\n    \n    [host resignFirstResponder];\n    [UIView beginAnimations:nil context:nil];\n    loadingView.alpha = 1;\n    loginView.alpha = 0;\n    [UIView commitAnimations];\n    \n    activity.hidden = NO;\n    [[NetworkConnection sharedInstance] requestConfigurationWithHandler:^(IRCCloudJSONObject *result) {\n        if(result) {\n            IRCCLOUD_HOST = [result objectForKey:@\"api_host\"];\n            [self _stripIRCCloudHost];\n            if([[result objectForKey:@\"enterprise\"] isKindOfClass:[NSDictionary class]]) {\n                dispatch_async(dispatch_get_main_queue(), ^{\n                    self->enterpriseHint.text = [[result objectForKey:@\"enterprise\"] objectForKey:@\"fullname\"];\n                });\n            }\n            if(![[result objectForKey:@\"auth_mechanism\"] isEqualToString:@\"internal\"])\n                self->signupHint.enabled = YES;\n            \n            if([[result objectForKey:@\"auth_mechanism\"] isEqualToString:@\"saml\"]) {\n                dispatch_async(dispatch_get_main_queue(), ^{\n                    [self->login setTitle:[NSString stringWithFormat:@\"Login with %@\", [result objectForKey:@\"saml_provider\"]] forState:UIControlStateNormal];\n                    self->login.enabled = YES;\n                });\n                self->_authURL = [NSString stringWithFormat:@\"https://%@/saml/auth\", IRCCLOUD_HOST];\n                self->signupHint.enabled = NO;\n            } else {\n                dispatch_async(dispatch_get_main_queue(), ^{\n                    [self->login setTitle:@\"Login\" forState:UIControlStateNormal];\n                    self->login.enabled = NO;\n                });\n                self->_authURL = nil;\n            }\n        } else {\n            IRCCLOUD_HOST = nil;\n            dispatch_async(dispatch_get_main_queue(), ^{\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Connection Failed\" message:@\"Please check your host and try again shortly, or contact your system administrator for assistance.\" preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n            });\n        }\n        \n        dispatch_async(dispatch_get_main_queue(), ^{\n            if(self->_accessLink && IRCCLOUD_HOST.length) {\n                [self _loginWithAccessLink];\n            } else {\n                if(IRCCLOUD_HOST.length) {\n                    self->enterpriseHint.alpha = 0;\n                    self->host.alpha = 0;\n                    self->hostHint.alpha = 0;\n                    self->next.alpha = 0;\n                    self->enterpriseLearnMore.alpha = 0;\n                    \n                    if(!self->_authURL) {\n                        self->username.alpha = 1;\n                        self->password.alpha = 1;\n                        self->forgotPasswordHint.alpha = 1;\n                        self->resetPasswordHint.alpha = 1;\n                    }\n                    if(self->signupHint.enabled)\n                        self->signupHint.alpha = 1;\n                    else\n                        self->enterpriseHint.alpha = 1;\n                    self->login.alpha = 1;\n                    [self transitionToSize:self.view.bounds.size];\n                }\n                [UIView beginAnimations:nil context:nil];\n                self->loginView.alpha = 1;\n                self->loadingView.alpha = 0;\n                [UIView commitAnimations];\n            }\n        });\n    }];\n}\n\n-(IBAction)enterpriseLearnMorePressed:(id)sender {\n    if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@\"irccloud://\"]]) {\n        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@\"irccloud://\"] options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n    } else {\n        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@\"itms://itunes.apple.com/app/irccloud/id672699103\"] options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n    }\n}\n\n-(IBAction)hideKeyboard:(id)sender {\n    [self.view endEditing:YES];\n}\n\n-(IBAction)loginButtonPressed:(id)sender {\n    if(self->_authURL) {\n        SamlLoginViewController *c = [[SamlLoginViewController alloc] initWithURL:self->_authURL];\n        c.navigationItem.title = login.titleLabel.text;\n        [self presentViewController:[[UINavigationController alloc] initWithRootViewController:c] animated:YES completion:nil];\n        return;\n    }\n    [username resignFirstResponder];\n    [password resignFirstResponder];\n    [UIView beginAnimations:nil context:nil];\n    loginView.alpha = 0;\n    loadingView.alpha = 1;\n    [UIView commitAnimations];\n    if(name.alpha)\n        [status setText:@\"Creating Account\"];\n    else\n        [status setText:@\"Signing in\"];\n    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, status.text);\n    [activity startAnimating];\n    activity.hidden = NO;\n    NSString *user = [username.text stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet];\n    NSString *pass = password.text;\n    NSString *realname = [name.text stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet];\n    CGFloat nameAlpha = name.alpha;\n    \n#ifndef ENTERPRISE\n    IRCCLOUD_HOST = @\"api.irccloud.com\";\n#endif\n    [[NetworkConnection sharedInstance] requestConfigurationWithHandler:^(IRCCloudJSONObject *config) {\n        if(!config) {\n            dispatch_async(dispatch_get_main_queue(), ^{\n                [UIView beginAnimations:nil context:nil];\n                self->loginView.alpha = 1;\n                self->loadingView.alpha = 0;\n                [UIView commitAnimations];\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Communication Error\" message:@\"Unable to fetch configuration. Please try again shortly.\" preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Send Feedback\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                    [[NetworkConnection sharedInstance] sendFeedbackReport:self];\n                }]];\n                [self presentViewController:alert animated:YES completion:nil];\n            });\n            return;\n        }\n        [[NetworkConnection sharedInstance] updateAPIHost:[config objectForKey:@\"api_host\"]];\n        \n        [[NetworkConnection sharedInstance] requestAuthTokenWithHandler:^(IRCCloudJSONObject *result) {\n            if([[result objectForKey:@\"success\"] intValue] == 1) {\n                IRCCloudAPIResultHandler handler = ^(IRCCloudJSONObject *result) {\n                    if([[result objectForKey:@\"success\"] intValue] == 1) {\n                        if([result objectForKey:@\"websocket_path\"])\n                            IRCCLOUD_PATH = [result objectForKey:@\"websocket_path\"];\n                        [NetworkConnection sharedInstance].session = [result objectForKey:@\"session\"];\n                        [[NSUserDefaults standardUserDefaults] setObject:IRCCLOUD_PATH forKey:@\"path\"];\n                        [[NSUserDefaults standardUserDefaults] synchronize];\n                        if([result objectForKey:@\"api_host\"])\n                            [[NetworkConnection sharedInstance] updateAPIHost:[result objectForKey:@\"api_host\"]];\n#ifdef ENTERPRISE\n                        NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n                        NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n                        [d setObject:IRCCLOUD_HOST forKey:@\"host\"];\n                        [d setObject:IRCCLOUD_PATH forKey:@\"path\"];\n                        [d synchronize];\n#ifndef ENTERPRISE\n                        if(!self->_gotCredentialsFromPasswordManager) {\n                            if (@available(macCatalyst 14.0, *)) {\n                                SecAddSharedWebCredential((CFStringRef)@\"www.irccloud.com\", (__bridge CFStringRef)user, (__bridge CFStringRef)pass, ^(CFErrorRef error) {\n                                    if (error != NULL) {\n                                        CLS_LOG(@\"Unable to save shared credentials: %@\", error);\n                                        return;\n                                    }\n                                });\n                            }\n                        }\n#endif\n                        self->loginHint.alpha = 0;\n                        self->signupHint.alpha = 0;\n                        self->enterpriseHint.alpha = 0;\n                        self->forgotPasswordLogin.alpha = 0;\n                        self->forgotPasswordSignup.alpha = 0;\n                        [((AppDelegate *)([UIApplication sharedApplication].delegate)) showMainView:YES];\n                    } else {\n                        CLS_LOG(@\"Failure: %@\", result);\n                        [UIView beginAnimations:nil context:nil];\n                        self->loginView.alpha = 1;\n                        self->loadingView.alpha = 0;\n                        [UIView commitAnimations];\n                        NSString *message = self->name.alpha?@\"Invalid email address or password. Please try again.\":@\"Unable to login to IRCCloud.  Please check your username and password, and try again shortly.\";\n                        if([[result objectForKey:@\"message\"] isEqualToString:@\"auth\"]\n                           || [[result objectForKey:@\"message\"] isEqualToString:@\"email\"]\n                           || [[result objectForKey:@\"message\"] isEqualToString:@\"password\"]\n                           || [[result objectForKey:@\"message\"] isEqualToString:@\"legacy_account\"])\n                            message = @\"Incorrect username or password.  Please try again.\";\n                        if([[result objectForKey:@\"message\"] isEqualToString:@\"realname\"])\n                            message = @\"Please enter a valid name and try again.\";\n                        if([[result objectForKey:@\"message\"] isEqualToString:@\"email_exists\"])\n                            message = @\"This email address is already in use, please sign in or try another.\";\n                        if([[result objectForKey:@\"message\"] isEqualToString:@\"rate_limited\"])\n                            message = @\"Rate limited, please try again in a few minutes.\";\n                        if([[result objectForKey:@\"message\"] isEqualToString:@\"password_error\"])\n                            message = @\"Invalid password, please try again.\";\n                        if([[result objectForKey:@\"message\"] isEqualToString:@\"banned\"] || [[result objectForKey:@\"message\"] isEqualToString:@\"ip_banned\"])\n                            message = @\"Signup server unavailable, please try again later.\";\n                        if([[result objectForKey:@\"message\"] isEqualToString:@\"bad_email\"])\n                            message = @\"No signups allowed from that domain.\";\n                        if([[result objectForKey:@\"message\"] isEqualToString:@\"tor_blocked\"])\n                            message = @\"No signups allowed from TOR exit nodes\";\n                        if([[result objectForKey:@\"message\"] isEqualToString:@\"signup_ip_blocked\"])\n                            message = @\"Your IP address has been blacklisted.\";\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:self->name.alpha?@\"Sign Up Failed\":@\"Login Failed\" message:message preferredStyle:UIAlertControllerStyleAlert];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Send Feedback\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                            [[NetworkConnection sharedInstance] sendFeedbackReport:self];\n                        }]];\n                        [self presentViewController:alert animated:YES completion:nil];\n                    }\n                };\n                \n                if(nameAlpha)\n                    [[NetworkConnection sharedInstance] signup:user password:pass realname:realname token:[result objectForKey:@\"token\"] handler:handler];\n                else\n                    [[NetworkConnection sharedInstance] login:user password:pass token:[result objectForKey:@\"token\"] handler:handler];\n            } else {\n                CLS_LOG(@\"Failure: %@\", result);\n                [UIView beginAnimations:nil context:nil];\n                self->loginView.alpha = 1;\n                self->loadingView.alpha = 0;\n                [UIView commitAnimations];\n                NSString *message = @\"Unable to communicate with the IRCCloud servers.  Please try again shortly.\";\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Login Failed\" message:message preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Send Feedback\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                    [[NetworkConnection sharedInstance] sendFeedbackReport:self];\n                }]];\n                [self presentViewController:alert animated:YES completion:nil];\n            }\n        }];\n    }];\n}\n\n-(IBAction)textFieldChanged:(id)sender {\n    login.enabled = (username.text.length > 0 && password.text.length > 0);\n    signup.enabled = (name.alpha == 0) || (username.text.length > 0 && password.text.length > 0 && name.text.length > 0);\n    next.enabled = (host.text.length > 0);\n    sendAccessLink.enabled = (username.text.length > 0);\n}\n\n-(BOOL)textFieldShouldReturn:(UITextField *)textField {\n    if(textField == username)\n        [password becomeFirstResponder];\n    else if(textField == name)\n        [username becomeFirstResponder];\n    else if(textField == host)\n        [self nextButtonPressed:host];\n    else\n        [self loginButtonPressed:textField];\n    return YES;\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskPortrait:UIInterfaceOrientationMaskAll;\n}\n\n-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/MainViewController.h",
    "content": "//\n//  MainViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import <AudioToolbox/AudioToolbox.h>\n#import <MessageUI/MFMailComposeViewController.h>\n#import \"BuffersTableView.h\"\n#import \"UsersTableView.h\"\n#import \"EventsTableView.h\"\n#import \"UIExpandingTextView.h\"\n#import \"NickCompletionView.h\"\n#import \"FileUploader.h\"\n#import \"FilesTableViewController.h\"\n#import \"LinkLabel.h\"\n#import \"IRCColorPickerView.h\"\n\n@interface UpdateSuggestionsTask : NSObject {\n    BOOL _force, _atMention;\n    BOOL _cancelled;\n    UIExpandingTextView *_message;\n    Buffer *_buffer;\n    NickCompletionView *_nickCompletionView;\n    NSString *_text;\n}\n\n@property UIExpandingTextView *message;\n@property Buffer *buffer;\n@property NickCompletionView *nickCompletionView;\n@property BOOL force, atMention, cancelled, isEmoji;\n\n-(void)cancel;\n-(void)run;\n\n@end\n\n@interface MainViewController : UIViewController<FilesTableViewDelegate,NickCompletionViewDelegate,BuffersTableViewDelegate,UIExpandingTextViewDelegate,EventsTableViewDelegate,UsersTableViewDelegate,UITextFieldDelegate,UIImagePickerControllerDelegate,UINavigationBarDelegate,FileUploaderDelegate,UIDocumentPickerDelegate,NSUserActivityDelegate,UIPopoverPresentationControllerDelegate,UIViewControllerPreviewingDelegate,UIGestureRecognizerDelegate,MFMailComposeViewControllerDelegate,LinkLabelDelegate,IRCColorPickerViewDelegate,UIDropInteractionDelegate\n> {\n    IBOutlet EventsTableView *_eventsView;\n    IBOutlet UIView *_connectingView;\n    IBOutlet UILabel *_connectingStatus;\n    IBOutlet UIView *_bottomBar;\n    IBOutlet UILabel *_serverStatus;\n    IBOutlet UIView *_serverStatusBar;\n    IBOutlet UIActivityIndicatorView *_eventActivity;\n    IBOutlet UIActivityIndicatorView *_headerActivity;\n    IBOutlet UIView *_titleView;\n    IBOutlet UILabel *_titleLabel;\n    IBOutlet UILabel *_topicLabel;\n    IBOutlet UILabel *_lock;\n    IBOutlet UIView *_borders;\n    IBOutlet UIView *_swipeTip;\n    IBOutlet UIView *_2swipeTip;\n    IBOutlet UIView *_mentionTip;\n    IBOutlet UIView *_globalMsgContainer;\n    IBOutlet LinkLabel *_globalMsg;\n    IBOutlet UIButton *_loadMoreBacklog;\n    IBOutlet NSLayoutConstraint *_eventsViewWidthConstraint;\n    IBOutlet NSLayoutConstraint *_eventsViewHeightConstraint;\n    IBOutlet NSLayoutConstraint *_eventsViewOffsetLeftConstraint;\n    IBOutlet NSLayoutConstraint *_bottomBarOffsetConstraint;\n    IBOutlet NSLayoutConstraint *_bottomBarHeightConstraint;\n    IBOutlet NSLayoutConstraint *_titleOffsetXConstraint;\n    IBOutlet NSLayoutConstraint *_titleOffsetYConstraint;\n    IBOutlet NSLayoutConstraint *_topicWidthConstraint;\n    IBOutlet NSLayoutConstraint *_topUnreadBarYOffsetConstraint;\n    IBOutlet NSLayoutConstraint *_bottomUnreadBarYOffsetConstraint;\n    IBOutlet NSLayoutConstraint *_connectingXOffsetConstraint;\n    IBOutlet NSLayoutConstraint *_topicXOffsetConstraint;\n    UIProgressView *_connectingProgress;\n    NSLayoutConstraint *_messageHeightConstraint;\n    NSLayoutConstraint *_messageWidthConstraint;\n    BuffersTableView *_buffersView;\n    UsersTableView *_usersView;\n    UIExpandingTextView *_message;\n    UIButton *_menuBtn, *_sendBtn, *_settingsBtn, *_uploadsBtn;\n    UIBarButtonItem *_usersButtonItem;\n    Buffer *_buffer;\n    User *_selectedUser;\n    Event *_selectedEvent;\n    CGRect _selectedRect;\n    Buffer *_selectedBuffer;\n    NSString *_selectedURL;\n    int _cidToOpen;\n    NSString *_bufferToOpen;\n    NSURL *_urlToOpen;\n    NSString *_incomingDraft;\n    NSTimer *_doubleTapTimer;\n    NSMutableArray *_pendingEvents;\n    int _bidToOpen;\n    NSTimeInterval _eidToOpen;\n    IRCCloudJSONObject *_alertObject;\n    SystemSoundID alertSound;\n    CGSize _kbSize;\n    NickCompletionView *_nickCompletionView;\n    NSTimer *_nickCompletionTimer;\n    NSTimeInterval _lastNotificationTime;\n    BOOL _isShowingPreview;\n    NSString *_currentTheme;\n    UpdateSuggestionsTask *_updateSuggestionsTask;\n    IRCColorPickerView *_colorPickerView;\n    NSDictionary *_currentMessageAttributes;\n    BOOL _textIsChanging;\n    UIFont *_defaultTextareaFont;\n    id<UIViewControllerPreviewing> __previewer;\n    BOOL _ignoreVisibilityChanges;\n    BOOL _ignoreInsetChanges;\n    NSString *_msgid;\n    UIView *_leftBorder, *_rightBorder;\n    NSTimer *_handoffTimer;\n    CGFloat _previousWidth;\n    NSString *_sceneTitleExtra;\n    NSTimer *_typingIndicatorTimer;\n    UILabel *_typingIndicator;\n    NSTimer *_typingTimer;\n    NSTimeInterval _lastTypingTime;\n}\n@property (assign) int cidToOpen;\n@property (assign) int bidToOpen;\n@property (assign) NSTimeInterval eidToOpen;\n@property (copy) NSString *incomingDraft;\n@property (copy) NSString *bufferToOpen;\n@property (readonly) EventsTableView *eventsView;\n@property (readonly) Buffer *buffer;\n@property BOOL isShowingPreview;\n@property BOOL ignoreVisibilityChanges;\n-(void)bufferSelected:(int)bid;\n-(void)sendButtonPressed:(id)sender;\n-(void)usersButtonPressed:(id)sender;\n-(void)listButtonPressed:(id)sender;\n-(IBAction)serverStatusBarPressed:(id)sender;\n-(IBAction)titleAreaPressed:(id)sender;\n-(IBAction)globalMsgPressed:(id)sender;\n-(void)launchURL:(NSURL *)url;\n-(void)refresh;\n-(void)_setSelectedBuffer:(Buffer *)b;\n-(void)setMsgId:(NSString *)msgId;\n-(void)applyTheme;\n-(void)clearText;\n-(void)clearMsgId;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/MainViewController.m",
    "content": "\n//\n//  MainViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#if !TARGET_OS_MACCATALYST\n#import <AssetsLibrary/AssetsLibrary.h>\n#endif\n#import <MobileCoreServices/UTCoreTypes.h>\n#import <MobileCoreServices/UTType.h>\n#import <UserNotifications/UserNotifications.h>\n#import <Intents/Intents.h>\n#import \"MainViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"ColorFormatter.h\"\n#import \"ChannelModeListTableViewController.h\"\n#import \"AppDelegate.h\"\n#import \"IgnoresTableViewController.h\"\n#import \"EditConnectionViewController.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"ECSlidingViewController.h\"\n#import \"ChannelInfoViewController.h\"\n#import \"ChannelListTableViewController.h\"\n#import \"SettingsViewController.h\"\n#import \"CallerIDTableViewController.h\"\n#import \"WhoisViewController.h\"\n#import \"DisplayOptionsViewController.h\"\n#import \"WhoListTableViewController.h\"\n#import \"NamesListTableViewController.h\"\n#import <objc/message.h>\n#import \"config.h\"\n#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n#import \"FileMetadataViewController.h\"\n#import \"FilesTableViewController.h\"\n#import \"PastebinEditorViewController.h\"\n#import \"PastebinsTableViewController.h\"\n#import \"ARChromeActivity.h\"\n#import \"TUSafariActivity.h\"\n#import \"OpenInChromeController.h\"\n#import \"ServerReorderViewController.h\"\n#import \"FontAwesome.h\"\n#import \"YouTubeViewController.h\"\n#import \"AvatarsDataSource.h\"\n#import \"TextTableViewController.h\"\n#import \"SpamViewController.h\"\n#import \"LinksListTableViewController.h\"\n#import \"WhoWasTableViewController.h\"\n#import \"LogExportsTableViewController.h\"\n#import \"ImageCache.h\"\n#import \"AvatarsTableViewController.h\"\n#import \"PinReorderViewController.h\"\n#import \"LicenseViewController.h\"\n@import Firebase;\n\n#define TEXT_AREA_FONT_SIZE (FONT_SIZE > 14 ? FONT_SIZE : 14)\n\nextern NSDictionary *emojiMap;\n\nNSArray *_sortedUsers;\nNSArray *_sortedChannels;\n\n@implementation UpdateSuggestionsTask\n\n-(UIExpandingTextView *)message {\n    return _message;\n}\n\n-(void)setMessage:(UIExpandingTextView *)message {\n    self->_message = message;\n    self->_text = message.text;\n}\n\n-(void)cancel {\n    self->_cancelled = YES;\n}\n\n-(void)run {\n    self.isEmoji = NO;\n    NSMutableSet *suggestions_set = [[NSMutableSet alloc] init];\n    NSMutableArray *suggestions = [[NSMutableArray alloc] init];\n    \n    if(self->_text.length > 0) {\n        NSString *text = self->_text.lowercaseString;\n        NSUInteger lastSpace = [text rangeOfString:@\" \" options:NSBackwardsSearch].location;\n        if(lastSpace != NSNotFound && lastSpace != text.length) {\n            text = [text substringFromIndex:lastSpace + 1];\n        }\n        if([text hasSuffix:@\":\"])\n            text = [text substringToIndex:text.length - 1];\n        if([text hasPrefix:@\"@\"]) {\n            self->_atMention = YES;\n            text = [text substringFromIndex:1];\n        } else {\n            self->_atMention = NO;\n        }\n        \n        if(!_sortedChannels)\n            _sortedChannels = [[[ChannelsDataSource sharedInstance] channels] sortedArrayUsingSelector:@selector(compare:)];\n        \n        if([[[[NSUserDefaults standardUserDefaults] objectForKey:@\"disable-nick-suggestions\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue]) {\n            if(self->_atMention || _force) {\n                if(_sortedUsers.count == 0)\n                    _sortedUsers = nil;\n            } else {\n                _sortedUsers = @[];\n            }\n        }\n        if(!_sortedUsers)\n            _sortedUsers = [[[UsersDataSource sharedInstance] usersForBuffer:self->_buffer.bid] sortedArrayUsingSelector:@selector(compareByMentionTime:)];\n        if(self->_cancelled)\n            return;\n        \n        if(text.length > 1 || _force) {\n            if([self->_buffer.type isEqualToString:@\"channel\"] && [[self->_buffer.name lowercaseString] hasPrefix:text]) {\n                [suggestions_set addObject:self->_buffer.name.lowercaseString];\n                [suggestions addObject:self->_buffer.name];\n            }\n            for(Channel *channel in _sortedChannels) {\n                if(self->_cancelled)\n                    return;\n                \n                if(text.length > 0 && channel.name.length > 0 && [channel.name characterAtIndex:0] == [text characterAtIndex:0] && channel.bid != self->_buffer.bid && [[channel.name lowercaseString] hasPrefix:text] && ![suggestions_set containsObject:channel.name.lowercaseString] && ![[BuffersDataSource sharedInstance] getBuffer:channel.bid].isMPDM) {\n                    [suggestions_set addObject:channel.name.lowercaseString];\n                    [suggestions addObject:channel.name];\n                    self.isEmoji = YES;\n                }\n            }\n            \n            for(User *user in _sortedUsers) {\n                if(self->_cancelled)\n                    return;\n                \n                NSString *nick = user.nick.lowercaseString;\n                NSString *displayName = user.display_name.lowercaseString;\n                NSUInteger location = [nick rangeOfCharacterFromSet:[NSCharacterSet alphanumericCharacterSet]].location;\n                if([text rangeOfCharacterFromSet:[NSCharacterSet alphanumericCharacterSet]].location == 0 && location != NSNotFound && location > 0) {\n                    nick = [nick substringFromIndex:location];\n                }\n                \n                if((text.length == 0 || [nick hasPrefix:text] || [displayName hasPrefix:text]) && ![suggestions_set containsObject:user.nick.lowercaseString]) {\n                    [suggestions_set addObject:user.nick.lowercaseString];\n                    if(![user.nick isEqualToString:user.display_name])\n                        [suggestions addObject:[NSString stringWithFormat:@\"%@\\u00a0(%@)\",user.display_name,user.nick]];\n                    else\n                        [suggestions addObject:user.nick];\n                }\n            }\n        }\n        \n        if(text.length > 2 && [text hasPrefix:@\":\"]) {\n            NSString *q = [text substringFromIndex:1];\n            \n            for(NSString *emocode in emojiMap.keyEnumerator) {\n                if(self->_cancelled)\n                    return;\n                \n                if([emocode hasPrefix:q]) {\n                    NSString *emoji = [emojiMap objectForKey:emocode];\n                    if(![suggestions_set containsObject:emoji]) {\n                        self.isEmoji = YES;\n                        [suggestions_set addObject:emoji];\n                        [suggestions addObject:emoji];\n                    }\n                }\n            }\n        }\n    }\n    \n    if(self->_cancelled)\n        return;\n    \n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        if(self->_nickCompletionView.selection == -1 || suggestions.count == 0)\n            [self->_nickCompletionView setSuggestions:suggestions];\n        \n        if(self->_cancelled)\n            return;\n        \n        if(suggestions.count == 0) {\n            if(self->_nickCompletionView.alpha > 0) {\n                [UIView animateWithDuration:0.25 animations:^{ self->_nickCompletionView.alpha = 0; } completion:nil];\n                _sortedChannels = nil;\n                _sortedUsers = nil;\n            }\n            self->_atMention = NO;\n        } else {\n            if(self->_nickCompletionView.alpha == 0) {\n                [UIView animateWithDuration:0.25 animations:^{ self->_nickCompletionView.alpha = 1; } completion:nil];\n                NSString *text = self->_message.text;\n                id delegate = self->_message.delegate;\n                self->_message.delegate = nil;\n                self->_message.text = text;\n                self->_message.selectedRange = NSMakeRange(text.length, 0);\n                if(self->_force && self->_nickCompletionView.selection == -1) {\n                    [self->_nickCompletionView setSelection:0];\n                    NSString *text = self->_message.text;\n                    if(text.length == 0) {\n                        if(self->_buffer.serverIsSlack)\n                            self->_message.text = [NSString stringWithFormat:@\"@%@\",[self->_nickCompletionView suggestion]];\n                        else\n                            self->_message.text = [self->_nickCompletionView suggestion];\n                    } else {\n                        while(text.length > 0 && [text characterAtIndex:text.length - 1] != ' ') {\n                            text = [text substringToIndex:text.length - 1];\n                        }\n                        if(self->_buffer.serverIsSlack)\n                            text = [text stringByAppendingString:@\"@\"];\n                        text = [text stringByAppendingString:[self->_nickCompletionView suggestion]];\n                        self->_message.text = text;\n                    }\n                    if([text rangeOfString:@\" \"].location == NSNotFound && !self->_buffer.serverIsSlack)\n                        self->_message.text = [self->_message.text stringByAppendingString:@\":\"];\n                }\n                self->_message.delegate = delegate;\n            }\n        }\n    }];\n}\n@end\n\n@implementation MainViewController\n\n-(instancetype)initWithCoder:(NSCoder *)aDecoder {\n    if(self = [super initWithCoder:aDecoder]) {\n        self->_cidToOpen = -1;\n        self->_bidToOpen = -1;\n        self->_pendingEvents = [[NSMutableArray alloc] init];\n    }\n    return self;\n}\n\n-(void)dealloc {\n    AudioServicesDisposeSystemSoundID(alertSound);\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n- (void)_themeChanged {\n    if(![self->_currentTheme isEqualToString:[UIColor currentTheme]]) {\n        self->_currentTheme = [UIColor currentTheme];\n        UIView *v = self.navigationController.view.superview;\n        if(v) {\n            [self.navigationController.view removeFromSuperview];\n            [v addSubview: self.navigationController.view];\n        }\n\n        [self applyTheme];\n    }\n}\n\n- (void)applyTheme {\n    self->_currentTheme = [UIColor currentTheme];\n    if (@available(iOS 13, *)) {\n        self.view.window.overrideUserInterfaceStyle = self.view.overrideUserInterfaceStyle = [self->_currentTheme isEqualToString:@\"dawn\"]?UIUserInterfaceStyleLight:UIUserInterfaceStyleDark;\n    }\n    self.view.window.backgroundColor = [UIColor textareaBackgroundColor];\n    self.view.backgroundColor = [UIColor contentBackgroundColor];\n    self.slidingViewController.view.backgroundColor = self.navigationController.view.backgroundColor = [UIColor navBarColor];\n    self->_bottomBar.backgroundColor = [UIColor contentBackgroundColor];\n    [self.navigationController.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    if (@available(iOS 13.0, *)) {\n        UINavigationBarAppearance *a = [[UINavigationBarAppearance alloc] init];\n        a.backgroundImage = [UIColor navBarBackgroundImage];\n        a.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor navBarHeadingColor]};\n        self.navigationController.navigationBar.standardAppearance = a;\n        self.navigationController.navigationBar.compactAppearance = a;\n        self.navigationController.navigationBar.scrollEdgeAppearance = a;\n        if (@available(iOS 15.0, *)) {\n#if !TARGET_OS_MACCATALYST\n            self.navigationController.navigationBar.compactScrollEdgeAppearance = a;\n#endif\n        }\n    }\n    [self->_uploadsBtn setTintColor:[UIColor textareaBackgroundColor]];\n    UIColor *c = ([NetworkConnection sharedInstance].state == kIRCCloudStateConnected)?([UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor unreadBlueColor]):[UIColor textareaBackgroundColor];\n    [self->_sendBtn setTitleColor:c forState:UIControlStateNormal];\n    [self->_sendBtn setTitleColor:c forState:UIControlStateDisabled];\n    [self->_sendBtn setTitleColor:c forState:UIControlStateHighlighted];\n    [self->_settingsBtn setTintColor:[UIColor textareaBackgroundColor]];\n    [self->_message setBackgroundImage:[UIColor textareaBackgroundImage]];\n    self->_message.textColor = [UIColor textareaTextColor];\n    self->_message.keyboardAppearance = [UITextField appearance].keyboardAppearance;\n    self->_defaultTextareaFont = [UIFont systemFontOfSize:TEXT_AREA_FONT_SIZE weight:UIFontWeightRegular];\n    if(!_message.text.length)\n        self->_message.font = self->_defaultTextareaFont;\n    self->_message.minimumHeight = TEXT_AREA_FONT_SIZE + 22;\n    if(self->_message.minimumHeight < 35)\n        self->_message.minimumHeight = 35;\n    self->_typingIndicator.textColor = [UIColor timestampColor];\n    \n    UIButton *users = [UIButton buttonWithType:UIButtonTypeCustom];\n    [users setImage:[[UIImage imageNamed:@\"users\"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];\n    [users addTarget:self action:@selector(usersButtonPressed:) forControlEvents:UIControlEventTouchUpInside];\n    users.frame = CGRectMake(0,0,24,22);\n    [users setTintColor:[UIColor navBarSubheadingColor]];\n    users.accessibilityLabel = @\"Channel members list\";\n    self->_usersButtonItem = [[UIBarButtonItem alloc] initWithCustomView:users];\n    \n    self->_menuBtn.tintColor = [UIColor navBarSubheadingColor];\n    \n    self->_eventsView.topUnreadView.backgroundColor = [UIColor chatterBarColor];\n    self->_eventsView.bottomUnreadView.backgroundColor = [UIColor chatterBarColor];\n    self->_eventsView.topUnreadLabel.textColor = [UIColor chatterBarTextColor];\n    self->_eventsView.bottomUnreadLabel.textColor = [UIColor chatterBarTextColor];\n    self->_eventsView.topUnreadArrow.textColor = self->_eventsView.bottomUnreadArrow.textColor = [UIColor chatterBarTextColor];\n    [self->_eventsView clearRowCache];\n    \n    self->_borders.backgroundColor = _leftBorder.backgroundColor = _rightBorder.backgroundColor = [UIColor iPadBordersColor];\n    [[self->_borders.subviews objectAtIndex:0] setBackgroundColor:[UIColor contentBackgroundColor]];\n    \n    self->_eventActivity.activityIndicatorViewStyle = self->_headerActivity.activityIndicatorViewStyle = [UIColor activityIndicatorViewStyle];\n    \n    self->_globalMsg.linkAttributes = [UIColor lightLinkAttributes];\n    \n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    \n    [self->_buffersView viewWillAppear:NO];\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.slidingViewController.view.frame = self.view.window.bounds;\n\n    [self->_eventsView viewDidLoad];\n\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(backlogStarted:)\n                                                 name:kIRCCloudBacklogStartedNotification object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(backlogProgress:)\n                                                 name:kIRCCloudBacklogProgressNotification object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(backlogCompleted:)\n                                                 name:kIRCCloudBacklogCompletedNotification object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(connectivityChanged:)\n                                                 name:kIRCCloudConnectivityNotification object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(keyboardWillShow:)\n                                                 name:UIKeyboardWillShowNotification object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(keyboardWillBeHidden:)\n                                                 name:UIKeyboardWillHideNotification object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(didSwipe:)\n                                                 name:ECSlidingViewUnderLeftWillAppear object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(didSwipe:)\n                                                 name:ECSlidingViewUnderRightWillAppear object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(didSwipe:)\n                                                 name:ECSlidingViewUnderLeftWillDisappear object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(didSwipe:)\n                                                 name:ECSlidingViewUnderRightWillDisappear object:nil];\n    \n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(statusBarFrameWillChange:)\n                                                 name:UIApplicationWillChangeStatusBarFrameNotification object:nil];\n    [super viewDidLoad];\n    [self addChildViewController:self->_eventsView];\n    \n    AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@\"a\" ofType:@\"caf\"]], &alertSound);\n    \n    self->_globalMsg.linkDelegate = self;\n    [self->_globalMsg addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(globalMsgPressed:)]];\n    \n    if(!_buffersView) {\n        self->_buffersView = [[BuffersTableView alloc] initWithStyle:UITableViewStylePlain];\n        self->_buffersView.view.autoresizingMask = UIViewAutoresizingNone;\n        self->_buffersView.view.translatesAutoresizingMaskIntoConstraints = NO;\n        self->_buffersView.delegate = self;\n    }\n\n    if(!_usersView) {\n        self->_usersView = [[UsersTableView alloc] initWithStyle:UITableViewStylePlain];\n        self->_usersView.view.autoresizingMask = UIViewAutoresizingNone;\n        self->_usersView.view.translatesAutoresizingMaskIntoConstraints = NO;\n        self->_usersView.delegate = self;\n    }\n    \n    if(self->_swipeTip)\n        self->_swipeTip.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@\"tip_bg\"]];\n    \n    if(_2swipeTip)\n        _2swipeTip.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@\"tip_bg\"]];\n    \n    if(self->_mentionTip)\n        self->_mentionTip.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@\"tip_bg\"]];\n    \n    self->_lock.font = [UIFont fontWithName:@\"FontAwesome\" size:18];\n\n    self->_uploadsBtn = [UIButton buttonWithType:UIButtonTypeCustom];\n    self->_uploadsBtn.contentMode = UIViewContentModeCenter;\n    self->_uploadsBtn.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;\n    [self->_uploadsBtn setImage:[[UIImage imageNamed:@\"upload_arrow\"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];\n    [self->_uploadsBtn addTarget:self action:@selector(uploadsButtonPressed:) forControlEvents:UIControlEventTouchUpInside];\n    [self->_uploadsBtn sizeToFit];\n    self->_uploadsBtn.frame = CGRectMake(((AppDelegate *)([UIApplication sharedApplication].delegate)).isOnVisionOS ? 16 : 6,6,_uploadsBtn.frame.size.width + 24, _uploadsBtn.frame.size.height + 24);\n    self->_uploadsBtn.accessibilityLabel = @\"Uploads\";\n    [self->_bottomBar addSubview:self->_uploadsBtn];\n\n    self->_sendBtn = [UIButton buttonWithType:UIButtonTypeCustom];\n    self->_sendBtn.contentMode = UIViewContentModeCenter;\n    self->_sendBtn.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin;\n    [self->_sendBtn setTitle:@\"Send\" forState:UIControlStateNormal];\n    [self->_sendBtn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled];\n    [self->_sendBtn sizeToFit];\n    self->_sendBtn.frame = CGRectMake(self->_bottomBar.frame.size.width - _sendBtn.frame.size.width - 8,12,_sendBtn.frame.size.width,_sendBtn.frame.size.height);\n    [self->_sendBtn addTarget:self action:@selector(sendButtonPressed:) forControlEvents:UIControlEventTouchUpInside];\n    [self->_sendBtn sizeToFit];\n    self->_sendBtn.enabled = NO;\n    self->_sendBtn.adjustsImageWhenHighlighted = NO;\n    [self->_bottomBar addSubview:self->_sendBtn];\n\n    self->_settingsBtn = [UIButton buttonWithType:UIButtonTypeCustom];\n    self->_settingsBtn.contentMode = UIViewContentModeCenter;\n    self->_settingsBtn.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin;\n    [self->_settingsBtn setImage:[[UIImage imageNamed:@\"settings\"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];\n    [self->_settingsBtn addTarget:self action:@selector(settingsButtonPressed:) forControlEvents:UIControlEventTouchUpInside];\n    [self->_settingsBtn sizeToFit];\n    self->_settingsBtn.accessibilityLabel = @\"Menu\";\n    self->_settingsBtn.enabled = NO;\n    self->_settingsBtn.alpha = 0;\n    self->_settingsBtn.frame = CGRectMake(self->_bottomBar.frame.size.width - _settingsBtn.frame.size.width - 24,10,_settingsBtn.frame.size.width + 16,_settingsBtn.frame.size.height + 16);\n    [self->_bottomBar addSubview:self->_settingsBtn];\n    \n    self.slidingViewController.shouldAllowPanningPastAnchor = NO;\n    if(self.slidingViewController.underLeftViewController == nil)\n        self.slidingViewController.underLeftViewController = self->_buffersView;\n    if(self.slidingViewController.underRightViewController == nil)\n        self.slidingViewController.underRightViewController = self->_usersView;\n    self.slidingViewController.anchorLeftRevealAmount = 240;\n    self.slidingViewController.anchorRightRevealAmount = 240;\n    self.slidingViewController.underLeftWidthLayout = ECFixedRevealWidth;\n    self.slidingViewController.underRightWidthLayout = ECFixedRevealWidth;\n\n    self->_menuBtn = [UIButton buttonWithType:UIButtonTypeCustom];\n    [self->_menuBtn setImage:[[UIImage imageNamed:@\"menu\"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];\n    [self->_menuBtn addTarget:self action:@selector(listButtonPressed:) forControlEvents:UIControlEventTouchUpInside];\n    self->_menuBtn.frame = CGRectMake(0,0,20,18);\n    self->_menuBtn.accessibilityLabel = @\"Channels list\";\n    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self->_menuBtn];\n    \n    self->_message = [[UIExpandingTextView alloc] initWithFrame:CGRectZero];\n    self->_message.delegate = self;\n    self->_message.returnKeyType = UIReturnKeySend;\n    self->_message.autoresizesSubviews = NO;\n    self->_message.translatesAutoresizingMaskIntoConstraints = NO;\n    //    _message.internalTextView.font = self->_defaultTextareaFont = [UIFont fontWithDescriptor:[UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody] size:FONT_SIZE];\n    self->_message.internalTextView.font = self->_defaultTextareaFont = [UIFont systemFontOfSize:TEXT_AREA_FONT_SIZE weight:UIFontWeightRegular];\n    self->_messageWidthConstraint = [NSLayoutConstraint constraintWithItem:self->_message attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1.0f constant:0.0f];\n    self->_messageHeightConstraint = [NSLayoutConstraint constraintWithItem:self->_message attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1.0f constant:36.0f];\n    [self->_message addConstraints:@[self->_messageWidthConstraint, _messageHeightConstraint]];\n\n    [self->_bottomBar addSubview:self->_message];\n\n    self->_typingIndicator = [[UILabel alloc] initWithFrame:CGRectZero];\n    self->_typingIndicator.font = [UIFont systemFontOfSize:12 weight:UIFontWeightRegular];\n    self->_typingIndicator.translatesAutoresizingMaskIntoConstraints = NO;\n    self->_typingIndicator.lineBreakMode = NSLineBreakByTruncatingHead;\n    [self->_bottomBar addSubview:_typingIndicator];\n\n    [self->_bottomBar addConstraints:@[\n        [NSLayoutConstraint constraintWithItem:self->_message attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self->_bottomBar attribute:NSLayoutAttributeLeading multiplier:1.0f constant:((AppDelegate *)([UIApplication sharedApplication].delegate)).isOnVisionOS ? 68.0f : 50.0f],\n                             [NSLayoutConstraint constraintWithItem:self->_message attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self->_bottomBar attribute:NSLayoutAttributeTop multiplier:1.0f constant:12.0f],\n                             [NSLayoutConstraint constraintWithItem:self->_typingIndicator attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self->_message attribute:NSLayoutAttributeLeading multiplier:1.0f constant:0],\n                             [NSLayoutConstraint constraintWithItem:self->_typingIndicator attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self->_bottomBar attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-6.0f],\n                             [NSLayoutConstraint constraintWithItem:self->_typingIndicator attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self->_message attribute:NSLayoutAttributeWidth multiplier:1.0f constant:0]\n                             ]];\n    \n    self->_nickCompletionView = [[NickCompletionView alloc] initWithFrame:CGRectZero];\n    self->_nickCompletionView.translatesAutoresizingMaskIntoConstraints = NO;\n    self->_nickCompletionView.completionDelegate = self;\n    self->_nickCompletionView.alpha = 0;\n    [self.view addSubview:self->_nickCompletionView];\n    [self.view addConstraints:@[\n                                [NSLayoutConstraint constraintWithItem:self->_nickCompletionView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self->_eventsView.tableView attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0.0f],\n                                [NSLayoutConstraint constraintWithItem:self->_nickCompletionView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self->_eventsView.tableView attribute:NSLayoutAttributeWidth multiplier:1.0f constant:-20.0f],\n                                 [NSLayoutConstraint constraintWithItem:self->_nickCompletionView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self->_eventsView.bottomUnreadView attribute:NSLayoutAttributeTop multiplier:1.0f constant:-6.0f]\n                                 ]];\n\n    self->_colorPickerView = [[IRCColorPickerView alloc] initWithFrame:CGRectZero];\n    self->_colorPickerView.translatesAutoresizingMaskIntoConstraints = NO;\n    self->_colorPickerView.delegate = self;\n    self->_colorPickerView.alpha = 0;\n    [self.view addSubview:self->_colorPickerView];\n    [self.view addConstraints:@[\n                                [NSLayoutConstraint constraintWithItem:self->_colorPickerView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self->_eventsView.tableView attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0.0f],\n                                [NSLayoutConstraint constraintWithItem:self->_colorPickerView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self->_bottomBar attribute:NSLayoutAttributeTop multiplier:1.0f constant:-2.0f]\n                                ]];\n    \n    self->_connectingProgress = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];\n    [self->_connectingProgress sizeToFit];\n    self->_connectingProgress.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;\n    self->_connectingProgress.frame = CGRectMake(0,self.navigationController.navigationBar.bounds.size.height - _connectingProgress.bounds.size.height,self.navigationController.navigationBar.bounds.size.width,_connectingProgress.bounds.size.height);\n    [self.navigationController.navigationBar addSubview:self->_connectingProgress];\n    \n    self->_connectingStatus.font = [UIFont boldSystemFontOfSize:20];\n    self.navigationItem.titleView = self->_titleView;\n    self->_connectingProgress.hidden = YES;\n    self->_connectingProgress.progress = 0;\n    [UIColor setTheme];\n    [self _themeChanged];\n    [self connectivityChanged:nil];\n    [self updateLayout];\n    [self _updateEventsInsets];\n    \n    UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeBack:)];\n    swipe.numberOfTouchesRequired = 2;\n    swipe.direction = UISwipeGestureRecognizerDirectionRight;\n    [self.view addGestureRecognizer:swipe];\n    \n    swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeForward:)];\n    swipe.numberOfTouchesRequired = 2;\n    swipe.direction = UISwipeGestureRecognizerDirectionLeft;\n    [self.view addGestureRecognizer:swipe];\n\n    if([self respondsToSelector:@selector(registerForPreviewingWithDelegate:sourceView:)]) {\n        __previewer = [self registerForPreviewingWithDelegate:self sourceView:self.navigationController.view];\n    }\n    \n    [self.view addInteraction:[[UIDropInteraction alloc] initWithDelegate:self]];\n    \n    _leftBorder = [[UIView alloc] init];\n    _leftBorder.backgroundColor = [UIColor iPadBordersColor];\n    [self.navigationController.view addSubview:_leftBorder];\n    _rightBorder = [[UIView alloc] init];\n    _rightBorder.backgroundColor = [UIColor iPadBordersColor];\n    [self.navigationController.view addSubview:_rightBorder];\n    self.navigationController.view.clipsToBounds = NO;\n    \n    if (@available(iOS 17, *)) {\n        self.view.keyboardLayoutGuide.usesBottomSafeArea = YES;\n        self.view.keyboardLayoutGuide.followsUndockedKeyboard = YES;\n    }\n    [self applyTheme];\n}\n\n-(BOOL)dropInteraction:(UIDropInteraction *)interaction canHandleSession:(id<UIDropSession>)session __attribute__((availability(ios,introduced=11))) {\n    return session.items.count == 1 && [session hasItemsConformingToTypeIdentifiers:@[@\"com.apple.DocumentManager.uti.FPItem.File\", @\"public.image\", @\"public.movie\"]];\n}\n\n-(UIDropProposal *)dropInteraction:(UIDropInteraction *)interaction sessionDidUpdate:(id<UIDropSession>)session __attribute__((availability(ios,introduced=11))) {\n    return [[UIDropProposal alloc] initWithDropOperation:UIDropOperationCopy];\n}\n\n-(void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id<UIDropSession>)session __attribute__((availability(ios,introduced=11))) {\n    NSItemProvider *i = session.items.firstObject.itemProvider;\n    \n    FileUploader *u = [[FileUploader alloc] init];\n    u.delegate = self;\n    u.to = @[@{@\"cid\":@(self->_buffer.cid), @\"to\":self->_buffer.name}];\n    u.msgid = self->_msgid;\n    NSString *UTI = i.registeredTypeIdentifiers.lastObject;\n    u.originalFilename = i.suggestedName;\n    if(![u.originalFilename containsString:@\".\"] && ![UTI hasPrefix:@\"dyn.\"]) {\n        u.originalFilename = [u.originalFilename stringByAppendingPathExtension:[UTI componentsSeparatedByString:@\".\"].lastObject];\n    }\n    u.mimeType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef _Nonnull)(UTI), kUTTagClassMIMEType);\n    FileMetadataViewController *fvc = [[FileMetadataViewController alloc] initWithUploader:u];\n    u.metadatadelegate = fvc;\n    [i loadPreviewImageWithOptions:nil completionHandler:^(UIImage *preview, NSError *error) {\n        if(preview) {\n            [fvc setImage:preview];\n        } else if([i canLoadObjectOfClass:UIImage.class]) {\n            [i loadObjectOfClass:UIImage.class completionHandler:^(UIImage *item, NSError *error) {\n                if(item) {\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        [fvc setImage:item];\n                    }];\n                }\n            }];\n        }\n    }];\n    \n    id imageHandler = ^(UIImage *item, NSError *error) {\n        if(item) {\n            CLS_LOG(@\"Uploading dropped image to IRCCloud\");\n            [u uploadImage:item];\n        } else {\n            CLS_LOG(@\"Unable to handle dropped image: %@\", error);\n        }\n    };\n    \n    if([i hasItemConformingToTypeIdentifier:@\"com.apple.DocumentManager.uti.FPItem.File\"]) {\n        [i loadInPlaceFileRepresentationForTypeIdentifier:@\"com.apple.DocumentManager.uti.FPItem.File\" completionHandler:^(NSURL *url, BOOL isInPlace, NSError *error) {\n            if(url) {\n                CLS_LOG(@\"Uploading dropped file to IRCCloud\");\n                [i hasItemConformingToTypeIdentifier:@\"public.movie\"]?[u uploadVideo:url]:[u uploadFile:url];\n            } else {\n                CLS_LOG(@\"Unable to handle dropped file: %@\", error);\n            }\n        }];\n    } else if([i hasItemConformingToTypeIdentifier:@\"public.movie\"]) {\n        [i loadInPlaceFileRepresentationForTypeIdentifier:@\"public.movie\" completionHandler:^(NSURL *url, BOOL isInPlace, NSError *error) {\n            if(url) {\n                CLS_LOG(@\"Uploading dropped movie to IRCCloud\");\n                [u uploadVideo:url];\n            } else {\n                CLS_LOG(@\"Unable to handle dropped movie: %@\", error);\n            }\n        }];\n    } else if([i hasItemConformingToTypeIdentifier:@\"public.image\"]) {\n        [i loadObjectOfClass:UIImage.class completionHandler:imageHandler];\n    }\n    \n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:fvc];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationFormSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        [self presentViewController:nc animated:YES completion:nil];\n    }];\n}\n\n- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location {\n    if(CGRectContainsPoint(self->_titleView.frame, [self->_titleView convertPoint:location fromView:self.navigationController.view])) {\n        if(self->_buffer && [self->_buffer.type isEqualToString:@\"channel\"] && [[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid]) {\n            previewingContext.sourceRect = [self.navigationController.view convertRect:self->_titleView.frame fromView:self.navigationController.navigationBar];\n            ChannelInfoViewController *c = [[ChannelInfoViewController alloc] initWithChannel:[[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid]];\n            UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:c];\n            [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n            nc.navigationBarHidden = YES;\n            if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                nc.modalPresentationStyle = UIModalPresentationFormSheet;\n            else\n                nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n            return nc;\n        }\n    }\n    return nil;\n}\n\n- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit {\n    if([viewControllerToCommit isKindOfClass:[UINavigationController class]]) {\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:((UINavigationController *)viewControllerToCommit).topViewController];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationFormSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        viewControllerToCommit = nc;\n    }\n    [self presentViewController:viewControllerToCommit animated:YES completion:nil];\n}\n\n- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {\n    if (object == self->_eventsView.topUnreadView) {\n        if(![[change objectForKey:NSKeyValueChangeOldKey] isEqualToNumber:[change objectForKey:NSKeyValueChangeNewKey]])\n            [self _updateEventsInsets];\n    } else if(object == self->_eventsView.tableView.layer) {\n        CGRect old = [[change objectForKey:NSKeyValueChangeOldKey] CGRectValue];\n        CGRect new = [[change objectForKey:NSKeyValueChangeNewKey] CGRectValue];\n        if(new.size.height > 0 && old.size.width != new.size.width) {\n            [self->_eventsView clearCachedHeights];\n        }\n    } else {\n        NSLog(@\"Change: %@\", change);\n    }\n}\n\n- (void)swipeBack:(UISwipeGestureRecognizer *)sender {\n    if(self->_buffer.lastBuffer) {\n        Buffer *b = self->_buffer;\n        Buffer *last = self->_buffer.lastBuffer.lastBuffer;\n        [self bufferSelected:b.lastBuffer.bid];\n        self->_buffer.lastBuffer = last;\n        self->_buffer.nextBuffer = b;\n    }\n}\n\n- (void)swipeForward:(UISwipeGestureRecognizer *)sender {\n    if(self->_buffer.nextBuffer) {\n        Buffer *b = self->_buffer;\n        Buffer *last = self->_buffer.lastBuffer;\n        Buffer *next = self->_buffer.nextBuffer;\n        Buffer *nextnext = self->_buffer.nextBuffer.nextBuffer;\n        [self bufferSelected:next.bid];\n        self->_buffer.nextBuffer = nextnext;\n        b.nextBuffer = next;\n        b.lastBuffer = last;\n    }\n}\n\n- (void)_updateUnreadIndicator {\n    @synchronized(self->_buffer) {\n        int unreadCount = 0;\n        int highlightCount = 0;\n        NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n        \n        NSArray *buffers = [[BuffersDataSource sharedInstance] getBuffers];\n        for(Buffer *buffer in buffers) {\n            int type = -1;\n            int joined = 1;\n            if([buffer.type isEqualToString:@\"channel\"]) {\n                type = 1;\n                Channel *channel = [[ChannelsDataSource sharedInstance] channelForBuffer:buffer.bid];\n                if(!channel) {\n                    joined = 0;\n                }\n            } else if([buffer.type isEqualToString:@\"conversation\"]) {\n                type = 2;\n            }\n            if(joined > 0 && buffer.archived == 0) {\n                int unread = 0;\n                int highlights = 0;\n                if(unreadCount == 0)\n                    unread = [[EventsDataSource sharedInstance] unreadStateForBuffer:buffer.bid lastSeenEid:buffer.last_seen_eid type:buffer.type];\n                highlights = [[EventsDataSource sharedInstance] highlightStateForBuffer:buffer.bid lastSeenEid:buffer.last_seen_eid type:buffer.type];\n                if(type == 1) {\n                    if([[prefs objectForKey:@\"channel-disableTrackUnread\"] isKindOfClass:[NSDictionary class]] && [[[prefs objectForKey:@\"channel-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] == 1)\n                        unread = 0;\n                } else {\n                    if([[prefs objectForKey:@\"buffer-disableTrackUnread\"] isKindOfClass:[NSDictionary class]] && [[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] == 1)\n                        unread = 0;\n                    if(type == 2 && [[prefs objectForKey:@\"buffer-disableTrackUnread\"] isKindOfClass:[NSDictionary class]] && [[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] == 1)\n                        highlights = 0;\n                }\n                if([[prefs objectForKey:@\"disableTrackUnread\"] intValue] == 1) {\n                    if(type == 1) {\n                        if(![[prefs objectForKey:@\"channel-enableTrackUnread\"] isKindOfClass:[NSDictionary class]] || [[[prefs objectForKey:@\"channel-enableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] != 1)\n                            unread = 0;\n                    } else {\n                        if(![[prefs objectForKey:@\"buffer-enableTrackUnread\"] isKindOfClass:[NSDictionary class]] || [[[prefs objectForKey:@\"buffer-enableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] != 1)\n                            unread = 0;\n                        if(type == 2 && (![[prefs objectForKey:@\"buffer-enableTrackUnread\"] isKindOfClass:[NSDictionary class]] || [[[prefs objectForKey:@\"buffer-enableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",buffer.bid]] intValue] != 1))\n                            highlights = 0;\n                    }\n                }\n                if(buffer.bid != self->_buffer.bid) {\n                    unreadCount += unread;\n                    highlightCount += highlights;\n                }\n                if(highlightCount > 0)\n                    break;\n            }\n        }\n        \n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            if(highlightCount) {\n                self->_menuBtn.tintColor = [UIColor redColor];\n                self->_menuBtn.accessibilityValue = @\"Unread highlights\";\n                self->_sceneTitleExtra = [NSString stringWithFormat:@\"(%i) \", highlightCount];\n            } else if(unreadCount) {\n                if(![self->_menuBtn.tintColor isEqual:[UIColor unreadBlueColor]])\n                    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @\"New unread messages\");\n                self->_menuBtn.tintColor = [UIColor unreadBlueColor];\n                self->_menuBtn.accessibilityValue = @\"Unread messages\";\n                self->_sceneTitleExtra = @\"* \";\n            } else {\n                self->_menuBtn.tintColor = [UIColor navBarSubheadingColor];\n                self->_menuBtn.accessibilityValue = nil;\n                self->_sceneTitleExtra = nil;\n            }\n            \n            [self _updateTitleArea];\n        }];\n    }\n}\n\n- (void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    Channel *c;\n    Buffer *b = nil;\n    IRCCloudJSONObject *o = nil;\n    ChannelModeListTableViewController *cmltv = nil;\n    ChannelListTableViewController *ctv = nil;\n    CallerIDTableViewController *citv = nil;\n    WhoListTableViewController *wtv = nil;\n    NamesListTableViewController *ntv = nil;\n    Event *e = nil;\n    Server *s = nil;\n    NSString *msg = nil;\n    NSString *type = nil;\n    UIAlertController *ac = nil;\n    switch(event) {\n        case kIRCEventSessionDeleted:\n            [self bufferSelected:-1];\n            [(AppDelegate *)([UIApplication sharedApplication].delegate) showLoginView];\n            break;\n        case kIRCEventGlobalMsg:\n            [self _updateGlobalMsg];\n            break;\n        case kIRCEventWhois:\n        {\n            if([self.presentedViewController isKindOfClass:UINavigationController.class] && [((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:WhoisViewController.class]) {\n                WhoisViewController *wvc = (WhoisViewController *)(((UINavigationController *)self.presentedViewController).topViewController);\n                [wvc setData:notification.object];\n            } else {\n                WhoisViewController *wvc = [[WhoisViewController alloc] init];\n                [wvc setData:notification.object];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:wvc];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                \n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n        }\n            break;\n        case kIRCEventChannelTopicIs:\n            o = notification.object;\n            b = [[BuffersDataSource sharedInstance] getBufferWithName:[o objectForKey:@\"chan\"] server:o.cid];\n            if(b) {\n                c = [[ChannelsDataSource sharedInstance] channelForBuffer:b.bid];\n            } else {\n                c = [[Channel alloc] init];\n                c.cid = o.cid;\n                c.bid = -1;\n                c.name = [o objectForKey:@\"chan\"];\n                c.topic_author = [o objectForKey:@\"author\"]?[o objectForKey:@\"author\"]:[o objectForKey:@\"server\"];\n                c.topic_time = [[o objectForKey:@\"time\"] doubleValue];\n                c.topic_text = [o objectForKey:@\"text\"];\n            }\n            if(c) {\n                ChannelInfoViewController *cvc = [[ChannelInfoViewController alloc] initWithChannel:c];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:cvc];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationFormSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventChannelInit:\n        case kIRCEventChannelTopic:\n        case kIRCEventChannelMode:\n            [self _updateTitleArea];\n            [self _updateUserListVisibility];\n            break;\n        case kIRCEventBadChannelKey: {\n            self->_alertObject = notification.object;\n            s = [[ServersDataSource sharedInstance] getServer:self->_alertObject.cid];\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [self dismissKeyboard];\n                [self.view.window endEditing:YES];\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:[NSString stringWithFormat:@\"Password for %@\",[self->_alertObject objectForKey:@\"chan\"]] preferredStyle:UIAlertControllerStyleAlert];\n                \n                [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Join\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                    if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length)\n                        [[NetworkConnection sharedInstance] join:[self->_alertObject objectForKey:@\"chan\"] key:((UITextField *)[alert.textFields objectAtIndex:0]).text cid:self->_alertObject.cid handler:^(IRCCloudJSONObject *result) {\n                            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:[NSString stringWithFormat:@\"Unable to join channel: %@. Please try again shortly.\", [result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                            [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n                            [self presentViewController:alert animated:YES completion:nil];\n                        }];\n                }]];\n                \n                [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n                    textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n                }];\n                \n                [self presentViewController:alert animated:YES completion:nil];\n            }];}\n            break;\n        case kIRCEventAlert:\n            o = notification.object;\n            type = o.type;\n            \n            if([type isEqualToString:@\"help\"] || [type isEqualToString:@\"stats\"]) {\n                TextTableViewController *tv;\n                if([self.presentedViewController isKindOfClass:UINavigationController.class] && [((UINavigationController *)self.presentedViewController).viewControllers.firstObject isKindOfClass:TextTableViewController.class]) {\n                    tv = ((UINavigationController *)self.presentedViewController).viewControllers.firstObject;\n                    if(![tv.type isEqualToString:type])\n                        tv = nil;\n                }\n                NSString *msg = [o objectForKey:@\"parts\"];\n                if([[o objectForKey:@\"msg\"] length]) {\n                    if(msg.length)\n                        msg = [msg stringByAppendingFormat:@\": %@\", [o objectForKey:@\"msg\"]];\n                    else\n                        msg = [o objectForKey:@\"msg\"];\n                }\n                msg = [msg stringByAppendingString:@\"\\n\"];\n                if(!msg)\n                    msg = @\"\\n\";\n                if(tv) {\n                    [tv appendText:msg];\n                } else {\n                    tv = [[TextTableViewController alloc] initWithText:msg];\n                    if([[o objectForKey:@\"command\"] length])\n                        tv.navigationItem.title = [NSString stringWithFormat:@\"HELP For %@\", [o objectForKey:@\"command\"]];\n                    else\n                        tv.navigationItem.title = type.uppercaseString;\n                    tv.server = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n                    tv.type = type;\n                    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:tv];\n                    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                        nc.modalPresentationStyle = UIModalPresentationFormSheet;\n                    else\n                        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                    if(self.presentedViewController)\n                        [self dismissViewControllerAnimated:NO completion:nil];\n                    [self presentViewController:nc animated:YES completion:nil];\n                }\n            } else {\n                if([type isEqualToString:@\"invite_only_chan\"])\n                    msg = [NSString stringWithFormat:@\"You need an invitation to join %@\", [o objectForKey:@\"chan\"]];\n                else if([type isEqualToString:@\"channel_full\"])\n                    msg = [NSString stringWithFormat:@\"%@ isn't allowing any more members to join.\", [o objectForKey:@\"chan\"]];\n                else if([type isEqualToString:@\"banned_from_channel\"])\n                    msg = [NSString stringWithFormat:@\"You've been banned from %@\", [o objectForKey:@\"chan\"]];\n                else if([type isEqualToString:@\"invalid_nickchange\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"ban_channel\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"bad_channel_name\"])\n                    msg = [NSString stringWithFormat:@\"Bad channel name: %@\", [o objectForKey:@\"chan\"]];\n                else if([type isEqualToString:@\"no_messages_from_non_registered\"]) {\n                    if([[o objectForKey:@\"nick\"] length])\n                        msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"nick\"], [o objectForKey:@\"msg\"]];\n                    else\n                        msg = [o objectForKey:@\"msg\"];\n                } else if([type isEqualToString:@\"not_registered\"]) {\n                    NSString *first = [o objectForKey:@\"first\"];\n                    if([[o objectForKey:@\"rest\"] length])\n                        first = [first stringByAppendingString:[o objectForKey:@\"rest\"]];\n                    msg = [NSString stringWithFormat:@\"%@: %@\", first, [o objectForKey:@\"msg\"]];\n                } else if([type isEqualToString:@\"too_many_channels\"])\n                    msg = [NSString stringWithFormat:@\"Couldn't join %@: %@\", [o objectForKey:@\"chan\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"too_many_targets\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"description\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"no_such_server\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"server\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"unknown_command\"]) {\n                    NSString *m = [o objectForKey:@\"msg\"];\n                    if(!m.length)\n                        m = @\"Unknown command\";\n                    msg = [NSString stringWithFormat:@\"%@: %@\", m, [o objectForKey:@\"command\"]];\n                } else if([type isEqualToString:@\"help_not_found\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"topic\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"accept_exists\"])\n                    msg = [NSString stringWithFormat:@\"%@ %@\", [o objectForKey:@\"nick\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"accept_not\"])\n                    msg = [NSString stringWithFormat:@\"%@ %@\", [o objectForKey:@\"nick\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"nick_collision\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"collision\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"nick_too_fast\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"nick\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"save_nick\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@: %@\", [o objectForKey:@\"nick\"], [o objectForKey:@\"msg\"], [o objectForKey:@\"new_nick\"]];\n                else if([type isEqualToString:@\"unknown_mode\"])\n                    msg = [NSString stringWithFormat:@\"Missing mode: %@\", [o objectForKey:@\"param\"]];\n                else if([type isEqualToString:@\"user_not_in_channel\"])\n                    msg = [NSString stringWithFormat:@\"%@ is not in %@\", [o objectForKey:@\"nick\"], [o objectForKey:@\"channel\"]];\n                else if([type isEqualToString:@\"need_more_params\"])\n                    msg = [NSString stringWithFormat:@\"Missing parameters for command: %@\", [o objectForKey:@\"command\"]];\n                else if([type isEqualToString:@\"chan_privs_needed\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"chan\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"not_on_channel\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"channel\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"ban_on_chan\"])\n                    msg = [NSString stringWithFormat:@\"You cannot change your nick to %@ while banned on %@\", [o objectForKey:@\"proposed_nick\"], [o objectForKey:@\"channel\"]];\n                else if([type isEqualToString:@\"cannot_send_to_chan\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"channel\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"cant_send_to_user\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"nick\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"user_on_channel\"])\n                    msg = [NSString stringWithFormat:@\"%@ is already a member of %@\", [o objectForKey:@\"nick\"], [o objectForKey:@\"channel\"]];\n                else if([type isEqualToString:@\"nickname_in_use\"])\n                    msg = [NSString stringWithFormat:@\"%@ is already in use\", [o objectForKey:@\"nick\"]];\n                else if([type isEqualToString:@\"no_nick_given\"])\n                    msg = [NSString stringWithFormat:@\"No nickname given\"];\n                else if([type isEqualToString:@\"silence\"]) {\n                    NSString *mask = [o objectForKey:@\"usermask\"];\n                    if([mask hasPrefix:@\"-\"])\n                        msg = [NSString stringWithFormat:@\"%@ removed from silence list\", [mask substringFromIndex:1]];\n                    else if([mask hasPrefix:@\"+\"])\n                        msg = [NSString stringWithFormat:@\"%@ added to silence list\", [mask substringFromIndex:1]];\n                    else\n                        msg = [NSString stringWithFormat:@\"Silence list change: %@\", mask];\n                } else if([type isEqualToString:@\"no_channel_topic\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"channel\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"time\"]) {\n                    msg = [o objectForKey:@\"time_string\"];\n                    if([[o objectForKey:@\"time_stamp\"] length]) {\n                        msg = [msg stringByAppendingFormat:@\" (%@)\", [o objectForKey:@\"time_stamp\"]];\n                    }\n                    msg = [msg stringByAppendingFormat:@\" — %@\", [o objectForKey:@\"time_server\"]];\n                }\n                else if([type isEqualToString:@\"blocked_channel\"])\n                    msg = @\"This channel is blocked, you have been disconnected.\";\n                else if([type isEqualToString:@\"unknown_error\"])\n                    msg = [NSString stringWithFormat:@\"Unknown Error [%@] %@\", [o objectForKey:@\"command\"], [o objectForKey:@\"msg\"]];\n                else if([type isEqualToString:@\"pong\"]) {\n                    if([o objectForKey:@\"origin\"])\n                        msg = [NSString stringWithFormat:@\"PONG from %@: %@\", [o objectForKey:@\"origin\"], [o objectForKey:@\"msg\"]];\n                    else\n                        msg = [NSString stringWithFormat:@\"PONG: %@\", [o objectForKey:@\"msg\"]];\n                }\n                else if([type isEqualToString:@\"monitor_full\"]) {\n                    if([[o objectForKey:@\"limit\"] respondsToSelector:@selector(intValue)] && [[o objectForKey:@\"limit\"] intValue])\n                        msg = [NSString stringWithFormat:@\"%@: %@ (limit: %i)\", [o objectForKey:@\"targets\"], [o objectForKey:@\"msg\"], [[o objectForKey:@\"limit\"] intValue]];\n                    else\n                        msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"targets\"], [o objectForKey:@\"msg\"]];\n                }\n                else if([type isEqualToString:@\"mlock_restricted\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\\nMLOCK: %@\\nRequested mode change: %@\", [o objectForKey:@\"channel\"], [o objectForKey:@\"msg\"], [o objectForKey:@\"mlock\"], [o objectForKey:@\"mode_change\"]];\n                else if([type isEqualToString:@\"cannot_do_cmd\"]) {\n                    if([o objectForKey:@\"cmd\"])\n                        msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"cmd\"], [o objectForKey:@\"msg\"]];\n                    else\n                        msg = [o objectForKey:@\"msg\"];\n                }\n                else if([type isEqualToString:@\"cannot_change_chan_mode\"]) {\n                    if([o objectForKey:@\"mode\"])\n                        msg = [NSString stringWithFormat:@\"You can't change channel mode: %@; %@\", [o objectForKey:@\"mode\"], [o objectForKey:@\"msg\"]];\n                    else\n                        msg = [NSString stringWithFormat:@\"You can't change channel mode; %@\", [o objectForKey:@\"msg\"]];\n                }\n                else if([type isEqualToString:@\"metadata_limit\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"msg\"], [o objectForKey:@\"target\"]];\n                else if([type isEqualToString:@\"metadata_targetinvalid\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@\", [o objectForKey:@\"msg\"], [o objectForKey:@\"target\"]];\n                else if([type isEqualToString:@\"metadata_nomatchingkey\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@ for target %@\", [o objectForKey:@\"msg\"], [o objectForKey:@\"key\"], [o objectForKey:@\"target\"]];\n                else if([type isEqualToString:@\"metadata_keyinvalid\"])\n                    msg = [NSString stringWithFormat:@\"Invalid metadata key: %@\", [o objectForKey:@\"key\"]];\n                else if([type isEqualToString:@\"metadata_keynotset\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@ for target %@\", [o objectForKey:@\"msg\"], [o objectForKey:@\"key\"], [o objectForKey:@\"target\"]];\n                else if([type isEqualToString:@\"metadata_keynopermission\"])\n                    msg = [NSString stringWithFormat:@\"%@: %@ for target %@\", [o objectForKey:@\"msg\"], [o objectForKey:@\"key\"], [o objectForKey:@\"target\"]];\n                else if([type isEqualToString:@\"metadata_toomanysubs\"])\n                    msg = [NSString stringWithFormat:@\"Metadata key subscription limit reached, keys after and including '%@' are not subscribed\", [o objectForKey:@\"key\"]];\n                else if([[o objectForKey:@\"message\"] isEqualToString:@\"invalid_nick\"])\n                    msg = @\"Invalid nickname\";\n                else if([type isEqualToString:@\"fail\"])\n                    msg = [NSString stringWithFormat:@\"FAIL: %@: %@: %@: %@\", [o objectForKey:@\"command\"], [o objectForKey:@\"code\"], [o objectForKey:@\"description\"], [o objectForKey:@\"context\"]];\n                else\n                    msg = [o objectForKey:@\"msg\"];\n\n                s = [[ServersDataSource sharedInstance] getServer:o.cid];\n                if (s) {\n                    UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:msg preferredStyle:UIAlertControllerStyleAlert];\n                    [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                    [self presentViewController:alert animated:YES completion:nil];\n                } else {\n                    UIAlertController *alert = [UIAlertController alertControllerWithTitle:msg message:nil preferredStyle:UIAlertControllerStyleAlert];\n                    [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                    [self presentViewController:alert animated:YES completion:nil];\n                }\n            }\n            break;\n        case kIRCEventStatusChanged:\n            [self _updateUserListVisibility];\n        case kIRCEventAway:\n            [self _updateTitleArea];\n        case kIRCEventSelfBack:\n        case kIRCEventConnectionLag:\n            [self _updateServerStatus];\n            break;\n        case kIRCEventBanList:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid && (![self.presentedViewController isKindOfClass:[UINavigationController class]] || ![((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:[ChannelModeListTableViewController class]])) {\n                cmltv = [[ChannelModeListTableViewController alloc] initWithList:event mode:@\"b\" param:@\"bans\" placeholder:@\"No bans in effect.\\n\\nYou can ban someone by tapping their nickname in the user list, long-pressing a message, or by using `/ban`.\\n\" cid: self->_buffer.cid bid:self->_buffer.bid];\n                cmltv.event = o;\n                cmltv.data = [o objectForKey:@\"bans\"];\n                cmltv.navigationItem.title = [NSString stringWithFormat:@\"Bans for %@\", [o objectForKey:@\"channel\"]];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:cmltv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventQuietList:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid && (![self.presentedViewController isKindOfClass:[UINavigationController class]] || ![((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:[ChannelModeListTableViewController class]])) {\n                cmltv = [[ChannelModeListTableViewController alloc] initWithList:event mode:@\"q\" param:@\"list\" placeholder:@\"Empty quiet list.\" cid: self->_buffer.cid bid:self->_buffer.bid];\n                cmltv.event = o;\n                cmltv.data = [o objectForKey:@\"list\"];\n                cmltv.navigationItem.title = [NSString stringWithFormat:@\"Quiet list for %@\", [o objectForKey:@\"channel\"]];\n                cmltv.mask = @\"quiet_mask\";\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:cmltv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventInviteList:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid && (![self.presentedViewController isKindOfClass:[UINavigationController class]] || ![((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:[ChannelModeListTableViewController class]])) {\n                cmltv = [[ChannelModeListTableViewController alloc] initWithList:event mode:@\"I\" param:@\"list\" placeholder:@\"Empty invite list.\" cid: self->_buffer.cid bid:self->_buffer.bid];\n                cmltv.event = o;\n                cmltv.data = [o objectForKey:@\"list\"];\n                cmltv.navigationItem.title = [NSString stringWithFormat:@\"Invite list for %@\", [o objectForKey:@\"channel\"]];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:cmltv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventBanExceptionList:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid && (![self.presentedViewController isKindOfClass:[UINavigationController class]] || ![((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:[ChannelModeListTableViewController class]])) {\n                cmltv = [[ChannelModeListTableViewController alloc] initWithList:event mode:@\"e\" param:@\"exceptions\" placeholder:@\"Empty exception list.\" cid: self->_buffer.cid bid:self->_buffer.bid];\n                cmltv.event = o;\n                cmltv.data = [o objectForKey:@\"exceptions\"];\n                cmltv.navigationItem.title = [NSString stringWithFormat:@\"Exception list for %@\", [o objectForKey:@\"channel\"]];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:cmltv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventChanFilterList:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid && (![self.presentedViewController isKindOfClass:[UINavigationController class]] || ![((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:[ChannelModeListTableViewController class]])) {\n                cmltv = [[ChannelModeListTableViewController alloc] initWithList:event mode:@\"g\" param:@\"list\" placeholder:@\"No channel filter patterns.\" cid: self->_buffer.cid bid:self->_buffer.bid];\n                cmltv.event = o;\n                cmltv.data = [o objectForKey:@\"list\"];\n                cmltv.mask = @\"pattern\";\n                cmltv.navigationItem.title = [NSString stringWithFormat:@\"Channel filter for %@\", [o objectForKey:@\"channel\"]];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:cmltv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventListResponseFetching:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                ctv = [[ChannelListTableViewController alloc] initWithStyle:UITableViewStylePlain];\n                ctv.event = o;\n                ctv.navigationItem.title = @\"Channel List\";\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:ctv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventAcceptList:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid && (![self.presentedViewController isKindOfClass:[UINavigationController class]] || ![((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:[CallerIDTableViewController class]])) {\n                citv = [[CallerIDTableViewController alloc] initWithStyle:UITableViewStylePlain];\n                citv.event = o;\n                citv.nicks = [o objectForKey:@\"nicks\"];\n                citv.navigationItem.title = @\"Accept List\";\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:citv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventWhoList:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                wtv = [[WhoListTableViewController alloc] initWithStyle:UITableViewStylePlain];\n                wtv.event = o;\n                wtv.navigationItem.title = [NSString stringWithFormat:@\"WHO For %@\", [o objectForKey:@\"subject\"]];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:wtv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventWhoSpecialResponse:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                TextTableViewController *tv = [[TextTableViewController alloc] initWithData:[o objectForKey:@\"users\"]];\n                tv.navigationItem.title = [NSString stringWithFormat:@\"WHO For %@\", [o objectForKey:@\"subject\"]];\n                tv.server = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:tv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventModulesList:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                TextTableViewController *tv = [[TextTableViewController alloc] initWithData:[o objectForKey:@\"modules\"]];\n                tv.server = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n                tv.navigationItem.title = [NSString stringWithFormat:@\"Modules list for %@\", tv.server.hostname];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:tv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventTraceResponse:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                TextTableViewController *tv = [[TextTableViewController alloc] initWithData:[o objectForKey:@\"trace\"]];\n                tv.navigationItem.title = [NSString stringWithFormat:@\"Trace for %@\", [o objectForKey:@\"server\"]];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:tv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventLinksResponse:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                LinksListTableViewController *lv = [[LinksListTableViewController alloc] init];\n                lv.event = o;\n                lv.navigationItem.title = [o objectForKey:@\"server\"];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:lv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventChannelQuery:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                NSString *type = [o objectForKey:@\"query_type\"];\n                NSString *msg = nil;\n                \n                if([type isEqualToString:@\"mode\"]) {\n                    msg = [NSString stringWithFormat:@\"%@ mode is %c%@%c\", [o objectForKey:@\"channel\"], BOLD, [o objectForKey:@\"diff\"], CLEAR];\n                } else if([type isEqualToString:@\"timestamp\"]) {\n                    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];\n                    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];\n                    [dateFormatter setTimeStyle:NSDateFormatterShortStyle];\n                    msg = [NSString stringWithFormat:@\"%@ created on %c%@%c\", [o objectForKey:@\"channel\"], BOLD, [dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:[[o objectForKey:@\"timestamp\"] intValue]]], CLEAR];\n                } else {\n                    CLS_LOG(@\"Unhandled channel_query type: %@\", type);\n                }\n                \n                if(msg) {\n                    if([self.presentedViewController isKindOfClass:[UINavigationController class]] && [((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:[TextTableViewController class]] && [((TextTableViewController *)(((UINavigationController *)self.presentedViewController).topViewController)).type isEqualToString:@\"channel_query\"]) {\n                        TextTableViewController *tv = ((TextTableViewController *)(((UINavigationController *)self.presentedViewController).topViewController));\n                        [tv appendData:@[msg]];\n                    } else {\n                        TextTableViewController *tv = [[TextTableViewController alloc] initWithData:@[msg]];\n                        tv.server = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n                        tv.type = @\"channel_query\";\n                        tv.navigationItem.title = tv.server.hostname;\n                        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:tv];\n                        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                            nc.modalPresentationStyle = UIModalPresentationFormSheet;\n                        else\n                            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                        if(self.presentedViewController)\n                            [self dismissViewControllerAnimated:NO completion:nil];\n                        [self presentViewController:nc animated:YES completion:nil];\n                    }\n                }\n            }\n            break;\n        case kIRCEventTextList:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                if([self.presentedViewController isKindOfClass:[UINavigationController class]] && [((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:[TextTableViewController class]] && [((TextTableViewController *)(((UINavigationController *)self.presentedViewController).topViewController)).type isEqualToString:@\"text\"]) {\n                    TextTableViewController *tv = ((TextTableViewController *)(((UINavigationController *)self.presentedViewController).topViewController));\n                    [tv appendText:@\"\\n\"];\n                    [tv appendText:[o objectForKey:@\"msg\"]];\n                } else {\n                    TextTableViewController *tv = [[TextTableViewController alloc] initWithText:[o objectForKey:@\"msg\"]];\n                    tv.server = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n                    tv.type = @\"text\";\n                    tv.navigationItem.title = [o objectForKey:@\"server\"];\n                    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:tv];\n                    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                        nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                    else\n                        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                    if(self.presentedViewController)\n                        [self dismissViewControllerAnimated:NO completion:nil];\n                    [self presentViewController:nc animated:YES completion:nil];\n                }\n            }\n            break;\n        case kIRCEventNamesList:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                ntv = [[NamesListTableViewController alloc] initWithStyle:UITableViewStylePlain];\n                ntv.event = o;\n                ntv.navigationItem.title = [NSString stringWithFormat:@\"NAMES For %@\", [o objectForKey:@\"chan\"]];\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:ntv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventServerMap:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                TextTableViewController *smtv = [[TextTableViewController alloc] initWithData:[o objectForKey:@\"servers\"]];\n                smtv.server = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n                smtv.navigationItem.title = @\"Server Map\";\n                UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:smtv];\n                [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                    nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                else\n                    nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self presentViewController:nc animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventWhoWas:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                if([self.presentedViewController isKindOfClass:[UINavigationController class]] && [((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:[WhoWasTableViewController class]]) {\n                    WhoWasTableViewController *tv = ((WhoWasTableViewController *)(((UINavigationController *)self.presentedViewController).topViewController));\n                    tv.event = o;\n                    [tv refresh];\n                } else {\n                    WhoWasTableViewController *tv = [[WhoWasTableViewController alloc] initWithStyle:UITableViewStyleGrouped];\n                    tv.event = o;\n                    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:tv];\n                    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                        nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                    else\n                        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                    if(self.presentedViewController)\n                        [self dismissViewControllerAnimated:NO completion:nil];\n                    [self presentViewController:nc animated:YES completion:nil];\n                }\n            }\n            break;\n        case kIRCEventLinkChannel:\n            o = notification.object;\n            if(self->_cidToOpen == o.cid && [[o objectForKey:@\"invalid_chan\"] isKindOfClass:[NSString class]] && [[[o objectForKey:@\"invalid_chan\"] lowercaseString] isEqualToString:[self->_bufferToOpen lowercaseString]]) {\n                if([[o objectForKey:@\"valid_chan\"] isKindOfClass:[NSString class]] && [[o objectForKey:@\"valid_chan\"] length]) {\n                    self->_bufferToOpen = [o objectForKey:@\"valid_chan\"];\n                    b = [[BuffersDataSource sharedInstance] getBuffer:o.bid];\n                }\n            } else {\n                self->_cidToOpen = o.cid;\n                self->_bufferToOpen = nil;\n            }\n            if(!b)\n                break;\n        case kIRCEventMakeBuffer:\n            if(!b)\n                b = notification.object;\n            if(self->_cidToOpen == b.cid && [[b.name lowercaseString] isEqualToString:[self->_bufferToOpen lowercaseString]] && ![[self->_buffer.name lowercaseString] isEqualToString:[self->_bufferToOpen lowercaseString]]) {\n                [self bufferSelected:b.bid];\n                self->_bufferToOpen = nil;\n                self->_cidToOpen = -1;\n            } else if(self->_buffer.bid == -1 && b.cid == self->_buffer.cid && [b.name isEqualToString:self->_buffer.name]) {\n                [self bufferSelected:b.bid];\n                self->_bufferToOpen = nil;\n                self->_cidToOpen = -1;\n            } else if(self->_cidToOpen == b.cid && _bufferToOpen == nil) {\n                [self bufferSelected:b.bid];\n            }\n            break;\n        case kIRCEventOpenBuffer:\n            o = notification.object;\n            b = [[BuffersDataSource sharedInstance] getBufferWithName:[o objectForKey:@\"name\"] server:o.cid];\n            if(!b) {\n                self->_bufferToOpen = [o objectForKey:@\"name\"];\n                self->_cidToOpen = o.cid;\n            } else if (b != self->_buffer) {\n                [self bufferSelected:b.bid];\n            }\n            break;\n        case kIRCEventUserInfo:\n        {\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [ColorFormatter loadFonts];\n                [self _themeChanged];\n            }];\n        }\n        case kIRCEventPart:\n        case kIRCEventKick:\n            [self _updateTitleArea];\n            [self _updateUserListVisibility];\n            break;\n        case kIRCEventAuthFailure:\n            [[NetworkConnection sharedInstance] performSelectorOnMainThread:@selector(logout) withObject:nil waitUntilDone:YES];\n            [self bufferSelected:-1];\n            [(AppDelegate *)([UIApplication sharedApplication].delegate) showLoginView];\n            break;\n        case kIRCEventBufferMsg:\n            e = notification.object;\n            if(e.bid == self->_buffer.bid) {\n                if(e.isHighlight) {\n                    [self showMentionTip];\n                }\n                if(!e.isSelf && !_buffer.scrolledUp && !self.view.accessibilityElementsHidden) {\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        if(e.from.length)\n                            UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, [NSString stringWithFormat:@\"New message from %@: %@\", e.from, [[ColorFormatter format:e.msg defaultColor:[UIColor blackColor] mono:NO linkify:NO server:nil links:nil] string]]);\n                        else if([e.type isEqualToString:@\"buffer_me_msg\"])\n                            UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, [NSString stringWithFormat:@\"New action: %@ %@\", e.nick, [[ColorFormatter format:e.msg defaultColor:[UIColor blackColor] mono:NO linkify:NO server:nil links:nil] string]]);\n                    }];\n                }\n            } else {\n                Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:e.bid];\n                if(b && [e isImportant:b.type]) {\n                    Server *s = [[ServersDataSource sharedInstance] getServer:b.cid];\n                    Ignore *ignore = s.ignore;\n                    if(e.ignoreMask && [ignore match:e.ignoreMask])\n                        break;\n                    NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n                    BOOL muted = [[prefs objectForKey:@\"notifications-mute\"] boolValue];\n                    if(muted) {\n                        NSDictionary *disableMap;\n                        \n                        if([b.type isEqualToString:@\"channel\"]) {\n                            disableMap = [prefs objectForKey:@\"channel-notifications-mute-disable\"];\n                        } else {\n                            disableMap = [prefs objectForKey:@\"buffer-notifications-mute-disable\"];\n                        }\n                        \n                        if(disableMap && [[disableMap objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] boolValue])\n                            muted = NO;\n                    } else {\n                        NSDictionary *enableMap;\n                        \n                        if([b.type isEqualToString:@\"channel\"]) {\n                            enableMap = [prefs objectForKey:@\"channel-notifications-mute\"];\n                        } else {\n                            enableMap = [prefs objectForKey:@\"buffer-notifications-mute\"];\n                        }\n                        \n                        if(enableMap && [[enableMap objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] boolValue])\n                            muted = YES;\n                    }\n                    if((e.isHighlight || [b.type isEqualToString:@\"conversation\"]) && !muted) {\n                        self->_menuBtn.tintColor = [UIColor redColor];\n                        self->_menuBtn.accessibilityValue = @\"Unread highlights\";\n                        if (@available(iOS 14.0, *)) {\n                            if([NSProcessInfo processInfo].macCatalystApp) {\n                                [self _updateUnreadIndicator];\n                            }\n                        }\n                    } else if(self->_menuBtn.accessibilityValue == nil) {\n                        NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n                        if([b.type isEqualToString:@\"channel\"]) {\n                            if([[prefs objectForKey:@\"channel-disableTrackUnread\"] isKindOfClass:[NSDictionary class]] && [[[prefs objectForKey:@\"channel-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] == 1)\n                                break;\n                        } else {\n                            if([[prefs objectForKey:@\"buffer-disableTrackUnread\"] isKindOfClass:[NSDictionary class]] && [[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] == 1)\n                                break;\n                        }\n                        if([[prefs objectForKey:@\"disableTrackUnread\"] intValue] == 1) {\n                            if([b.type isEqualToString:@\"channel\"]) {\n                                if(![[prefs objectForKey:@\"channel-enableTrackUnread\"] isKindOfClass:[NSDictionary class]] || [[[prefs objectForKey:@\"channel-enableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] != 1)\n                                    break;\n                            } else {\n                                if(![[prefs objectForKey:@\"buffer-enableTrackUnread\"] isKindOfClass:[NSDictionary class]] || [[[prefs objectForKey:@\"buffer-enableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] != 1)\n                                    break;\n                            }\n                        }\n                        UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @\"New unread messages\");\n                        self->_menuBtn.tintColor = [UIColor unreadBlueColor];\n                        self->_menuBtn.accessibilityValue = @\"Unread messages\";\n                        if (@available(iOS 14.0, *)) {\n                            if([NSProcessInfo processInfo].macCatalystApp) {\n                                self->_sceneTitleExtra = @\"* \";\n                                [self _updateTitleArea];\n                            }\n                        }\n                    }\n                }\n            }\n            if([[e.from lowercaseString] isEqualToString:[[[BuffersDataSource sharedInstance] getBuffer:e.bid].name lowercaseString]]) {\n                for(Event *ev in [self->_pendingEvents copy]) {\n                    if(ev.bid == e.bid) {\n                        if(ev.expirationTimer && [ev.expirationTimer isValid])\n                            [ev.expirationTimer invalidate];\n                        ev.expirationTimer = nil;\n                        [self->_pendingEvents removeObject:ev];\n                        [[EventsDataSource sharedInstance] removeEvent:ev.eid buffer:ev.bid];\n                    }\n                }\n            } else {\n                int reqid = e.reqId;\n                if(e.reqId > 0)\n                    CLS_LOG(@\"Removing expiration timer for reqid %i\", e.reqId);\n                for(Event *e in _pendingEvents) {\n                    if(e.reqId == reqid) {\n                        if(e.expirationTimer && [e.expirationTimer isValid])\n                            [e.expirationTimer invalidate];\n                        e.expirationTimer = nil;\n                        [[EventsDataSource sharedInstance] removeEvent:e.eid buffer:e.bid];\n                        [self->_pendingEvents removeObject:e];\n                        break;\n                    }\n                }\n            }\n            /*b = [[BuffersDataSource sharedInstance] getBuffer:e.bid];\n            if(b && !b.scrolledUp && [[EventsDataSource sharedInstance] highlightStateForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type] == 0 && [[EventsDataSource sharedInstance] sizeOfBuffer:b.bid] > 200 && [self->_eventsView.tableView numberOfRowsInSection:0] > 100) {\n                [[EventsDataSource sharedInstance] pruneEventsForBuffer:b.bid maxSize:100];\n                if(b.bid == self->_buffer.bid) {\n                    if(b.last_seen_eid < e.eid)\n                        b.last_seen_eid = e.eid;\n                    [[ImageCache sharedInstance] clear];\n                    [self->_eventsView refresh];\n                }\n            }*/\n            break;\n        case kIRCEventHeartbeatEcho:\n        {\n            o = notification.object;\n            BOOL important = NO;\n            NSDictionary *seenEids = [o objectForKey:@\"seenEids\"];\n            for(NSNumber *cid in seenEids.allKeys) {\n                NSDictionary *eids = [seenEids objectForKey:cid];\n                for(NSNumber *bid in eids.allKeys) {\n                    if([bid intValue] != self->_buffer.bid) {\n                        important = YES;\n                        break;\n                    }\n                }\n            }\n            if(important) {\n                [self performSelectorInBackground:@selector(_updateUnreadIndicator) withObject:nil];\n            }\n            break;\n        }\n        case kIRCEventDeleteBuffer:\n        case kIRCEventBufferArchived:\n            o = notification.object;\n            if(o.bid == self->_buffer.bid && ![self->_buffer.type isEqualToString:@\"console\"]) {\n                if(self->_buffer && _buffer.lastBuffer && [[BuffersDataSource sharedInstance] getBuffer:self->_buffer.lastBuffer.bid])\n                    [self bufferSelected:self->_buffer.lastBuffer.bid];\n                else if([[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] && [[BuffersDataSource sharedInstance] getBuffer:[[[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] intValue]])\n                    [self bufferSelected:[[[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] intValue]];\n                else\n                    [self bufferSelected:[[BuffersDataSource sharedInstance] mostRecentBid]];\n            }\n            [self performSelectorInBackground:@selector(_updateUnreadIndicator) withObject:nil];\n            break;\n        case kIRCEventConnectionDeleted:\n            o = notification.object;\n            if(o.cid == self->_buffer.cid) {\n                if(self->_buffer && _buffer.lastBuffer) {\n                    [self bufferSelected:self->_buffer.lastBuffer.bid];\n                } else if([[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] && [[BuffersDataSource sharedInstance] getBuffer:[[[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] intValue]]) {\n                    [self bufferSelected:[[[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] intValue]];\n                } else if([[ServersDataSource sharedInstance] count]) {\n                    [self bufferSelected:[[BuffersDataSource sharedInstance] mostRecentBid]];\n                } else {\n                    [self bufferSelected:-1];\n                    [(AppDelegate *)[UIApplication sharedApplication].delegate showConnectionView];\n                }\n            }\n            [self performSelectorInBackground:@selector(_updateUnreadIndicator) withObject:nil];\n            break;\n        case kIRCEventLogExportFinished:\n            o = notification.object;\n            if([o objectForKey:@\"export\"]) {\n                NSDictionary *export = [o objectForKey:@\"export\"];\n                Server *s = ![[export objectForKey:@\"cid\"] isKindOfClass:[NSNull class]] ? [[ServersDataSource sharedInstance] getServer:[[export objectForKey:@\"cid\"] intValue]] : nil;\n                Buffer *b = ![[export objectForKey:@\"bid\"] isKindOfClass:[NSNull class]] ? [[BuffersDataSource sharedInstance] getBuffer:[[export objectForKey:@\"bid\"] intValue]] : nil;\n                \n                NSString *serverName = s ? (s.name.length ? s.name : s.hostname) : [NSString stringWithFormat:@\"Unknown Network (%@)\", [export objectForKey:@\"cid\"]];\n                NSString *bufferName = b ? b.name : [NSString stringWithFormat:@\"Unknown Log (%@)\", [export objectForKey:@\"bid\"]];\n                \n                NSString *msg = @\"Your log export is ready for download\";\n                if(![[export objectForKey:@\"bid\"] isKindOfClass:[NSNull class]])\n                    msg = [NSString stringWithFormat:@\"Logs for %@: %@ are ready for download\", serverName, bufferName];\n                else if(![[export objectForKey:@\"cid\"] isKindOfClass:[NSNull class]])\n                    msg = [NSString stringWithFormat:@\"Logs for %@ are ready for download\", serverName];\n\n                ac = [UIAlertController alertControllerWithTitle:@\"Export Finished\" message:msg preferredStyle:UIAlertControllerStyleAlert];\n                [ac addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n                [ac addAction:[UIAlertAction actionWithTitle:@\"Download\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                    [self launchURL:[NSURL URLWithString:[export objectForKey:@\"redirect_url\"]]];\n                }]];\n                \n                [self presentViewController:ac animated:YES completion:nil];\n            }\n            break;\n        case kIRCEventUserTyping:\n            o = notification.object;\n            if(o.bid == self->_buffer.bid) {\n                [self _updateTypingIndicatorTimer];\n            }\n            break;\n        default:\n            break;\n    }\n}\n\n-(void)_showConnectingView {\n    self.navigationItem.titleView = self->_connectingView;\n}\n\n-(void)_hideConnectingView {\n    self.navigationItem.titleView = self->_titleView;\n    self->_connectingProgress.hidden = YES;\n}\n\n-(void)connectivityChanged:(NSNotification *)notification {\n    self->_connectingStatus.textColor = [UIColor navBarHeadingColor];\n    UIColor *c = ([NetworkConnection sharedInstance].state == kIRCCloudStateConnected)?([UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor unreadBlueColor]):[UIColor textareaBackgroundColor];\n    [self->_sendBtn setTitleColor:c forState:UIControlStateNormal];\n    [self->_sendBtn setTitleColor:c forState:UIControlStateDisabled];\n    [self->_sendBtn setTitleColor:c forState:UIControlStateHighlighted];\n    \n    switch([NetworkConnection sharedInstance].state) {\n        case kIRCCloudStateConnecting:\n            [self _showConnectingView];\n            self->_connectingStatus.text = @\"Connecting\";\n            self->_connectingProgress.progress = 0;\n            self->_connectingProgress.hidden = YES;\n            UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @\"Connecting\");\n            break;\n        case kIRCCloudStateDisconnected:\n            [self _showConnectingView];\n            if([NetworkConnection sharedInstance].reconnectTimestamp > 0) {\n                int seconds = (int)([NetworkConnection sharedInstance].reconnectTimestamp - [[NSDate date] timeIntervalSince1970]) + 1;\n                if(seconds < 0) {\n                    seconds = 0;\n                    if([NetworkConnection sharedInstance].session.length && [NetworkConnection shouldReconnect]) {\n                        CLS_LOG(@\"Reconnect timestamp in the past, reconnecting\");\n                        [[NetworkConnection sharedInstance] connect:NO];\n                    } else {\n                        CLS_LOG(@\"Reconnect timestamp in the past but app is in the background\");\n                    }\n                }\n                [self->_connectingStatus setText:[NSString stringWithFormat:@\"Reconnecting in 0:%02i\", seconds]];\n                self->_connectingProgress.progress = 0;\n                self->_connectingProgress.hidden = YES;\n                [self performSelector:@selector(connectivityChanged:) withObject:nil afterDelay:1];\n            } else {\n                UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @\"Disconnected\");\n                if([[NetworkConnection sharedInstance] reachable] == kIRCCloudReachable) {\n                    self->_connectingStatus.text = @\"Disconnected\";\n                    if([NetworkConnection sharedInstance].session.length && [NetworkConnection shouldReconnect]) {\n                        CLS_LOG(@\"I'm disconnected but IRCCloud is reachable, reconnecting\");\n                        [[NetworkConnection sharedInstance] connect:NO];\n                    }\n                } else {\n                    self->_connectingStatus.text = @\"Offline\";\n                }\n                self->_connectingProgress.progress = 0;\n                self->_connectingProgress.hidden = YES;\n            }\n            break;\n        case kIRCCloudStateConnected:\n            for(Event *e in [self->_pendingEvents copy]) {\n                if(e.reqId == -1 && (([[NSDate date] timeIntervalSince1970] - (e.eid/1000000) - [NetworkConnection sharedInstance].clockOffset) < 60)) {\n                    [e.expirationTimer invalidate];\n                    e.expirationTimer = nil;\n                    e.reqId = [[NetworkConnection sharedInstance] say:e.command to:e.to cid:e.cid handler:^(IRCCloudJSONObject *result) {\n                        if(![[result objectForKey:@\"success\"] boolValue]) {\n                            [self->_pendingEvents removeObject:e];\n                            e.height = 0;\n                            e.pending = NO;\n                            e.rowType = ROW_FAILED;\n                            e.color = [UIColor networkErrorColor];\n                            e.bgColor = [UIColor errorBackgroundColor];\n                            [e.expirationTimer invalidate];\n                            e.expirationTimer = nil;\n                            [self->_eventsView reloadData];\n                        }\n                    }];\n                    if(e.reqId < 0)\n                        e.expirationTimer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(_sendRequestDidExpire:) userInfo:e repeats:NO];\n                } else {\n                    [self->_pendingEvents removeObject:e];\n                    e.height = 0;\n                    e.pending = NO;\n                    e.rowType = ROW_FAILED;\n                    e.color = [UIColor networkErrorColor];\n                    e.bgColor = [UIColor errorBackgroundColor];\n                    [e.expirationTimer invalidate];\n                    e.expirationTimer = nil;\n                }\n            }\n            break;\n    }\n}\n\n-(void)backlogStarted:(NSNotification *)notification {\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            if(!self->_connectingView.hidden) {\n                self->_connectingStatus.textColor = [UIColor navBarHeadingColor];\n                [self->_connectingStatus setText:@\"Loading\"];\n                self->_connectingProgress.progress = 0;\n                self->_connectingProgress.hidden = NO;\n            }\n        }];\n}\n\n-(void)backlogProgress:(NSNotification *)notification {\n    if(!_connectingView.hidden) {\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self->_connectingProgress setProgress:[notification.object floatValue] animated:YES];\n        }];\n    }\n}\n\n-(void)backlogCompleted:(NSNotification *)notification {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        if([notification.object bid] == -1) {\n          [self _themeChanged];\n            if(!((AppDelegate *)([UIApplication sharedApplication].delegate)).movedToBackground && [NetworkConnection sharedInstance].ready && ![NetworkConnection sharedInstance].notifier && [ServersDataSource sharedInstance].count < 1) {\n                [(AppDelegate *)([UIApplication sharedApplication].delegate) showConnectionView];\n                return;\n            }\n        }\n        [self _hideConnectingView];\n        if(self->_buffer && !self->_urlToOpen && self->_bidToOpen < 1 && self->_eidToOpen < 1 && self->_cidToOpen < 1 && [[BuffersDataSource sharedInstance] getBuffer:self->_buffer.bid]) {\n            [self _updateTitleArea];\n            [self _updateServerStatus];\n            [self _updateUserListVisibility];\n            [self performSelectorInBackground:@selector(_updateUnreadIndicator) withObject:nil];\n            [self _updateGlobalMsg];\n        } else {\n            [[NSNotificationCenter defaultCenter] removeObserver:self->_eventsView name:kIRCCloudBacklogCompletedNotification object:nil];\n            int bid = [self _lastSelectedBid];\n            if(self->_bidToOpen > 0) {\n                CLS_LOG(@\"backlog complete: BID to open: %i\", self->_bidToOpen);\n                bid = self->_bidToOpen;\n                self->_bidToOpen = -1;\n            } else if(self->_eidToOpen > 0) {\n                bid = self->_buffer.bid;\n            } else if(self->_cidToOpen > 0 && self->_bufferToOpen) {\n                Buffer *b = [[BuffersDataSource sharedInstance] getBufferWithName:self->_bufferToOpen server:self->_cidToOpen];\n                if(b) {\n                    bid = b.bid;\n                    self->_cidToOpen = -1;\n                    self->_bufferToOpen = nil;\n                }\n            }\n            [self bufferSelected:bid];\n            self->_eidToOpen = -1;\n            if(self->_urlToOpen)\n                [self launchURL:self->_urlToOpen];\n            [[NSNotificationCenter defaultCenter] addObserver:self->_eventsView selector:@selector(backlogCompleted:) name:kIRCCloudBacklogCompletedNotification object:nil];\n        }\n    }];\n}\n\n-(void)keyboardWillShow:(NSNotification*)notification {\n    if (@available(iOS 13.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp) {\n            self->_kbSize = CGSizeMake(0,0);\n            return;\n        }\n    }\n    if(self->_eventsView.topUnreadView.observationInfo) {\n        @try {\n            [self->_eventsView.tableView.layer removeObserver:self forKeyPath:@\"bounds\"];\n        } @catch(id anException) {\n            //Not registered yet\n        }\n    }\n    \n    CGSize size;\n    int height;\n    \n    if (@available(iOS 17, *)) {\n        if ([UIScreen mainScreen].focusedView == nil || [UIScreen mainScreen].bounds.size.height == self.view.window.bounds.size.height || [UIScreen mainScreen].focusedView.window == self.view.window || self.view.window.frame.size.width == self.view.keyboardLayoutGuide.layoutFrame.size.width) {\n            size = self.view.keyboardLayoutGuide.layoutFrame.size;\n            height = size.height;\n            if (size.width < self.view.window.frame.size.width)\n                height += self.slidingViewController.view.window.safeAreaInsets.bottom;\n        } else {\n            height = 0;\n            size = CGSizeZero;\n        }\n    } else {\n        size = [self.view convertRect:[[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] toView:nil].size;\n        CGPoint origin = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin;\n        height = [UIScreen mainScreen].bounds.size.height - origin.y;\n        height -= self.slidingViewController.view.window.safeAreaInsets.bottom / 2;\n    }\n    \n    if (height > self.view.bounds.size.height - 72) {\n        height = self.view.bounds.size.height - 72;\n    }\n\n    if(height != self->_kbSize.height) {\n        self->_kbSize = size;\n        self->_kbSize.height = height;\n\n        [UIView beginAnimations:nil context:NULL];\n        [UIView setAnimationBeginsFromCurrentState:YES];\n        [UIView setAnimationCurve:[[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];\n        [UIView setAnimationDuration:[[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];\n\n        [self updateLayout];\n        \n        [UIView commitAnimations];\n        [self expandingTextViewDidChange:self->_message];\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self->_buffersView scrollViewDidScroll:self->_buffersView.tableView];\n        }];\n    }\n    [self->_eventsView.tableView.layer addObserver:self forKeyPath:@\"bounds\" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];\n}\n\n-(void)_observeKeyboard {\n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(keyboardWillShow:)\n                                                 name:UIKeyboardWillShowNotification object:nil];\n}\n\n-(void)keyboardWillBeHidden:(NSNotification*)notification {\n    if(self->_eventsView.topUnreadView.observationInfo) {\n        @try {\n            [self->_eventsView.tableView.layer removeObserver:self forKeyPath:@\"bounds\"];\n        } @catch(id anException) {\n            //Not registered yet\n        }\n    }\n    self->_kbSize = CGSizeMake(0,0);\n    \n    [UIView beginAnimations:nil context:NULL];\n    [UIView setAnimationBeginsFromCurrentState:YES];\n    [UIView setAnimationCurve:[[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];\n    [UIView setAnimationDuration:[[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];\n\n    [self.slidingViewController updateUnderLeftLayout];\n    [self.slidingViewController updateUnderRightLayout];\n    [self updateLayout];\n\n    [self->_buffersView scrollViewDidScroll:self->_buffersView.tableView];\n    self->_nickCompletionView.alpha = 0;\n    self->_updateSuggestionsTask.atMention = NO;\n    [UIView commitAnimations];\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"keepScreenOn\"])\n        [UIApplication sharedApplication].idleTimerDisabled = YES;\n    [self->_eventsView.tableView.layer addObserver:self forKeyPath:@\"bounds\" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];\n}\n\n- (int)_lastSelectedBid {\n    int bid = [BuffersDataSource sharedInstance].mostRecentBid;\n    \n    if(self->_buffer && self->_buffer.lastBuffer && [[BuffersDataSource sharedInstance] getBuffer:self->_buffer.lastBuffer.bid]) {\n        bid = self->_buffer.lastBuffer.bid;\n    } else if([[NSUserDefaults standardUserDefaults] objectForKey:@\"last_selected_bid\"] && [[BuffersDataSource sharedInstance] getBuffer:[[[NSUserDefaults standardUserDefaults] objectForKey:@\"last_selected_bid\"] intValue]]) {\n        bid = [[[NSUserDefaults standardUserDefaults] objectForKey:@\"last_selected_bid\"] intValue];\n    } else if([NetworkConnection sharedInstance].userInfo && [[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] &&\n              [[BuffersDataSource sharedInstance] getBuffer:[[[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] intValue]]) {\n            bid = [[[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] intValue];\n    }\n    return bid;\n}\n\n- (void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    if(self->_ignoreVisibilityChanges)\n        return;\n    [UIColor setCurrentTraits:self.traitCollection];\n    [UIColor setTheme];\n    if(![self->_currentTheme isEqualToString:[UIColor currentTheme]]) {\n        CLS_LOG(@\"Switched from %@ to %@\", self->_currentTheme, [UIColor currentTheme]);\n        [self applyTheme];\n        if([ColorFormatter shouldClearFontCache]) {\n            [ColorFormatter clearFontCache];\n            [ColorFormatter loadFonts];\n        }\n        [[EventsDataSource sharedInstance] reformat];\n        [[AvatarsDataSource sharedInstance] invalidate];\n        \n        [self->_eventsView clearRowCache];\n        [self->_eventsView refresh];\n    }\n    self->_isShowingPreview = NO;\n    [self->_eventsView viewWillAppear:animated];\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"keepScreenOn\"])\n        [UIApplication sharedApplication].idleTimerDisabled = YES;\n    for(Event *e in [self->_pendingEvents copy]) {\n        if(e.reqId != -1) {\n            [self->_pendingEvents removeObject:e];\n            [[EventsDataSource sharedInstance] removeEvent:e.eid buffer:e.bid];\n        }\n    }\n    [[EventsDataSource sharedInstance] clearPendingAndFailed];\n    if(!_buffer || ![[BuffersDataSource sharedInstance] getBuffer:self->_buffer.bid]) {\n        int bid = [self _lastSelectedBid];\n        if(self->_bidToOpen > 0) {\n            CLS_LOG(@\"viewwillappear: BID to open: %i\", _bidToOpen);\n            bid = self->_bidToOpen;\n        }\n        [self bufferSelected:bid];\n        if(self->_urlToOpen) {\n            [self launchURL:self->_urlToOpen];\n        }\n    } else {\n        [self bufferSelected:self->_buffer.bid];\n    }\n    if(!self.presentedViewController) {\n        self.navigationController.navigationBar.translucent = NO;\n        self.edgesForExtendedLayout=UIRectEdgeNone;\n    }\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    [self.navigationController.view addGestureRecognizer:self.slidingViewController.panGesture];\n    [self performSelectorInBackground:@selector(_updateUnreadIndicator) withObject:nil];\n    [self.slidingViewController resetTopView];\n    \n    NSString *session = [NetworkConnection sharedInstance].session;\n#ifdef DEBUG\n    if(![[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"]) {\n#endif\n    if(session.length) {\n        UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];\n        \n        [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionBadge + UNAuthorizationOptionProvidesAppNotificationSettings) completionHandler:^(BOOL granted, NSError * _Nullable error) {\n            if(!granted)\n                CLS_LOG(@\"Notification permission denied: %@\", error);\n        }];\n#ifdef DEBUG\n        CLS_LOG(@\"This is a debug build, skipping APNs registration\");\n#else\n        CLS_LOG(@\"APNs registration\");\n        [[UIApplication sharedApplication] registerForRemoteNotifications];\n#endif\n    }\n#ifdef DEBUG\n    }\n#endif\n    if([NetworkConnection shouldReconnect] && [NetworkConnection sharedInstance].state != kIRCCloudStateConnected && [NetworkConnection sharedInstance].state != kIRCCloudStateConnecting && session != nil && [session length] > 0) {\n        [[NetworkConnection sharedInstance] connect:NO];\n    }\n    \n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"autoCaps\"]) {\n        self->_message.internalTextView.autocapitalizationType = UITextAutocapitalizationTypeSentences;\n    } else {\n        self->_message.internalTextView.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    }\n    \n    self.slidingViewController.view.autoresizesSubviews = NO;\n    [self updateLayout];\n    \n    self->_buffersView.tableView.scrollsToTop = YES;\n    self->_usersView.tableView.scrollsToTop = YES;\n    if(self->_eventsView.topUnreadView.observationInfo) {\n        @try {\n            [self->_eventsView.topUnreadView removeObserver:self forKeyPath:@\"alpha\"];\n            [self->_eventsView.tableView.layer removeObserver:self forKeyPath:@\"bounds\"];\n        } @catch(id anException) {\n            //Not registered yet\n        }\n    }\n    [self->_eventsView.topUnreadView addObserver:self forKeyPath:@\"alpha\" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];\n    [self->_eventsView.tableView.layer addObserver:self forKeyPath:@\"bounds\" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];\n    \n    if (@available(iOS 14.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp) {\n            [[UIMenuSystem mainSystem] setNeedsRebuild];\n        }\n    }\n}\n\n- (void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    if(self->_ignoreVisibilityChanges)\n        return;\n    [self->_eventsView viewWillDisappear:animated];\n    [UIApplication sharedApplication].idleTimerDisabled = NO;\n    [self.navigationController.view removeGestureRecognizer:self.slidingViewController.panGesture];\n    [self->_doubleTapTimer invalidate];\n    self->_doubleTapTimer = nil;\n    self->_eidToOpen = -1;\n    \n    self.slidingViewController.view.autoresizesSubviews = YES;\n    [self.slidingViewController resetTopView];\n    \n    self->_buffersView.tableView.scrollsToTop = NO;\n    self->_usersView.tableView.scrollsToTop = NO;\n\n    if(self->_eventsView.topUnreadView.observationInfo) {\n        @try {\n            [self->_eventsView.topUnreadView removeObserver:self forKeyPath:@\"alpha\"];\n            [self->_eventsView.tableView.layer removeObserver:self forKeyPath:@\"bounds\"];\n        } @catch(id anException) {\n            //Not registered yet\n        }\n    }\n}\n\n- (void)viewDidAppear:(BOOL)animated {\n    [super viewDidAppear:animated];\n    [self->_eventsView viewDidAppear:animated];\n    [self updateLayout];\n    UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, _titleLabel);\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"keepScreenOn\"])\n        [UIApplication sharedApplication].idleTimerDisabled = YES;\n    \n    self.slidingViewController.view.autoresizesSubviews = NO;\n    \n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"imgur_removed\"]) {\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Imgur Uploading Unavailable\" message:@\"Uploading images to imgur is no longer available due to limitations in imgur's API.\\n\\nNew images will be stored on IRCCloud, and your existing images will remain available on imgur.\\n\\nImages from imgur can still be shared by using the 'share' button in an external application.\" preferredStyle:UIAlertControllerStyleAlert];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n        [self presentViewController:alert animated:YES completion:nil];\n        \n        [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"imgur_removed\"];\n        [[NSUserDefaults standardUserDefaults] synchronize];\n    }\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    CLS_LOG(@\"Received low memory warning, cleaning up backlog\");\n    for(Buffer *b in [[BuffersDataSource sharedInstance] getBuffers]) {\n        if(b != self->_buffer && !b.scrolledUp && [[EventsDataSource sharedInstance] highlightStateForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type] == 0)\n            [[EventsDataSource sharedInstance] pruneEventsForBuffer:b.bid maxSize:50];\n    }\n    if(!_buffer.scrolledUp && [[EventsDataSource sharedInstance] highlightStateForBuffer:self->_buffer.bid lastSeenEid:self->_buffer.last_seen_eid type:self->_buffer.type] == 0) {\n        [[EventsDataSource sharedInstance] pruneEventsForBuffer:self->_buffer.bid maxSize:100];\n        [self->_eventsView setBuffer:self->_buffer];\n    }\n    [[ImageCache sharedInstance] clear];\n}\n\n-(IBAction)serverStatusBarPressed:(id)sender {\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n    if(s) {\n        if([s.status isEqualToString:@\"disconnected\"])\n            [[NetworkConnection sharedInstance] reconnect:self->_buffer.cid handler:nil];\n        else if([s.away isKindOfClass:[NSString class]] && s.away.length) {\n            [[NetworkConnection sharedInstance] back:self->_buffer.cid handler:nil];\n            s.away = @\"\";\n            [self _updateServerStatus];\n        }\n    }\n}\n\n-(void)sendButtonPressed:(id)sender {\n    @synchronized(self->_message) {\n        if(self->_message.text && _message.text.length) {\n            id k = ((id (*)(id, SEL)) objc_msgSend)(NSClassFromString(@\"UIKeyboard\"), NSSelectorFromString(@\"activeKeyboard\"));\n            SEL sel = NSSelectorFromString(@\"acceptAutocorrection\");\n            if([k respondsToSelector:sel]) {\n                ((id (*)(id, SEL)) objc_msgSend)(k, sel);\n            }\n            \n            NSAttributedString *messageText = self->_message.attributedText;\n            if([[NSUserDefaults standardUserDefaults] boolForKey:@\"clearFormattingAfterSending\"]) {\n                [self resetColors];\n                if(self->_defaultTextareaFont) {\n                    self->_message.internalTextView.font = self->_defaultTextareaFont;\n                    self->_message.internalTextView.textColor = [UIColor textareaTextColor];\n                    self->_message.internalTextView.typingAttributes = @{NSForegroundColorAttributeName:[UIColor textareaTextColor], NSFontAttributeName:self->_defaultTextareaFont };\n                }\n            }\n            \n            if(messageText.length > 1 && [messageText.string hasSuffix:@\" \"])\n                messageText = [messageText attributedSubstringFromRange:NSMakeRange(0, messageText.length - 1)];\n\n            NSString *messageString = messageText.string;\n            \n            Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n            if(s) {\n                if([messageString isEqualToString:@\"/ignore\"]) {\n                    [self->_message clearText];\n                    self->_buffer.draft = nil;\n                    IgnoresTableViewController *itv = [[IgnoresTableViewController alloc] initWithStyle:UITableViewStylePlain];\n                    itv.ignores = s.ignores;\n                    itv.cid = s.cid;\n                    itv.navigationItem.title = @\"Ignore List\";\n                    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:itv];\n                    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                        nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                    else\n                        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                    [self presentViewController:nc animated:YES completion:nil];\n                    return;\n                } else if([messageString isEqualToString:@\"/clear\"]) {\n                    [self->_message clearText];\n                    self->_buffer.draft = nil;\n                    [[EventsDataSource sharedInstance] removeEventsForBuffer:self->_buffer.bid];\n                    [self->_eventsView refresh];\n                    self->_eventsView.shouldAutoFetch = NO;\n                    return;\n#ifndef APPSTORE\n                } else if([messageString isEqualToString:@\"/crash\"]) {\n                    CLS_LOG(@\"/crash requested\");\n                    assert(NO);\n                } else if([messageString isEqualToString:@\"/compact 1\"]) {\n                    CLS_LOG(@\"Set compact\");\n                    NSMutableDictionary *p = [[NetworkConnection sharedInstance] prefs].mutableCopy;\n                    [p setObject:@YES forKey:@\"ascii-compact\"];\n                    SBJson5Writer *writer = [[SBJson5Writer alloc] init];\n                    NSString *json = [writer stringWithObject:p];\n                    [[NetworkConnection sharedInstance] setPrefs:json handler:nil];\n                    [self->_message clearText];\n                    self->_buffer.draft = nil;\n                    return;\n                } else if([messageString isEqualToString:@\"/compact 0\"]) {\n                    NSMutableDictionary *p = [[NetworkConnection sharedInstance] prefs].mutableCopy;\n                    [p setObject:@NO forKey:@\"ascii-compact\"];\n                    SBJson5Writer *writer = [[SBJson5Writer alloc] init];\n                    NSString *json = [writer stringWithObject:p];\n                    [[NetworkConnection sharedInstance] setPrefs:json handler:nil];\n                    [self->_message clearText];\n                    self->_buffer.draft = nil;\n                    return;\n                } else if([messageString isEqualToString:@\"/mono 1\"]) {\n                    CLS_LOG(@\"Set monospace\");\n                    NSMutableDictionary *p = [[NetworkConnection sharedInstance] prefs].mutableCopy;\n                    [p setObject:@\"mono\" forKey:@\"font\"];\n                    SBJson5Writer *writer = [[SBJson5Writer alloc] init];\n                    NSString *json = [writer stringWithObject:p];\n                    [[NetworkConnection sharedInstance] setPrefs:json handler:nil];\n                    [self->_message clearText];\n                    self->_buffer.draft = nil;\n                    return;\n                } else if([messageString isEqualToString:@\"/mono 0\"]) {\n                    NSMutableDictionary *p = [[NetworkConnection sharedInstance] prefs].mutableCopy;\n                    [p setObject:@\"sans\" forKey:@\"font\"];\n                    SBJson5Writer *writer = [[SBJson5Writer alloc] init];\n                    NSString *json = [writer stringWithObject:p];\n                    [[NetworkConnection sharedInstance] setPrefs:json handler:nil];\n                    [self->_message clearText];\n                    self->_buffer.draft = nil;\n                    return;\n                } else if([messageString hasPrefix:@\"/fontsize \"]) {\n                    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInteger:\n                                                                      MIN(FONT_MAX, MAX(FONT_MIN, ceilf([[messageString substringFromIndex:10] intValue])))\n                                                                      ]\n                                                              forKey:@\"fontSize\"];\n                    if([ColorFormatter shouldClearFontCache]) {\n                        [ColorFormatter clearFontCache];\n                        [ColorFormatter loadFonts];\n                    }\n                    [[EventsDataSource sharedInstance] clearFormattingCache];\n                    [[AvatarsDataSource sharedInstance] invalidate];\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudEventNotification object:nil userInfo:@{kIRCCloudEventKey:[NSNumber numberWithInt:kIRCEventUserInfo]}];\n                    }];\n                    [self->_message clearText];\n                    self->_buffer.draft = nil;\n                    return;\n                } else if([messageString isEqualToString:@\"/read\"]) {\n                    UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:self->_eventsView.YUNoHeartbeat preferredStyle:UIAlertControllerStyleAlert];\n                    [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n                    [self presentViewController:alert animated:YES completion:nil];\n                    [self->_message clearText];\n                    self->_buffer.draft = nil;\n                    return;\n#endif\n                } else if(messageString.length > 1080 || [messageString isEqualToString:@\"/paste\"] || [messageString hasPrefix:@\"/paste \"] || [messageString rangeOfString:@\"\\n\"].location < messageString.length - 1) {\n                    BOOL prompt = YES;\n                    if([[[[NetworkConnection sharedInstance] prefs] objectForKey:@\"pastebin-disableprompt\"] isKindOfClass:[NSNumber class]]) {\n                        prompt = ![[[[NetworkConnection sharedInstance] prefs] objectForKey:@\"pastebin-disableprompt\"] boolValue];\n                    } else {\n                        prompt = YES;\n                    }\n\n                    if(prompt || [messageString isEqualToString:@\"/paste\"] || [messageString hasPrefix:@\"/paste \"]) {\n                        if([messageString isEqualToString:@\"/paste\"])\n                           [self->_message clearText];\n                        else if([messageString hasPrefix:@\"/paste \"])\n                            messageString = [messageString substringFromIndex:7];\n                        self->_buffer.draft = messageString;\n                        PastebinEditorViewController *pv = [[PastebinEditorViewController alloc] initWithBuffer:self->_buffer];\n                        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:pv];\n                        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n                        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                            nc.modalPresentationStyle = UIModalPresentationPageSheet;\n                        else\n                            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n                        if(self.presentedViewController)\n                            [self dismissViewControllerAnimated:NO completion:nil];\n                        [self presentViewController:nc animated:YES completion:nil];\n                        return;\n                    }\n#ifndef APPSTORE\n                } else if([messageString isEqualToString:@\"/buffers\"]) {\n                    [self->_message clearText];\n                    self->_buffer.draft = nil;\n                    NSMutableString *msg = [[NSMutableString alloc] init];\n                    [msg appendString:@\"=== Buffers ===\\n\"];\n                    NSArray *buffers = [[BuffersDataSource sharedInstance] getBuffersForServer:self->_buffer.cid];\n                    for(Buffer *buffer in buffers) {\n                        [msg appendFormat:@\"CID: %i BID: %i Name: %@ lastSeenEID: %f unread: %i highlight: %i extra: %i\\n\", buffer.cid, buffer.bid, buffer.name, buffer.last_seen_eid, [[EventsDataSource sharedInstance] unreadStateForBuffer:buffer.bid lastSeenEid:buffer.last_seen_eid type:buffer.type], [[EventsDataSource sharedInstance] highlightCountForBuffer:buffer.bid lastSeenEid:buffer.last_seen_eid type:buffer.type], buffer.extraHighlights];\n                        NSArray *events = [[EventsDataSource sharedInstance] eventsForBuffer:buffer.bid];\n                        Event *e = [events firstObject];\n                        [msg appendFormat:@\"First event: %f %@\\n\", e.eid, e.type];\n                        e = [events lastObject];\n                        [msg appendFormat:@\"Last event: %f %@\\n\", e.eid, e.type];\n                        [msg appendString:@\"======\\n\"];\n                    }\n                    \n                    CLS_LOG(@\"%@\", msg);\n                    \n                    Event *e = [[Event alloc] init];\n                    e.cid = s.cid;\n                    e.bid = self->_buffer.bid;\n                    e.eid = [[NSDate date] timeIntervalSince1970] * 1000000;\n                    if(e.eid < [[EventsDataSource sharedInstance] lastEidForBuffer:e.bid])\n                        e.eid = [[EventsDataSource sharedInstance] lastEidForBuffer:e.bid] + 1000;\n                    e.isSelf = YES;\n                    e.from = nil;\n                    e.nick = nil;\n                    e.msg = msg;\n                    e.type = @\"buffer_msg\";\n                    e.color = [UIColor timestampColor];\n                    if([self->_buffer.name isEqualToString:s.nick])\n                        e.bgColor = [UIColor whiteColor];\n                    else\n                        e.bgColor = [UIColor selfBackgroundColor];\n                    e.rowType = 0;\n                    e.formatted = nil;\n                    e.formattedMsg = nil;\n                    e.groupMsg = nil;\n                    e.linkify = YES;\n                    e.targetMode = nil;\n                    e.isHighlight = NO;\n                    e.reqId = -1;\n                    e.pending = YES;\n                    [self->_eventsView scrollToBottom];\n                    [[EventsDataSource sharedInstance] addEvent:e];\n                    [self->_eventsView insertEvent:e backlog:NO nextIsGrouped:NO];\n                    return;\n#endif\n                } else if([messageString isEqualToString:@\"/badge\"]) {\n                    [self->_message clearText];\n                    self->_buffer.draft = nil;\n                    [[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray *notifications) {\n                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                            NSMutableString *msg = [[NSMutableString alloc] init];\n                            [msg appendFormat:@\"Notification Center currently has %lu notifications\\n\", (unsigned long)notifications.count];\n                            for(UNNotification *n in notifications) {\n                                NSArray *d = [n.request.content.userInfo objectForKey:@\"d\"];\n                                [msg appendFormat:@\"ID: %@ BID: %i EID: %f\\n\", n.request.identifier, [[d objectAtIndex:1] intValue], [[d objectAtIndex:2] doubleValue]];\n                            }\n                            \n                            for(UNNotification *n in notifications) {\n                                NSArray *d = [n.request.content.userInfo objectForKey:@\"d\"];\n                                Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:[[d objectAtIndex:1] intValue]];\n                                [msg appendFormat:@\"BID %i last_seen_eid: %f extraHighlights: %i\\n\", b.bid, b.last_seen_eid, b.extraHighlights];\n                                if((!b && [NetworkConnection sharedInstance].state == kIRCCloudStateConnected && [NetworkConnection sharedInstance].ready) || [[d objectAtIndex:2] doubleValue] <= b.last_seen_eid) {\n                                    [msg appendFormat:@\"Stale notification: %@\\n\", n.request.identifier];\n                                }\n                            }\n                            \n                            CLS_LOG(@\"%@\", msg);\n                            \n                            Event *e = [[Event alloc] init];\n                            e.cid = s.cid;\n                            e.bid = self->_buffer.bid;\n                            e.eid = [[NSDate date] timeIntervalSince1970] * 1000000;\n                            if(e.eid < [[EventsDataSource sharedInstance] lastEidForBuffer:e.bid])\n                                e.eid = [[EventsDataSource sharedInstance] lastEidForBuffer:e.bid] + 1000;\n                            e.isSelf = YES;\n                            e.from = nil;\n                            e.nick = nil;\n                            e.msg = msg;\n                            e.type = @\"buffer_msg\";\n                            e.color = [UIColor timestampColor];\n                            if([self->_buffer.name isEqualToString:s.nick])\n                                e.bgColor = [UIColor whiteColor];\n                            else\n                                e.bgColor = [UIColor selfBackgroundColor];\n                            e.rowType = 0;\n                            e.formatted = nil;\n                            e.formattedMsg = nil;\n                            e.groupMsg = nil;\n                            e.linkify = YES;\n                            e.targetMode = nil;\n                            e.isHighlight = NO;\n                            e.reqId = -1;\n                            e.pending = YES;\n                            [self->_eventsView scrollToBottom];\n                            [[EventsDataSource sharedInstance] addEvent:e];\n                            [self->_eventsView insertEvent:e backlog:NO nextIsGrouped:NO];\n                        }];\n                    }];\n                    return;\n                }\n                \n                User *u = [[UsersDataSource sharedInstance] getUser:s.nick cid:s.cid bid:self->_buffer.bid];\n                Event *e = [[Event alloc] init];\n                NSMutableString *msg = messageString.mutableCopy;\n                NSMutableString *formattedMsg = s.isSlack?messageString.mutableCopy:[ColorFormatter toIRC:messageText].mutableCopy;\n                \n                BOOL disableConvert = [[NetworkConnection sharedInstance] prefs] && [[[[NetworkConnection sharedInstance] prefs] objectForKey:@\"emoji-disableconvert\"] boolValue];\n                if(!disableConvert)\n                    [ColorFormatter emojify:formattedMsg];\n                \n                if([msg hasPrefix:@\"//\"])\n                    [msg deleteCharactersInRange:NSMakeRange(0, 1)];\n                else if([msg hasPrefix:@\"/\"] && ![[msg lowercaseString] hasPrefix:@\"/me \"])\n                    msg = nil;\n                if(msg) {\n                    e.cid = s.cid;\n                    e.bid = self->_buffer.bid;\n                    e.eid = ([[NSDate date] timeIntervalSince1970] + [NetworkConnection sharedInstance].clockOffset) * 1000000;\n                    if(e.eid < [[EventsDataSource sharedInstance] lastEidForBuffer:e.bid])\n                        e.eid = [[EventsDataSource sharedInstance] lastEidForBuffer:e.bid] + 1000;\n                    e.isSelf = YES;\n                    e.from = s.from;\n                    e.nick = s.nick;\n                    e.fromNick = s.nick;\n                    e.avatar = s.avatar;\n                    e.avatarURL = s.avatarURL;\n                    e.hostmask = s.usermask;\n                    if(u)\n                        e.fromMode = u.mode;\n                    e.msg = formattedMsg;\n                    if(msg && [[msg lowercaseString] hasPrefix:@\"/me \"]) {\n                        e.type = @\"buffer_me_msg\";\n                        e.msg = [formattedMsg substringFromIndex:4];\n                    } else {\n                        e.type = @\"buffer_msg\";\n                    }\n                    e.color = [UIColor timestampColor];\n                    e.bgColor = [UIColor selfBackgroundColor];\n                    e.rowType = 0;\n                    e.formatted = nil;\n                    e.formattedMsg = nil;\n                    e.groupMsg = nil;\n                    e.linkify = YES;\n                    e.targetMode = nil;\n                    e.isHighlight = NO;\n                    e.reqId = -1;\n                    e.pending = YES;\n                    e.realname = s.server_realname;\n                    [[EventsDataSource sharedInstance] addEvent:e];\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n#ifndef APPSTORE\n                        CLS_LOG(@\"Scrolling down after sending a message\");\n#endif\n                        [self->_eventsView scrollToBottom];\n                        [self->_eventsView insertEvent:e backlog:NO nextIsGrouped:NO];\n                    }];\n                }\n                e.to = self->_buffer.name;\n                e.command = formattedMsg;\n                if(e.msg)\n                    [self->_pendingEvents addObject:e];\n                [self->_message clearText];\n                self->_buffer.draft = nil;\n                msg = e.command.mutableCopy;\n                if(!disableConvert)\n                    [ColorFormatter emojify:msg];\n                if(self->_msgid) {\n                    e.isReply = YES;\n                    e.entities = @{@\"reply\":self->_msgid};\n                    e.reqId = [[NetworkConnection sharedInstance] reply:msg to:self->_buffer.name cid:self->_buffer.cid msgid:self->_msgid handler:^(IRCCloudJSONObject *result) {\n                        if(![[result objectForKey:@\"success\"] boolValue]) {\n                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                                [self->_pendingEvents removeObject:e];\n                                e.entities = @{@\"reply\":self->_msgid};\n                                e.height = 0;\n                                e.pending = NO;\n                                e.rowType = ROW_FAILED;\n                                e.color = [UIColor networkErrorColor];\n                                e.bgColor = [UIColor errorBackgroundColor];\n                                e.formatted = nil;\n                                e.height = 0;\n                                [e.expirationTimer invalidate];\n                                e.expirationTimer = nil;\n                                [self->_eventsView reloadData];\n                            }];\n                        }\n                    }];\n                } else {\n                    e.reqId = [[NetworkConnection sharedInstance] say:msg to:self->_buffer.name cid:self->_buffer.cid handler:^(IRCCloudJSONObject *result) {\n                        if(![[result objectForKey:@\"success\"] boolValue]) {\n                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                                [self->_pendingEvents removeObject:e];\n                                e.height = 0;\n                                e.pending = NO;\n                                e.rowType = ROW_FAILED;\n                                e.color = [UIColor networkErrorColor];\n                                e.bgColor = [UIColor errorBackgroundColor];\n                                e.formatted = nil;\n                                e.height = 0;\n                                [e.expirationTimer invalidate];\n                                e.expirationTimer = nil;\n                                [self->_eventsView reloadData];\n                            }];\n                        }\n                    }];\n                }\n                if(e.reqId < 0)\n                    e.expirationTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(_sendRequestDidExpire:) userInfo:e repeats:NO];\n                CLS_LOG(@\"Sending message with reqid %i\", e.reqId);\n            }\n        }\n    }\n}\n\n-(void)_sendRequestDidExpire:(NSTimer *)timer {\n    Event *e = timer.userInfo;\n    e.expirationTimer = nil;\n    if([self->_pendingEvents containsObject:e]) {\n        [self->_pendingEvents removeObject:e];\n        e.height = 0;\n        e.pending = NO;\n        e.rowType = ROW_FAILED;\n        e.color = [UIColor networkErrorColor];\n        e.bgColor = [UIColor errorBackgroundColor];\n        e.formatted = nil;\n        e.height = 0;\n        [self->_eventsView reloadData];\n    }\n}\n\n-(void)nickSelected:(NSString *)nick {\n    self->_message.selectedRange = NSMakeRange(0, 0);\n    NSString *text = self->_message.text;\n    BOOL isChannel = NO;\n    \n    for(Channel *channel in _sortedChannels) {\n        if([nick isEqualToString:channel.name]) {\n            isChannel = YES;\n            break;\n        }\n    }\n    \n    if(self->_updateSuggestionsTask.atMention || (!_updateSuggestionsTask.isEmoji && _buffer.serverIsSlack))\n        nick = [NSString stringWithFormat:@\"@%@\", nick];\n\n    if(!isChannel && !_buffer.serverIsSlack && ![text hasPrefix:@\":\"] && [text rangeOfString:@\" \"].location == NSNotFound)\n        nick = [nick stringByAppendingString:@\": \"];\n    else\n        nick = [nick stringByAppendingString:@\" \"];\n    \n    if(text.length == 0) {\n        self->_message.text = nick;\n    } else {\n        while(text.length > 0 && [text characterAtIndex:text.length - 1] != ' ') {\n            text = [text substringToIndex:text.length - 1];\n        }\n        text = [text stringByAppendingString:nick];\n        self->_message.text = text;\n    }\n    \n}\n\n-(void)updateSuggestions:(BOOL)force {\n    if(self->_updateSuggestionsTask)\n        [self->_updateSuggestionsTask cancel];\n    \n    self->_updateSuggestionsTask = [[UpdateSuggestionsTask alloc] init];\n    self->_updateSuggestionsTask.message = self->_message;\n    self->_updateSuggestionsTask.buffer = self->_buffer;\n    self->_updateSuggestionsTask.nickCompletionView = self->_nickCompletionView;\n    self->_updateSuggestionsTask.force = force;\n    \n    [self->_updateSuggestionsTask performSelectorInBackground:@selector(run) withObject:nil];\n}\n\n-(void)_updateSuggestionsTimer {\n    self->_nickCompletionTimer = nil;\n    [self updateSuggestions:NO];\n}\n\n-(void)scheduleSuggestionsTimer {\n    if(self->_nickCompletionTimer)\n        [self->_nickCompletionTimer invalidate];\n    self->_nickCompletionTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(_updateSuggestionsTimer) userInfo:nil repeats:NO];\n}\n\n-(void)cancelSuggestionsTimer {\n    if(self->_nickCompletionTimer)\n        [self->_nickCompletionTimer invalidate];\n    self->_nickCompletionTimer = nil;\n}\n\n-(void)_updateTypingIndicatorTimer {\n    NSMutableString *typing = nil;\n\n    [self->_buffer purgeExpiredTypingIndicators];\n    \n    NSUInteger count = self->_buffer.typingIndicators.count;\n    if (count > 5) {\n        typing = [NSString stringWithFormat:@\"%lu people are typing\", (unsigned long)count].mutableCopy;\n    } else if (count == 1) {\n        typing = [NSString stringWithFormat:@\"%@ is typing\", self->_buffer.typingIndicators.allKeys.firstObject].mutableCopy;\n    } else if (count > 0) {\n        typing = [[NSMutableString alloc] init];\n        int i = 0;\n        for (NSString *from in self->_buffer.typingIndicators.allKeys) {\n            if (++i == count)\n                [typing appendString:@\"and \"];\n            [typing appendString:from];\n            if(count != 2 && i > 0 && i < count)\n                [typing appendString:@\",\"];\n            [typing appendString:@\" \"];\n        }\n        [typing appendString:@\"are typing\"];\n    }\n    \n#ifdef DEBUG\n    if([[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"]) {\n        typing = @\"ike and kira are typing\";\n    }\n#endif\n    \n    self->_typingIndicator.text = typing;\n    \n    if(count && !self->_typingIndicatorTimer)\n        [self scheduleTypingIndicatorTimer];\n\n    if(!count && self->_typingIndicatorTimer)\n        [self cancelTypingIndicatorTimer];\n}\n\n-(void)scheduleTypingIndicatorTimer {\n    if(self->_typingIndicatorTimer)\n        [self->_typingIndicatorTimer invalidate];\n    self->_typingIndicatorTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(_updateTypingIndicatorTimer) userInfo:nil repeats:YES];\n}\n\n-(void)cancelTypingIndicatorTimer {\n    if(self->_typingIndicatorTimer)\n        [self->_typingIndicatorTimer invalidate];\n    self->_typingIndicatorTimer = nil;\n}\n\n\n-(void)_updateMessageWidth {\n    self->_message.animateHeightChange = NO;\n    BOOL dirty = NO;\n    CGFloat messageWidth;\n    \n    if(self->_message.text.length > 0) {\n        messageWidth = self->_eventsViewWidthConstraint.constant - _sendBtn.frame.size.width - _message.frame.origin.x - _uploadsBtn.frame.origin.x - 16;\n    } else {\n        messageWidth = self->_eventsViewWidthConstraint.constant - _settingsBtn.frame.size.width - _message.frame.origin.x - _uploadsBtn.frame.origin.x - 16;\n    }\n    messageWidth -= self.slidingViewController.view.window.safeAreaInsets.right;\n\n    if(self->_message.text.length > 0) {\n        if(self->_messageWidthConstraint.constant != messageWidth) {\n            self->_messageWidthConstraint.constant = messageWidth;\n            [self.view layoutIfNeeded];\n            dirty = YES;\n        }\n        if(self->_sendBtn.alpha != 1) {\n            self->_sendBtn.enabled = YES;\n            self->_sendBtn.alpha = 1;\n            self->_settingsBtn.enabled = NO;\n            self->_settingsBtn.alpha = 0;\n        }\n    } else {\n        if(self->_messageWidthConstraint.constant != messageWidth) {\n            self->_messageWidthConstraint.constant = messageWidth;\n            [self.view layoutIfNeeded];\n            dirty = YES;\n        }\n        if(self->_sendBtn.alpha != 0) {\n            self->_sendBtn.enabled = NO;\n            self->_sendBtn.alpha = 0;\n            self->_settingsBtn.enabled = YES;\n            self->_settingsBtn.alpha = 1;\n            self->_message.delegate = nil;\n            [self->_message clearText];\n            self->_message.delegate = self;\n        }\n    }\n    self->_message.animateHeightChange = YES;\n    \n    if(dirty || self->_messageHeightConstraint.constant != self->_message.frame.size.height) {\n        self->_messageHeightConstraint.constant = self->_message.frame.size.height;\n        self->_bottomBarHeightConstraint.constant = self->_message.frame.size.height + 12 + 16;\n        CGRect frame = self->_settingsBtn.frame;\n        frame.origin.x = self->_eventsViewWidthConstraint.constant - _settingsBtn.frame.size.width - 10 - self.slidingViewController.view.window.safeAreaInsets.right;\n        self->_settingsBtn.frame = frame;\n        frame = self->_sendBtn.frame;\n        frame.origin.x = self->_eventsViewWidthConstraint.constant - _sendBtn.frame.size.width - 8 - self.slidingViewController.view.window.safeAreaInsets.right;\n        self->_sendBtn.frame = frame;\n        [self _updateEventsInsets];\n        [self.view layoutIfNeeded];\n    }\n}\n\n-(BOOL)expandingTextView:(UIExpandingTextView *)expandingTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {\n    self->_textIsChanging = YES;\n    if(range.location == expandingTextView.text.length) {\n        self->_currentMessageAttributes = expandingTextView.internalTextView.typingAttributes;\n    } else {\n        self->_currentMessageAttributes = nil;\n    }\n    return YES;\n}\n\n-(void)expandingTextViewDidChange:(UIExpandingTextView *)expandingTextView {\n    if(!_textIsChanging)\n        self->_currentMessageAttributes = expandingTextView.internalTextView.typingAttributes;\n    else\n        expandingTextView.internalTextView.typingAttributes = self->_currentMessageAttributes;\n    self->_textIsChanging = NO;\n    [self.view layoutIfNeeded];\n    [UIView beginAnimations:nil context:nil];\n    [self _updateMessageWidth];\n    [self.view layoutIfNeeded];\n    [UIView commitAnimations];\n    if(self->_nickCompletionView.alpha == 1) {\n        [self updateSuggestions:NO];\n    } else {\n        [self performSelectorOnMainThread:@selector(scheduleSuggestionsTimer) withObject:nil waitUntilDone:NO];\n    }\n    UIColor *c = ([NetworkConnection sharedInstance].state == kIRCCloudStateConnected)?([UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor unreadBlueColor]):[UIColor textareaBackgroundColor];\n    [self->_sendBtn setTitleColor:c forState:UIControlStateNormal];\n    [self->_sendBtn setTitleColor:c forState:UIControlStateDisabled];\n    [self->_sendBtn setTitleColor:c forState:UIControlStateHighlighted];\n    \n    if(!self->_handoffTimer)\n        self->_handoffTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(_updateHandoffTimer) userInfo:nil repeats:NO];\n    \n    if(![self->_buffer.type isEqualToString:@\"console\"] && expandingTextView.text.length && [NetworkConnection sharedInstance].prefs) {\n        BOOL disableTypingStatus = [[[[NetworkConnection sharedInstance].prefs objectForKey:[self->_buffer.type isEqualToString:@\"channel\"]?@\"channel-disableTypingStatus\":@\"buffer-disableTypingStatus\"] objectForKey:[NSString stringWithFormat:@\"%i\",self->_buffer.bid]] boolValue] || [[[NetworkConnection sharedInstance].prefs objectForKey:@\"disableTypingStatus\"] intValue] == 1;\n        if([[[[NetworkConnection sharedInstance].prefs objectForKey:[self->_buffer.type isEqualToString:@\"channel\"]?@\"channel-enableTypingStatus\":@\"buffer-enableTypingStatus\"] objectForKey:[NSString stringWithFormat:@\"%i\",self->_buffer.bid]] boolValue])\n            disableTypingStatus = NO;\n        \n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        if(!s.hasMessageTags)\n            disableTypingStatus = YES;\n        \n        if(s.blocksTyping)\n            disableTypingStatus = YES;\n        \n        if([_buffer.type isEqualToString:@\"channel\"] && ![[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid])\n            disableTypingStatus = YES;\n        \n        if(self->_lastTypingTime > 0 && [NSDate date].timeIntervalSince1970 - self->_lastTypingTime < 3)\n            disableTypingStatus = YES;\n\n        if(!disableTypingStatus && !self->_typingTimer) {\n            self->_lastTypingTime = [NSDate date].timeIntervalSince1970;\n            self->_typingTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(sendTyping) userInfo:nil repeats:NO];\n        }\n    }\n}\n\n-(void)sendTyping {\n    [[NetworkConnection sharedInstance] typing:@\"active\" cid:self->_buffer.cid to:self->_buffer.name handler:nil];\n    self->_typingTimer = nil;\n}\n\n-(void)_cancelHandoffTimer {\n    if(self->_handoffTimer)\n        [self->_handoffTimer invalidate];\n    _handoffTimer = nil;\n}\n\n-(void)_updateHandoffTimer {\n    _handoffTimer = nil;\n    [[self userActivity] setNeedsSave:YES];\n    [self userActivityWillSave:[self userActivity]];\n    if(self->_buffer) {\n        self->_buffer.draft = _message.text.length ? _message.text : nil;\n    }\n}\n\n-(BOOL)expandingTextViewShouldReturn:(UIExpandingTextView *)expandingTextView {\n    [self sendButtonPressed:expandingTextView];\n    return NO;\n}\n\n-(void)expandingTextView:(UIExpandingTextView *)expandingTextView willChangeHeight:(float)height {\n    if(expandingTextView.frame.size.height != height) {\n        [self.view layoutIfNeeded];\n        self->_messageHeightConstraint.constant = height;\n        [self.view layoutIfNeeded];\n        [self updateLayout];\n    }\n}\n\n-(void)_updateTitleArea {\n    NSString *sceneTitle = nil;\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n    self->_lock.hidden = YES;\n    self->_titleLabel.textColor = [UIColor navBarHeadingColor];\n    self->_topicLabel.textColor = [UIColor navBarSubheadingColor];\n    if([self->_buffer.type isEqualToString:@\"console\"]) {\n        if(s.name.length)\n            self->_titleLabel.text = s.name;\n        else\n            self->_titleLabel.text = s.hostname;\n        self->_titleLabel.accessibilityLabel = @\"Server\";\n        self->_titleLabel.accessibilityValue = self->_titleLabel.text;\n        self.navigationItem.title = self->_titleLabel.text;\n        self->_topicLabel.hidden = NO;\n        self->_titleLabel.font = [UIFont boldSystemFontOfSize:18];\n        self->_topicLabel.text = [NSString stringWithFormat:@\"%@:%i\", s.hostname, s.port];\n        self->_lock.hidden = NO;\n        if(s.isSlack)\n            self->_lock.text = FA_SLACK;\n        else if(s.ssl > 0)\n            self->_lock.text = FA_SHIELD;\n        else\n            self->_lock.text = FA_GLOBE;\n        self->_lock.textColor = [UIColor navBarHeadingColor];\n        if(s)\n            sceneTitle = [NSString stringWithFormat:@\"%@\", s.name.length?s.name:s.hostname];\n    } else {\n        self.navigationItem.title = self->_titleLabel.text = self->_buffer.displayName;\n        self->_titleLabel.font = [UIFont boldSystemFontOfSize:20];\n        self->_titleLabel.accessibilityValue = self->_buffer.accessibilityValue;\n        self->_topicLabel.hidden = YES;\n        self->_lock.text = FA_LOCK;\n        self->_lock.textColor = [UIColor navBarHeadingColor];\n        if([self->_buffer.type isEqualToString:@\"channel\"]) {\n            self->_titleLabel.accessibilityLabel = self->_buffer.isMPDM ? @\"Conversation with\" : @\"Channel\";\n            BOOL lock = NO;\n            Channel *channel = [[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid];\n            if(channel) {\n                if(channel.key || (self->_buffer.serverIsSlack && !_buffer.isMPDM && [channel hasMode:@\"s\"]))\n                    lock = YES;\n                if([channel.topic_text isKindOfClass:[NSString class]] && channel.topic_text.length) {\n                    self->_topicLabel.hidden = NO;\n                    self->_titleLabel.font = [UIFont boldSystemFontOfSize:18];\n                    self->_topicLabel.text = [channel.topic_text stripIRCFormatting];\n                    self->_topicLabel.accessibilityLabel = @\"Topic\";\n                    self->_topicLabel.accessibilityValue = self->_topicLabel.text;\n                } else {\n                    self->_topicLabel.hidden = YES;\n                }\n            }\n            if(lock) {\n                self->_lock.hidden = NO;\n            } else {\n                self->_lock.hidden = YES;\n            }\n        } else if([self->_buffer.type isEqualToString:@\"conversation\"]) {\n            self->_titleLabel.accessibilityLabel = @\"Conversation with\";\n            self.navigationItem.title = self->_titleLabel.text = self->_buffer.name;\n            self->_topicLabel.hidden = NO;\n            self->_titleLabel.font = [UIFont boldSystemFontOfSize:18];\n            if(self->_buffer.away_msg.length) {\n                self->_topicLabel.text = [NSString stringWithFormat:@\"Away: %@\", _buffer.away_msg];\n            } else {\n                User *u = [[UsersDataSource sharedInstance] getUser:self->_buffer.name cid:self->_buffer.cid];\n                if(u && u.away) {\n                    if(u.away_msg.length)\n                        self->_topicLabel.text = [NSString stringWithFormat:@\"Away: %@\", u.away_msg];\n                    else\n                        self->_topicLabel.text = @\"Away\";\n                } else {\n                    Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n                    if(s.name.length)\n                        self->_topicLabel.text = s.name;\n                    else\n                        self->_topicLabel.text = s.hostname;\n                }\n            }\n        }\n        if(s && _buffer)\n            sceneTitle = [NSString stringWithFormat:@\"%@ | %@\", _buffer.displayName, s.name.length?s.name:s.hostname];\n    }\n    if(self->_msgid) {\n        self->_topicLabel.text = self->_titleLabel.text;\n        self->_topicLabel.hidden = NO;\n        self->_titleLabel.text = @\"Thread\";\n        self->_titleLabel.font = [UIFont boldSystemFontOfSize:18];\n        self->_lock.hidden = YES;\n        self->_titleLabel.accessibilityLabel = @\"Thread from\";\n        self->_titleLabel.accessibilityValue = self->_topicLabel.text;\n    }\n    if(self->_lock.hidden == NO && _lock.alpha == 1)\n        self->_titleOffsetXConstraint.constant = self->_lock.frame.size.width / 2;\n    else\n        self->_titleOffsetXConstraint.constant = 0;\n    if(self->_topicLabel.hidden == NO && _topicLabel.alpha == 1)\n        self->_titleOffsetYConstraint.constant = -10;\n    else\n        self->_titleOffsetYConstraint.constant = 0;\n    [self->_titleView setNeedsUpdateConstraints];\n    \n    if (@available(iOS 13.0, *)) {\n        if(sceneTitle && self->_sceneTitleExtra.length)\n            sceneTitle = [self->_sceneTitleExtra stringByAppendingString:sceneTitle];\n        UIScene *scene = [(AppDelegate *)[UIApplication sharedApplication].delegate sceneForWindow:self.view.window];\n        scene.title = sceneTitle ? sceneTitle : @\"IRCCloud\";\n    }\n}\n\n-(void)showJoinPrompt:(NSString *)channel server:(Server *)s {\n    if(channel && s) {\n        NSString *key = nil;\n        NSRange range = [channel rangeOfString:@\",\"];\n        if(range.location != NSNotFound) {\n            key = [channel substringFromIndex:range.location + 1];\n            channel = [channel substringToIndex:range.location];\n        }\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Join A Channel\" message:[NSString stringWithFormat:@\"Would you like to join the channel %@ on %@?\", channel, s.name.length?s.name:s.hostname] preferredStyle:UIAlertControllerStyleAlert];\n        \n        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Join\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n            [[NetworkConnection sharedInstance] join:channel key:key cid:s.cid handler:nil];\n        }]];\n        \n        [self presentViewController:alert animated:YES completion:nil];\n    }\n}\n\n-(void)launchURL:(NSURL *)url {\n    self->_urlToOpen = nil;\n    if([url.path hasPrefix:@\"/log-export/\"]) {\n        LogExportsTableViewController *lvc;\n        \n        if([self.presentedViewController isKindOfClass:[UINavigationController class]] && [((UINavigationController *)self.presentedViewController).topViewController isKindOfClass:[LogExportsTableViewController class]]) {\n            lvc = (LogExportsTableViewController *)(((UINavigationController *)self.presentedViewController).topViewController);\n        } else {\n            lvc = [[LogExportsTableViewController alloc] initWithStyle:UITableViewStyleGrouped];\n            lvc.buffer = self->_buffer;\n            lvc.server = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n            UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:lvc];\n            [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n            if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                nc.modalPresentationStyle = UIModalPresentationFormSheet;\n            else\n                nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n            [self presentViewController:nc animated:YES completion:nil];\n        }\n        [lvc download:url];\n        return;\n    }\n    \n    if([url.path hasPrefix:@\"/irc/\"] && url.pathComponents.count >= 4) {\n        NSString *network = [[url.pathComponents objectAtIndex:2] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];\n        NSString *type = [url.pathComponents objectAtIndex:3];\n        if([type isEqualToString:@\"channel\"] || [type isEqualToString:@\"messages\"]) {\n            NSString *name = [[url.pathComponents objectAtIndex:4] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];\n            \n            if(name) {\n                for(Server *s in [[ServersDataSource sharedInstance] getServers]) {\n                    NSString *serverHost = [s.hostname lowercaseString];\n                    if([serverHost hasPrefix:@\"irc.\"])\n                        serverHost = [serverHost substringFromIndex:4];\n                    serverHost = [serverHost stringByReplacingOccurrencesOfString:@\"_\" withString:@\"-\"];\n                    \n                    NSString *serverName = [s.name lowercaseString];\n                    serverName = [serverName stringByReplacingOccurrencesOfString:@\"_\" withString:@\"-\"];\n\n                    if([network isEqualToString:serverHost] || [network isEqualToString:serverName]) {\n                        for(Buffer *b in [[BuffersDataSource sharedInstance] getBuffersForServer:s.cid]) {\n                            if(([type isEqualToString:@\"channel\"] && [b.type isEqualToString:@\"channel\"]) || ([type isEqualToString:@\"messages\"] && [b.type isEqualToString:@\"conversation\"])) {\n                                NSString *bufferName = b.name;\n                                \n                                if([b.type isEqualToString:@\"channel\"]) {\n                                    if([bufferName hasPrefix:@\"#\"])\n                                        bufferName = [bufferName substringFromIndex:1];\n                                    if(![bufferName isEqualToString:[b accessibilityValue]])\n                                        bufferName = b.name;\n                                }\n                                \n                                if([bufferName isEqualToString:name]) {\n                                    [self bufferSelected:b.bid];\n                                    return;\n                                }\n                            }\n                        }\n                        if([type isEqualToString:@\"channel\"])\n                            [self showJoinPrompt:name server:s];\n                        else if([type isEqualToString:@\"messages\"])\n                            [[NetworkConnection sharedInstance] say:[NSString stringWithFormat:@\"/query %@\", name] to:nil cid:s.cid handler:nil];\n                    }\n                }\n            }\n        }\n        return;\n    }\n\n    if(self.presentedViewController)\n        [self dismissViewControllerAnimated:NO completion:nil];\n    \n    if([url.host isEqualToString:@\"youtu.be\"] || [url.host hasSuffix:@\"youtube.com\"]) {\n        YouTubeViewController *yvc = [[YouTubeViewController alloc] initWithURL:url];\n        yvc.modalPresentationStyle = UIModalPresentationCustom;\n        [self presentViewController:yvc animated:NO completion:nil];\n        return;\n    }\n    \n    int port = [url.port intValue];\n    int ssl = [url.scheme hasSuffix:@\"s\"]?1:0;\n    BOOL match = NO;\n    kIRCCloudState state = [NetworkConnection sharedInstance].state;\n    \n    if([url.host intValue] > 0 && url.path && url.path.length > 1) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:[url.host intValue]];\n        if(s != nil) {\n            match = YES;\n            NSString *channel = [[url.path stringByRemovingPercentEncoding] substringFromIndex:1];\n            Buffer *b = [[BuffersDataSource sharedInstance] getBufferWithName:channel server:s.cid];\n            if([b.type isEqualToString:@\"channel\"] && ![[ChannelsDataSource sharedInstance] channelForBuffer:b.bid])\n                b = nil;\n            if(b)\n                [self bufferSelected:b.bid];\n            else if(channel && state == kIRCCloudStateConnected)\n                [self showJoinPrompt:channel server:s];\n            else\n                match = NO;\n        }\n    }\n    \n    if(!match) {\n        for(Server *s in [[ServersDataSource sharedInstance] getServers]) {\n            if([[s.hostname lowercaseString] isEqualToString:[url.host lowercaseString]])\n                match = YES;\n            if(port > 0 && port != 6667 && port != s.port)\n                match = NO;\n            if(ssl == 1 && !s.ssl)\n                match = NO;\n            if(match) {\n                if(url.path && url.path.length > 1) {\n                    NSString *channel = [url.path substringFromIndex:1];\n                    Buffer *b = [[BuffersDataSource sharedInstance] getBufferWithName:channel server:s.cid];\n                    if([b.type isEqualToString:@\"channel\"] && ![[ChannelsDataSource sharedInstance] channelForBuffer:b.bid])\n                        b = nil;\n                    if(b)\n                        [self bufferSelected:b.bid];\n                    else if(channel && state == kIRCCloudStateConnected)\n                        [self showJoinPrompt:channel server:s];\n                    else\n                        match = NO;\n                } else {\n                    Buffer *b = [[BuffersDataSource sharedInstance] getBufferWithName:@\"*\" server:s.cid];\n                    if(b)\n                        [self bufferSelected:b.bid];\n                    else\n                        match = NO;\n                }\n                break;\n            }\n        }\n    }\n\n    if(!match) {\n        if(state == kIRCCloudStateConnected) {\n            EditConnectionViewController *evc = [[EditConnectionViewController alloc] initWithStyle:UITableViewStyleGrouped];\n            [evc setURL:url];\n            UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:evc];\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n            [self.navigationController presentViewController:nc animated:YES completion:nil];\n        } else {\n            self->_urlToOpen = url;\n        }\n    }\n}\n\n-(void)bufferSelected:(int)bid {\n    [self performSelectorOnMainThread:@selector(cancelSuggestionsTimer) withObject:nil waitUntilDone:NO];\n    [self performSelectorOnMainThread:@selector(_cancelHandoffTimer) withObject:nil waitUntilDone:NO];\n    _sortedChannels = nil;\n    _sortedUsers = nil;\n    BOOL changed = (self->_buffer && _buffer.bid != bid) || !_buffer;\n    if(self->_buffer && _buffer.bid != bid && _bidToOpen != bid) {\n        self->_eidToOpen = -1;\n    }\n\n    if(changed) {\n        [[EventsDataSource sharedInstance] pruneEventsForBuffer:bid maxSize:500];\n\n        [self resetColors];\n        self->_msgid = self->_eventsView.msgid = nil;\n        if(self->_defaultTextareaFont) {\n            self->_message.internalTextView.font = self->_defaultTextareaFont;\n            self->_message.internalTextView.textColor = [UIColor textareaTextColor];\n            self->_message.internalTextView.typingAttributes = @{NSForegroundColorAttributeName:[UIColor textareaTextColor], NSFontAttributeName:self->_defaultTextareaFont };\n        }\n        if(self->_typingTimer) {\n            [self->_typingTimer invalidate];\n            self->_typingTimer = nil;\n        }\n    }\n    \n    Buffer *lastBuffer = self->_buffer;\n    self->_buffer = [[BuffersDataSource sharedInstance] getBuffer:bid];\n    if(lastBuffer && changed) {\n        if([NetworkConnection sharedInstance].prefs) {\n            BOOL enabled = [[[[NetworkConnection sharedInstance].prefs objectForKey:[lastBuffer.type isEqualToString:@\"channel\"]?@\"channel-enableReadOnSelect\":@\"buffer-enableReadOnSelect\"] objectForKey:[NSString stringWithFormat:@\"%i\",lastBuffer.bid]] boolValue] || [[[NetworkConnection sharedInstance].prefs objectForKey:@\"enableReadOnSelect\"] intValue] == 1;\n            if([[[[NetworkConnection sharedInstance].prefs objectForKey:[lastBuffer.type isEqualToString:@\"channel\"]?@\"channel-disableReadOnSelect\":@\"buffer-disableReadOnSelect\"] objectForKey:[NSString stringWithFormat:@\"%i\",lastBuffer.bid]] boolValue])\n                enabled = NO;\n            \n            if(enabled) {\n                NSArray *events = [[EventsDataSource sharedInstance] eventsForBuffer:lastBuffer.bid];\n                NSTimeInterval eid = 0;\n                Event *last;\n                for(NSInteger i = events.count - 1; i >= 0; i--) {\n                    last = [events objectAtIndex:i];\n                    if(!last.pending && last.rowType != ROW_LASTSEENEID)\n                        break;\n                }\n                if(!last.pending) {\n                    eid = last.eid;\n                }\n                if(eid >= 0 && eid >= lastBuffer.last_seen_eid) {\n                    [[NetworkConnection sharedInstance] heartbeat:self->_buffer.bid cid:lastBuffer.cid bid:lastBuffer.bid lastSeenEid:eid handler:nil];\n                    lastBuffer.last_seen_eid = eid;\n                }\n            }\n        }\n        self->_buffer.lastBuffer = lastBuffer;\n        self->_buffer.nextBuffer = nil;\n        lastBuffer.draft = self->_message.text.length ? _message.text : nil;\n        [self showTwoSwipeTip];\n    }\n    if(self->_buffer) {\n        if(self->_incomingDraft) {\n            if(changed) {\n                self->_buffer.draft = self->_incomingDraft;\n            } else {\n                [self->_message setText:self->_incomingDraft];\n            }\n            self->_incomingDraft = nil;\n        }\n        if(self->_buffer.cid == self->_cidToOpen)\n            self->_cidToOpen = -1;\n        else if(self->_cidToOpen > 0)\n            CLS_LOG(@\"cid%i selected, but was waiting for cid%i\", self->_buffer.cid, self->_cidToOpen);\n        if(self->_buffer.bid == self->_bidToOpen)\n            self->_bidToOpen = -1;\n        else if(self->_bidToOpen > 0)\n            CLS_LOG(@\"bid%i selected, but was waiting for bid%i\", self->_buffer.bid, self->_bidToOpen);\n        self->_eidToOpen = -1;\n        self->_bufferToOpen = nil;\n        CLS_LOG(@\"BID selected: cid%i bid%i\", _buffer.cid, bid);\n        NSArray *events = [[EventsDataSource sharedInstance] eventsForBuffer:self->_buffer.bid];\n        for(Event *event in events) {\n            if(event.isHighlight) {\n                User *u = [[UsersDataSource sharedInstance] getUser:event.from cid:event.cid bid:event.bid];\n                if(u && u.lastMention < event.eid) {\n                    u.lastMention = event.eid;\n                }\n            }\n        }\n        [[NetworkConnection sharedInstance] setLastSelectedBID:bid];\n        [[NSUserDefaults standardUserDefaults] setObject:@(bid) forKey:@\"last_selected_bid\"];\n        [[NSUserDefaults standardUserDefaults] synchronize];\n        NSUserActivity *activity = [self userActivity];\n        if(![activity.activityType hasSuffix:@\".buffer\"]) {\n            [activity invalidate];\n#ifdef ENTERPRISE\n            activity = [[NSUserActivity alloc] initWithActivityType: @\"com.irccloud.enterprise.buffer\"];\n#else\n            activity = [[NSUserActivity alloc] initWithActivityType: @\"com.irccloud.buffer\"];\n#endif\n            activity.delegate = self;\n            [self setUserActivity:activity];\n        }\n        [activity setNeedsSave:YES];\n        [self userActivityWillSave:activity];\n        [activity becomeCurrent];\n    } else {\n        CLS_LOG(@\"BID selected but not found: bid%i\", bid);\n    }\n    \n    [self _updateTitleArea];\n    [self->_buffersView setBuffer:self->_buffer];\n    self->_eventsView.eidToOpen = self->_eidToOpen;\n    [UIView animateWithDuration:0.1 animations:^{\n        self->_eventsView.stickyAvatar.alpha = 0;\n        self->_eventsView.tableView.alpha = 0;\n        self->_eventsView.topUnreadView.alpha = 0;\n        self->_eventsView.bottomUnreadView.alpha = 0;\n        self->_eventActivity.alpha = 1;\n        [self->_eventActivity startAnimating];\n        if(changed) {\n            NSString *draft = self->_buffer.draft.length ? self->_buffer.draft : nil;\n            self->_message.delegate = nil;\n            [self->_message clearText];\n            self->_message.delegate = self;\n            self->_buffer.draft = draft;\n        }\n    } completion:^(BOOL finished){\n        [self->_eventsView setBuffer:self->_buffer];\n        [UIView animateWithDuration:0.1 animations:^{\n            self->_eventsView.stickyAvatar.alpha = 1;\n            self->_eventsView.tableView.alpha = 1;\n            self->_eventActivity.alpha = 0;\n            if(changed) {\n                self->_message.delegate = nil;\n                self->_message.text = self->_buffer.draft;\n                self->_message.delegate = self;\n            }\n        } completion:^(BOOL finished){\n            [self->_eventActivity stopAnimating];\n        }];\n    }];\n    [self->_usersView setBuffer:self->_buffer];\n    [self _updateUserListVisibility];\n    [self _updateServerStatus];\n    [self.slidingViewController resetTopView];\n    [self performSelectorInBackground:@selector(_updateUnreadIndicator) withObject:nil];\n    [self updateSuggestions:NO];\n    [self _updateTypingIndicatorTimer];\n    self->_lastTypingTime = 0;\n    \n    if([[ServersDataSource sharedInstance] getServer:self->_buffer.cid].isSlack) {\n        [UIMenuController sharedMenuController].menuItems = @[];\n        [self resetColors];\n        self->_message.internalTextView.allowsEditingTextAttributes = NO;\n    } else {\n        [UIMenuController sharedMenuController].menuItems = @[[[UIMenuItem alloc] initWithTitle:@\"Paste With Style\" action:@selector(pasteRich:)],\n                                                              [[UIMenuItem alloc] initWithTitle:@\"Color\" action:@selector(chooseFGColor)],\n                                                              [[UIMenuItem alloc] initWithTitle:@\"Background\" action:@selector(chooseBGColor)],\n                                                              [[UIMenuItem alloc] initWithTitle:@\"Reset Colors\" action:@selector(resetColors)],\n                                                              ];\n        self->_message.internalTextView.allowsEditingTextAttributes = YES;\n    }\n#ifdef DEBUG\n    if([[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"] && [[NSProcessInfo processInfo].arguments containsObject:@\"-memberlist\"]) {\n        [self.slidingViewController performSelector:@selector(anchorTopViewTo:) withObject:nil afterDelay:0.5];\n    }\n#endif\n}\n\n-(void)userActivityWasContinued:(NSUserActivity *)userActivity {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        [self->_message clearText];\n    }];\n}\n\n-(void)userActivityWillSave:(NSUserActivity *)activity {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n#ifndef ENTERPRISE\n    NSString *draft_escaped = self->_message.text?self->_message.text:@\"\";\n    draft_escaped = [draft_escaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n    if([self->_buffer.type isEqualToString:@\"console\"]) {\n        if(self->_message.text.length)\n            activity.webpageURL = [NSURL URLWithString:[NSString stringWithFormat:@\"https://www.irccloud.com/#?/text=%@&url=%@%@:%i\", draft_escaped, s.ssl?@\"ircs://\":@\"\", s.hostname, s.port]];\n        else\n            activity.webpageURL = [NSURL URLWithString:[NSString stringWithFormat:@\"https://www.irccloud.com/!%@%@:%i\", s.ssl?@\"ircs://\":@\"\", s.hostname, s.port]];\n        activity.title = s.hostname;\n    } else {\n        if(self->_message.text.length)\n            activity.webpageURL = [NSURL URLWithString:[NSString stringWithFormat:@\"https://www.irccloud.com/#?/text=%@&url=%@%@:%i/%@\", draft_escaped, s.ssl?@\"ircs://\":@\"\", s.hostname, s.port, [self->_buffer.name stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]]];\n        else\n            activity.webpageURL = [NSURL URLWithString:[NSString stringWithFormat:@\"https://www.irccloud.com/#!/%@%@:%i/%@\", s.ssl?@\"ircs://\":@\"\", s.hostname, s.port, [self->_buffer.name stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]]];\n        activity.title = self->_buffer.name;\n    }\n#endif\n        [activity addUserInfoEntriesFromDictionary:@{@\"bid\":@(self->_buffer.bid), @\"cid\":@(self->_buffer.cid), @\"draft\":(self->_message.text?self->_message.text:@\"\")}];\n        activity.eligibleForPrediction = YES;\n        activity.persistentIdentifier = [NSString stringWithFormat:@\"%i.%i\", self->_buffer.cid, self->_buffer.bid];\n        [activity becomeCurrent];\n    }];\n}\n\n-(void)_updateGlobalMsg {\n    if([NetworkConnection sharedInstance].globalMsg.length) {\n        self->_globalMsgContainer.hidden = NO;\n        self->_globalMsg.userInteractionEnabled = YES;\n        NSString *msg = [NetworkConnection sharedInstance].globalMsg;\n        msg = [msg stringByReplacingOccurrencesOfString:@\"<b>\" withString:[NSString stringWithFormat:@\"%c\", BOLD]];\n        msg = [msg stringByReplacingOccurrencesOfString:@\"</b>\" withString:[NSString stringWithFormat:@\"%c\", BOLD]];\n        msg = [msg stringByReplacingOccurrencesOfString:@\"<strong>\" withString:[NSString stringWithFormat:@\"%c\", BOLD]];\n        msg = [msg stringByReplacingOccurrencesOfString:@\"</strong>\" withString:[NSString stringWithFormat:@\"%c\", BOLD]];\n        msg = [msg stringByReplacingOccurrencesOfString:@\"<i>\" withString:[NSString stringWithFormat:@\"%c\", ITALICS]];\n        msg = [msg stringByReplacingOccurrencesOfString:@\"</i>\" withString:[NSString stringWithFormat:@\"%c\", ITALICS]];\n        msg = [msg stringByReplacingOccurrencesOfString:@\"<u>\" withString:[NSString stringWithFormat:@\"%c\", UNDERLINE]];\n        msg = [msg stringByReplacingOccurrencesOfString:@\"</u>\" withString:[NSString stringWithFormat:@\"%c\", UNDERLINE]];\n        msg = [msg stringByReplacingOccurrencesOfString:@\"<br>\" withString:@\"\\n\"];\n        msg = [msg stringByReplacingOccurrencesOfString:@\"<br/>\" withString:@\"\\n\"];\n        \n        NSArray *links;\n        NSMutableAttributedString *s = (NSMutableAttributedString *)[ColorFormatter format:msg defaultColor:[UIColor blackColor] mono:NO linkify:YES server:nil links:&links];\n        \n        NSMutableParagraphStyle *p = [[NSMutableParagraphStyle alloc] init];\n        p.alignment = NSTextAlignmentCenter;\n        [s addAttribute:NSParagraphStyleAttributeName value:p range:NSMakeRange(0, [s length])];\n\n        self->_globalMsg.textColor = [UIColor messageTextColor];\n        self->_globalMsg.attributedText = s;\n        for(NSTextCheckingResult *result in links) {\n            if(result.resultType == NSTextCheckingTypeLink) {\n                [self->_globalMsg addLinkWithTextCheckingResult:result];\n            }\n        }\n        self->_topUnreadBarYOffsetConstraint.constant = self->_globalMsg.intrinsicContentSize.height + 12;\n        [self.view layoutIfNeeded];\n    } else {\n        self->_globalMsgContainer.hidden = YES;\n        self->_topUnreadBarYOffsetConstraint.constant = 0;\n    }\n    [self _updateEventsInsets];\n}\n\n-(IBAction)globalMsgPressed:(id)sender {\n    [NetworkConnection sharedInstance].globalMsg = nil;\n    [self _updateGlobalMsg];\n}\n\n-(void)_updateServerStatus {\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n    if(s && (![s.status isEqualToString:@\"connected_ready\"] || ([s.away isKindOfClass:[NSString class]] && s.away.length))) {\n        if(self->_serverStatusBar.hidden) {\n            self->_serverStatusBar.hidden = NO;\n        }\n        self->_serverStatusBar.backgroundColor = [UIColor connectionBarColor];\n        self->_serverStatus.textColor = [UIColor connectionBarTextColor];\n        self->_serverStatus.font = [UIFont systemFontOfSize:FONT_SIZE];\n        if([s.status isEqualToString:@\"connected_ready\"]) {\n            if([s.away isKindOfClass:[NSString class]]) {\n                self->_serverStatusBar.backgroundColor = [UIColor awayBarColor];\n                self->_serverStatus.textColor = [UIColor awayBarTextColor];\n                if(![[s.away lowercaseString] isEqualToString:@\"away\"]) {\n                    self->_serverStatus.text = [NSString stringWithFormat:@\"Away (%@). Tap to come back.\", s.away];\n                } else {\n                    self->_serverStatus.text = @\"Away. Tap to come back.\";\n                }\n            }\n        } else if([s.status isEqualToString:@\"quitting\"]) {\n            self->_serverStatus.text = @\"Disconnecting\";\n        } else if([s.status isEqualToString:@\"disconnected\"]) {\n            NSString *type = [s.fail_info objectForKey:@\"type\"];\n            if([type isKindOfClass:[NSString class]] && [type length]) {\n                NSString *reason = [s.fail_info objectForKey:@\"reason\"];\n                if([type isEqualToString:@\"killed\"]) {\n                    self->_serverStatus.text = [NSString stringWithFormat:@\"Disconnected - Killed: %@\", reason];\n                } else if([type isEqualToString:@\"connecting_restricted\"]) {\n                    self->_serverStatus.text = [EventsDataSource reason:reason];\n                    if([self->_serverStatus.text isEqualToString:reason])\n                        self->_serverStatus.text = @\"You can’t connect to this server with a free account.\";\n                } else if([type isEqualToString:@\"connection_blocked\"]) {\n                    self->_serverStatus.text = @\"Disconnected - Connections to this server have been blocked\";\n                } else {\n                    if([reason isKindOfClass:[NSString class]] && [reason length] && [reason isEqualToString:@\"ssl_verify_error\"])\n                        self->_serverStatus.text = [NSString stringWithFormat:@\"Strict transport security error: %@\", [EventsDataSource SSLreason:[s.fail_info objectForKey:@\"ssl_verify_error\"]]];\n                    else\n                        self->_serverStatus.text = [NSString stringWithFormat:@\"Disconnected: %@\", [EventsDataSource reason:reason]];\n                }\n                self->_serverStatusBar.backgroundColor = [UIColor connectionErrorBarColor];\n                self->_serverStatus.textColor = [UIColor connectionErrorBarTextColor];\n            } else {\n                self->_serverStatus.text = @\"Disconnected. Tap to reconnect.\";\n            }\n        } else if([s.status isEqualToString:@\"queued\"]) {\n            self->_serverStatus.text = @\"Connection Queued\";\n        } else if([s.status isEqualToString:@\"connecting\"]) {\n            self->_serverStatus.text = @\"Connecting\";\n        } else if([s.status isEqualToString:@\"connected\"]) {\n            self->_serverStatus.text = @\"Connected\";\n        } else if([s.status isEqualToString:@\"connected_joining\"]) {\n            self->_serverStatus.text = @\"Connected: Joining Channels\";\n        } else if([s.status isEqualToString:@\"pool_unavailable\"]) {\n            self->_serverStatus.text = @\"Connection temporarily unavailable\";\n            self->_serverStatusBar.backgroundColor = [UIColor connectionErrorBarColor];\n            self->_serverStatus.textColor = [UIColor connectionErrorBarTextColor];\n        } else if([s.status isEqualToString:@\"waiting_to_retry\"]) {\n            double seconds = ([[s.fail_info objectForKey:@\"timestamp\"] doubleValue] + [[s.fail_info objectForKey:@\"retry_timeout\"] intValue]) - [[NSDate date] timeIntervalSince1970];\n            if(seconds > 0) {\n                NSString *reason = [EventsDataSource reason:[s.fail_info objectForKey:@\"reason\"]];\n                NSString *text = @\"Disconnected\";\n                if([reason isKindOfClass:[NSString class]] && [reason length])\n                    text = [text stringByAppendingFormat:@\": %@, \", reason];\n                else\n                    text = [text stringByAppendingString:@\"; \"];\n                text = [text stringByAppendingFormat:@\"Reconnecting in %i seconds.\", (int)seconds];\n                self->_serverStatus.text = text;\n                self->_serverStatusBar.backgroundColor = [UIColor connectionErrorBarColor];\n                self->_serverStatus.textColor = [UIColor connectionErrorBarTextColor];\n            } else {\n                self->_serverStatus.text = @\"Ready to connect.  Waiting our turn…\";\n            }\n            [self performSelector:@selector(_updateServerStatus) withObject:nil afterDelay:0.5];\n        } else if([s.status isEqualToString:@\"ip_retry\"]) {\n            self->_serverStatus.text = @\"Trying another IP address\";\n        } else {\n            CLS_LOG(@\"Unhandled server status: %@\", s.status);\n        }\n        self->_bottomUnreadBarYOffsetConstraint.constant = self->_serverStatus.intrinsicContentSize.height + 12;\n    } else {\n        if(!_serverStatusBar.hidden) {\n            self->_serverStatusBar.hidden = YES;\n        }\n        self->_bottomUnreadBarYOffsetConstraint.constant = 0;\n    }\n    [self _updateEventsInsets];\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    if(self.slidingViewController.view.window.safeAreaInsets.bottom) {\n        return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeRight;\n    }\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(BOOL)prefersStatusBarHidden {\n    if (@available(iOS 14.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp) {\n            return YES;\n        }\n    }\n    return UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) && [UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPad;\n}\n\n-(void)statusBarFrameWillChange:(NSNotification *)n {\n    if(self.slidingViewController.view.window.safeAreaInsets.bottom)\n        return;\n    CGRect newFrame = [[n.userInfo objectForKey:UIApplicationStatusBarFrameUserInfoKey] CGRectValue];\n    if(newFrame.size.width > 0 && newFrame.size.width == [UIApplication sharedApplication].statusBarFrame.size.width) {\n        [UIView animateWithDuration:0.25f animations:^{\n            [self updateLayout:newFrame.size.height];\n        }];\n    }\n}\n\n-(void)viewSafeAreaInsetsDidChange {\n    [super viewSafeAreaInsetsDidChange];\n    [self performSelector:@selector(updateLayout) withObject:nil afterDelay:0.25];\n}\n\n-(void)updateLayout {\n    BOOL scrolledUp = _buffer.scrolledUp;\n    [UIApplication sharedApplication].statusBarHidden = self.prefersStatusBarHidden;\n    \n    if(self.view.window.bounds.size.height == [UIScreen mainScreen].bounds.size.height && self.slidingViewController.view.window.safeAreaInsets.top != self.slidingViewController.view.safeAreaInsets.top) {\n        NSLog(@\"Insets mismatch\");\n        UIWindow *w = self.slidingViewController.view.window;\n        w.rootViewController = nil;\n        w.rootViewController = self.slidingViewController;\n    }\n    \n    [UIColor setSafeInsets:self.slidingViewController.view.window.safeAreaInsets];\n    if(self.slidingViewController.view.window.safeAreaInsets.bottom)\n        [self updateLayout:0];\n    else\n        [self updateLayout:[UIApplication sharedApplication].statusBarFrame.size.height];\n    CGPoint contentOffset = _eventsView.tableView.contentOffset;\n    [self.slidingViewController adjustLayout];\n    [self.slidingViewController.view layoutIfNeeded];\n    if(!scrolledUp)\n        [self->_eventsView _scrollToBottom];\n    else\n        [self->_eventsView.tableView setContentOffset:contentOffset];\n}\n\n-(void)updateLayout:(float)sbHeight {\n    CGRect frame = self.slidingViewController.view.frame;\n    if(sbHeight >= 20 && [[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPad)\n        frame.origin.y = (sbHeight - 20);\n\n    frame.size = self.slidingViewController.view.window.bounds.size;\n\n    if(frame.size.width > 0 && frame.size.height > 0) {\n        if(sbHeight > 20 && [[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPad)\n            frame.size.height -= sbHeight;\n        \n        self.slidingViewController.view.frame = frame;\n        [self.slidingViewController updateUnderLeftLayout];\n        [self.slidingViewController updateUnderRightLayout];\n        [self transitionToSize:frame.size];\n    }\n}\n\n-(void)transitionToSize:(CGSize)size {\n    BOOL isCatalyst = NO;\n    if (@available(iOS 13.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp)\n            isCatalyst = YES;\n    }\n    CLS_LOG(@\"Transitioning to size: %f, %f\", size.width, size.height);\n    _ignoreInsetChanges = YES;\n    CGPoint center = self.slidingViewController.view.window.center;\n    if(self.slidingViewController.underLeftShowing)\n        center.x += self->_buffersView.tableView.frame.size.width;\n    if(self.slidingViewController.underRightShowing)\n        center.x -= self->_buffersView.tableView.frame.size.width;\n    \n    self.navigationController.view.frame = self.slidingViewController.view.window.bounds;\n    self.navigationController.view.center = center;\n    self.navigationController.view.layer.position = self.navigationController.view.center;\n\n    self->_bottomBarHeightConstraint.constant = self->_message.frame.size.height + 12 + 16;\n    self->_eventsViewHeightConstraint.constant = self.slidingViewController.view.frame.size.height - self.navigationController.navigationBar.frame.size.height - self.slidingViewController.view.window.safeAreaInsets.top - self.slidingViewController.view.window.safeAreaInsets.bottom;\n    \n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"tabletMode\"] && size.width > size.height\n       - (isCatalyst ? 78 : 0)\n       && (isCatalyst || size.width == [UIScreen mainScreen].bounds.size.width)\n       && ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad || [[UIDevice currentDevice] isBigPhone])) {\n        int buffersViewWidth = [[UIDevice currentDevice] isBigPhone]?200:240;\n        self->_borders.hidden = NO;\n        self->_eventsViewWidthConstraint.constant = self.view.frame.size.width - buffersViewWidth - 1;\n        self->_eventsViewOffsetLeftConstraint.constant = buffersViewWidth + 1;\n        self->_connectingXOffsetConstraint.constant = buffersViewWidth + 1;\n        self->_topicXOffsetConstraint.constant = buffersViewWidth + 1;\n        self.navigationItem.leftBarButtonItem = nil;\n        self.navigationItem.rightBarButtonItem = nil;\n        self.slidingViewController.underLeftViewController = nil;\n        if(self->_buffersView.view.superview != self.navigationController.navigationBar.superview) {\n            [self->_buffersView willMoveToParentViewController:self.navigationController];\n            [self->_buffersView viewWillAppear:NO];\n            self->_buffersView.view.hidden = NO;\n            [self.navigationController.navigationBar.superview addSubview:self->_buffersView.view];\n            self->_buffersView.view.autoresizingMask = UIViewAutoresizingNone;\n        }\n#if TARGET_OS_MACCATALYST\n        self->_buffersView.view.frame = CGRectMake(0,self.slidingViewController.view.window.safeAreaInsets.top,buffersViewWidth,self.slidingViewController.view.frame.size.height - self.slidingViewController.view.window.safeAreaInsets.top);\n#else\n        self->_buffersView.view.frame = CGRectMake(0,0,buffersViewWidth,self.slidingViewController.view.frame.size.height);\n#endif\n        [self.navigationController.navigationBar.superview bringSubviewToFront:self->_buffersView.view];\n        self.navigationController.view.center = self.slidingViewController.view.center;\n    } else {\n        self->_borders.hidden = YES;\n        self->_eventsViewWidthConstraint.constant = size.width + self.slidingViewController.view.window.safeAreaInsets.left / 2;\n        self->_eventsViewOffsetLeftConstraint.constant = self.slidingViewController.view.window.safeAreaInsets.left / 2;\n        self->_connectingXOffsetConstraint.constant = 0;\n        self->_topicXOffsetConstraint.constant = 0;\n        if(!self.slidingViewController.underLeftViewController)\n            self.slidingViewController.underLeftViewController = self->_buffersView;\n        if(!self.navigationItem.leftBarButtonItem)\n            self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self->_menuBtn];\n        [self.slidingViewController updateUnderLeftLayout];\n        [self.slidingViewController updateUnderRightLayout];\n    }\n    self->_buffersView.view.backgroundColor = [UIColor buffersDrawerBackgroundColor];\n    CGRect frame = self->_titleView.frame;\n    if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {\n        frame.size.height = (size.width > size.height)?24:40;\n        self->_topicLabel.alpha = (size.width > size.height)?0:1;\n    }\n    self->_topicWidthConstraint.constant = frame.size.width = size.width - 128 - self->_topicXOffsetConstraint.constant;\n    frame.size.width -= self.slidingViewController.view.window.safeAreaInsets.left;\n    frame.size.width -= self.slidingViewController.view.window.safeAreaInsets.right;\n    self->_topicWidthConstraint.constant -= self.slidingViewController.view.window.safeAreaInsets.left;\n    self->_topicWidthConstraint.constant -= self.slidingViewController.view.window.safeAreaInsets.right;\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"tabletMode\"] && [[UIDevice currentDevice] isBigPhone] && (size.width > size.height))\n        frame.size.width -= self->_buffersView.tableView.frame.size.width;\n    self->_connectingView.frame = self->_titleView.frame = frame;\n\n    [self _updateUserListVisibility];\n    [self.view layoutIfNeeded];\n\n    [self _updateTitleArea];\n    [self _updateServerStatus];\n    [self _updateGlobalMsg];\n    [self _updateTypingIndicatorTimer];\n    \n    [self.view layoutIfNeeded];\n    \n    //Re-calculate the expanding text view height for the new layout width\n    if(_previousWidth != size.width)\n        _message.text = _message.text;\n    \n    UIView *v = self.navigationItem.titleView;\n    self.navigationItem.titleView = nil;\n    self.navigationItem.titleView = v;\n    self.navigationController.view.layer.shadowPath = nil;\n    \n    _leftBorder.frame = CGRectMake(-1,0,1,size.height);\n    _rightBorder.frame = CGRectMake(size.width + 1,0,1,size.height);\n\n    _ignoreInsetChanges = NO;\n    [self _updateEventsInsets];\n    _previousWidth = size.width;\n}\n\n-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {\n    if(self->_eventsView.topUnreadView.observationInfo) {\n        @try {\n            [self->_eventsView.topUnreadView removeObserver:self forKeyPath:@\"alpha\"];\n            [self->_eventsView.tableView.layer removeObserver:self forKeyPath:@\"bounds\"];\n        } @catch(id anException) {\n            //Not registered yet\n        }\n    }\n    [self->_eventsView viewWillResize];\n    self->_eventActivity.alpha = 1;\n    [self->_eventActivity startAnimating];\n    [self.slidingViewController resetTopView];\n    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];\n    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n        [UIApplication sharedApplication].statusBarHidden = self.prefersStatusBarHidden;\n        [self transitionToSize:size];\n    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n        self->_eventActivity.alpha = 0;\n        [self->_eventActivity stopAnimating];\n        if(self->_eventsView.topUnreadView.observationInfo) {\n            @try {\n                [self->_eventsView.topUnreadView removeObserver:self forKeyPath:@\"alpha\"];\n                [self->_eventsView.tableView.layer removeObserver:self forKeyPath:@\"bounds\"];\n            } @catch(id anException) {\n                //Not registered yet\n            }\n        }\n        [UIColor setTheme];\n        [self updateLayout];\n        [self->_eventsView viewDidResize];\n        [self->_eventsView.topUnreadView addObserver:self forKeyPath:@\"alpha\" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];\n        [self->_eventsView.tableView.layer addObserver:self forKeyPath:@\"bounds\" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];\n    }];\n}\n\n-(void)_updateEventsInsets {\n    if(_ignoreInsetChanges)\n        return;\n    self->_bottomBarOffsetConstraint.constant = self->_kbSize.height;\n    if(self.slidingViewController.view.window.safeAreaInsets.bottom) {\n        if(UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) || _kbSize.height > 0)\n            self->_bottomBarOffsetConstraint.constant -= self.slidingViewController.view.window.safeAreaInsets.bottom/2;\n        if(self.slidingViewController.view.window.safeAreaInsets.top >= 51) //iPhone 14 with Dynamic Island returns the wrong bottom safe area inset\n            self->_bottomBarOffsetConstraint.constant -= 12;\n    }\n    CGFloat height = self->_bottomBarHeightConstraint.constant + _kbSize.height;\n    CGFloat top = 0;\n    if(!_globalMsgContainer.hidden)\n        top += self->_globalMsgContainer.frame.size.height;\n    if(self->_eventsView.topUnreadView.alpha > 0)\n        top += self->_eventsView.topUnreadView.frame.size.height;\n    if(!_serverStatusBar.hidden)\n        height += self->_serverStatusBar.bounds.size.height;\n    if(UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation))\n        height -= self.slidingViewController.view.window.safeAreaInsets.bottom/2;\n    CGFloat diff = height - _eventsView.tableView.contentInset.bottom;\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        CGFloat bottom = self->_kbSize.height + self.slidingViewController.view.window.safeAreaInsets.bottom;\n        if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))\n            bottom += self.slidingViewController.view.window.safeAreaInsets.top;\n        if(@available(iOS 14, *)) {\n            self->_buffersView.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0,0,0,0);\n            self->_usersView.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0,0,0,0);\n        } else if(@available(iOS 13, *)) {\n        } else {\n            self->_buffersView.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0,0,bottom,0);\n            self->_usersView.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0,0,bottom,0);\n        }\n        self->_buffersView.tableView.contentInset = UIEdgeInsetsZero;\n        if(self->_buffersView.tableView.adjustedContentInset.bottom > 0) { //Sometimes iOS 11 automatically adds the keyboard padding even though I told it not to\n            bottom -= self->_buffersView.tableView.adjustedContentInset.bottom;\n        }\n        self->_buffersView.tableView.contentInset = UIEdgeInsetsMake(0,0,bottom,0);\n        self->_usersView.tableView.contentInset = UIEdgeInsetsMake(0,0,bottom,0);\n    }];\n\n    if(!_isShowingPreview && (self->_eventsView.tableView.contentInset.top != top || _eventsView.tableView.contentInset.bottom != height)) {\n        [self->_eventsView.tableView setContentInset:UIEdgeInsetsMake(top, 0, height, 0)];\n        [self->_eventsView.tableView setScrollIndicatorInsets:UIEdgeInsetsMake(top, 0, height, 0)];\n\n        if(self->_eventsView.tableView.contentSize.height > (self->_eventsView.tableView.frame.size.height - _eventsView.tableView.contentInset.top - _eventsView.tableView.contentInset.bottom)) {\n#ifndef APPSTORE\n            CLS_LOG(@\"Adjusting content offset after changing insets\");\n#endif\n            if(floorf(self->_eventsView.tableView.contentOffset.y + diff + (self->_eventsView.tableView.frame.size.height - _eventsView.tableView.contentInset.top - _eventsView.tableView.contentInset.bottom)) >= floorf(self->_eventsView.tableView.contentSize.height)) {\n                if(!_buffer.scrolledUp)\n                    [self->_eventsView _scrollToBottom];\n#ifndef APPSTORE\n                else\n                    CLS_LOG(@\"Buffer was scrolled up, ignoring\");\n#endif\n            } else if(diff > 0 || _buffer.scrolledUp)\n                self->_eventsView.tableView.contentOffset = CGPointMake(0, _eventsView.tableView.contentOffset.y + diff);\n        }\n    }\n}\n\n-(void)refresh {\n    [self->_buffersView refresh];\n    [self->_eventsView refresh];\n    [self->_usersView refresh];\n    [self _updateTitleArea];\n    [self performSelectorInBackground:@selector(_updateUnreadIndicator) withObject:nil];\n}\n\n-(void)setMsgId:(NSString *)msgId {\n    self->_eventsView.msgid = self->_msgid = msgId;\n    [self->_eventsView refresh];\n    [self _updateTitleArea];\n    [self _updateUserListVisibility];\n}\n\n-(void)clearMsgId {\n    self->_eventsView.msgid = self->_msgid = nil;\n}\n\n-(void)_closeThread {\n    [self setMsgId:nil];\n}\n\n-(void)_updateUserListVisibility {\n    BOOL isCatalyst = NO;\n    if (@available(iOS 13.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp)\n            isCatalyst = YES;\n    }\n    /*if(![NSThread currentThread].isMainThread) {\n        [self performSelectorOnMainThread:@selector(_updateUserListVisibility) withObject:nil waitUntilDone:YES];\n        return;\n    }*/\n    if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && ![[UIDevice currentDevice] isBigPhone]) {\n        if(self->_msgid) {\n            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(_closeThread)];\n            self.slidingViewController.underRightViewController = nil;\n        } else if([self->_buffer.type isEqualToString:@\"channel\"] && [[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid]) {\n            self.navigationItem.rightBarButtonItem = self->_usersButtonItem;\n            if(self.slidingViewController.underRightViewController == nil)\n                self.slidingViewController.underRightViewController = self->_usersView;\n        } else {\n            self.navigationItem.rightBarButtonItem = nil;\n            self.slidingViewController.underRightViewController = nil;\n        }\n    } else {\n        if(self.view.bounds.size.width > self.view.bounds.size.height\n           && (isCatalyst || self.view.bounds.size.width == [UIScreen mainScreen].bounds.size.width)\n           && [[NSUserDefaults standardUserDefaults] boolForKey:@\"tabletMode\"] && ![[NSUserDefaults standardUserDefaults] boolForKey:@\"hiddenMembers\"]) {\n            if([self->_buffer.type isEqualToString:@\"channel\"] && [[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid] && !([NetworkConnection sharedInstance].prefs && [[[[NetworkConnection sharedInstance].prefs objectForKey:@\"channel-hiddenMembers\"] objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] boolValue]) && ![[UIDevice currentDevice] isBigPhone] && !self->_msgid) {\n                self.navigationItem.rightBarButtonItem = nil;\n                if(self.slidingViewController.underRightViewController) {\n                    self.slidingViewController.underRightViewController = nil;\n                    [self addChildViewController:self->_usersView];\n                    [self->_usersView willMoveToParentViewController:self];\n                    [self->_usersView viewWillAppear:NO];\n                    self->_usersView.view.autoresizingMask = UIViewAutoresizingNone;\n                }\n                self->_usersView.view.frame = CGRectMake(self.view.frame.size.width - 200,0,200,self.view.frame.size.height);\n                self->_usersView.view.hidden = NO;\n                if(self->_usersView.view.superview != self.view)\n                    [self.view insertSubview:self->_usersView.view atIndex:1];\n                self->_eventsViewWidthConstraint.constant = self.view.frame.size.width - self->_buffersView.view.frame.size.width - 202;\n            } else {\n                if(self->_msgid) {\n                    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(_closeThread)];\n                    self.slidingViewController.underRightViewController = nil;\n                    self->_usersView.view.hidden = YES;\n                } else if([self->_buffer.type isEqualToString:@\"channel\"] && [[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid]) {\n                    self.navigationItem.rightBarButtonItem = self->_usersButtonItem;\n                    if(self.slidingViewController.underRightViewController == nil) {\n                        [self->_usersView.view removeFromSuperview];\n                        [self->_usersView removeFromParentViewController];\n                        CGRect frame = self->_usersView.view.frame;\n                        frame.origin.x = 0;\n                        frame.size.width = 220;\n                        self->_usersView.view.frame = frame;\n                        self.slidingViewController.underRightViewController = self->_usersView;\n                    }\n                    self->_usersView.view.hidden = NO;\n                } else {\n                    self.navigationItem.rightBarButtonItem = nil;\n                    self.slidingViewController.underRightViewController = nil;\n                    self->_usersView.view.hidden = YES;\n                }\n                self->_eventsViewWidthConstraint.constant = self.view.frame.size.width - self->_buffersView.tableView.frame.size.width - 2;\n                self->_eventsViewWidthConstraint.constant += self.slidingViewController.view.window.safeAreaInsets.right;\n                if(self.slidingViewController.underRightViewController) {\n                    self->_eventsViewWidthConstraint.constant++;\n                }\n            }\n        } else {\n            if(self->_msgid) {\n                self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(_closeThread)];\n                self.slidingViewController.underRightViewController = nil;\n            } else if([self->_buffer.type isEqualToString:@\"channel\"] && [[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid]) {\n                self.navigationItem.rightBarButtonItem = self->_usersButtonItem;\n                if(self.slidingViewController.underRightViewController == nil)\n                    self.slidingViewController.underRightViewController = self->_usersView;\n            } else {\n                self.navigationItem.rightBarButtonItem = nil;\n                self.slidingViewController.underRightViewController = nil;\n            }\n        }\n    }\n    [self _updateMessageWidth];\n    [self->_message updateConstraints];\n    [self.view layoutIfNeeded];\n}\n\n-(void)showMentionTip {\n    [self->_mentionTip.superview bringSubviewToFront:self->_mentionTip];\n\n    if(![[NSUserDefaults standardUserDefaults] boolForKey:@\"mentionTip\"]) {\n        [[NSUserDefaults standardUserDefaults] setObject:@YES forKey:@\"mentionTip\"];\n        [UIView animateWithDuration:0.5 animations:^{\n            self->_mentionTip.alpha = 1;\n        } completion:^(BOOL finished){\n            [self performSelector:@selector(hideMentionTip) withObject:nil afterDelay:2];\n        }];\n    }\n}\n\n-(void)hideMentionTip {\n    [UIView animateWithDuration:0.5 animations:^{\n        self->_mentionTip.alpha = 0;\n    } completion:nil];\n}\n\n-(void)didSwipe:(NSNotification *)n {\n    [[NSUserDefaults standardUserDefaults] setObject:@YES forKey:@\"swipeTip\"];\n    if([n.name isEqualToString:ECSlidingViewUnderLeftWillAppear]) {\n        UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, [self->_buffersView.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]);\n        self.view.accessibilityElementsHidden = YES;\n        [self->_buffersView viewWillAppear:YES];\n    } else if([n.name isEqualToString:ECSlidingViewUnderRightWillAppear]) {\n        UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, [self->_usersView.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]);\n        self.view.accessibilityElementsHidden = YES;\n    } else {\n        UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, _titleLabel);\n        self.view.accessibilityElementsHidden = NO;\n        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{\n            [self->_buffersView viewWillDisappear:NO];\n        });\n    }\n}\n\n-(void)showSwipeTip {\n    [self->_swipeTip.superview bringSubviewToFront:self->_swipeTip];\n    \n    if(![[NSUserDefaults standardUserDefaults] boolForKey:@\"swipeTip\"]) {\n        [[NSUserDefaults standardUserDefaults] setObject:@YES forKey:@\"swipeTip\"];\n        [UIView animateWithDuration:0.5 animations:^{\n            self->_swipeTip.alpha = 1;\n        } completion:^(BOOL finished){\n            [self performSelector:@selector(hideSwipeTip) withObject:nil afterDelay:2];\n        }];\n    }\n}\n\n-(void)hideSwipeTip {\n    [UIView animateWithDuration:0.5 animations:^{\n        self->_swipeTip.alpha = 0;\n    } completion:nil];\n}\n\n-(void)showTwoSwipeTip {\n    [_2swipeTip.superview bringSubviewToFront:self->_2swipeTip];\n    \n    if(![[NSUserDefaults standardUserDefaults] boolForKey:@\"twoSwipeTip\"]) {\n        [[NSUserDefaults standardUserDefaults] setObject:@YES forKey:@\"twoSwipeTip\"];\n        [UIView animateWithDuration:0.5 animations:^{\n            self->_2swipeTip.alpha = 1;\n        } completion:^(BOOL finished){\n            [self performSelector:@selector(hideTwoSwipeTip) withObject:nil afterDelay:2];\n        }];\n    }\n}\n\n-(void)hideTwoSwipeTip {\n    [UIView animateWithDuration:0.5 animations:^{\n        self->_2swipeTip.alpha = 0;\n    } completion:nil];\n}\n\n-(void)usersButtonPressed:(id)sender {\n    [self showSwipeTip];\n    [self.slidingViewController anchorTopViewTo:ECLeft];\n}\n\n-(void)listButtonPressed:(id)sender {\n    [self showSwipeTip];\n    [self.slidingViewController anchorTopViewTo:ECRight];\n}\n\n-(IBAction)settingsButtonPressed:(id)sender {\n    [self dismissKeyboard];\n    self->_selectedBuffer = self->_buffer;\n    self->_selectedUser = nil;\n    self->_selectedEvent = nil;\n    User *me = [[UsersDataSource sharedInstance] getUser:[[ServersDataSource sharedInstance] getServer:self->_buffer.cid].nick cid:self->_buffer.cid bid:self->_buffer.bid];\n\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];\n    if (@available(iOS 13, *)) {\n        alert.overrideUserInterfaceStyle = self.view.overrideUserInterfaceStyle;\n    }\n\n    void (^handler)(UIAlertAction *action) = ^(UIAlertAction *a) {\n        [self actionSheetActionClicked:a.title];\n    };\n    \n    [self _addPinAction:alert buffer:self->_buffer];\n    \n    if([self->_buffer.type isEqualToString:@\"console\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        if([s.status isEqualToString:@\"disconnected\"]) {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Reconnect\" style:UIAlertActionStyleDefault handler:handler]];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDefault handler:handler]];\n        } else {\n            //[sheet addButtonWithTitle:@\"Identify Nickname…\"];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Disconnect\" style:UIAlertActionStyleDefault handler:handler]];\n        }\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Edit Connection\" style:UIAlertActionStyleDefault handler:handler]];\n    } else if([self->_buffer.type isEqualToString:@\"channel\"]) {\n        if([[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid]) {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Leave\" style:UIAlertActionStyleDefault handler:handler]];\n            if([me.mode rangeOfString:@\"q\"].location != NSNotFound || [me.mode rangeOfString:@\"a\"].location != NSNotFound || [me.mode rangeOfString:@\"o\"].location != NSNotFound) {\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ban List\" style:UIAlertActionStyleDefault handler:handler]];\n            }\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Invite to Channel\" style:UIAlertActionStyleDefault handler:handler]];\n        } else {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Rejoin\" style:UIAlertActionStyleDefault handler:handler]];\n            [alert addAction:[UIAlertAction actionWithTitle:(self->_buffer.archived)?@\"Unarchive\":@\"Archive\" style:UIAlertActionStyleDefault handler:handler]];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Rename\" style:UIAlertActionStyleDefault handler:handler]];\n        }\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDefault handler:handler]];\n    } else {\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Whois\" style:UIAlertActionStyleDefault handler:handler]];\n        if(self->_buffer.archived) {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Unarchive\" style:UIAlertActionStyleDefault handler:handler]];\n        } else {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Archive\" style:UIAlertActionStyleDefault handler:handler]];\n        }\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Rename\" style:UIAlertActionStyleDefault handler:handler]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDefault handler:handler]];\n    }\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Ignore List\" style:UIAlertActionStyleDefault handler:handler]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Add Network\" style:UIAlertActionStyleDefault handler:handler]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Join a Channel\" style:UIAlertActionStyleDefault handler:handler]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Display Options\" style:UIAlertActionStyleDefault handler:handler]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Download Logs\" style:UIAlertActionStyleDefault handler:handler]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Settings\" style:UIAlertActionStyleDefault handler:handler]];\n//#ifndef DEBUG\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Send Feedback\" style:UIAlertActionStyleDefault handler:handler]];\n//#endif\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Logout\" style:UIAlertActionStyleDefault handler:handler]];\n    if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:handler]];\n    }\n\n    alert.popoverPresentationController.sourceRect = CGRectMake(self->_bottomBar.frame.origin.x + _settingsBtn.frame.origin.x, _bottomBar.frame.origin.y,_settingsBtn.frame.size.width,_settingsBtn.frame.size.height);\n    alert.popoverPresentationController.sourceView = self.view;\n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)dismissKeyboard {\n    [self->_message resignFirstResponder];\n}\n\n-(void)_eventTapped:(NSTimer *)timer {\n    self->_doubleTapTimer = nil;\n    [self->_message resignFirstResponder];\n    Event *e = timer.userInfo;\n    if(e.rowType == ROW_FAILED) {\n        self->_selectedEvent = e;\n        Server *s = [[ServersDataSource sharedInstance] getServer:e.cid];\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"This message could not be sent\" preferredStyle:UIAlertControllerStyleAlert];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Try Again\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n            self->_selectedEvent.height = 0;\n            self->_selectedEvent.rowType = ROW_MESSAGE;\n            self->_selectedEvent.bgColor = [UIColor selfBackgroundColor];\n            self->_selectedEvent.pending = YES;\n            if([self->_selectedEvent.entities objectForKey:@\"reply\"])\n                self->_selectedEvent.reqId = [[NetworkConnection sharedInstance] reply:self->_selectedEvent.command to:self->_buffer.name cid:self->_buffer.cid msgid:[self->_selectedEvent.entities objectForKey:@\"reply\"] handler:nil];\n            else\n                self->_selectedEvent.reqId = [[NetworkConnection sharedInstance] say:self->_selectedEvent.command to:self->_buffer.name cid:self->_buffer.cid handler:nil];\n            if(self->_selectedEvent.msg)\n                [self->_pendingEvents addObject:self->_selectedEvent];\n            [self->_eventsView reloadData];\n            if(self->_selectedEvent.reqId < 0)\n                self->_selectedEvent.expirationTimer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(_sendRequestDidExpire:) userInfo:self->_selectedEvent repeats:NO];\n        }]];\n        [self presentViewController:alert animated:YES completion:nil];\n    } else if(e.rowType == ROW_REPLY_COUNT) {\n        [self setMsgId:((Event *)[e.entities objectForKey:@\"parent\"]).msgid];\n    } else {\n        [self->_eventsView clearLastSeenMarker];\n    }\n    [self closeColorPicker];\n}\n\n-(void)rowSelected:(Event *)event {\n    if(self->_doubleTapTimer) {\n        [self->_doubleTapTimer invalidate];\n        self->_doubleTapTimer = nil;\n        NSString *from = event.from;\n        if(!from.length)\n            from = event.nick;\n        if(from.length) {\n            self->_selectedUser = [[UsersDataSource sharedInstance] getUser:from cid:event.cid bid:event.bid];\n            if(!_selectedUser) {\n                self->_selectedUser = [[User alloc] init];\n                self->_selectedUser.nick = event.fromNick;\n                self->_selectedUser.display_name = event.from;\n                self->_selectedUser.hostmask = event.hostmask;\n                self->_selectedUser.parted = YES;\n            }\n            [self _mention];\n        }\n    } else {\n        self->_doubleTapTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(_eventTapped:) userInfo:event repeats:NO];\n    }\n}\n\n-(void)_mention {\n    NSString *from = self->_selectedUser.nick;\n\n    if(!from)\n        return;\n\n    [[NSUserDefaults standardUserDefaults] setObject:@YES forKey:@\"mentionTip\"];\n    \n    [self.slidingViewController resetTopView];\n    \n    if(self->_message.text.length == 0) {\n        self->_message.text = self->_buffer.serverIsSlack ? [NSString stringWithFormat:@\"@%@ \",_selectedUser.nick] : [NSString stringWithFormat:@\"%@: \",_selectedUser.nick];\n    } else {\n        NSInteger oldPosition = self->_message.selectedRange.location;\n        NSString *text = self->_message.text;\n        NSInteger start = oldPosition - 1;\n        if(start > 0 && [text characterAtIndex:start] == ' ')\n            start--;\n        while(start > 0 && [text characterAtIndex:start] != ' ')\n            start--;\n        if(start < 0)\n            start = 0;\n        NSRange range = [text rangeOfString:from options:0 range:NSMakeRange(start, text.length - start)];\n        NSInteger match = range.location;\n        char nextChar = (range.location != NSNotFound && range.location + range.length < text.length)?[text characterAtIndex:range.location + range.length]:0;\n        if(match != NSNotFound && (nextChar == 0 || nextChar == ' ' || nextChar == ':')) {\n            NSMutableString *newtext = [[NSMutableString alloc] init];\n            if(match > 1 && ([text characterAtIndex:match - 1] == ' ' || [text characterAtIndex:match - 1] == '@'))\n                [newtext appendString:[text substringWithRange:NSMakeRange(0, match - 1)]];\n            else\n                [newtext appendString:[text substringWithRange:NSMakeRange(0, match)]];\n            if(match+from.length < text.length && [text characterAtIndex:match+from.length] == ':' &&\n               match+from.length+1 < text.length && [text characterAtIndex:match+from.length+1] == ' ') {\n                if(match+from.length+2 < text.length)\n                    [newtext appendString:[text substringWithRange:NSMakeRange(match+from.length+2, text.length - (match+from.length+2))]];\n            } else if(match+from.length < text.length) {\n                [newtext appendString:[text substringWithRange:NSMakeRange(match+from.length, text.length - (match+from.length))]];\n            }\n            if([newtext hasSuffix:@\" \"])\n                newtext = (NSMutableString *)[newtext substringWithRange:NSMakeRange(0, newtext.length - 1)];\n            if([newtext isEqualToString:@\":\"])\n                newtext = (NSMutableString *)@\"\";\n            if([newtext isEqualToString:@\"@\"])\n                newtext = (NSMutableString *)@\"\";\n            self->_message.text = newtext;\n            if(match < newtext.length)\n                self->_message.selectedRange = NSMakeRange(match, 0);\n            else\n                self->_message.selectedRange = NSMakeRange(newtext.length, 0);\n        } else {\n            if(oldPosition == text.length - 1) {\n                text = [NSString stringWithFormat:@\" %@\", from];\n            } else {\n                NSMutableString *newtext = [[NSMutableString alloc] initWithString:[text substringWithRange:NSMakeRange(0, oldPosition)]];\n                if(self->_buffer.serverIsSlack && ![newtext hasSuffix:@\"@\"])\n                    from = [NSString stringWithFormat:@\"@%@\", from];\n                if(![newtext hasSuffix:@\" \"])\n                    from = [NSString stringWithFormat:@\" %@\", from];\n                if(![[text substringWithRange:NSMakeRange(oldPosition, text.length - oldPosition)] hasPrefix:@\" \"])\n                    from = [NSString stringWithFormat:@\"%@ \", from];\n                [newtext appendString:from];\n                [newtext appendString:[text substringWithRange:NSMakeRange(oldPosition, text.length - oldPosition)]];\n                if([newtext hasSuffix:@\" \"])\n                    newtext = (NSMutableString *)[newtext substringWithRange:NSMakeRange(0, newtext.length - 1)];\n                text = newtext;\n            }\n            self->_message.text = text;\n            if(text.length > 0) {\n                if(oldPosition + from.length + 2 < text.length)\n                    self->_message.selectedRange = NSMakeRange(oldPosition + from.length, 0);\n                else\n                    self->_message.selectedRange = NSMakeRange(text.length, 0);\n            }\n        }\n    }\n    [self->_message becomeFirstResponder];\n}\n\n-(void)_showUserPopupInRect:(CGRect)rect {\n    [self dismissKeyboard];\n    NSString *title = @\"\";;\n    Server *server = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n    if(self->_selectedUser) {\n        if(!_buffer.serverIsSlack && ([self->_selectedUser.hostmask isKindOfClass:[NSString class]] &&_selectedUser.hostmask.length && (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) || [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)))\n            title = [NSString stringWithFormat:@\"%@\\n(%@)\",_selectedUser.display_name,[self->_selectedUser.hostmask stripIRCFormatting]];\n        else\n            title = self->_selectedUser.nick;\n    }\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];\n    if (@available(iOS 13, *)) {\n        alert.overrideUserInterfaceStyle = self.view.overrideUserInterfaceStyle;\n    }\n    \n    void (^handler)(UIAlertAction *action) = ^(UIAlertAction *a) {\n        [self actionSheetActionClicked:a.title];\n    };\n    if(self->_selectedURL) {\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Copy URL\" style:UIAlertActionStyleDefault handler:handler]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Share URL\" style:UIAlertActionStyleDefault handler:handler]];\n    }\n    if(self->_selectedEvent) {\n        if([[self->_selectedEvent.entities objectForKey:@\"own_file\"] intValue]) {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Delete File\" style:UIAlertActionStyleDefault handler:handler]];\n        }\n        if(self->_selectedEvent.rowType == ROW_THUMBNAIL || _selectedEvent.rowType == ROW_FILE)\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Close Preview\" style:UIAlertActionStyleDefault handler:handler]];\n        if(self->_selectedEvent.msg.length || self->_selectedEvent.groupMsg.length)\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Copy Message\" style:UIAlertActionStyleDefault handler:handler]];\n        if(!self->_selectedEvent.deleted && !self->_selectedEvent.redacted) {\n            if(!server.blocksReplies && !_msgid && _selectedEvent.msgid && ([self->_selectedEvent.type isEqualToString:@\"buffer_msg\"] || [self->_selectedEvent.type isEqualToString:@\"buffer_me_msg\"] || [self->_selectedEvent.type isEqualToString:@\"notice\"])) {\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Reply\" style:UIAlertActionStyleDefault handler:handler]];\n            }\n            if(!server.blocksEdits && server.hasLabels && [self->_selectedEvent hasSameAccount:server.account] && _selectedEvent.msgid.length && self->_selectedEvent.chan) {\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Edit Message\" style:UIAlertActionStyleDefault handler:handler]];\n            }\n            if((!server.blocksDeletes || server.hasRedaction) && server.hasLabels && self->_selectedEvent.isSelf && _selectedEvent.msgid.length) {\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Delete Message\" style:UIAlertActionStyleDefault handler:handler]];\n            }\n        }\n    }\n    if(self->_selectedUser) {\n        if(self->_buffer.serverIsSlack)\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Slack Profile\" style:UIAlertActionStyleDefault handler:handler]];\n        if(!_buffer.serverIsSlack)\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Whois\" style:UIAlertActionStyleDefault handler:handler]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Send a Message\" style:UIAlertActionStyleDefault handler:handler]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Mention\" style:UIAlertActionStyleDefault handler:handler]];\n        if(!_buffer.serverIsSlack)\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Invite to Channel\" style:UIAlertActionStyleDefault handler:handler]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Ignore\" style:UIAlertActionStyleDefault handler:handler]];\n        if(!_buffer.serverIsSlack && [self->_buffer.type isEqualToString:@\"channel\"]) {\n            User *me = [[UsersDataSource sharedInstance] getUser:[[ServersDataSource sharedInstance] getServer:self->_buffer.cid].nick cid:self->_buffer.cid bid:self->_buffer.bid];\n            if([me.mode rangeOfString:server?server.MODE_OPER:@\"Y\"].location != NSNotFound || [me.mode rangeOfString:server?server.MODE_OWNER:@\"q\"].location != NSNotFound || [me.mode rangeOfString:server?server.MODE_ADMIN:@\"a\"].location != NSNotFound || [me.mode rangeOfString:server?server.MODE_OP:@\"o\"].location != NSNotFound) {\n                if([self->_selectedUser.mode rangeOfString:server?server.MODE_OP:@\"o\"].location != NSNotFound)\n                    [alert addAction:[UIAlertAction actionWithTitle:@\"Deop\" style:UIAlertActionStyleDefault handler:handler]];\n                else\n                    [alert addAction:[UIAlertAction actionWithTitle:@\"Op\" style:UIAlertActionStyleDefault handler:handler]];\n            }\n            if([me.mode rangeOfString:server?server.MODE_OPER:@\"Y\"].location != NSNotFound || [me.mode rangeOfString:server?server.MODE_OWNER:@\"q\"].location != NSNotFound || [me.mode rangeOfString:server?server.MODE_ADMIN:@\"a\"].location != NSNotFound || [me.mode rangeOfString:server?server.MODE_OP:@\"o\"].location != NSNotFound || [me.mode rangeOfString:server?server.MODE_HALFOP:@\"h\"].location != NSNotFound) {\n                if([self->_selectedUser.mode rangeOfString:server?server.MODE_VOICED:@\"v\"].location != NSNotFound)\n                    [alert addAction:[UIAlertAction actionWithTitle:@\"Devoice\" style:UIAlertActionStyleDefault handler:handler]];\n                else\n                    [alert addAction:[UIAlertAction actionWithTitle:@\"Voice\" style:UIAlertActionStyleDefault handler:handler]];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Kick\" style:UIAlertActionStyleDefault handler:handler]];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ban\" style:UIAlertActionStyleDefault handler:handler]];\n            }\n        }\n        if(!_buffer.serverIsSlack)\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Copy Hostmask\" style:UIAlertActionStyleDefault handler:handler]];\n    }\n    \n    if(self->_selectedEvent)\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Clear Backlog\" style:UIAlertActionStyleDefault handler:handler]];\n\n    if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:handler]];\n    }\n    \n    alert.popoverPresentationController.sourceRect = rect;\n    alert.popoverPresentationController.sourceView = self.view;\n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)_userTapped {\n    [self _showUserPopupInRect:self->_selectedRect];\n    self->_doubleTapTimer = nil;\n}\n\n-(void)userSelected:(NSString *)nick rect:(CGRect)rect {\n    rect = [_usersView.tableView convertRect:rect toView:self.view];\n    self->_selectedRect = rect;\n    self->_selectedEvent = nil;\n    self->_selectedURL = nil;\n    self->_selectedUser = [[UsersDataSource sharedInstance] getUser:nick cid:self->_buffer.cid bid:self->_buffer.bid];\n    if(self->_doubleTapTimer) {\n        [self->_doubleTapTimer invalidate];\n        self->_doubleTapTimer = nil;\n        [self.slidingViewController resetTopViewWithAnimations:nil onComplete:^{\n            [self _mention];\n        }];\n    } else {\n        self->_doubleTapTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(_userTapped) userInfo:nil repeats:NO];\n    }\n}\n\n-(void)markAsRead {\n    [[NetworkConnection sharedInstance] heartbeat:self->_buffer.bid cid:self->_buffer.cid bid:self->_buffer.bid lastSeenEid:[[EventsDataSource sharedInstance] lastEidForBuffer:self->_buffer.bid] handler:nil];\n    self->_buffer.last_seen_eid = [[EventsDataSource sharedInstance] lastEidForBuffer:self->_buffer.bid];\n}\n\n-(void)markAllAsRead {\n    NSMutableArray *cids = [[NSMutableArray alloc] init];\n    NSMutableArray *bids = [[NSMutableArray alloc] init];\n    NSMutableArray *eids = [[NSMutableArray alloc] init];\n    \n    for(Buffer *b in [[BuffersDataSource sharedInstance] getBuffers]) {\n        if([[EventsDataSource sharedInstance] unreadStateForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type] && [[EventsDataSource sharedInstance] lastEidForBuffer:b.bid]) {\n            [cids addObject:@(b.cid)];\n            [bids addObject:@(b.bid)];\n            [eids addObject:@([[EventsDataSource sharedInstance] lastEidForBuffer:b.bid])];\n        }\n    }\n    \n    [[NetworkConnection sharedInstance] heartbeat:self->_buffer.bid cids:cids bids:bids lastSeenEids:eids handler:nil];\n}\n\n-(void)editConnection {\n    EditConnectionViewController *ecv = [[EditConnectionViewController alloc] initWithStyle:UITableViewStyleGrouped];\n    [ecv setServer:self->_selectedBuffer.cid];\n    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:ecv];\n    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n        nc.modalPresentationStyle = UIModalPresentationPageSheet;\n    else\n        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n    if(self.presentedViewController)\n        [self dismissViewControllerAnimated:NO completion:nil];\n    [self presentViewController:nc animated:YES completion:nil];\n}\n\n-(void)_deleteSelectedBuffer {\n    [self dismissKeyboard];\n    [self.view.window endEditing:YES];\n    NSString *title = [self->_selectedBuffer.type isEqualToString:@\"console\"]?@\"Delete Connection\":@\"Clear History\";\n    NSString *msg;\n    if([self->_selectedBuffer.type isEqualToString:@\"console\"]) {\n        msg = @\"Are you sure you want to remove this connection?\";\n    } else if([self->_selectedBuffer.type isEqualToString:@\"channel\"]) {\n        msg = [NSString stringWithFormat:@\"Are you sure you want to clear your history in %@?\", _selectedBuffer.name];\n    } else {\n        msg = [NSString stringWithFormat:@\"Are you sure you want to clear your history with %@?\", _selectedBuffer.name];\n    }\n    \n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];\n    \n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {\n        if([self->_selectedBuffer.type isEqualToString:@\"console\"]) {\n            [[NetworkConnection sharedInstance] deleteServer:self->_selectedBuffer.cid handler:nil];\n        } else if(self->_selectedBuffer == nil || self->_selectedBuffer.bid == -1) {\n            if([[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] && [[BuffersDataSource sharedInstance] getBuffer:[[[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] intValue]])\n                [self bufferSelected:[[[NetworkConnection sharedInstance].userInfo objectForKey:@\"last_selected_bid\"] intValue]];\n            else\n                [self bufferSelected:[[BuffersDataSource sharedInstance] mostRecentBid]];\n        } else {\n            [[NetworkConnection sharedInstance] deleteBuffer:self->_selectedBuffer.bid cid:self->_selectedBuffer.cid handler:nil];\n        }\n    }]];\n    \n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)addNetwork {\n    EditConnectionViewController *ecv = [[EditConnectionViewController alloc] initWithStyle:UITableViewStyleGrouped];\n    [self.slidingViewController resetTopView];\n    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:ecv];\n    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n        nc.modalPresentationStyle = UIModalPresentationPageSheet;\n    else\n        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n    [self presentViewController:nc animated:YES completion:nil];\n}\n\n-(void)_reorder {\n    ServerReorderViewController *svc = [[ServerReorderViewController alloc] initWithStyle:UITableViewStylePlain];\n    [self.slidingViewController resetTopView];\n    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:svc];\n    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n        nc.modalPresentationStyle = UIModalPresentationFormSheet;\n    else\n        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n    [self presentViewController:nc animated:YES completion:nil];\n}\n\n-(void)_inviteToChannel {\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_selectedUser?_buffer.cid:self->_selectedBuffer.cid];\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Invite to channel\" preferredStyle:UIAlertControllerStyleAlert];\n    \n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Invite\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n        if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n            if(self->_selectedUser)\n                [[NetworkConnection sharedInstance] invite:self->_selectedUser.nick chan:((UITextField *)[alert.textFields objectAtIndex:0]).text cid:self->_buffer.cid handler:nil];\n            else\n                [[NetworkConnection sharedInstance] invite:((UITextField *)[alert.textFields objectAtIndex:0]).text chan:self->_selectedBuffer.name cid:self->_selectedBuffer.cid handler:nil];\n        }\n    }]];\n    \n    [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n        textField.placeholder = self->_selectedUser?@\"#channel\":@\"nickname\";\n        textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n    }];\n    \n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)_joinAChannel {\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_selectedBuffer.cid];\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Which channel do you want to join?\" preferredStyle:UIAlertControllerStyleAlert];\n    \n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Join\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n        if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n            [[NetworkConnection sharedInstance] say:[NSString stringWithFormat:@\"/join %@\",((UITextField *)[alert.textFields objectAtIndex:0]).text] to:nil cid:self->_selectedBuffer.cid handler:nil];\n        }\n    }]];\n    \n    [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n        textField.placeholder = @\"#channel\";\n        textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n    }];\n    \n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)_renameBuffer:(Buffer *)b msg:(NSString *)msg {\n    if(!msg) {\n        msg = [NSString stringWithFormat:@\"Choose a new name for this %@\", b.type];\n    } else {\n        if([msg isEqualToString:@\"invalid_name\"]) {\n            if([b.type isEqualToString:@\"channel\"])\n                msg = @\"You must choose a valid channel name\";\n            else\n                msg = @\"You must choose a valid nick name\";\n        } else if([msg isEqualToString:@\"not_conversation\"]) {\n            msg = @\"You can only rename private messages\";\n        } else if([msg isEqualToString:@\"not_channel\"]) {\n            msg = @\"You can only rename channels\";\n        } else if([msg isEqualToString:@\"name_exists\"]) {\n            msg = @\"That name is already taken\";\n        } else if([msg isEqualToString:@\"channel_joined\"]) {\n            msg = @\"You can only rename parted channels\";\n        }\n        msg = [NSString stringWithFormat:@\"Error renaming: %@. Please choose a new name for this %@\", msg, b.type];\n    }\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_selectedBuffer.cid];\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:msg preferredStyle:UIAlertControllerStyleAlert];\n    \n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Rename\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n        if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n            id handler = ^(IRCCloudJSONObject *result) {\n                if([[result objectForKey:@\"success\"] intValue] == 0) {\n                    CLS_LOG(@\"Rename failed: %@\", result);\n                    [self _renameBuffer:self->_selectedBuffer msg:[result objectForKey:@\"message\"]];\n                }\n            };\n            if([self->_selectedBuffer.type isEqualToString:@\"channel\"])\n                [[NetworkConnection sharedInstance] renameChannel:((UITextField *)[alert.textFields objectAtIndex:0]).text cid:self->_selectedBuffer.cid bid:self->_selectedBuffer.bid handler:handler];\n            else\n                [[NetworkConnection sharedInstance] renameConversation:((UITextField *)[alert.textFields objectAtIndex:0]).text cid:self->_selectedBuffer.cid bid:self->_selectedBuffer.bid handler:handler];\n        }\n    }]];\n    \n    [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n        textField.text = b.name;\n        textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n    }];\n    \n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)bufferLongPressed:(int)bid rect:(CGRect)rect {\n    self->_selectedUser = nil;\n    self->_selectedURL = nil;\n    self->_selectedBuffer = [[BuffersDataSource sharedInstance] getBuffer:bid];\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];\n    if (@available(iOS 13, *)) {\n        alert.overrideUserInterfaceStyle = self.view.overrideUserInterfaceStyle;\n    }\n    if([self->_selectedBuffer.type isEqualToString:@\"console\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_selectedBuffer.cid];\n        if([s.status isEqualToString:@\"disconnected\"]) {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Reconnect\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [[NetworkConnection sharedInstance] reconnect:self->_selectedBuffer.cid handler:nil];\n            }]];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *alert) {\n                [self _deleteSelectedBuffer];\n            }]];\n        } else {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Disconnect\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [[NetworkConnection sharedInstance] disconnect:self->_selectedBuffer.cid msg:nil handler:nil];\n            }]];\n        }\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Edit Connection\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n            [self editConnection];\n        }]];\n#ifndef ENTERPRISE\n        Buffer *b = [[BuffersDataSource sharedInstance] getBufferWithName:@\"*\" server:s.cid];\n        if(b.archived) {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Expand\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [[NetworkConnection sharedInstance] unarchiveBuffer:b.bid cid:b.cid handler:nil];\n            }]];\n        } else {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Collapse\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [[NetworkConnection sharedInstance] archiveBuffer:b.bid cid:b.cid handler:nil];\n            }]];\n        }\n#endif\n    } else if([self->_selectedBuffer.type isEqualToString:@\"channel\"]) {\n        if([[ChannelsDataSource sharedInstance] channelForBuffer:self->_selectedBuffer.bid]) {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Leave\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [[NetworkConnection sharedInstance] part:self->_selectedBuffer.name msg:nil cid:self->_selectedBuffer.cid handler:nil];\n            }]];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Invite to Channel\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [self _inviteToChannel];\n            }]];\n        } else {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Rejoin\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [[NetworkConnection sharedInstance] join:self->_selectedBuffer.name key:nil cid:self->_selectedBuffer.cid handler:nil];\n            }]];\n            if(self->_selectedBuffer.archived) {\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Unarchive\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                    [[NetworkConnection sharedInstance] unarchiveBuffer:self->_selectedBuffer.bid cid:self->_selectedBuffer.cid handler:nil];\n                }]];\n            } else {\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Archive\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                    [[NetworkConnection sharedInstance] archiveBuffer:self->_selectedBuffer.bid cid:self->_selectedBuffer.cid handler:nil];\n                }]];\n            }\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Rename\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [self _renameBuffer:self->_selectedBuffer msg:nil];\n            }]];\n        }\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *alert) {\n            [self _deleteSelectedBuffer];\n        }]];\n    } else {\n        if(self->_selectedBuffer.archived) {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Unarchive\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [[NetworkConnection sharedInstance] unarchiveBuffer:self->_selectedBuffer.bid cid:self->_selectedBuffer.cid handler:nil];\n            }]];\n        } else {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Archive\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                [[NetworkConnection sharedInstance] archiveBuffer:self->_selectedBuffer.bid cid:self->_selectedBuffer.cid handler:nil];\n            }]];\n        }\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Rename\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n            [self _renameBuffer:self->_selectedBuffer msg:nil];\n        }]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *alert) {\n            [self _deleteSelectedBuffer];\n        }]];\n    }\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Mark All as Read\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        [self markAllAsRead];\n    }]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Add a Network\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        [self addNetwork];\n    }]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Join a Channel\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        [self _joinAChannel];\n    }]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Send a Message\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_selectedBuffer.cid];\n        UIAlertController *a = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Which nick do you want to message?\" preferredStyle:UIAlertControllerStyleAlert];\n        \n        [a addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n        [a addAction:[UIAlertAction actionWithTitle:@\"Message\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n            if(((UITextField *)[a.textFields objectAtIndex:0]).text.length) {\n                [[NetworkConnection sharedInstance] say:[NSString stringWithFormat:@\"/query %@\",((UITextField *)[a.textFields objectAtIndex:0]).text] to:nil cid:self->_selectedBuffer.cid handler:nil];\n            }\n        }]];\n        \n        [a addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n            textField.placeholder = @\"nickname\";\n            textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n        }];\n        \n        [self presentViewController:a animated:YES completion:nil];\n    }]];\n\n    BOOL activeCount = NO;\n    NSArray *buffers = [[BuffersDataSource sharedInstance] getBuffersForServer:self->_selectedBuffer.cid];\n    for(Buffer *b in buffers) {\n        if([b.type isEqualToString:@\"conversation\"] && !b.archived) {\n            activeCount = YES;\n            break;\n        }\n    }\n    \n    if(activeCount) {\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Delete Active Conversations\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *alert) {\n            [self spamSelected:self->_selectedBuffer.cid];\n        }]];\n    }\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Reorder Connections\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        [self _reorder];\n    }]];\n\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Reorder Pins\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        PinReorderViewController *pvc = [[PinReorderViewController alloc] initWithStyle:UITableViewStylePlain];\n        [self.slidingViewController resetTopView];\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:pvc];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationFormSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        [self presentViewController:nc animated:YES completion:nil];\n    }]];\n\n    [self _addPinAction:alert buffer:self->_selectedBuffer];\n\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    alert.popoverPresentationController.sourceRect = rect;\n    alert.popoverPresentationController.sourceView = self->_buffersView.tableView;\n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)_addPinAction:(UIAlertController *)alert buffer:(Buffer *)buffer {\n    if(!buffer.archived && ([buffer.type isEqualToString:@\"channel\"] || [buffer.type isEqualToString:@\"conversation\"])) {\n        BOOL pinned = NO;\n        \n        NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n        \n        if([[prefs objectForKey:@\"pinnedBuffers\"] isKindOfClass:NSArray.class] && [(NSArray *)[prefs objectForKey:@\"pinnedBuffers\"] count] > 0) {\n            for(NSNumber *n in [prefs objectForKey:@\"pinnedBuffers\"]) {\n                if(n.intValue == buffer.bid) {\n                    pinned = YES;\n                    break;\n                }\n            }\n        }\n        \n        if(pinned) {\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Remove Pin\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                NSMutableDictionary *mutablePrefs = prefs.mutableCopy;\n                NSMutableArray *pinnedBuffers;\n                if([[prefs objectForKey:@\"pinnedBuffers\"] isKindOfClass:NSArray.class] && [(NSArray *)[prefs objectForKey:@\"pinnedBuffers\"] count] > 0) {\n                    pinnedBuffers = ((NSArray *)[prefs objectForKey:@\"pinnedBuffers\"]).mutableCopy;\n                } else {\n                    pinnedBuffers = [[NSMutableArray alloc] init];\n                }\n                [pinnedBuffers removeObject:@(buffer.bid)];\n                [mutablePrefs setObject:pinnedBuffers forKey:@\"pinnedBuffers\"];\n                SBJson5Writer *writer = [[SBJson5Writer alloc] init];\n                NSString *json = [writer stringWithObject:mutablePrefs];\n\n                [[NetworkConnection sharedInstance] setPrefs:json handler:^(IRCCloudJSONObject *result) {\n                    if(![[result objectForKey:@\"success\"] boolValue]) {\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to save settings, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                        [self presentViewController:alert animated:YES completion:nil];\n                    }\n                }];\n            }]];\n        } else {\n            [alert addAction:[UIAlertAction actionWithTitle:[buffer.type isEqualToString:@\"channel\"]?@\"Pin Channel\":@\"Pin Conversation\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                NSMutableDictionary *mutablePrefs = prefs.mutableCopy;\n                NSMutableArray *pinnedBuffers;\n                if([[prefs objectForKey:@\"pinnedBuffers\"] isKindOfClass:NSArray.class] && [(NSArray *)[prefs objectForKey:@\"pinnedBuffers\"] count] > 0) {\n                    pinnedBuffers = ((NSArray *)[prefs objectForKey:@\"pinnedBuffers\"]).mutableCopy;\n                } else {\n                    pinnedBuffers = [[NSMutableArray alloc] init];\n                }\n                [pinnedBuffers addObject:@(buffer.bid)];\n                [mutablePrefs setObject:pinnedBuffers forKey:@\"pinnedBuffers\"];\n                SBJson5Writer *writer = [[SBJson5Writer alloc] init];\n                NSString *json = [writer stringWithObject:mutablePrefs];\n\n                [[NetworkConnection sharedInstance] setPrefs:json handler:^(IRCCloudJSONObject *result) {\n                    if(![[result objectForKey:@\"success\"] boolValue]) {\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to save settings, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                        [self presentViewController:alert animated:YES completion:nil];\n                    }\n                }];\n            }]];\n        }\n    }\n}\n\n-(void)spamSelected:(int)cid {\n    Server *s = [[ServersDataSource sharedInstance] getServer:cid];\n    SpamViewController *svc = [[SpamViewController alloc] initWithCid:cid];\n    svc.navigationItem.title = s.hostname;\n    [self.slidingViewController resetTopView];\n    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:svc];\n    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n        nc.modalPresentationStyle = UIModalPresentationFormSheet;\n    else\n        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n    [self presentViewController:nc animated:YES completion:nil];\n}\n\n-(void)rowLongPressed:(Event *)event rect:(CGRect)rect link:(NSString *)url {\n    rect = [_eventsView.tableView convertRect:rect toView:self.view];\n    if(event && (event.msg.length || event.groupMsg.length || event.rowType == ROW_THUMBNAIL)) {\n        NSString *from = event.from;\n        if(!from.length)\n            from = event.nick;\n        if(from) {\n            self->_selectedUser = [[UsersDataSource sharedInstance] getUser:from cid:self->_buffer.cid bid:self->_buffer.bid];\n            if(!_selectedUser) {\n                self->_selectedUser = [[User alloc] init];\n                self->_selectedUser.cid = self->_selectedEvent.cid;\n                self->_selectedUser.bid = self->_selectedEvent.bid;\n                self->_selectedUser.nick = from;\n                self->_selectedUser.parted = YES;\n            }\n            if(event.hostmask.length)\n                self->_selectedUser.hostmask = event.hostmask;\n        } else {\n            self->_selectedUser = nil;\n        }\n        self->_selectedEvent = event;\n        self->_selectedRect = rect;\n        self->_selectedURL = url;\n        if([self->_selectedURL hasPrefix:@\"irccloud-paste-\"])\n            self->_selectedURL = [self->_selectedURL substringFromIndex:15];\n        [self _showUserPopupInRect:rect];\n    }\n}\n\n-(IBAction)titleAreaPressed:(id)sender {\n    if([NetworkConnection sharedInstance].state == kIRCCloudStateDisconnected) {\n        [[NetworkConnection sharedInstance] connect:NO];\n    } else {\n        if(self->_buffer && !_buffer.isMPDM && [self->_buffer.type isEqualToString:@\"channel\"] && [[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid]) {\n            ChannelInfoViewController *c = [[ChannelInfoViewController alloc] initWithChannel:[[ChannelsDataSource sharedInstance] channelForBuffer:self->_buffer.bid]];\n            UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:c];\n            [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n            if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                nc.modalPresentationStyle = UIModalPresentationPageSheet;\n            else\n                nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n            [self presentViewController:nc animated:YES completion:nil];\n        }\n    }\n    [self closeColorPicker];\n}\n\n-(void)_setSelectedBuffer:(Buffer *)b {\n    self->_selectedBuffer = b;\n}\n\n-(void)clearText {\n    [self->_message clearText];\n}\n\n-(void)choosePhoto:(UIImagePickerControllerSourceType)sourceType {\n    UIImagePickerController *picker = [[UIImagePickerController alloc] init];\n    picker.sourceType = sourceType;\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"uploadsAvailable\"])\n        picker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:sourceType];\n    picker.delegate = (id)self;\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone || sourceType == UIImagePickerControllerSourceTypeCamera) {\n        [UIColor clearTheme];\n        [self presentViewController:picker animated:YES completion:nil];\n    } else {\n        [UIColor clearTheme];\n        picker.modalPresentationStyle = UIModalPresentationFormSheet;\n        picker.preferredContentSize = CGSizeMake(540, 576);\n        [self presentViewController:picker animated:YES completion:nil];\n    }\n}\n\n-(void)chooseFile {\n    UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[(NSString *)kUTTypePackage, (NSString *)kUTTypeData]\n                                                                                                            inMode:UIDocumentPickerModeImport];\n    documentPicker.delegate = self;\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n        documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;\n    else {\n        documentPicker.modalPresentationStyle = UIModalPresentationCurrentContext;\n    }\n    if(documentPicker) {\n        [UIColor clearTheme];\n        [self presentViewController:documentPicker animated:YES completion:nil];\n    }\n}\n\n-(void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {\n    [UIColor setTheme];\n    [self applyTheme];\n}\n\n- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {\n    [self documentPicker:controller didPickDocumentAtURL:urls[0]];\n}\n\n- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url {\n    [UIColor setTheme];\n    [self applyTheme];\n    FileUploader *u = [[FileUploader alloc] init];\n    FileMetadataViewController *fvc = [[FileMetadataViewController alloc] initWithUploader:u];\n    u.delegate = self;\n    u.metadatadelegate = fvc;\n    u.to = @[@{@\"cid\":@(self->_buffer.cid), @\"to\":self->_buffer.name}];\n    u.msgid = self->_msgid;\n    [u uploadFile:url];\n    \n    if([u.mimeType hasPrefix:@\"image/\"]) {\n        NSData *d = [NSData dataWithContentsOfURL:url];\n        UIImage *thumbnail = [UIImage imageWithData:d];\n        if(thumbnail) {\n            thumbnail = [FileUploader image:thumbnail scaledCopyOfSize:CGSizeMake(2048, 2048)];\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [fvc setImage:thumbnail];\n                [fvc viewWillAppear:YES];\n            }];\n        }\n    }\n\n    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:fvc];\n    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n        nc.modalPresentationStyle = UIModalPresentationFormSheet;\n    else\n        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n    [self presentViewController:nc animated:YES completion:nil];\n}\n\n- (void)_imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {\n    [UIColor setTheme];\n    [self applyTheme];\n    FileMetadataViewController *fvc = nil;\n    NSURL *refURL = [info valueForKey:UIImagePickerControllerReferenceURL];\n    NSURL *mediaURL = [info valueForKey:UIImagePickerControllerMediaURL];\n    UIImage *img = [info objectForKey:UIImagePickerControllerEditedImage];\n    if(!img)\n        img = [info objectForKey:UIImagePickerControllerOriginalImage];\n    \n    CLS_LOG(@\"Image file chosen: %@ %@\", refURL, mediaURL);\n    if(img || refURL || mediaURL) {\n        if(picker.sourceType == UIImagePickerControllerSourceTypeCamera && [[NSUserDefaults standardUserDefaults] boolForKey:@\"saveToCameraRoll\"]) {\n            if(img)\n                UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);\n            else if(UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(mediaURL.path))\n                UISaveVideoAtPathToSavedPhotosAlbum(mediaURL.path, nil, nil, nil);\n        }\n        FileUploader *u = [[FileUploader alloc] init];\n        u.delegate = self;\n        u.to = @[@{@\"cid\":@(self->_buffer.cid), @\"to\":self->_buffer.name}];\n        u.msgid = self->_msgid;\n        fvc = [[FileMetadataViewController alloc] initWithUploader:u];\n        if(picker == nil || picker.sourceType == UIImagePickerControllerSourceTypeCamera) {\n            [fvc showCancelButton];\n        }\n        \n        if(refURL) {\n#if !TARGET_OS_MACCATALYST\n            CLS_LOG(@\"Loading metadata from asset library\");\n            ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset) {\n                ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];\n                CLS_LOG(@\"Got filename: %@\", imageRep.filename);\n                u.originalFilename = imageRep.filename;\n                if([[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:@\"public.movie\"]) {\n                    CLS_LOG(@\"Uploading file URL\");\n                    u.originalFilename = [u.originalFilename stringByReplacingOccurrencesOfString:@\".MOV\" withString:@\".MP4\"];\n                    [u uploadVideo:[info objectForKey:UIImagePickerControllerMediaURL]];\n                    [fvc viewWillAppear:NO];\n                } else if([imageRep.filename.lowercaseString hasSuffix:@\".gif\"] || [imageRep.filename.lowercaseString hasSuffix:@\".png\"]) {\n                    CLS_LOG(@\"Uploading file data\");\n                    NSMutableData *data = [[NSMutableData alloc] initWithCapacity:(NSUInteger)imageRep.size];\n                    uint8_t buffer[4096];\n                    long long len = 0;\n                    while(len < imageRep.size) {\n                        long long i = [imageRep getBytes:buffer fromOffset:len length:4096 error:nil];\n                        [data appendBytes:buffer length:(NSUInteger)i];\n                        len += i;\n                    }\n                    [u uploadFile:imageRep.filename UTI:imageRep.UTI data:data];\n                    [fvc viewWillAppear:NO];\n                } else {\n                    CLS_LOG(@\"Uploading UIImage\");\n                    [u uploadImage:img];\n                    [fvc viewWillAppear:NO];\n                }\n                if(imageRep.fullScreenImage) {\n                    UIImage *thumbnail = [FileUploader image:[UIImage imageWithCGImage:imageRep.fullScreenImage] scaledCopyOfSize:CGSizeMake(2048, 2048)];\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        [fvc setImage:thumbnail];\n                    }];\n                }\n            };\n            \n            ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];\n            [assetslibrary assetForURL:refURL resultBlock:resultblock failureBlock:^(NSError *e) {\n                CLS_LOG(@\"Error getting asset: %@\", e);\n                if(img) {\n                    [u uploadImage:img];\n                    UIImage *thumbnail = [FileUploader image:img scaledCopyOfSize:CGSizeMake(2048, 2048)];\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        [fvc setImage:thumbnail];\n                    }];\n                } else if([[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:@\"public.movie\"]) {\n                    [u uploadVideo:mediaURL];\n                } else {\n                    [u uploadFile:mediaURL];\n                }\n                [fvc viewWillAppear:NO];\n            }];\n#endif\n        } else if([info objectForKey:@\"gifData\"]) {\n            CLS_LOG(@\"Uploading GIF from Pasteboard\");\n            [u uploadFile:[NSString stringWithFormat:@\"%li.GIF\", time(NULL)] UTI:@\"image/gif\" data:[info objectForKey:@\"gifData\"]];\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [fvc setImage:img];\n            }];\n        } else {\n            CLS_LOG(@\"no asset library URL, uploading image data instead\");\n            if(img) {\n                [u uploadImage:img];\n                UIImage *thumbnail = [FileUploader image:img scaledCopyOfSize:CGSizeMake(2048, 2048)];\n                [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                    [fvc setImage:thumbnail];\n                }];\n            } else if([[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:@\"public.movie\"]) {\n                [u uploadVideo:mediaURL];\n            } else {\n                [u uploadFile:mediaURL];\n            }\n        }\n    }\n    \n    UINavigationController *nc = nil;\n    \n    if(fvc) {\n        nc = [[UINavigationController alloc] initWithRootViewController:fvc];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationFormSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n    }\n    \n    if(self.presentedViewController) {\n        [self dismissViewControllerAnimated:YES completion:^{\n            if(nc)\n                [self presentViewController:nc animated:YES completion:nil];\n        }];\n    } else if(nc) {\n        [self presentViewController:nc animated:YES completion:nil];\n    }\n    \n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"keepScreenOn\"])\n        [UIApplication sharedApplication].idleTimerDisabled = YES;\n}\n\n- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {\n    [picker dismissViewControllerAnimated:YES completion:^{\n        [self _imagePickerController:picker didFinishPickingMediaWithInfo:info];\n    }];\n}\n\n-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {\n    CLS_LOG(@\"Image picker was cancelled\");\n    [UIColor setTheme];\n    [self applyTheme];\n    [self dismissViewControllerAnimated:YES completion:nil];\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"keepScreenOn\"])\n        [UIApplication sharedApplication].idleTimerDisabled = YES;\n    [self _hideConnectingView];\n}\n\n-(void)filesTableViewControllerDidSelectFile:(NSDictionary *)file message:(NSString *)message {\n    if(message.length)\n        message = [message stringByAppendingString:@\" \"];\n    message = [message stringByAppendingString:[file objectForKey:@\"url\"]];\n    [[NetworkConnection sharedInstance] say:message to:self->_buffer.name cid:self->_buffer.cid handler:nil];\n}\n\n-(void)fileUploadProgress:(float)progress {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        if(!self.presentedViewController) {\n            if(self.navigationItem.titleView != self->_connectingView) {\n                [self _showConnectingView];\n                self->_connectingStatus.text = @\"Uploading\";\n                self->_connectingProgress.progress = progress;\n            }\n            self->_connectingProgress.hidden = NO;\n            [self->_connectingProgress setProgress:progress animated:YES];\n        }\n    }];\n}\n\n-(void)fileUploadDidFail:(NSString *)reason {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        CLS_LOG(@\"File upload failed: %@\", reason);\n        NSString *msg;\n        if([reason isEqualToString:@\"upload_limit_reached\"]) {\n            msg = @\"Sorry, you can’t upload more than 100 MB of files.  Delete some uploads and try again.\";\n        } else if([reason isEqualToString:@\"upload_already_exists\"]) {\n            msg = @\"You’ve already uploaded this file\";\n        } else if([reason isEqualToString:@\"banned_content\"]) {\n            msg = @\"Banned content\";\n        } else {\n            msg = @\"Failed to upload file. Please try again shortly.\";\n        }\n        [self dismissViewControllerAnimated:YES completion:nil];\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Upload Failed\" message:msg preferredStyle:UIAlertControllerStyleAlert];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n        [self presentViewController:alert animated:YES completion:nil];\n        [self _hideConnectingView];\n    }];\n}\n\n-(void)fileUploadTooLarge {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        CLS_LOG(@\"File upload too large\");\n        [self dismissViewControllerAnimated:YES completion:nil];\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Upload Failed\" message:@\"Sorry, you can’t upload files larger than 15 MB\" preferredStyle:UIAlertControllerStyleAlert];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n        [self presentViewController:alert animated:YES completion:nil];\n        [self _hideConnectingView];\n    }];\n}\n\n-(void)fileUploadDidFinish {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        CLS_LOG(@\"File upload did finish\");\n        [self _hideConnectingView];\n    }];\n}\n\n-(void)fileUploadWasCancelled {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        CLS_LOG(@\"File upload was cancelled\");\n        [self _hideConnectingView];\n    }];\n}\n\n-(void)startPastebin {\n    if(self->_buffer) {\n        PastebinEditorViewController *pv = [[PastebinEditorViewController alloc] initWithBuffer:self->_buffer];\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:pv];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationPageSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        if(self.presentedViewController)\n            [self dismissViewControllerAnimated:NO completion:nil];\n        [self presentViewController:nc animated:YES completion:nil];\n    }\n}\n\n-(void)showPastebins {\n    PastebinsTableViewController *ptv = [[PastebinsTableViewController alloc] init];\n    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:ptv];\n    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n        nc.modalPresentationStyle = UIModalPresentationPageSheet;\n    else\n        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n    if(self.presentedViewController)\n        [self dismissViewControllerAnimated:NO completion:nil];\n    [self presentViewController:nc animated:YES completion:nil];\n}\n\n-(void)showUploads {\n    FilesTableViewController *fcv = [[FilesTableViewController alloc] initWithStyle:UITableViewStylePlain];\n    fcv.delegate = self;\n    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:fcv];\n    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n        nc.modalPresentationStyle = UIModalPresentationPageSheet;\n    else\n        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n    if(self.presentedViewController)\n        [self dismissViewControllerAnimated:NO completion:nil];\n    [self presentViewController:nc animated:YES completion:nil];\n}\n\n-(void)uploadsButtonPressed:(id)sender {\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];\n    if (@available(iOS 13, *)) {\n        alert.overrideUserInterfaceStyle = self.view.overrideUserInterfaceStyle;\n    }\n\n    BOOL isCatalyst = NO;\n    if (@available(iOS 13.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp)\n            isCatalyst = YES;\n    }\n    \n    if(!isCatalyst) {\n        if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {\n            [alert addAction:[UIAlertAction actionWithTitle:([[NSUserDefaults standardUserDefaults] boolForKey:@\"uploadsAvailable\"])?@\"Take Photo or Video\":@\"Take a Photo\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self choosePhoto:UIImagePickerControllerSourceTypeCamera];\n            }]];\n        }\n        if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {\n            [alert addAction:[UIAlertAction actionWithTitle:([[NSUserDefaults standardUserDefaults] boolForKey:@\"uploadsAvailable\"])?@\"Choose Photo or Video\":@\"Choose Photo\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n                if(self.presentedViewController)\n                    [self dismissViewControllerAnimated:NO completion:nil];\n                [self choosePhoto:UIImagePickerControllerSourceTypePhotoLibrary];\n            }]];\n        }\n    }\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"uploadsAvailable\"]) {\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Choose Document\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n            if(self.presentedViewController)\n                [self dismissViewControllerAnimated:NO completion:nil];\n            [self chooseFile];\n        }]];\n    }\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Start a Text Snippet\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        [self startPastebin];\n    }]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Text Snippets\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        [self showPastebins];\n    }]];\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"uploadsAvailable\"]) {\n        [alert addAction:[UIAlertAction actionWithTitle:@\"File Uploads\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n            [self showUploads];\n        }]];\n    }\n#ifndef ENTERPRISE\n    BOOL avatars_supported = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid].avatars_supported;\n    if([[ServersDataSource sharedInstance] getServer:self->_buffer.cid].isSlack)\n        avatars_supported = NO;\n    [alert addAction:[UIAlertAction actionWithTitle:avatars_supported?@\"Change Avatar\":@\"Change Public Avatar\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        AvatarsTableViewController *atv = [[AvatarsTableViewController alloc] initWithServer:avatars_supported?self->_buffer.cid:-1];\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:atv];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationFormSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        [self presentViewController:nc animated:YES completion:nil];\n    }]];\n#endif\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    alert.popoverPresentationController.sourceRect = CGRectMake(self->_bottomBar.frame.origin.x + _uploadsBtn.frame.origin.x, _bottomBar.frame.origin.y,_uploadsBtn.frame.size.width,_uploadsBtn.frame.size.height);\n    alert.popoverPresentationController.sourceView = self.view;\n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)actionSheetActionClicked:(NSString *)action {\n    [self->_message resignFirstResponder];\n    if(self.presentedViewController)\n        [self dismissViewControllerAnimated:NO completion:nil];\n        \n    if([action isEqualToString:@\"Copy Message\"]) {\n        Event *e = self->_selectedEvent;\n        if(e.parent)\n            e = [[EventsDataSource sharedInstance] event:e.parent buffer:e.bid];\n        UIPasteboard *pb = [UIPasteboard generalPasteboard];\n        NSString *irc;\n        if(e.groupMsg.length) {\n            irc = [NSString stringWithFormat:@\"%@ %@\",e.timestamp,e.groupMsg];\n        } else if(e.from.length || [e.type isEqualToString:@\"buffer_me_msg\"]) {\n            irc = [e.type isEqualToString:@\"buffer_me_msg\"]?[NSString stringWithFormat:@\"%@ %c— %@%c %@\",e.timestamp,BOLD,e.nick,CLEAR,e.msg]:[NSString stringWithFormat:@\"%@ %c<%@>%c %@\",e.timestamp,BOLD,e.from,CLEAR,e.msg];\n        } else {\n            irc = [NSString stringWithFormat:@\"%@ %@\",e.timestamp,e.msg];\n        }\n        irc = [irc stringByReplacingOccurrencesOfString:@\"\\u00a0\" withString:@\" \"];\n        NSAttributedString *msg = [ColorFormatter format:irc defaultColor:nil mono:NO linkify:NO server:nil links:nil];\n        pb.items = @[@{(NSString *)kUTTypeRTF:[msg dataFromRange:NSMakeRange(0, msg.length) documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType} error:nil],(NSString *)kUTTypeUTF8PlainText:msg.string,@\"IRC formatting type\":[irc dataUsingEncoding:NSUTF8StringEncoding]}];\n    } else if([action isEqualToString:@\"Clear Backlog\"]) {\n        int bid = self->_selectedBuffer?_selectedBuffer.bid:self->_selectedEvent.bid;\n        [[EventsDataSource sharedInstance] removeEventsForBuffer:bid];\n        if(self->_buffer.bid == bid)\n            [self->_eventsView refresh];\n    } else if([action isEqualToString:@\"Copy URL\"]) {\n        UIPasteboard *pb = [UIPasteboard generalPasteboard];\n        [pb setValue:self->_selectedURL forPasteboardType:(NSString *)kUTTypeUTF8PlainText];\n    } else if([action isEqualToString:@\"Share URL\"]) {\n        [UIColor clearTheme];\n        UIActivityViewController *activityController = [URLHandler activityControllerForItems:@[[NSURL URLWithString:self->_selectedURL]] type:@\"URL\"];\n        activityController.popoverPresentationController.sourceView = self.view;\n        activityController.popoverPresentationController.sourceRect = self->_selectedRect;\n        [self presentViewController:activityController animated:YES completion:nil];\n    } else if([action isEqualToString:@\"Delete Message\"]) {\n        [self dismissKeyboard];\n        [self.view.window endEditing:YES];\n\n        Server *s = [[ServersDataSource sharedInstance] getServer:_buffer.cid];\n        \n        if(s && s.hasRedaction) {\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Are you sure you want to delete this message?\" preferredStyle:UIAlertControllerStyleAlert];\n            \n            [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {\n                [[NetworkConnection sharedInstance] redact:self->_selectedEvent.msgid cid:self->_selectedEvent.cid to:self->_selectedEvent.chan reason:((UITextField *)[alert.textFields objectAtIndex:0]).text handler:^(IRCCloudJSONObject *result) {\n                    if(![[result objectForKey:@\"success\"] boolValue]) {\n                        CLS_LOG(@\"Error redacting message: %@\", result);\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to delete message, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                        [self presentViewController:alert animated:YES completion:nil];\n                    }\n                }];\n            }]];\n            \n            [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n                textField.placeholder = @\"Reason (optional)\";\n                textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n            }];\n            \n            [self presentViewController:alert animated:YES completion:nil];\n        } else {\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Are you sure you want to delete this message?\" preferredStyle:UIAlertControllerStyleAlert];\n            \n            [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {\n                [[NetworkConnection sharedInstance] deleteMessage:self->_selectedEvent.msgid cid:self->_selectedEvent.cid to:self->_selectedEvent.chan handler:^(IRCCloudJSONObject *result) {\n                    if(![[result objectForKey:@\"success\"] boolValue]) {\n                        CLS_LOG(@\"Error deleting message: %@\", result);\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to delete message, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                        [self presentViewController:alert animated:YES completion:nil];\n                    }\n                }];\n            }]];\n            \n            [self presentViewController:alert animated:YES completion:nil];\n        }\n    } else if([action isEqualToString:@\"Edit Message\"]) {\n        [self dismissKeyboard];\n        [self.view.window endEditing:YES];\n        \n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_selectedEvent.cid];\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Edit message\" preferredStyle:UIAlertControllerStyleAlert];\n        \n        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Edit\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n            if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length)\n                [[NetworkConnection sharedInstance] editMessage:self->_selectedEvent.msgid cid:self->_selectedEvent.cid to:self->_selectedEvent.chan msg:((UITextField *)[alert.textFields objectAtIndex:0]).text handler:^(IRCCloudJSONObject *result) {\n                    if(![[result objectForKey:@\"success\"] boolValue]) {\n                        CLS_LOG(@\"Error editing message: %@\", result);\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to edit message, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                        [self presentViewController:alert animated:YES completion:nil];\n                    }\n                }];\n        }]];\n        \n        [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n            textField.text = self->_selectedEvent.msg;\n            textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n        }];\n        \n        [self presentViewController:alert animated:YES completion:nil];\n    } else if([action isEqualToString:@\"Delete File\"]) {\n        [[NetworkConnection sharedInstance] deleteFile:[self->_selectedEvent.entities objectForKey:@\"id\"] handler:^(IRCCloudJSONObject *result) {\n            if([[result objectForKey:@\"success\"] boolValue]) {\n                [self->_eventsView uncacheFile:[self->_selectedEvent.entities objectForKey:@\"id\"]];\n                [self->_eventsView refresh];\n            } else {\n                CLS_LOG(@\"Error deleting file: %@\", result);\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to delete file, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n            }\n        }];\n    } else if([action isEqualToString:@\"Close Preview\"]) {\n        [self->_eventsView closePreview:self->_selectedEvent];\n    } else if([action isEqualToString:@\"Archive\"]) {\n        [[NetworkConnection sharedInstance] archiveBuffer:self->_selectedBuffer.bid cid:self->_selectedBuffer.cid handler:nil];\n    } else if([action isEqualToString:@\"Unarchive\"]) {\n        [[NetworkConnection sharedInstance] unarchiveBuffer:self->_selectedBuffer.bid cid:self->_selectedBuffer.cid handler:nil];\n    } else if([action isEqualToString:@\"Delete\"]) {\n        [self _deleteSelectedBuffer];\n    } else if([action isEqualToString:@\"Leave\"]) {\n        [[NetworkConnection sharedInstance] part:self->_selectedBuffer.name msg:nil cid:self->_selectedBuffer.cid handler:nil];\n    } else if([action isEqualToString:@\"Rejoin\"]) {\n        [[NetworkConnection sharedInstance] join:self->_selectedBuffer.name key:nil cid:self->_selectedBuffer.cid handler:nil];\n    } else if([action isEqualToString:@\"Rename\"]) {\n        [self _renameBuffer:self->_selectedBuffer msg:nil];\n    } else if([action isEqualToString:@\"Ban List\"]) {\n        [[NetworkConnection sharedInstance] mode:@\"b\" chan:self->_selectedBuffer.name cid:self->_selectedBuffer.cid handler:nil];\n    } else if([action isEqualToString:@\"Disconnect\"]) {\n        [[NetworkConnection sharedInstance] disconnect:self->_selectedBuffer.cid msg:nil handler:nil];\n    } else if([action isEqualToString:@\"Reconnect\"]) {\n        [[NetworkConnection sharedInstance] reconnect:self->_selectedBuffer.cid handler:nil];\n    } else if([action isEqualToString:@\"Logout\"]) {\n        [self logout];\n    } else if([action isEqualToString:@\"Ignore List\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        IgnoresTableViewController *itv = [[IgnoresTableViewController alloc] initWithStyle:UITableViewStylePlain];\n        itv.ignores = s.ignores;\n        itv.cid = s.cid;\n        itv.navigationItem.title = @\"Ignore List\";\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:itv];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationPageSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        [self presentViewController:nc animated:YES completion:nil];\n    } else if([action isEqualToString:@\"Mention\"]) {\n        [self.slidingViewController resetTopViewWithAnimations:nil onComplete:^{\n            [self showMentionTip];\n            [self _mention];\n        }];\n    } else if([action isEqualToString:@\"Edit Connection\"]) {\n        [self editConnection];\n    } else if([action isEqualToString:@\"Settings\"]) {\n        [self showSettings];\n    } else if([action isEqualToString:@\"Display Options\"]) {\n        DisplayOptionsViewController *dvc = [[DisplayOptionsViewController alloc] initWithStyle:UITableViewStyleGrouped];\n        dvc.buffer = self->_buffer;\n        dvc.navigationItem.title = self->_titleLabel.text;\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:dvc];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationFormSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        [self presentViewController:nc animated:YES completion:nil];\n    } else if([action isEqualToString:@\"Download Logs\"]) {\n        [self downloadLogs];\n    } else if([action isEqualToString:@\"Add Network\"]) {\n        [self addNetwork];\n    } else if([action isEqualToString:@\"Take a Photo\"] || [action isEqualToString:@\"Take Photo or Video\"]) {\n        if(self.presentedViewController)\n            [self dismissViewControllerAnimated:NO completion:nil];\n        [self choosePhoto:UIImagePickerControllerSourceTypeCamera];\n    } else if([action isEqualToString:@\"Choose Photo\"] || [action isEqualToString:@\"Choose Photo or Video\"]) {\n        if(self.presentedViewController)\n            [self dismissViewControllerAnimated:NO completion:nil];\n        [self choosePhoto:UIImagePickerControllerSourceTypePhotoLibrary];\n    } else if([action isEqualToString:@\"Choose Document\"]) {\n        if(self.presentedViewController)\n            [self dismissViewControllerAnimated:NO completion:nil];\n        [self chooseFile];\n    } else if([action isEqualToString:@\"File Uploads\"]) {\n        [self showUploads];\n    } else if([action isEqualToString:@\"Text Snippets\"]) {\n        [self showPastebins];\n    } else if([action isEqualToString:@\"Start a Text Snippet\"]) {\n        [self startPastebin];\n    } else if([action isEqualToString:@\"Mark All As Read\"]) {\n        [self markAllAsRead];\n    } else if([action isEqualToString:@\"Add A Network\"]) {\n        [self addNetwork];\n    } else if([action isEqualToString:@\"Reorder\"]) {\n        [self _reorder];\n    } else if([action isEqualToString:@\"Invite to Channel\"]) {\n        [self _inviteToChannel];\n    } else if([action isEqualToString:@\"Join a Channel\"]) {\n        [self _joinAChannel];\n    } else if([action isEqualToString:@\"Whois\"]) {\n        if(self->_selectedUser && _selectedUser.nick.length > 0) {\n            if(self->_selectedUser.parted) {\n                [[NetworkConnection sharedInstance] whois:self->_selectedUser.nick server:nil cid:self->_buffer.cid handler:nil];\n            } else {\n                NSString *ircserver = self->_selectedUser.ircserver;\n                if([ircserver rangeOfString:@\"*\"].location != NSNotFound)\n                    ircserver = nil;\n                [[NetworkConnection sharedInstance] whois:self->_selectedUser.nick server:ircserver.length?ircserver:self->_selectedUser.nick cid:self->_buffer.cid handler:nil];\n            }\n        } else if([self->_buffer.type isEqualToString:@\"conversation\"]) {\n            User *u = [[UsersDataSource sharedInstance] getUser:self->_buffer.name cid:self->_buffer.cid];\n            NSString *ircserver = u.ircserver;\n            if([ircserver rangeOfString:@\"*\"].location != NSNotFound)\n                ircserver = nil;\n            [[NetworkConnection sharedInstance] whois:self->_buffer.name server:ircserver.length?ircserver:nil cid:self->_buffer.cid handler:nil];\n        }\n    } else if([action isEqualToString:@\"Send Feedback\"]) {\n        [self sendFeedback];\n    }\n    \n    if(!_selectedUser || !_selectedUser.nick || _selectedUser.nick.length < 1)\n        return;\n    \n    if([action isEqualToString:@\"Copy Hostmask\"]) {\n        UIPasteboard *pb = [UIPasteboard generalPasteboard];\n        NSString *plaintext = [NSString stringWithFormat:@\"%@!%@\", _selectedUser.nick, _selectedUser.hostmask];\n        [pb setValue:plaintext forPasteboardType:(NSString *)kUTTypeUTF8PlainText];\n    } else if([action isEqualToString:@\"Send a Message\"]) {\n        Buffer *b = [[BuffersDataSource sharedInstance] getBufferWithName:self->_selectedUser.nick server:self->_buffer.cid];\n        if(b) {\n            [self bufferSelected:b.bid];\n        } else {\n            [[NetworkConnection sharedInstance] say:[NSString stringWithFormat:@\"/query %@\", _selectedUser.nick] to:nil cid:self->_buffer.cid handler:nil];\n        }\n    } else if([action isEqualToString:@\"Op\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        [[NetworkConnection sharedInstance] mode:[NSString stringWithFormat:@\"+%@ %@\",s?s.MODE_OP:@\"o\",_selectedUser.nick] chan:self->_buffer.name cid:self->_buffer.cid handler:nil];\n    } else if([action isEqualToString:@\"Deop\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        [[NetworkConnection sharedInstance] mode:[NSString stringWithFormat:@\"-%@ %@\",s?s.MODE_OP:@\"o\",_selectedUser.nick] chan:self->_buffer.name cid:self->_buffer.cid handler:nil];\n    } else if([action isEqualToString:@\"Voice\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        [[NetworkConnection sharedInstance] mode:[NSString stringWithFormat:@\"+%@ %@\",s?s.MODE_VOICED:@\"v\",_selectedUser.nick] chan:self->_buffer.name cid:self->_buffer.cid handler:nil];\n    } else if([action isEqualToString:@\"Devoice\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        [[NetworkConnection sharedInstance] mode:[NSString stringWithFormat:@\"-%@ %@\",s?s.MODE_VOICED:@\"v\",_selectedUser.nick] chan:self->_buffer.name cid:self->_buffer.cid handler:nil];\n    } else if([action isEqualToString:@\"Ban\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Add a ban mask\" preferredStyle:UIAlertControllerStyleAlert];\n        \n        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Ban\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n            if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n                [[NetworkConnection sharedInstance] mode:[NSString stringWithFormat:@\"+b %@\", ((UITextField *)[alert.textFields objectAtIndex:0]).text] chan:self->_buffer.name cid:self->_buffer.cid handler:nil];\n            }\n        }]];\n        \n        [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n            if(self->_selectedUser.hostmask.length)\n                textField.text = [NSString stringWithFormat:@\"*!%@\", self->_selectedUser.hostmask];\n            else\n                textField.text = [NSString stringWithFormat:@\"%@!*\", self->_selectedUser.nick];\n            textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n        }];\n        \n        [self presentViewController:alert animated:YES completion:nil];\n    } else if([action isEqualToString:@\"Ignore\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Ignore messages from this mask\" preferredStyle:UIAlertControllerStyleAlert];\n        \n        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Ignore\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n            if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n                [[NetworkConnection sharedInstance] ignore:((UITextField *)[alert.textFields objectAtIndex:0]).text cid:self->_buffer.cid handler:nil];\n            }\n        }]];\n        \n        [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n            if(self->_selectedUser.hostmask.length)\n                textField.text = [NSString stringWithFormat:@\"*!%@\", self->_selectedUser.hostmask];\n            else\n                textField.text = [NSString stringWithFormat:@\"%@!*\", self->_selectedUser.nick];\n            textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n        }];\n        \n        [self presentViewController:alert animated:YES completion:nil];\n    } else if([action isEqualToString:@\"Kick\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:@\"Give a reason for kicking\" preferredStyle:UIAlertControllerStyleAlert];\n        \n        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Kick\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n            if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n                [[NetworkConnection sharedInstance] kick:self->_selectedUser.nick chan:self->_buffer.name msg:((UITextField *)[alert.textFields objectAtIndex:0]).text cid:self->_buffer.cid handler:nil];\n            }\n        }]];\n        \n        [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n            textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n        }];\n        \n        [self presentViewController:alert animated:YES completion:nil];\n    } else if([action isEqualToString:@\"Slack Profile\"]) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@\"%@/team/%@\", s.slackBaseURL, _selectedUser.nick]];\n        [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:url];\n    } else if([action isEqualToString:@\"Reply\"]) {\n        NSString *msgid = self->_selectedEvent.reply;\n        if(!msgid)\n            msgid = self->_selectedEvent.msgid;\n        [self setMsgId:msgid];\n    }\n}\n\n-(void)downloadLogs{\n    LogExportsTableViewController *lvc = [[LogExportsTableViewController alloc] initWithStyle:UITableViewStyleGrouped];\n    lvc.buffer = self->_buffer;\n    lvc.server = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:lvc];\n    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n        nc.modalPresentationStyle = UIModalPresentationFormSheet;\n    else\n        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n    [self presentViewController:nc animated:YES completion:nil];\n}\n\n-(void)showSettings {\n//#if TARGET_OS_MACCATALYST\n//        [[UIApplication sharedApplication] requestSceneSessionActivation:nil userActivity:[[NSUserActivity alloc] initWithActivityType:@\"com.IRCCloud.settings\"] options:nil errorHandler:nil];\n//#else\n        SettingsViewController *svc = [[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];\n        UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:svc];\n        [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n            nc.modalPresentationStyle = UIModalPresentationPageSheet;\n        else\n            nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n        [self presentViewController:nc animated:YES completion:nil];\n//#endif\n}\n\n-(void)logout {\n    [self dismissKeyboard];\n    [self.view.window endEditing:YES];\n    \n    NSURL *documentsPath = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0];\n    NSArray *documents = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:documentsPath includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsHiddenFiles error:nil];\n\n    UIAlertController *alert;\n    if (documents.count) {\n        alert = [UIAlertController alertControllerWithTitle:@\"Logout\" message:[NSString stringWithFormat:@\"You currently have %lu log export%@ stored on this device. %@ will remain on this device after logging out.\", (unsigned long)documents.count, documents.count == 1?@\"\":@\"s\", documents.count == 1?@\"It\":@\"They\"] preferredStyle:UIAlertControllerStyleAlert];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Delete Log Exports\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {\n            for(NSURL *file in [[NSFileManager defaultManager] contentsOfDirectoryAtURL:documentsPath includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsHiddenFiles error:nil]) {\n                if(![file.absoluteString hasSuffix:@\"/\"]) {\n                    CLS_LOG(@\"Removing: %@\", file);\n                    [[NSFileManager defaultManager] removeItemAtURL:file error:nil];\n                }\n            }\n        }]];\n    } else {\n        alert = [UIAlertController alertControllerWithTitle:@\"Logout\" message:@\"Are you sure you want to logout of IRCCloud?\" preferredStyle:UIAlertControllerStyleAlert];\n    }\n    \n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Logout\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {\n        [[NetworkConnection sharedInstance] logout];\n        [self bufferSelected:-1];\n        [(AppDelegate *)([UIApplication sharedApplication].delegate) showLoginView];\n    }]];\n    \n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(BOOL)canBecomeFirstResponder {\n    return YES;\n}\n\n-(BOOL)canPerformAction:(SEL)action withSender:(id)sender {\n    if (action == @selector(paste:)) {\n        return [UIPasteboard generalPasteboard].hasImages;\n    } else if(action == @selector(chooseFGColor) || action == @selector(chooseBGColor) || action == @selector(resetColors)) {\n        return YES;\n    }\n\n    return [super canPerformAction:action withSender:sender];\n}\n\n-(void)resetColors {\n    if(self->_message.selectedRange.length) {\n        NSRange selection = self->_message.selectedRange;\n        NSMutableAttributedString *msg = self->_message.attributedText.mutableCopy;\n        [msg removeAttribute:NSForegroundColorAttributeName range:self->_message.selectedRange];\n        [msg removeAttribute:NSBackgroundColorAttributeName range:self->_message.selectedRange];\n        self->_message.attributedText = msg;\n        self->_message.selectedRange = selection;\n    } else {\n        if([UIColor textareaTextColor] && _message.font)\n            self->_currentMessageAttributes = self->_message.internalTextView.typingAttributes = @{NSForegroundColorAttributeName:[UIColor textareaTextColor], NSFontAttributeName:self->_message.font };\n    }\n}\n\n-(void)chooseFGColor {\n    [self->_colorPickerView updateButtonColors:NO];\n    [UIView animateWithDuration:0.25 animations:^{ self->_colorPickerView.alpha = 1; } completion:nil];\n}\n\n-(void)chooseBGColor {\n    [self->_colorPickerView updateButtonColors:YES];\n    [UIView animateWithDuration:0.25 animations:^{ self->_colorPickerView.alpha = 1; } completion:nil];\n}\n\n-(void)foregroundColorPicked:(UIColor *)color {\n    if(self->_message.selectedRange.length) {\n        NSRange selection = self->_message.selectedRange;\n        NSMutableAttributedString *msg = self->_message.attributedText.mutableCopy;\n        [msg addAttribute:NSForegroundColorAttributeName value:color range:self->_message.selectedRange];\n        self->_message.attributedText = msg;\n        self->_message.selectedRange = selection;\n    } else {\n        NSMutableDictionary *d = [[NSMutableDictionary alloc] initWithDictionary:self->_message.internalTextView.typingAttributes];\n        [d setObject:color forKey:NSForegroundColorAttributeName];\n        self->_message.internalTextView.typingAttributes = d;\n    }\n    [self closeColorPicker];\n}\n\n-(void)backgroundColorPicked:(UIColor *)color {\n    if(self->_message.selectedRange.length) {\n        NSRange selection = self->_message.selectedRange;\n        NSMutableAttributedString *msg = self->_message.attributedText.mutableCopy;\n        [msg addAttribute:NSBackgroundColorAttributeName value:color range:self->_message.selectedRange];\n        self->_message.attributedText = msg;\n        self->_message.selectedRange = selection;\n    } else {\n        NSMutableDictionary *d = [[NSMutableDictionary alloc] initWithDictionary:self->_message.internalTextView.typingAttributes];\n        [d setObject:color forKey:NSBackgroundColorAttributeName];\n        self->_message.internalTextView.typingAttributes = d;\n    }\n    [self closeColorPicker];\n}\n\n-(void)closeColorPicker {\n    [UIView animateWithDuration:0.25 animations:^{ self->_colorPickerView.alpha = 0; } completion:nil];\n}\n\n-(void)paste:(id)sender {\n    if([UIPasteboard generalPasteboard].hasImages && [UIPasteboard generalPasteboard].image && ![UIPasteboard generalPasteboard].hasURLs) {\n        if([UIPasteboard generalPasteboard].image && [[UIPasteboard generalPasteboard] containsPasteboardTypes:@[(__bridge NSString *)kUTTypeGIF]]) {\n            UIImage *img = [UIPasteboard generalPasteboard].image;\n            NSData *gifData = [[UIPasteboard generalPasteboard] dataForPasteboardType:(__bridge NSString *)kUTTypeGIF];\n            if(img != nil && gifData != nil)\n                [self _imagePickerController:[UIImagePickerController new] didFinishPickingMediaWithInfo:@{UIImagePickerControllerOriginalImage:img, @\"gifData\":gifData}];\n            return;\n        }\n        [self _imagePickerController:[UIImagePickerController new] didFinishPickingMediaWithInfo:@{UIImagePickerControllerOriginalImage:[UIPasteboard generalPasteboard].image}];\n    } else if([UIPasteboard generalPasteboard].hasStrings) {\n        NSMutableString *text = @\"\".mutableCopy;\n        for(NSString *s in [UIPasteboard generalPasteboard].strings) {\n            if(text.length)\n                [text appendString:@\" \"];\n            [text appendString:s];\n        }\n        \n        if(text.length) {\n            NSMutableAttributedString *msg = self->_message.attributedText.mutableCopy;\n            BOOL shouldMoveCursor = self->_message.selectedRange.location == 0 || self->_message.selectedRange.location == msg.length;\n            if(self->_message.selectedRange.length > 0)\n                [msg deleteCharactersInRange:self->_message.selectedRange];\n\n            NSDictionary *attributes = @{};\n            \n            if (self->_message.font && self->_message.textColor) {\n                attributes = @{NSFontAttributeName:self->_message.font,NSForegroundColorAttributeName:self->_message.textColor};\n            }\n            [msg insertAttributedString:[[NSAttributedString alloc] initWithString:text attributes:attributes] atIndex:self->_message.selectedRange.location];\n            \n            [self->_message setAttributedText:msg];\n            if(shouldMoveCursor)\n                self->_message.selectedRange = NSMakeRange(msg.length, 0);\n        }\n    }\n}\n\n-(void)pasteRich:(id)sender {\n    NSMutableAttributedString *msg = self->_message.attributedText.mutableCopy;\n    BOOL shouldMoveCursor = self->_message.selectedRange.location == 0 || self->_message.selectedRange.location == msg.length;\n\n    if([[UIPasteboard generalPasteboard] valueForPasteboardType:@\"IRC formatting type\"]) {\n        NSMutableAttributedString *msg = self->_message.attributedText.mutableCopy;\n        if(self->_message.selectedRange.length > 0)\n            [msg deleteCharactersInRange:self->_message.selectedRange];\n        [msg insertAttributedString:[ColorFormatter format:[[NSString alloc] initWithData:[[UIPasteboard generalPasteboard] valueForPasteboardType:@\"IRC formatting type\"] encoding:NSUTF8StringEncoding] defaultColor:self->_message.textColor mono:NO linkify:NO server:nil links:nil] atIndex:self->_message.internalTextView.selectedRange.location];\n        \n        [self->_message setAttributedText:msg];\n        if(shouldMoveCursor)\n            self->_message.selectedRange = NSMakeRange(msg.length, 0);\n    } else if([[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString *)kUTTypeRTF]) {\n        NSMutableAttributedString *msg = self->_message.attributedText.mutableCopy;\n        if(self->_message.selectedRange.length > 0)\n            [msg deleteCharactersInRange:self->_message.selectedRange];\n        [msg insertAttributedString:[ColorFormatter stripUnsupportedAttributes:[[NSAttributedString alloc] initWithData:[[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString *)kUTTypeRTF] options:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType} documentAttributes:nil error:nil] fontSize:self->_message.font.pointSize] atIndex:self->_message.internalTextView.selectedRange.location];\n        \n        [self->_message setAttributedText:msg];\n        if(shouldMoveCursor)\n            self->_message.selectedRange = NSMakeRange(msg.length, 0);\n    } else if([[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString *)kUTTypeFlatRTFD]) {\n        NSMutableAttributedString *msg = self->_message.attributedText.mutableCopy;\n        if(self->_message.selectedRange.length > 0)\n            [msg deleteCharactersInRange:self->_message.selectedRange];\n        [msg insertAttributedString:[ColorFormatter stripUnsupportedAttributes:[[NSAttributedString alloc] initWithData:[[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString *)kUTTypeFlatRTFD] options:@{NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType} documentAttributes:nil error:nil] fontSize:self->_message.font.pointSize] atIndex:self->_message.internalTextView.selectedRange.location];\n        \n        [self->_message setAttributedText:msg];\n        if(shouldMoveCursor)\n            self->_message.selectedRange = NSMakeRange(msg.length, 0);\n    } else if([[UIPasteboard generalPasteboard] valueForPasteboardType:@\"Apple Web Archive pasteboard type\"]) {\n        NSDictionary *d = [NSPropertyListSerialization propertyListWithData:[[UIPasteboard generalPasteboard] valueForPasteboardType:@\"Apple Web Archive pasteboard type\"] options:NSPropertyListImmutable format:NULL error:NULL];\n        NSMutableAttributedString *msg = self->_message.attributedText.mutableCopy;\n        if(self->_message.selectedRange.length > 0)\n            [msg deleteCharactersInRange:self->_message.selectedRange];\n        [msg insertAttributedString:[ColorFormatter stripUnsupportedAttributes:[[NSAttributedString alloc] initWithData:[[d objectForKey:@\"WebMainResource\"] objectForKey:@\"WebResourceData\"] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} documentAttributes:nil error:nil] fontSize:self->_message.font.pointSize] atIndex:self->_message.internalTextView.selectedRange.location];\n        \n        [self->_message setAttributedText:msg];\n        if(shouldMoveCursor)\n            self->_message.selectedRange = NSMakeRange(msg.length, 0);\n    } else if([UIPasteboard generalPasteboard].hasStrings) {\n        [self paste:nil];\n    }\n}\n\n- (void)LinkLabel:(LinkLabel *)label didSelectLinkWithTextCheckingResult:(NSTextCheckingResult *)result {\n    [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:result.URL];\n}\n\n-(NSArray<UIKeyCommand *> *)keyCommands {\n    NSArray *commands = @[\n             [UIKeyCommand keyCommandWithInput:@\"k\" modifierFlags:UIKeyModifierCommand action:@selector(jumpToChannel) discoverabilityTitle:@\"Jump to channel\"],\n             [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:UIKeyModifierCommand action:@selector(selectPrevious) discoverabilityTitle:@\"Switch to previous channel\"],\n             [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:UIKeyModifierCommand action:@selector(selectNext) discoverabilityTitle:@\"Switch to next channel\"],\n             [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:UIKeyModifierCommand|UIKeyModifierShift action:@selector(selectPreviousUnread) discoverabilityTitle:@\"Switch to previous unread channel\"],\n             [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:UIKeyModifierCommand|UIKeyModifierShift action:@selector(selectNextUnread) discoverabilityTitle:@\"Switch to next unread channel\"],\n             [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:UIKeyModifierAlternate action:@selector(selectPrevious)],\n             [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:UIKeyModifierAlternate action:@selector(selectNext)],\n             [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:UIKeyModifierAlternate|UIKeyModifierShift action:@selector(selectPreviousUnread)],\n             [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:UIKeyModifierAlternate|UIKeyModifierShift action:@selector(selectNextUnread)],\n             [UIKeyCommand keyCommandWithInput:@\"\\t\" modifierFlags:0 action:@selector(onTabPressed:) discoverabilityTitle:@\"Complete nicknames and channels\"],\n             [UIKeyCommand keyCommandWithInput:@\"r\" modifierFlags:UIKeyModifierCommand action:@selector(markAsRead) discoverabilityTitle:@\"Mark channel as read\"],\n             [UIKeyCommand keyCommandWithInput:@\"r\" modifierFlags:UIKeyModifierCommand|UIKeyModifierShift action:@selector(markAllAsRead) discoverabilityTitle:@\"Mark all channels as read\"],\n             [UIKeyCommand keyCommandWithInput:@\"b\" modifierFlags:UIKeyModifierCommand action:@selector(toggleBoldface:) discoverabilityTitle:@\"Bold\"],\n             [UIKeyCommand keyCommandWithInput:@\"i\" modifierFlags:UIKeyModifierCommand action:@selector(toggleItalics:) discoverabilityTitle:@\"Italic\"],\n             [UIKeyCommand keyCommandWithInput:@\"u\" modifierFlags:UIKeyModifierCommand action:@selector(toggleUnderline:) discoverabilityTitle:@\"Underline\"],\n             [UIKeyCommand keyCommandWithInput:@\"UIKeyInputPageUp\" modifierFlags:0 action:@selector(onPgUpPressed:)],\n             [UIKeyCommand keyCommandWithInput:@\"UIKeyInputPageDown\" modifierFlags:0 action:@selector(onPgDownPressed:)],\n             ];\n\n#if !TARGET_OS_MACCATALYST\n    if (@available(iOS 15.0, *)) {\n        for(UIKeyCommand *c in commands) {\n            c.wantsPriorityOverSystemBehavior = YES;\n        }\n    }\n#endif\n    return commands;\n}\n\n-(void)getMessageAttributesBold:(BOOL *)bold italic:(BOOL *)italic underline:(BOOL *)underline {\n    UIFont *font = [self->_message.internalTextView.typingAttributes objectForKey:NSFontAttributeName];\n    \n    *bold = font.fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold;\n    *italic = font.fontDescriptor.symbolicTraits & UIFontDescriptorTraitItalic;\n    *underline = [[self->_message.internalTextView.typingAttributes objectForKey:NSUnderlineStyleAttributeName] intValue] == NSUnderlineStyleSingle;\n}\n\n-(void)setMessageAttributesBold:(BOOL)bold italic:(BOOL)italic underline:(BOOL)underline {\n    UIFont *font = [self->_message.internalTextView.typingAttributes objectForKey:NSFontAttributeName];\n    UIFontDescriptorSymbolicTraits traits = 0;\n    \n    if(bold)\n        traits |= UIFontDescriptorTraitBold;\n    \n    if(italic)\n        traits |= UIFontDescriptorTraitItalic;\n    \n    font = [UIFont fontWithDescriptor:[font.fontDescriptor fontDescriptorWithSymbolicTraits:traits] size:font.pointSize];\n    \n    NSMutableDictionary *attributes = self->_message.internalTextView.typingAttributes.mutableCopy;\n    [attributes setObject:@(underline?NSUnderlineStyleSingle:NSUnderlineStyleNone) forKey:NSUnderlineStyleAttributeName];\n    [attributes setObject:font forKey:NSFontAttributeName];\n    self->_message.internalTextView.typingAttributes = attributes;\n}\n\n-(void)toggleBoldface:(UIKeyCommand *)sender {\n    BOOL hasBold, hasItalic, hasUnderline;\n    \n    [self getMessageAttributesBold:&hasBold italic:&hasItalic underline:&hasUnderline];\n    [self setMessageAttributesBold:!hasBold italic:hasItalic underline:hasUnderline];\n}\n\n-(void)toggleItalics:(UIKeyCommand *)sender {\n    BOOL hasBold, hasItalic, hasUnderline;\n    \n    [self getMessageAttributesBold:&hasBold italic:&hasItalic underline:&hasUnderline];\n    [self setMessageAttributesBold:hasBold italic:!hasItalic underline:hasUnderline];\n}\n\n-(void)toggleUnderline:(UIKeyCommand *)sender {\n    BOOL hasBold, hasItalic, hasUnderline;\n    \n    [self getMessageAttributesBold:&hasBold italic:&hasItalic underline:&hasUnderline];\n    [self setMessageAttributesBold:hasBold italic:hasItalic underline:!hasUnderline];\n}\n\n-(void)onPgUpPressed:(UIKeyCommand *)sender {\n    [self->_eventsView.tableView visibleCells];\n    NSIndexPath *first = [self->_eventsView.tableView indexPathsForVisibleRows].firstObject;\n    if(first && first.row > 0) {\n        [self->_eventsView.tableView scrollToRowAtIndexPath:first atScrollPosition:UITableViewScrollPositionBottom animated:YES];\n    }\n}\n\n-(void)onPgDownPressed:(UIKeyCommand *)sender {\n    [self->_eventsView.tableView visibleCells];\n    NSIndexPath *last = [self->_eventsView.tableView indexPathsForVisibleRows].lastObject;\n    if(last && last.row > 0) {\n        [self->_eventsView.tableView scrollToRowAtIndexPath:last atScrollPosition:UITableViewScrollPositionTop animated:YES];\n    }\n}\n\n-(void)jumpToChannel {\n    if(self.slidingViewController.underLeftViewController)\n        [self.slidingViewController anchorTopViewTo:ECRight];\n    [self->_buffersView focusSearchText];\n}\n\n-(void)selectPrevious {\n    [self->_buffersView prev];\n}\n\n-(void)selectNext {\n    [self->_buffersView next];\n}\n\n-(void)selectPreviousUnread {\n    [self->_buffersView prevUnread];\n}\n\n-(void)selectNextUnread {\n    [self->_buffersView nextUnread];\n}\n\n-(void)sendFeedback {\n    [[NetworkConnection sharedInstance] sendFeedbackReport:self];\n}\n\n-(void)joinFeedback {\n    [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:[NSURL URLWithString:@\"irc://irc.irccloud.com/%23feedback\"]];\n}\n\n-(void)joinBeta {\n    [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:[NSURL URLWithString:@\"https://testflight.apple.com/join/MApr7Une\"]];\n}\n\n-(void)FAQ {\n    [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:[NSURL URLWithString:@\"https://www.irccloud.com/faq\"]];\n}\n\n-(void)versionHistory {\n    [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:[NSURL URLWithString:@\"https://github.com/irccloud/ios/releases\"]];\n}\n\n-(void)openSourceLicenses {\n    LicenseViewController *lvc = [[LicenseViewController alloc] init];\n    \n    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:lvc];\n    [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n        nc.modalPresentationStyle = UIModalPresentationPageSheet;\n    else\n        nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n    if(self.presentedViewController)\n        [self dismissViewControllerAnimated:NO completion:nil];\n    [self presentViewController:nc animated:YES completion:nil];\n}\n\n-(void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {\n    [self->_message becomeFirstResponder];\n    [super pressesBegan:presses withEvent:event];\n}\n\n-(void)onTabPressed:(UIKeyCommand *)sender {\n    if(!self->_message.internalTextView.isFirstResponder)\n        [self->_message.internalTextView becomeFirstResponder];\n    if(self->_nickCompletionView.count == 0)\n        [self updateSuggestions:YES];\n    if(self->_nickCompletionView.count > 0) {\n        NSInteger s = self->_nickCompletionView.selection;\n        if(s == -1 || s == self->_nickCompletionView.count - 1)\n            s = 0;\n        else\n            s++;\n        [self->_nickCompletionView setSelection:s];\n        NSString *text = self->_message.text;\n        self->_message.delegate = nil;\n        if(text.length == 0) {\n            if(self->_buffer.serverIsSlack)\n                self->_message.text = [NSString stringWithFormat:@\"@%@\", [self->_nickCompletionView suggestion]];\n            else\n                self->_message.text = [self->_nickCompletionView suggestion];\n        } else {\n            while(text.length > 0 && [text characterAtIndex:text.length - 1] != ' ') {\n                text = [text substringToIndex:text.length - 1];\n            }\n            if(self->_buffer.serverIsSlack)\n                text = [text stringByAppendingString:@\"@\"];\n            text = [text stringByAppendingString:[self->_nickCompletionView suggestion]];\n            self->_message.text = text;\n        }\n        if([text rangeOfString:@\" \"].location == NSNotFound && !_buffer.serverIsSlack)\n            self->_message.text = [self->_message.text stringByAppendingString:@\":\"];\n        self->_message.delegate = self;\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/NamesListTableViewController.h",
    "content": "//\n//  NamesListTableViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"IRCCloudJSONObject.h\"\n\n@interface NamesListTableViewController : UITableViewController {\n    IRCCloudJSONObject *_event;\n    NSArray *_data;\n}\n@property (strong) IRCCloudJSONObject *event;\n-(void)refresh;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/NamesListTableViewController.m",
    "content": "//\n//  NamesListTableViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import \"NamesListTableViewController.h\"\n#import \"LinkTextView.h\"\n#import \"ColorFormatter.h\"\n#import \"NetworkConnection.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@interface NamesTableCell : UITableViewCell {\n    LinkTextView *_info;\n}\n@property (readonly) LinkTextView *info;\n@end\n\n@implementation NamesTableCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        \n        self->_info = [[LinkTextView alloc] init];\n        self->_info.font = [UIFont systemFontOfSize:FONT_SIZE];\n        self->_info.editable = NO;\n        self->_info.scrollEnabled = NO;\n        self->_info.selectable = NO;\n        self->_info.textContainerInset = UIEdgeInsetsZero;\n        self->_info.backgroundColor = [UIColor clearColor];\n        self->_info.textColor = [UIColor messageTextColor];\n        [self.contentView addSubview:self->_info];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n\t[super layoutSubviews];\n\t\n\tCGRect frame = [self.contentView bounds];\n    frame.origin.x = 6;\n    frame.origin.y = 6;\n    frame.size.width -= 12;\n    self->_info.frame = frame;\n}\n\n-(void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n@end\n\n@implementation NamesListTableViewController\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed)];\n    self.tableView.backgroundColor = [[UITableViewCell appearance] backgroundColor];\n    [self refresh];\n}\n\n-(void)refresh {\n    NSMutableArray *data = [[NSMutableArray alloc] init];\n    \n    for(NSDictionary *user in [self->_event objectForKey:@\"members\"]) {\n        NSMutableDictionary *u = [[NSMutableDictionary alloc] initWithDictionary:user];\n        NSString *name;\n        if([[user objectForKey:@\"mode\"] length])\n            name = [NSString stringWithFormat:@\"%c%@%c (+%@)\", BOLD, [user objectForKey:@\"nick\"], CLEAR, [user objectForKey:@\"mode\"]];\n        else\n            name = [NSString stringWithFormat:@\"%c%@\", BOLD, [user objectForKey:@\"nick\"]];\n        NSString *s = [NSString stringWithFormat:@\"%@%c%@%c\",name,CLEAR,[[user objectForKey:@\"away\"] intValue]?@\" [away]\":@\"\", ITALICS];\n        if([[user objectForKey:@\"usermask\"] length])\n            s = [s stringByAppendingFormat:@\"\\n%@\", [user objectForKey:@\"usermask\"]];\n        NSAttributedString *formatted = [ColorFormatter format:s defaultColor:[UITableViewCell appearance].textLabelColor mono:NO linkify:NO server:nil links:nil];\n        [u setObject:formatted forKey:@\"formatted\"];\n        [u setObject:@([LinkTextView heightOfString:formatted constrainedToWidth:self.tableView.bounds.size.width - 6 - 12]) forKey:@\"height\"];\n        [data addObject:u];\n    }\n    \n    self->_data = data;\n    [self.tableView reloadData];\n}\n\n-(void)doneButtonPressed {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n#pragma mark - Table view data source\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    return [[row objectForKey:@\"height\"] floatValue] + 12;\n}\n\n-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return [self->_data count];\n}\n\n-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NamesTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"namecell\"];\n    if(!cell)\n        cell = [[NamesTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"namecell\"];\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    cell.info.attributedText = [row objectForKey:@\"formatted\"];\n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [tableView deselectRowAtIndexPath:indexPath animated:NO];\n    [self dismissViewControllerAnimated:YES completion:nil];\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    [[NetworkConnection sharedInstance] say:[NSString stringWithFormat:@\"/query %@\", [row objectForKey:@\"nick\"]] to:nil cid:self->_event.cid handler:nil];\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/NetworkConnection.h",
    "content": "//\n//  NetworkConnection.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <SystemConfiguration/SystemConfiguration.h>\n#import \"WebSocket.h\"\n#import \"SBJson5.h\"\n#import \"ServersDataSource.h\"\n#import \"BuffersDataSource.h\"\n#import \"ChannelsDataSource.h\"\n#import \"UsersDataSource.h\"\n#import \"EventsDataSource.h\"\n#import \"NotificationsDataSource.h\"\n#import \"AvatarsDataSource.h\"\n#import \"CSURITemplate.h\"\n\nextern NSString *IRCCLOUD_HOST;\nextern NSString *IRCCLOUD_PATH;\n\nextern NSString *kIRCCloudConnectivityNotification;\nextern NSString *kIRCCloudEventNotification;\nextern NSString *kIRCCloudBacklogStartedNotification;\nextern NSString *kIRCCloudBacklogFailedNotification;\nextern NSString *kIRCCloudBacklogCompletedNotification;\nextern NSString *kIRCCloudBacklogProgressNotification;\n\nextern NSString *kIRCCloudEventKey;\n\ntypedef enum {\n    kIRCEventUserInfo,\n    kIRCEventMakeServer,\n    kIRCEventMakeBuffer,\n    kIRCEventDeleteBuffer,\n    kIRCEventBufferMsg,\n    kIRCEventHeartbeatEcho,\n    kIRCEventChannelInit,\n    kIRCEventChannelTopic,\n    kIRCEventJoin,\n    kIRCEventPart,\n    kIRCEventNickChange,\n    kIRCEventQuit,\n    kIRCEventMemberUpdates,\n    kIRCEventUserChannelMode,\n    kIRCEventBufferArchived,\n    kIRCEventBufferUnarchived,\n    kIRCEventRenameConversation,\n    kIRCEventStatusChanged,\n    kIRCEventConnectionDeleted,\n    kIRCEventAway,\n    kIRCEventSelfBack,\n    kIRCEventKick,\n    kIRCEventChannelMode,\n    kIRCEventChannelTimestamp,\n    kIRCEventSelfDetails,\n    kIRCEventUserMode,\n    kIRCEventSetIgnores,\n    kIRCEventBadChannelKey,\n    kIRCEventOpenBuffer,\n    kIRCEventBanList,\n    kIRCEventWhoList,\n    kIRCEventWhois,\n    kIRCEventNamesList,\n    kIRCEventLinkChannel,\n    kIRCEventListResponseFetching,\n    kIRCEventListResponse,\n    kIRCEventListResponseTooManyChannels,\n    kIRCEventConnectionLag,\n    kIRCEventGlobalMsg,\n    kIRCEventAcceptList,\n    kIRCEventReorderConnections,\n    kIRCEventChannelTopicIs,\n    kIRCEventServerMap,\n    kIRCEventSessionDeleted,\n    kIRCEventQuietList,\n    kIRCEventBanExceptionList,\n    kIRCEventInviteList,\n    kIRCEventWhoSpecialResponse,\n    kIRCEventModulesList,\n    kIRCEventChannelQuery,\n    kIRCEventLinksResponse,\n    kIRCEventWhoWas,\n    kIRCEventTraceResponse,\n    kIRCEventLogExportFinished,\n    kIRCEventAvatarChange,\n    kIRCEventChanFilterList,\n    kIRCEventAuthFailure,\n    kIRCEventTextList,\n    kIRCEventAlert,\n    kIRCEventMessageChanged,\n    kIRCEventUserTyping,\n    kIRCEventRefresh\n} kIRCEvent;\n\ntypedef enum {\n    kIRCCloudStateDisconnected,\n    kIRCCloudStateConnecting,\n    kIRCCloudStateConnected\n} kIRCCloudState;\n\ntypedef enum {\n    kIRCCloudUnreachable,\n    kIRCCloudReachable,\n    kIRCCloudUnknown\n} kIRCCloudReachability;\n\ntypedef void (^IRCCloudAPIResultHandler)(IRCCloudJSONObject *result);\n\n@interface NetworkConnection : NSObject<WebSocketDelegate> {\n    WebSocket *_socket;\n    SBJson5Parser *_parser;\n    SBJson5Writer *_writer;\n    ServersDataSource *_servers;\n    BuffersDataSource *_buffers;\n    ChannelsDataSource *_channels;\n    UsersDataSource *_users;\n    EventsDataSource *_events;\n    NotificationsDataSource *_notifications;\n    AvatarsDataSource *_avatars;\n    NSMutableArray *_oobQueue;\n    NSMutableDictionary *_awayOverride;\n    NSTimer *_idleTimer;\n    NSTimeInterval _idleInterval;\n    int _totalBuffers;\n    int _numBuffers;\n    int _lastReqId;\n    int _currentCount;\n    int _totalCount;\n    int _currentBid;\n    int _failCount;\n    NSTimeInterval _OOBStartTime;\n    NSTimeInterval _longestEventTime;\n    NSString *_longestEventType;\n    BOOL _resuming;\n    BOOL _notifier;\n    NSTimeInterval _firstEID;\n    NSString *_streamId;\n    int _accrued;\n    BOOL _ready;\n    BOOL _mock;\n    kIRCCloudState _state;\n    NSDictionary *_userInfo;\n    NSDictionary *_prefs;\n    NSDictionary *_config;\n    NSTimeInterval _clockOffset;\n    NSTimeInterval _reconnectTimestamp;\n    NSOperationQueue *_queue;\n    SCNetworkReachabilityRef _reachability;\n    BOOL _reachabilityValid;\n    NSDictionary *_parserMap;\n    NSString *_globalMsg;\n    NSString *_session;\n    int _keychainFailCount;\n    NSTimeInterval _highestEID;\n    NSMutableDictionary *_resultHandlers;\n    NSMutableArray *_pendingEdits;\n    id _httpMetric;\n    NSURLSession *_urlSession;\n    NSTimer *_serializeTimer;\n}\n@property (readonly) NSDictionary *parserMap;\n@property (readonly) kIRCCloudState state;\n@property NSDictionary *userInfo;\n@property (readonly) NSTimeInterval clockOffset;\n@property NSTimeInterval idleInterval;\n@property NSTimeInterval reconnectTimestamp;\n@property NSTimeInterval highestEID;\n@property BOOL notifier, reachabilityValid, mock;\n@property (readonly) kIRCCloudReachability reachable;\n@property NSString *globalMsg;\n@property int failCount;\n@property NSString *session;\n@property NSDictionary *config;\n@property (readonly) BOOL ready;\n@property (readonly) NSOperationQueue *queue;\n@property CSURITemplate *fileURITemplate, *pasteURITemplate, *avatarURITemplate, *avatarRedirectURITemplate;\n@property SCNetworkReachabilityRef reachability;\n@property (readonly) NSURLSession *urlSession;\n\n\n+(NetworkConnection*)sharedInstance;\n+(void)sync;\n+(void)sync:(NSURL *)file1 with:(NSURL *)file2;\n+(BOOL)shouldReconnect;\n-(BOOL)isWifi;\n-(void)serialize;\n-(NSDictionary *)prefs;\n-(void)connect:(BOOL)notifier;\n-(void)disconnect;\n-(void)clearPrefs;\n-(void)scheduleIdleTimer;\n-(void)cancelIdleTimer;\n-(void)cancelPendingBacklogRequests;\n-(void)requestBacklogForBuffer:(int)bid server:(int)cid completion:(void (^)(BOOL))completionHandler;\n-(void)requestBacklogForBuffer:(int)bid server:(int)cid beforeId:(NSTimeInterval)eid completion:(void (^)(BOOL))completionHandler;\n-(id)fetchOOB:(NSString *)url;\n-(void)logout;\n-(void)fail;\n-(void)requestArchives:(int)cid;\n-(void)setLastSelectedBID:(int)bid;\n-(void)parse:(NSDictionary *)object backlog:(BOOL)backlog;\n-(void)sendFeedbackReport:(UIViewController *)delegate;\n-(void)updateAPIHost:(NSString *)host;\n\n//WebSocket\n-(int)say:(NSString *)message to:(NSString *)to cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)reply:(NSString *)message to:(NSString *)to cid:(int)cid msgid:(NSString *)msgid handler:(IRCCloudAPIResultHandler)handler;\n-(int)heartbeat:(int)selectedBuffer cid:(int)cid bid:(int)bid lastSeenEid:(NSTimeInterval)lastSeenEid handler:(IRCCloudAPIResultHandler)handler;\n-(int)heartbeat:(int)selectedBuffer cids:(NSArray *)cids bids:(NSArray *)bids lastSeenEids:(NSArray *)lastSeenEids handler:(IRCCloudAPIResultHandler)handler;\n-(int)join:(NSString *)channel key:(NSString *)key cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)part:(NSString *)channel msg:(NSString *)msg cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)kick:(NSString *)nick chan:(NSString *)chan msg:(NSString *)msg cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)mode:(NSString *)mode chan:(NSString *)chan cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)invite:(NSString *)nick chan:(NSString *)chan cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)archiveBuffer:(int)bid cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)unarchiveBuffer:(int)bid cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)deleteBuffer:(int)bid cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)deleteServer:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)addServer:(NSString *)hostname port:(int)port ssl:(int)ssl netname:(NSString *)netname nick:(NSString *)nick realname:(NSString *)realname serverPass:(NSString *)serverPass nickservPass:(NSString *)nickservPass joinCommands:(NSString *)joinCommands channels:(NSString *)channels handler:(IRCCloudAPIResultHandler)handler;\n-(int)editServer:(int)cid hostname:(NSString *)hostname port:(int)port ssl:(int)ssl netname:(NSString *)netname nick:(NSString *)nick realname:(NSString *)realname serverPass:(NSString *)serverPass nickservPass:(NSString *)nickservPass joinCommands:(NSString *)joinCommands handler:(IRCCloudAPIResultHandler)handler;\n-(int)ignore:(NSString *)mask cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)unignore:(NSString *)mask cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)setPrefs:(NSString *)prefs handler:(IRCCloudAPIResultHandler)handler;\n-(int)setRealname:(NSString *)realname highlights:(NSString *)highlights autoaway:(BOOL)autoaway handler:(IRCCloudAPIResultHandler)handler;\n-(int)ns_help_register:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)setNickservPass:(NSString *)nspass cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)whois:(NSString *)nick server:(NSString *)server cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)topic:(NSString *)topic chan:(NSString *)chan cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)back:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)disconnect:(int)cid msg:(NSString *)msg handler:(IRCCloudAPIResultHandler)handler;\n-(int)reconnect:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(int)reorderConnections:(NSString *)cids handler:(IRCCloudAPIResultHandler)handler;\n-(int)resendVerifyEmailWithHandler:(IRCCloudAPIResultHandler)handler;\n-(int)changeEmail:(NSString *)email password:(NSString *)password handler:(IRCCloudAPIResultHandler)handler;\n-(int)deleteFile:(NSString *)fileID handler:(IRCCloudAPIResultHandler)handler;\n-(int)paste:(NSString *)name contents:(NSString *)contents extension:(NSString *)extension handler:(IRCCloudAPIResultHandler)handler;\n-(int)deletePaste:(NSString *)pasteID handler:(IRCCloudAPIResultHandler)handler;\n-(int)editPaste:(NSString *)pasteID name:(NSString *)name contents:(NSString *)contents extension:(NSString *)extension handler:(IRCCloudAPIResultHandler)handler;\n-(int)changePassword:(NSString *)password newPassword:(NSString *)newPassword handler:(IRCCloudAPIResultHandler)handler;\n-(int)deleteAccount:(NSString *)password handler:(IRCCloudAPIResultHandler)handler;\n-(int)exportLog:(NSString *)timezone cid:(int)cid bid:(int)bid handler:(IRCCloudAPIResultHandler)handler;\n-(int)renameChannel:(NSString *)name cid:(int)cid bid:(int)bid handler:(IRCCloudAPIResultHandler)handler;\n-(int)renameConversation:(NSString *)name cid:(int)cid bid:(int)bid handler:(IRCCloudAPIResultHandler)handler;\n-(int)setAvatar:(NSString *)avatarId orgId:(int)orgId handler:(IRCCloudAPIResultHandler)resultHandler;\n-(int)setAvatar:(NSString *)avatarId cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler;\n-(int)setNetworkName:(NSString *)name cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler;\n-(int)deleteMessage:(NSString *)msgId cid:(int)cid to:(NSString *)to handler:(IRCCloudAPIResultHandler)handler;\n-(int)editMessage:(NSString *)msgId cid:(int)cid to:(NSString *)to msg:(NSString *)msg handler:(IRCCloudAPIResultHandler)handler;\n-(int)typing:(NSString *)value cid:(int)cid to:(NSString *)to handler:(IRCCloudAPIResultHandler)handler;\n-(int)redact:(NSString *)msgId cid:(int)cid to:(NSString *)to reason:(NSString *)reason handler:(IRCCloudAPIResultHandler)handler;\n\n//GET\n-(void)requestConfigurationWithHandler:(IRCCloudAPIResultHandler)handler;\n-(void)getFiles:(int)page handler:(IRCCloudAPIResultHandler)handler;\n-(void)getPastebins:(int)page handler:(IRCCloudAPIResultHandler)handler;\n-(void)propertiesForFile:(NSString *)fileID handler:(IRCCloudAPIResultHandler)handler;\n-(void)getLogExportsWithHandler:(IRCCloudAPIResultHandler)handler;\n\n//POST\n-(void)requestAuthTokenWithHandler:(IRCCloudAPIResultHandler)handler;\n-(void)login:(NSString *)email password:(NSString *)password token:(NSString *)token handler:(IRCCloudAPIResultHandler)handler;\n-(void)login:(NSURL *)accessLink handler:(IRCCloudAPIResultHandler)handler;\n-(void)signup:(NSString *)email password:(NSString *)password realname:(NSString *)realname token:(NSString *)token handler:(IRCCloudAPIResultHandler)handler;\n-(void)POSTsay:(NSString *)message to:(NSString *)to cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n-(void)POSTreply:(NSString *)message to:(NSString *)to cid:(int)cid msgid:(NSString *)msgid handler:(IRCCloudAPIResultHandler)handler;\n-(void)POSTheartbeat:(int)selectedBuffer cid:(int)cid bid:(int)bid lastSeenEid:(NSTimeInterval)lastSeenEid handler:(IRCCloudAPIResultHandler)handler;\n-(void)POSTheartbeat:(int)selectedBuffer cids:(NSArray *)cids bids:(NSArray *)bids lastSeenEids:(NSArray *)lastSeenEids handler:(IRCCloudAPIResultHandler)handler;\n-(void)registerAPNs:(NSData *)token fcm:(NSString *)fcm handler:(IRCCloudAPIResultHandler)handler;\n-(void)unregisterAPNs:(NSData *)token fcm:(NSString *)fcm session:(NSString *)session handler:(IRCCloudAPIResultHandler)handler;\n-(void)requestAccessLink:(NSString *)email token:(NSString *)token handler:(IRCCloudAPIResultHandler)handler;\n-(void)requestPasswordReset:(NSString *)email token:(NSString *)token handler:(IRCCloudAPIResultHandler)handler;\n-(void)finalizeUpload:(NSString *)uploadID filename:(NSString *)filename originalFilename:(NSString *)originalFilename avatar:(BOOL)avatar orgId:(int)orgId cid:(int)cid handler:(IRCCloudAPIResultHandler)handler;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/NetworkConnection.m",
    "content": "//\n//  NetworkConnection.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <CoreTelephony/CTTelephonyNetworkInfo.h>\n#import <MessageUI/MFMailComposeViewController.h>\n#import <MobileCoreServices/UTCoreTypes.h>\n#import <Intents/Intents.h>\n#import <IntentsUI/IntentsUI.h>\n#import \"NetworkConnection.h\"\n#import \"HandshakeHeader.h\"\n#import \"IRCCloudJSONObject.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"ImageCache.h\"\n#import \"TrustKit.h\"\n#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n@import Firebase;\n\nNSURL *__logfile;\nNSOperationQueue *__logQueue;\n\nvoid FirebaseLog(NSString *format, ...) {\n    if (!format) {\n        return;\n    }\n\n    va_list args;\n#ifdef CRASHLYTICS_TOKEN\n    va_start(args, format);\n    [[FIRCrashlytics crashlytics] logWithFormat:format arguments:args];\n    va_end(args);\n#endif\n    va_start(args, format);\n    NSString *s = [[NSString alloc] initWithFormat:format arguments:args];\n    va_end(args);\n\n    [__logQueue addOperationWithBlock:^{\n        if(__logfile) {\n            NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:__logfile.path];\n            if(!fileHandle) {\n                [[NSFileManager defaultManager] createFileAtPath:__logfile.path contents:nil attributes:nil];\n                fileHandle = [NSFileHandle fileHandleForWritingAtPath:__logfile.path];\n            }\n            [fileHandle seekToEndOfFile];\n            [fileHandle writeData:[s dataUsingEncoding:NSUTF8StringEncoding]];\n            [fileHandle writeData:[@\"\\n\" dataUsingEncoding:NSUTF8StringEncoding]];\n            [fileHandle closeFile];\n        }\n\n        NSLog(@\"%@\", s);\n    }];\n}\n\nNSString *_userAgent = nil;\nNSString *kIRCCloudConnectivityNotification = @\"com.irccloud.notification.connectivity\";\nNSString *kIRCCloudEventNotification = @\"com.irccloud.notification.event\";\nNSString *kIRCCloudBacklogStartedNotification = @\"com.irccloud.notification.backlog.start\";\nNSString *kIRCCloudBacklogFailedNotification = @\"com.irccloud.notification.backlog.failed\";\nNSString *kIRCCloudBacklogCompletedNotification = @\"com.irccloud.notification.backlog.completed\";\nNSString *kIRCCloudBacklogProgressNotification = @\"com.irccloud.notification.backlog.progress\";\nNSString *kIRCCloudEventKey = @\"com.irccloud.event\";\n\n#if defined(BRAND_HOST)\nNSString *IRCCLOUD_HOST = @BRAND_HOST\n#elif defined(ENTERPRISE)\nNSString *IRCCLOUD_HOST = @\"\";\n#else\nNSString *IRCCLOUD_HOST = @\"api.irccloud.com\";\n#endif\nNSString *IRCCLOUD_PATH = @\"/\";\n\n#define TYPE_UNKNOWN 0\n#define TYPE_WIFI 1\n#define TYPE_WWAN 2\n\nNSLock *__serializeLock = nil;\nNSLock *__userInfoLock = nil;\nvolatile BOOL __socketPaused = NO;\n\n@interface OOBFetcher : NSObject<NSURLSessionDataDelegate> {\n    SBJson5Parser *_parser;\n    NSString *_url;\n    BOOL _cancelled;\n    BOOL _running;\n    NSURLSessionDataTask *_task;\n    int _bid;\n    void (^_completionHandler)(BOOL);\n}\n@property (readonly) NSString *url;\n@property int bid;\n@property (copy) void (^completionHandler)(BOOL);\n-(id)initWithURL:(NSString *)URL;\n-(void)cancel;\n-(void)start;\n@end\n\n@implementation OOBFetcher\n\n-(id)initWithURL:(NSString *)URL {\n    self = [super init];\n    if(self) {\n        NetworkConnection *conn = [NetworkConnection sharedInstance];\n        self->_url = URL;\n        self->_bid = -1;\n        self->_parser = [SBJson5Parser unwrapRootArrayParserWithBlock:^(id item, BOOL *stop) {\n            if(self->_cancelled)\n                *stop = YES;\n            else\n                [conn parse:item backlog:YES];\n        } errorHandler:^(NSError *error) {\n            CLS_LOG(@\"OOB JSON ERROR: %@\", error);\n        }];\n        self->_cancelled = NO;\n        self->_running = NO;\n        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self->_url] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];\n        [request setHTTPShouldHandleCookies:NO];\n        [request setValue:_userAgent forHTTPHeaderField:@\"User-Agent\"];\n        [request setValue:[NSString stringWithFormat:@\"session=%@\",[NetworkConnection sharedInstance].session] forHTTPHeaderField:@\"Cookie\"];\n        \n        NSURLSession *session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration delegate:self delegateQueue:[NetworkConnection sharedInstance].queue];\n        self->_task = [session dataTaskWithRequest:request];\n    }\n    return self;\n}\n-(void)cancel {\n    CLS_LOG(@\"Cancelled OOB fetcher for URL: %@\", _url);\n    self->_cancelled = YES;\n    self->_running = NO;\n    [self->_task cancel];\n}\n-(void)start {\n    if(self->_cancelled || _running) {\n        CLS_LOG(@\"Not starting cancelled OOB fetcher\");\n        return;\n    }\n    \n    if(self->_task) {\n        CLS_LOG(@\"Fetching backlog\");\n        self->_running = YES;\n        [self->_task resume];\n        [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudBacklogStartedNotification object:self];\n    } else {\n        CLS_LOG(@\"Failed to create NSURLConnection\");\n        [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudBacklogFailedNotification object:self];\n        if(self->_completionHandler)\n            self->_completionHandler(NO);\n    }\n}\n-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {\n    if(error) {\n        if(self->_cancelled) {\n            CLS_LOG(@\"Request failed for cancelled OOB fetcher, ignoring\");\n            return;\n        }\n        CLS_LOG(@\"Request failed: %@\", error);\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudBacklogFailedNotification object:self];\n            if(self->_completionHandler)\n                self->_completionHandler(NO);\n        }];\n        self->_cancelled = YES;\n    } else {\n        if(self->_cancelled) {\n            CLS_LOG(@\"Connection finished loading for cancelled OOB fetcher, ignoring\");\n            return;\n        }\n        CLS_LOG(@\"Backlog download completed\");\n        if(!self->_cancelled) {\n            [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudBacklogCompletedNotification object:self];\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                if(self->_completionHandler)\n                    self->_completionHandler(YES);\n            }];\n        }\n    }\n    self->_running = NO;\n}\n- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {\n    if(!self->_cancelled && ((NSHTTPURLResponse *)response).statusCode != 200) {\n        CLS_LOG(@\"HTTP status code: %li\", (long)((NSHTTPURLResponse *)response).statusCode);\n\t\tCLS_LOG(@\"HTTP headers: %@\", [((NSHTTPURLResponse *)response) allHeaderFields]);\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudBacklogFailedNotification object:self];\n            if(self->_completionHandler)\n                self->_completionHandler(NO);\n        }];\n        self->_cancelled = YES;\n        completionHandler(NSURLSessionResponseCancel);\n    } else {\n        completionHandler(NSURLSessionResponseAllow);\n    }\n}\n-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {\n    if(!self->_cancelled) {\n        [self->_parser parse:data];\n    } else {\n        CLS_LOG(@\"Ignoring data for cancelled OOB fetcher\");\n    }\n}\n\n@end\n\n@implementation NetworkConnection\n\n+(NetworkConnection *)sharedInstance {\n    static NetworkConnection *sharedInstance;\n\t\n    @synchronized(self) {\n        if(!sharedInstance)\n            sharedInstance = [[NetworkConnection alloc] init];\n\t\t\n        return sharedInstance;\n    }\n\treturn nil;\n}\n\n+(void)sync:(NSURL *)file1 with:(NSURL *)file2 {\n    NSDictionary *a1 = [[NSFileManager defaultManager] attributesOfItemAtPath:file1.path error:nil];\n    NSDictionary *a2 = [[NSFileManager defaultManager] attributesOfItemAtPath:file2.path error:nil];\n\n    if(a1) {\n        if(a2 == nil || [[a2 fileModificationDate] compare:[a1 fileModificationDate]] == NSOrderedAscending) {\n            [[NSFileManager defaultManager] copyItemAtURL:file1 toURL:file2 error:NULL];\n        }\n    }\n    \n    if(a2) {\n        if(a1 == nil || [[a1 fileModificationDate] compare:[a2 fileModificationDate]] == NSOrderedAscending) {\n            [[NSFileManager defaultManager] copyItemAtURL:file2 toURL:file1 error:NULL];\n        }\n    }\n\n    [file1 setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL];\n    [file2 setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL];\n}\n\n+(void)sync {\n    __block BOOL __interrupt = NO;\n#ifndef EXTENSION\n    UIBackgroundTaskIdentifier background_task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^ {\n        CLS_LOG(@\"NetworkConnection sync task expired\");\n        __interrupt = YES;\n    }];\n#endif\n#ifdef ENTERPRISE\n    NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.enterprise.share\"];\n#else\n    NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.share\"];\n#endif\n    if(sharedcontainer) {\n        NSURL *caches = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] objectAtIndex:0];\n        \n        if(!__interrupt)\n            [NetworkConnection sync:[caches URLByAppendingPathComponent:@\"avatarURLs\"] with:[sharedcontainer URLByAppendingPathComponent:@\"avatarURLs\"]];\n        if(!__interrupt)\n            [NetworkConnection sync:[caches URLByAppendingPathComponent:@\"servers\"] with:[sharedcontainer URLByAppendingPathComponent:@\"servers\"]];\n        if(!__interrupt)\n            [NetworkConnection sync:[caches URLByAppendingPathComponent:@\"buffers\"] with:[sharedcontainer URLByAppendingPathComponent:@\"buffers\"]];\n        if(!__interrupt)\n            [NetworkConnection sync:[caches URLByAppendingPathComponent:@\"channels\"] with:[sharedcontainer URLByAppendingPathComponent:@\"channels\"]];\n        if(!__interrupt)\n            [NetworkConnection sync:[caches URLByAppendingPathComponent:@\"stream\"] with:[sharedcontainer URLByAppendingPathComponent:@\"stream\"]];\n    }\n#ifndef EXTENSION\n    [[UIApplication sharedApplication] endBackgroundTask: background_task];\n#endif\n}\n\n-(id)init {\n    self = [super init];\n#ifdef ENTERPRISE\n    IRCCLOUD_HOST = [[NSUserDefaults standardUserDefaults] objectForKey:@\"host\"];\n#endif\n    if(self) {\n        NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration];\n        config.timeoutIntervalForRequest = 30;\n        config.waitsForConnectivity = NO;\n        _urlSession = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:NSOperationQueue.mainQueue];\n        \n        [TrustKit initializeWithConfiguration:@{\n                                                kTSKSwizzleNetworkDelegates: @YES,\n                                                kTSKPinnedDomains : @{\n                                                        @\"irccloud.com\" : @{\n                                                                kTSKExpirationDate: @\"2020-10-09\",\n                                                                kTSKPublicKeyAlgorithms : @[kTSKAlgorithmRsa2048,kTSKAlgorithmEcDsaSecp256r1],\n                                                                kTSKPublicKeyHashes : @[\n                                                                        @\"5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w=\",\n                                                                        @\"Y9mvm0exBk1JoQ57f9Vm28jKo5lFm/woKcVxrYxu80o=\",\n                                                                        @\"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=\"\n                                                                        ],\n                                                                kTSKIncludeSubdomains : @YES\n                                                                }\n                                                        }}];\n    __serializeLock = [[NSLock alloc] init];\n    __userInfoLock = [[NSLock alloc] init];\n    __logQueue = [[NSOperationQueue alloc] init];\n    [__logQueue setMaxConcurrentOperationCount:1];\n    self->_queue = [[NSOperationQueue alloc] init];\n    self->_avatars = [AvatarsDataSource sharedInstance];\n    self->_servers = [ServersDataSource sharedInstance];\n    self->_buffers = [BuffersDataSource sharedInstance];\n    self->_channels = [ChannelsDataSource sharedInstance];\n    self->_users = [UsersDataSource sharedInstance];\n    self->_events = [EventsDataSource sharedInstance];\n    self->_notifications = [NotificationsDataSource sharedInstance];\n    self->_state = kIRCCloudStateDisconnected;\n    self->_oobQueue = [[NSMutableArray alloc] init];\n    self->_awayOverride = nil;\n    self->_lastReqId = 1;\n    self->_idleInterval = 20;\n    self->_reconnectTimestamp = -1;\n    self->_failCount = 0;\n    self->_notifier = NO;\n    [self _createJSONParser];\n    self->_writer = [[SBJson5Writer alloc] init];\n    self->_reachabilityValid = NO;\n    self->_reachability = nil;\n    self->_resultHandlers = [[NSMutableDictionary alloc] init];\n    self->_pendingEdits = [[NSMutableArray alloc] init];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_backlogStarted:) name:kIRCCloudBacklogStartedNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_backlogCompleted:) name:kIRCCloudBacklogCompletedNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_backlogFailed:) name:kIRCCloudBacklogFailedNotification object:nil];\n#ifdef APPSTORE\n    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"];\n#else\n    NSString *version = [NSString stringWithFormat:@\"%@-%@\",[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"], [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleVersion\"]];\n#endif\n#ifdef EXTENSION\n    NSString *app = @\"ShareExtension\";\n#else\n#ifdef ENTERPRISE\n    NSString *app = @\"IRCEnterprise\";\n#else\n    NSString *app = @\"IRCCloud\";\n#endif\n#endif\n        \n    NSString *model = [UIDevice currentDevice].model;\n    if (@available(iOS 14.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp) {\n            model = @\"Mac\";\n        }\n    }\n\n    _userAgent = [NSString stringWithFormat:@\"%@/%@ (%@; %@; %@ %@)\", app, version, model, [[[NSUserDefaults standardUserDefaults] objectForKey: @\"AppleLanguages\"] objectAtIndex:0], [UIDevice currentDevice].systemName, [UIDevice currentDevice].systemVersion];\n    \n    NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"stream\"];\n    [__userInfoLock lock];\n    NSError* error = nil;\n    self->_userInfo = [[NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:NSDictionary.class, NSMutableArray.class, NSNull.class,NSString.class,NSNumber.class, nil] fromData:[NSData dataWithContentsOfFile:cacheFile] error:&error] mutableCopy];\n    if(error)\n        CLS_LOG(@\"Error: %@\", error);\n    [__userInfoLock unlock];\n    if(self.userInfo) {\n        self->_config = [self.userInfo objectForKey:@\"config\"];\n        [self _configLoaded];\n    }\n    \n    CLS_LOG(@\"%@\", _userAgent);\n        \n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"cacheVersion\"];\n    [[NSUserDefaults standardUserDefaults] synchronize];\n    \n    void (^ignored)(IRCCloudJSONObject *object, BOOL backlog) = ^(IRCCloudJSONObject *object, BOOL backlog) {\n    };\n    \n    void (^alert)(IRCCloudJSONObject *object, BOOL backlog) = ^(IRCCloudJSONObject *object, BOOL backlog) {\n        if(!backlog && !self->_resuming)\n            [self postObject:object forEvent:kIRCEventAlert];\n    };\n    \n    void (^makeserver)(IRCCloudJSONObject *object, BOOL backlog) = ^(IRCCloudJSONObject *object, BOOL backlog) {\n        Server *server = [self->_servers getServer:object.cid];\n        if(!server) {\n            server = [[Server alloc] init];\n            [self->_servers addServer:server];\n        }\n        server.cid = object.cid;\n        server.name = [object objectForKey:@\"name\"];\n        server.hostname = [object objectForKey:@\"hostname\"];\n        server.port = [[object objectForKey:@\"port\"] intValue];\n        server.nick = [object objectForKey:@\"nick\"];\n        server.status = [object objectForKey:@\"status\"];\n        server.ssl = [[object objectForKey:@\"ssl\"] intValue];\n        server.realname = [object objectForKey:@\"realname\"];\n        if([[object objectForKey:@\"server_realname\"] isKindOfClass:[NSString class]])\n            server.server_realname = [object objectForKey:@\"server_realname\"];\n        server.server_pass = [object objectForKey:@\"server_pass\"];\n        server.nickserv_pass = [object objectForKey:@\"nickserv_pass\"];\n        server.join_commands = [object objectForKey:@\"join_commands\"];\n        server.fail_info = [object objectForKey:@\"fail_info\"];\n        server.caps = [object objectForKey:@\"caps\"];\n        server.usermask = [object objectForKey:@\"usermask\"];\n        server.away = (backlog && [self->_awayOverride objectForKey:@(object.cid)])?@\"\":[object objectForKey:@\"away\"];\n        if([[self.userInfo objectForKey:@\"autoaway\"] intValue] && [server.away isEqualToString:@\"Auto-away\"])\n            server.away = @\"\";\n        server.ignores = [object objectForKey:@\"ignores\"];\n        if([[object objectForKey:@\"order\"] isKindOfClass:[NSNumber class]])\n            server.order = [[object objectForKey:@\"order\"] intValue];\n        else\n            server.order = 0;\n        if([[object objectForKey:@\"deferred_archives\"] isKindOfClass:[NSNumber class]])\n            server.deferred_archives = [[object objectForKey:@\"deferred_archives\"] intValue];\n        else\n            server.deferred_archives = 0;\n        if([[object objectForKey:@\"ircserver\"] isKindOfClass:[NSString class]])\n            server.ircserver = [object objectForKey:@\"ircserver\"];\n        else\n            server.ircserver = nil;\n        if([[object objectForKey:@\"orgid\"] isKindOfClass:[NSNumber class]])\n            server.orgId = [[object objectForKey:@\"orgid\"] intValue];\n        else\n            server.orgId = 0;\n        if([[object objectForKey:@\"avatar\"] isKindOfClass:[NSString class]])\n            server.avatar = [object objectForKey:@\"avatar\"];\n        else\n            server.avatar = nil;\n        if([[object objectForKey:@\"avatar_url\"] isKindOfClass:[NSString class]])\n            server.avatarURL = [object objectForKey:@\"avatar_url\"];\n        else\n            server.avatarURL = nil;\n        if([[object objectForKey:@\"avatars_supported\"] isKindOfClass:[NSNumber class]])\n            server.avatars_supported = [[object objectForKey:@\"avatars_supported\"] intValue];\n        else\n            server.avatars_supported = 0;\n        if([[object objectForKey:@\"slack\"] isKindOfClass:[NSNumber class]])\n            server.slack = [[object objectForKey:@\"slack\"] intValue];\n        else\n            server.slack = 0;\n        if([[object objectForKey:@\"account\"] isKindOfClass:[NSString class]])\n            server.account = [object objectForKey:@\"account\"];\n        else\n            server.account = nil;\n        if(!backlog && !self->_resuming)\n            [self postObject:server forEvent:kIRCEventMakeServer];\n    };\n    \n    void (^msg)(IRCCloudJSONObject *object, BOOL backlog) = ^(IRCCloudJSONObject *object, BOOL backlog) {\n        Buffer *b = [self->_buffers getBuffer:object.bid];\n        if(b) {\n            Event *event = [self->_events addJSONObject:object];\n            if(event.eid == -1) {\n                alert(object,backlog);\n            } else {\n                if((!backlog || self->_resuming || [[self->_oobQueue firstObject] bid] == -1) && event.eid > self->_highestEID) {\n                    self->_highestEID = event.eid;\n                }\n                if([event isImportant:b.type]) {\n#ifndef EXTENSION\n                    if([b.type isEqualToString:@\"conversation\"] && [b.name isEqualToString:event.from])\n                        [self->_avatars setAvatarURL:[event avatar:512] bid:event.bid eid:event.eid];\n#endif\n                    User *u = [self->_users getUser:event.from cid:event.cid bid:event.bid];\n                    if(u) {\n                        if(u.lastMessage < event.eid)\n                            u.lastMessage = event.eid;\n                        if(event.isHighlight && u.lastMention < event.eid)\n                            u.lastMention = event.eid;\n                    }\n                    if(event.eid > b.last_seen_eid && (event.isHighlight || [b.type isEqualToString:@\"conversation\"])) {\n                        BOOL show = YES;\n                        if([[self->_servers getServer:event.cid].ignore match:event.ignoreMask] || [[[[self prefs] objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:@(b.bid)] integerValue]) {\n                            show = NO;\n                        }\n                        \n                        if(show && ![self->_notifications getNotification:event.eid bid:event.bid]) {\n                            [self->_notifications notify:[NSString stringWithFormat:@\"<%@> %@\",event.from,event.msg] category:event.type cid:event.cid bid:event.bid eid:event.eid];\n                            if(!backlog)\n                                [self->_notifications updateBadgeCount];\n                        }\n                    }\n                }\n                if((!backlog && !self->_resuming) || event.reqId > 0) {\n                    [self postObject:event forEvent:kIRCEventBufferMsg];\n                    event.entities = [object objectForKey:@\"entities\"];\n                    \n                    NSTimeInterval entity_eid = event.eid;\n                    for(int i = 0; i < [[event.entities objectForKey:@\"files\"] count]; i++) {\n                        entity_eid += 1;\n                        [self postObject:[self->_events event:entity_eid buffer:event.bid] forEvent:kIRCEventBufferMsg];\n                    }\n                }\n            }\n        }\n    };\n    \n    void (^joined_channel)(IRCCloudJSONObject *object, BOOL backlog) = ^(IRCCloudJSONObject *object, BOOL backlog) {\n        [self->_events addJSONObject:object];\n        if(!backlog) {\n            User *user = [self->_users getUser:[object objectForKey:@\"nick\"] cid:object.cid bid:object.bid];\n            if(!user) {\n                user = [[User alloc] init];\n                user.cid = object.cid;\n                user.bid = object.bid;\n                user.nick = [object objectForKey:@\"nick\"];\n                [self->_users addUser:user];\n            }\n            if(user.nick)\n                user.old_nick = user.nick;\n            user.hostmask = [object objectForKey:@\"hostmask\"];\n            user.mode = @\"\";\n            user.away = 0;\n            user.away_msg = @\"\";\n            user.ircserver = [object objectForKey:@\"ircserver\"];\n            if([[object objectForKey:@\"display_name\"] isKindOfClass:NSString.class])\n                user.display_name = [object objectForKey:@\"display_name\"];\n            else\n                user.display_name = nil;\n            if(!self->_resuming)\n                [self postObject:object forEvent:kIRCEventJoin];\n        }\n    };\n    \n    void (^parted_channel)(IRCCloudJSONObject *object, BOOL backlog) = ^(IRCCloudJSONObject *object, BOOL backlog) {\n        [self->_events addJSONObject:object];\n        if(!backlog) {\n            [self->_users removeUser:[object objectForKey:@\"nick\"] cid:object.cid bid:object.bid];\n            if([object.type isEqualToString:@\"you_parted_channel\"]) {\n                [self->_channels removeChannelForBuffer:object.bid];\n                [self->_users removeUsersForBuffer:object.bid];\n            }\n            if(!self->_resuming)\n                [self postObject:object forEvent:kIRCEventPart];\n        }\n    };\n    \n    void (^kicked_channel)(IRCCloudJSONObject *object, BOOL backlog) = ^(IRCCloudJSONObject *object, BOOL backlog) {\n        [self->_events addJSONObject:object];\n        if(!backlog) {\n            [self->_users removeUser:[object objectForKey:@\"nick\"] cid:object.cid bid:object.bid];\n            if([object.type isEqualToString:@\"you_kicked_channel\"]) {\n                [self->_channels removeChannelForBuffer:object.bid];\n                [self->_users removeUsersForBuffer:object.bid];\n            }\n            if(!self->_resuming)\n                [self postObject:object forEvent:kIRCEventKick];\n        }\n    };\n    \n    void (^nickchange)(IRCCloudJSONObject *object, BOOL backlog) = ^(IRCCloudJSONObject *object, BOOL backlog) {\n        [self->_events addJSONObject:object];\n        if(!backlog) {\n            [self->_users updateNick:[object objectForKey:@\"newnick\"] oldNick:[object objectForKey:@\"oldnick\"] cid:object.cid bid:object.bid];\n            if([object.type isEqualToString:@\"you_nickchange\"])\n                [self->_servers updateNick:[object objectForKey:@\"newnick\"] server:object.cid];\n            if(!self->_resuming)\n                [self postObject:object forEvent:kIRCEventNickChange];\n        }\n    };\n        \n    void (^pendingEdit)(IRCCloudJSONObject *object, BOOL backlog) = ^(IRCCloudJSONObject *object, BOOL backlog) {\n        @synchronized (self) {\n            [self->_pendingEdits addObject:object];\n        }\n        [self _processPendingEdits:backlog];\n    };\n    \n    NSMutableDictionary *parserMap = @{\n                   @\"idle\":ignored, @\"end_of_backlog\":ignored, @\"oob_skipped\":ignored, @\"num_invites\":ignored, @\"user_account\":ignored, @\"twitch_hosttarget_start\":ignored, @\"twitch_hosttarget_stop\":ignored, @\"twitch_usernotice\":ignored,\n                   @\"header\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       self->_state = kIRCCloudStateConnected;\n                       [self performSelectorOnMainThread:@selector(_postConnectivityChange) withObject:nil waitUntilDone:YES];\n                       self->_idleInterval = ([[object objectForKey:@\"idle_interval\"] doubleValue] / 1000.0) + 10;\n                       self->_clockOffset = [[NSDate date] timeIntervalSince1970] - [[object objectForKey:@\"time\"] doubleValue];\n                       self->_streamId = [object objectForKey:@\"streamid\"];\n                       self->_accrued = [[object objectForKey:@\"accrued\"] intValue];\n                       self->_currentCount = 0;\n                       self->_resuming = [[object objectForKey:@\"resumed\"] boolValue];\n                       CLS_LOG(@\"idle interval: %f clock offset: %f stream id: %@ resumed: %i\", self->_idleInterval, self->_clockOffset, self->_streamId, self->_resuming);\n                       if(self->_accrued > 0) {\n                           [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                               [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudBacklogStartedNotification object:nil];\n                           }];\n                       }\n                       if(self->_highestEID > 0 && !self->_resuming) {\n                           CLS_LOG(@\"Unable to resume socket, requesting a full OOB load\");\n                           [self->_events clear];\n                           self->_highestEID = 0;\n                           self->_streamId = nil;\n                           self->_pendingEdits = [[NSMutableArray alloc] init];\n                           [self performSelectorOnMainThread:@selector(disconnect) withObject:nil waitUntilDone:NO];\n                           self->_state = kIRCCloudStateDisconnected;\n                           [self performSelectorOnMainThread:@selector(fail) withObject:nil waitUntilDone:NO];\n                       }\n                   },\n                   @\"backlog_cache_init\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_events removeEventsBefore:object.eid buffer:object.bid];\n                   },\n                   @\"global_system_message\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       if(!self->_resuming && !backlog && [object objectForKey:@\"system_message_type\"] && ![[object objectForKey:@\"system_message_type\"] isEqualToString:@\"eval\"] && ![[object objectForKey:@\"system_message_type\"] isEqualToString:@\"refresh\"]) {\n                           self->_globalMsg = [object objectForKey:@\"msg\"];\n                           [self postObject:object forEvent:kIRCEventGlobalMsg];\n                       }\n                   },\n                   @\"oob_include\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       __socketPaused = YES;\n                       self->_awayOverride = [[NSMutableDictionary alloc] init];\n                       self->_reconnectTimestamp = -1;\n                       CLS_LOG(@\"oob_include, invalidating BIDs\");\n                       [self->_buffers invalidate];\n                       [self->_channels invalidate];\n                       [self fetchOOB:[NSString stringWithFormat:@\"%@%@\", [object objectForKey:@\"api_host\"], [object objectForKey:@\"url\"]]];\n                   },\n                   @\"oob_timeout\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       CLS_LOG(@\"OOB timed out\");\n                       [self clearOOB];\n                       self->_highestEID = 0;\n                       self->_streamId = nil;\n                       [self performSelectorOnMainThread:@selector(disconnect) withObject:nil waitUntilDone:NO];\n                       self->_state = kIRCCloudStateDisconnected;\n                       [self performSelectorOnMainThread:@selector(fail) withObject:nil waitUntilDone:NO];\n                   },\n                   @\"stat_user\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [__userInfoLock lock];\n                       self->_userInfo = object.dictionary;\n                       [__userInfoLock unlock];\n                       if([[self.userInfo objectForKey:@\"uploads_disabled\"] intValue] == 1 && [[self.userInfo objectForKey:@\"id\"] intValue] != 11694)\n                           [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@\"uploadsAvailable\"];\n                       else\n                           [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@\"uploadsAvailable\"];\n#ifdef ENTERPRISE\n                       NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n                       NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n                       [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"uploadsAvailable\"] forKey:@\"uploadsAvailable\"];\n                       [d synchronize];\n\n                       self->_prefs = nil;\n#ifndef EXTENSION\n#ifdef DEBUG\n                       if(![[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"]) {\n#endif\n                       NSDictionary *p = [self prefs];\n                       if([p objectForKey:@\"theme\"] && ![[NSUserDefaults standardUserDefaults] objectForKey:@\"theme\"]) {\n                           dispatch_sync(dispatch_get_main_queue(), ^{\n                               [UIColor setTheme:[p objectForKey:@\"theme\"]];\n                           });\n                           [[NSUserDefaults standardUserDefaults] setObject:[p objectForKey:@\"theme\"] forKey:@\"theme\"];\n                       }\n                       if([p objectForKey:@\"time-left\"]) {\n                           if(![[NSUserDefaults standardUserDefaults] objectForKey:@\"time-left\"])\n                               [[NSUserDefaults standardUserDefaults] setObject:[p objectForKey:@\"time-left\"] forKey:@\"time-left\"];\n                       }\n                       if([p objectForKey:@\"avatars-off\"]) {\n                           if(![[NSUserDefaults standardUserDefaults] objectForKey:@\"avatars-off\"])\n                               [[NSUserDefaults standardUserDefaults] setObject:[p objectForKey:@\"avatars-off\"] forKey:@\"avatars-off\"];\n                       }\n                       if([p objectForKey:@\"chat-oneline\"]) {\n                           if(![[NSUserDefaults standardUserDefaults] objectForKey:@\"chat-oneline\"])\n                               [[NSUserDefaults standardUserDefaults] setObject:[p objectForKey:@\"chat-oneline\"] forKey:@\"chat-oneline\"];\n                       }\n                       if([p objectForKey:@\"chat-norealname\"]) {\n                           if(![[NSUserDefaults standardUserDefaults] objectForKey:@\"chat-norealname\"])\n                               [[NSUserDefaults standardUserDefaults] setObject:[p objectForKey:@\"chat-norealname\"] forKey:@\"chat-norealname\"];\n                       }\n                       if([[p objectForKey:@\"labs\"] objectForKey:@\"avatars\"]) {\n                           if(![[NSUserDefaults standardUserDefaults] objectForKey:@\"avatarImages\"])\n                               [[NSUserDefaults standardUserDefaults] setObject:[[p objectForKey:@\"labs\"] objectForKey:@\"avatars\"] forKey:@\"avatarImages\"];\n                       }\n                       if([p objectForKey:@\"hiddenMembers\"]) {\n                           if(![[NSUserDefaults standardUserDefaults] objectForKey:@\"hiddenMembers\"])\n                               [[NSUserDefaults standardUserDefaults] setObject:[p objectForKey:@\"hiddenMembers\"] forKey:@\"hiddenMembers\"];\n                       }\n                       if([object objectForKey:@\"id\"]) {\n                           [[NSUserDefaults standardUserDefaults] setObject:[object objectForKey:@\"id\"] forKey:@\"last_uid\"];\n                       }\n                       [[NSUserDefaults standardUserDefaults] synchronize];\n#ifdef DEBUG\n                       }\n#endif\n                       [self->_events reformat];\n#endif\n                       [[FIRCrashlytics crashlytics] setUserID:[NSString stringWithFormat:@\"uid%@\",[self.userInfo objectForKey:@\"id\"]]];\n                       CLS_LOG(@\"Prefs: %@\", [self prefs]);\n                       [self _serializeUserInfo];\n                       [self postObject:object forEvent:kIRCEventUserInfo];\n                   },\n                   @\"backlog_starts\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       if([object objectForKey:@\"numbuffers\"]) {\n                           CLS_LOG(@\"I currently have %lu servers with %lu buffers\", (unsigned long)[self->_servers count], (unsigned long)[self->_buffers count]);\n                           self->_numBuffers = [[object objectForKey:@\"numbuffers\"] intValue];\n                           self->_totalBuffers = 0;\n                           CLS_LOG(@\"OOB includes has %i buffers\", self->_numBuffers);\n                       }\n                   },\n                   @\"makeserver\": makeserver,\n                   @\"server_details_changed\": makeserver,\n                   @\"makebuffer\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       Buffer *buffer = [self->_buffers getBuffer:object.bid];\n                       if(!buffer) {\n                           buffer = [[Buffer alloc] init];\n                           buffer.bid = object.bid;\n                           buffer.scrolledUpFrom = -1;\n                           buffer.savedScrollOffset = -1;\n                           [self->_buffers addBuffer:buffer];\n                       }\n                       buffer.bid = object.bid;\n                       buffer.cid = object.cid;\n                       buffer.created = [[object objectForKey:@\"created\"] doubleValue];\n                       buffer.min_eid = [[object objectForKey:@\"min_eid\"] doubleValue];\n                       buffer.last_seen_eid = [[object objectForKey:@\"last_seen_eid\"] doubleValue];\n                       buffer.name = [object objectForKey:@\"name\"];\n                       buffer.type = [object objectForKey:@\"buffer_type\"];\n                       buffer.archived = [[object objectForKey:@\"archived\"] intValue];\n                       buffer.deferred = [[object objectForKey:@\"deferred\"] intValue];\n                       buffer.timeout = [[object objectForKey:@\"timeout\"] intValue];\n                       buffer.valid = YES;\n                       Server *server = [[ServersDataSource sharedInstance] getServer:buffer.cid];\n                       buffer.serverIsSlack = server.isSlack;\n                       if(buffer.timeout)\n                           [[EventsDataSource sharedInstance] removeEventsForBuffer:buffer.bid];\n                       if(backlog && buffer.archived) {\n                           if(server.deferred_archives)\n                               server.deferred_archives--;\n                       }\n                       [self->_notifications removeNotificationsForBID:buffer.bid olderThan:buffer.last_seen_eid];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:buffer forEvent:kIRCEventMakeBuffer];\n                       if(self->_numBuffers > 0) {\n                           self->_totalBuffers++;\n                           [self performSelectorOnMainThread:@selector(_postLoadingProgress:) withObject:@((float)self->_totalBuffers / (float)self->_numBuffers) waitUntilDone:YES];\n                       }\n                   },\n                   @\"backlog_complete\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       if(!backlog && self->_oobQueue.count == 0) {\n                           [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                               CLS_LOG(@\"backlog_complete from websocket\");\n                               [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudBacklogCompletedNotification object:nil];\n                           }];\n                       }\n                   },\n                   @\"who_response\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       if(!backlog && !self->_resuming) {\n                           Buffer *b = [self->_buffers getBufferWithName:[object objectForKey:@\"subject\"] server:[[object objectForKey:@\"cid\"] intValue]];\n                           if(b) {\n                               for(NSDictionary *user in [object objectForKey:@\"users\"]) {\n                                   [self->_users updateHostmask:[user objectForKey:@\"usermask\"] nick:[user objectForKey:@\"nick\"] cid:b.cid bid:b.bid];\n                                   [self->_users updateAway:[[user objectForKey:@\"away\"] intValue] nick:[user objectForKey:@\"nick\"] cid:b.cid];\n                               }\n                           }\n                           [self postObject:object forEvent:kIRCEventWhoList];\n                       }\n                   },\n                   @\"connection_deleted\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_servers removeAllDataForServer:object.cid];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventConnectionDeleted];\n                   },\n                   @\"delete_buffer\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_buffers removeAllDataForBuffer:object.bid];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventDeleteBuffer];\n                   },\n                   @\"buffer_archived\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_buffers updateArchived:1 buffer:object.bid];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventBufferArchived];\n                   },\n                   @\"buffer_unarchived\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_buffers updateArchived:0 buffer:object.bid];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventBufferUnarchived];\n                   },\n                   @\"rename_conversation\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_buffers updateName:[object objectForKey:@\"new_name\"] buffer:object.bid];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventRenameConversation];\n                   },\n                   @\"rename_channel\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_buffers updateName:[object objectForKey:@\"new_name\"] buffer:object.bid];\n                       Channel *c = [self->_channels channelForBuffer:object.bid];\n                       if(c)\n                           c.name = [object objectForKey:@\"new_name\"];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventRenameConversation];\n                   },\n                   @\"status_changed\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       CLS_LOG(@\"cid%i changed to status %@ (backlog: %i resuming: %i)\", object.cid, [object objectForKey:@\"new_status\"], backlog, self->_resuming);\n                       [self->_servers updateStatus:[object objectForKey:@\"new_status\"] failInfo:[object objectForKey:@\"fail_info\"] server:object.cid];\n                       if(!backlog) {\n                           if([[object objectForKey:@\"new_status\"] isEqualToString:@\"disconnected\"]) {\n                               NSArray *channels = [self->_channels channelsForServer:object.cid];\n                               for(Channel *c in channels) {\n                                   [self->_channels removeChannelForBuffer:c.bid];\n                               }\n                           }\n                           [self postObject:object forEvent:kIRCEventStatusChanged];\n                       }\n                   },\n                   @\"time\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       Event *event = [self->_events addJSONObject:object];\n                       if(!backlog && !self->_resuming) {\n                           [self postObject:object forEvent:kIRCEventAlert];\n                           [self postObject:event forEvent:kIRCEventBufferMsg];\n                       }\n                   },\n                   @\"link_channel\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_events addJSONObject:object];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventLinkChannel];\n                   },\n                   @\"channel_init\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       Channel *channel = [self->_channels channelForBuffer:object.bid];\n                       if(!channel) {\n                           channel = [[Channel alloc] init];\n                           [self->_channels addChannel:channel];\n                       }\n                       channel.cid = object.cid;\n                       channel.bid = object.bid;\n                       channel.name = [object objectForKey:@\"chan\"];\n                       channel.type = [object objectForKey:@\"channel_type\"];\n                       channel.timestamp = [[object objectForKey:@\"timestamp\"] doubleValue];\n                       channel.topic_text = [[object objectForKey:@\"topic\"] objectForKey:@\"text\"];\n                       channel.topic_author = [[[object objectForKey:@\"topic\"] objectForKey:@\"nick\"] length]?[[object objectForKey:@\"topic\"] objectForKey:@\"nick\"]:[[object objectForKey:@\"topic\"] objectForKey:@\"server\"];\n                       channel.topic_time = [[[object objectForKey:@\"topic\"] objectForKey:@\"time\"] doubleValue];\n                       channel.mode = @\"\";\n                       channel.modes = [[NSMutableArray alloc] init];\n                       channel.url = [object objectForKey:@\"url\"];\n                       channel.valid = YES;\n                       channel.key = NO;\n                       [self->_channels updateMode:[object objectForKey:@\"mode\"] buffer:object.bid ops:[object objectForKey:@\"ops\"]];\n                       [self->_users removeUsersForBuffer:object.bid];\n                       for(NSDictionary *member in [object objectForKey:@\"members\"]) {\n                           User *user = [[User alloc] init];\n                           user.cid = object.cid;\n                           user.bid = object.bid;\n                           user.nick = [member objectForKey:@\"nick\"];\n                           user.hostmask = [member objectForKey:@\"usermask\"];\n                           user.mode = [member objectForKey:@\"mode\"];\n                           user.away = [[member objectForKey:@\"away\"] intValue];\n                           user.ircserver = [member objectForKey:@\"ircserver\"];\n                           if([[member objectForKey:@\"display_name\"] isKindOfClass:NSString.class])\n                               user.display_name = [member objectForKey:@\"display_name\"];\n                           else\n                               user.display_name = nil;\n                           [self->_users addUser:user];\n                       }\n                       if(!backlog && !self->_resuming)\n                           [self postObject:channel forEvent:kIRCEventChannelInit];\n                   },\n                   @\"channel_topic\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_events addJSONObject:object];\n                       if(!backlog) {\n                           [self->_channels updateTopic:[object objectForKey:@\"topic\"] time:object.eid/1000000 author:[[object objectForKey:@\"author\"] length]?[object objectForKey:@\"author\"]:[object objectForKey:@\"server\"] buffer:object.bid];\n                           if(!self->_resuming)\n                               [self postObject:object forEvent:kIRCEventChannelTopic];\n                       }\n                   },\n                   @\"channel_topic_is\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       if(!backlog) {\n                           Buffer *b = [self->_buffers getBufferWithName:[object objectForKey:@\"chan\"] server:object.cid];\n                           if(b) {\n                               [self->_channels updateTopic:[object objectForKey:@\"text\"] time:[[object objectForKey:@\"time\"] longValue] author:[object objectForKey:@\"author\"] buffer:b.bid];\n                           }\n                           if(!self->_resuming)\n                               [self postObject:object forEvent:kIRCEventChannelTopicIs];\n                       }\n                   },\n                   @\"channel_url\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       if(!backlog)\n                           [self->_channels updateURL:[object objectForKey:@\"url\"] buffer:object.bid];\n                   },\n                   @\"channel_mode\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_events addJSONObject:object];\n                       if(!backlog) {\n                           [self->_channels updateMode:[object objectForKey:@\"newmode\"] buffer:object.bid ops:[object objectForKey:@\"ops\"]];\n                           if(!self->_resuming)\n                               [self postObject:object forEvent:kIRCEventChannelMode];\n                       }\n                   },\n                   @\"channel_mode_is\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_events addJSONObject:object];\n                       if(!backlog) {\n                           [self->_channels updateMode:[object objectForKey:@\"newmode\"] buffer:object.bid ops:[object objectForKey:@\"ops\"]];\n                           if(!self->_resuming)\n                               [self postObject:object forEvent:kIRCEventChannelMode];\n                       }\n                   },\n                   @\"channel_timestamp\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       if(!backlog) {\n                           [self->_channels updateTimestamp:[[object objectForKey:@\"timestamp\"] doubleValue] buffer:object.bid];\n                           if(!self->_resuming)\n                               [self postObject:object forEvent:kIRCEventChannelTimestamp];\n                       }\n                   },\n                   @\"joined_channel\":joined_channel, @\"you_joined_channel\":joined_channel,\n                   @\"parted_channel\":parted_channel, @\"you_parted_channel\":parted_channel,\n                   @\"kicked_channel\":kicked_channel, @\"you_kicked_channel\":kicked_channel,\n                   @\"nickchange\":nickchange, @\"you_nickchange\":nickchange,\n                   @\"quit\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_events addJSONObject:object];\n                       if(!backlog) {\n                           [self->_users removeUser:[object objectForKey:@\"nick\"] cid:object.cid bid:object.bid];\n                           if(!self->_resuming)\n                               [self postObject:object forEvent:kIRCEventQuit];\n                       }\n                   },\n                   @\"quit_server\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_events addJSONObject:object];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventQuit];\n                   },\n                   @\"user_channel_mode\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_events addJSONObject:object];\n                       if(!backlog) {\n                           [self->_users updateMode:[object objectForKey:@\"newmode\"] nick:[object objectForKey:@\"nick\"] cid:object.cid bid:object.bid];\n                           if(!self->_resuming)\n                               [self postObject:object forEvent:kIRCEventUserChannelMode];\n                       }\n                   },\n                   @\"member_updates\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       NSDictionary *updates = [object objectForKey:@\"updates\"];\n                       NSEnumerator *keys = updates.keyEnumerator;\n                       NSString *nick;\n                       while((nick = (NSString *)(keys.nextObject))) {\n                           NSDictionary *update = [updates objectForKey:nick];\n                           [self->_users updateAway:[[update objectForKey:@\"away\"] intValue] nick:nick cid:object.cid];\n                           [self->_users updateHostmask:[update objectForKey:@\"usermask\"] nick:nick cid:object.cid bid:object.bid];\n                       }\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventMemberUpdates];\n                   },\n                   @\"user_away\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       Buffer *b = [self->_buffers getBuffer:object.bid];\n                       if([b.type isEqualToString:@\"console\"]) {\n                           [self->_users updateAway:1 msg:[object objectForKey:@\"msg\"] nick:[object objectForKey:@\"nick\"] cid:object.cid];\n                           [self->_buffers updateAway:[object objectForKey:@\"msg\"] nick:[object objectForKey:@\"nick\"] server:object.cid];\n                           if(!backlog && !self->_resuming)\n                               [self postObject:object forEvent:kIRCEventAway];\n                       }\n                   },\n                   @\"away\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       Buffer *b = [self->_buffers getBuffer:object.bid];\n                       if([b.type isEqualToString:@\"console\"]) {\n                           [self->_users updateAway:1 msg:[object objectForKey:@\"msg\"] nick:[object objectForKey:@\"nick\"] cid:object.cid];\n                           [self->_buffers updateAway:[object objectForKey:@\"msg\"] nick:[object objectForKey:@\"nick\"] server:object.cid];\n                           if(!backlog && !self->_resuming)\n                               [self postObject:object forEvent:kIRCEventAway];\n                       }\n                   },\n                   @\"user_back\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       Buffer *b = [self->_buffers getBuffer:object.bid];\n                       if([b.type isEqualToString:@\"console\"]) {\n                           [self->_users updateAway:0 msg:@\"\" nick:[object objectForKey:@\"nick\"] cid:object.cid];\n                           [self->_buffers updateAway:@\"\" nick:[object objectForKey:@\"nick\"] server:object.cid];\n                           if(!backlog && !self->_resuming)\n                               [self postObject:object forEvent:kIRCEventAway];\n                       }\n                   },\n                   @\"self_away\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       if(!self->_resuming) {\n                           [self->_users updateAway:1 msg:[object objectForKey:@\"away_msg\"] nick:[object objectForKey:@\"nick\"] cid:object.cid];\n                           [self->_servers updateAway:[object objectForKey:@\"away_msg\"] server:object.cid];\n                           if(!backlog)\n                               [self postObject:object forEvent:kIRCEventAway];\n                       }\n                   },\n                   @\"self_back\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_awayOverride setObject:@YES forKey:@(object.cid)];\n                       [self->_users updateAway:0 msg:@\"\" nick:[object objectForKey:@\"nick\"] cid:object.cid];\n                       [self->_servers updateAway:@\"\" server:object.cid];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventSelfBack];\n                   },\n                   @\"self_details\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       Event *e = [self->_events addJSONObject:object];\n                       Server *s = [self->_servers getServer:e.cid];\n                       if([[object objectForKey:@\"server_realname\"] isKindOfClass:[NSString class]])\n                           s.server_realname = [object objectForKey:@\"server_realname\"];\n                       s.usermask = [object objectForKey:@\"usermask\"];\n                       if(!backlog && !self->_resuming) {\n                           [self postObject:e forEvent:kIRCEventSelfDetails];\n                           e = [self->_events event:e.eid + 1 buffer:e.bid];\n                           if(e)\n                               [self postObject:e forEvent:kIRCEventSelfDetails];\n                       }\n                   },\n                   @\"user_mode\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_events addJSONObject:object];\n                       if(!backlog) {\n                           [self->_servers updateMode:[object objectForKey:@\"newmode\"] server:object.cid];\n                           if(!self->_resuming)\n                               [self postObject:object forEvent:kIRCEventUserMode];\n                       }\n                   },\n                   @\"isupport_params\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_servers updateIsupport:[object objectForKey:@\"params\"] server:object.cid];\n                       [self->_servers updateUserModes:[object objectForKey:@\"usermodes\"] server:object.cid];\n                   },\n                   @\"set_ignores\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_servers updateIgnores:[object objectForKey:@\"masks\"] server:object.cid];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventSetIgnores];\n                   },\n                   @\"ignore_list\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self->_servers updateIgnores:[object objectForKey:@\"masks\"] server:object.cid];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventSetIgnores];\n                   },\n                   @\"heartbeat_echo\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       NSDictionary *seenEids = [object objectForKey:@\"seenEids\"];\n                       for(NSNumber *cid in seenEids.allKeys) {\n                           NSDictionary *eids = [seenEids objectForKey:cid];\n                           for(id bid in eids.allKeys) {\n                               if([[eids objectForKey:bid] isKindOfClass:NSNumber.class]) {\n                                   NSTimeInterval eid = [[eids objectForKey:bid] doubleValue];\n                                   Buffer *buffer = [self->_buffers getBuffer:[bid intValue]];\n                                   if(buffer) {\n                                       buffer.last_seen_eid = eid;\n                                       buffer.extraHighlights = 0;\n                                   }\n                                   [self->_notifications removeNotificationsForBID:[bid intValue] olderThan:eid];\n                               }\n                           }\n                       }\n                       [self->_notifications updateBadgeCount];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventHeartbeatEcho];\n                   },\n                   @\"reorder_connections\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       NSArray *order = [object objectForKey:@\"order\"];\n                       \n                       for(int i = 0; i < order.count; i++) {\n                           Server *s = [self->_servers getServer:[[order objectAtIndex:i] intValue]];\n                           s.order = i + 1;\n                       }\n\n                       if(!backlog && !self->_resuming)\n                           [self postObject:object forEvent:kIRCEventReorderConnections];\n                   },\n                   @\"session_deleted\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       [self logout];\n                       [self postObject:object forEvent:kIRCEventSessionDeleted];\n                   },\n                   @\"display_name_change\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       if(!backlog) {\n                           [self->_users updateDisplayName:[object objectForKey:@\"display_name\"] nick:[object objectForKey:@\"nick\"] cid:object.cid];\n                           if(!self->_resuming)\n                               [self postObject:object forEvent:kIRCEventNickChange];\n                       }\n                   },\n                   @\"avatar_change\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       if(!backlog && [[object objectForKey:@\"self\"] boolValue]) {\n                           Server *s = [self->_servers getServer:object.cid];\n                           if(s) {\n                               s.avatar = [[object objectForKey:@\"avatar\"] isKindOfClass:NSString.class] ? [object objectForKey:@\"avatar\"] : nil;\n                               s.avatarURL = [[object objectForKey:@\"avatar_url\"] isKindOfClass:NSString.class] ? [object objectForKey:@\"avatar_url\"] : nil;\n                           }\n                           \n                           if(!self->_resuming)\n                               [self postObject:object forEvent:kIRCEventAvatarChange];\n                       }\n                   },\n                   @\"empty_msg\": pendingEdit,\n                   @\"redact\": pendingEdit,\n                   @\"watch_status\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       NSMutableDictionary *d = object.dictionary.mutableCopy;\n                       [d setObject:@([[NSDate date] timeIntervalSince1970] * 1000000) forKey:@\"eid\"];\n                       Event *e = [self->_events addJSONObject:[[IRCCloudJSONObject alloc] initWithDictionary:d]];\n                       if(!backlog && !self->_resuming)\n                           [self postObject:e forEvent:kIRCEventBufferMsg];\n                   },\n                   @\"user_typing\": ^(IRCCloudJSONObject *object, BOOL backlog) {\n                       Buffer *b = [self->_buffers getBuffer:object.bid];\n                       if(b) {\n                           [b addTyping:[object objectForKey:@\"from\"]];\n\n                           if(!backlog && !self->_resuming)\n                               [self postObject:object forEvent:kIRCEventUserTyping];\n                       }\n                   },\n               }.mutableCopy;\n        \n        for(NSString *type in @[@\"buffer_msg\", @\"buffer_me_msg\", @\"wait\", @\"banned\", @\"kill\", @\"connectingself->_cancelled\",\n                                @\"target_callerid\", @\"notice\", @\"server_motdstart\", @\"server_welcome\", @\"server_motd\", @\"server_endofmotd\",\n                                @\"server_nomotd\", @\"server_luserclient\", @\"server_luserop\", @\"server_luserconns\", @\"server_luserme\", @\"server_n_local\",\n                                @\"server_luserchannels\", @\"server_n_global\", @\"server_yourhost\",@\"server_created\", @\"server_luserunknown\",\n                                @\"services_down\", @\"your_unique_id\", @\"callerid\", @\"target_notified\", @\"myinfo\", @\"hidden_host_set\", @\"unhandled_line\",\n                                @\"unparsed_line\", @\"connecting_failed\", @\"nickname_in_use\", @\"channel_invite\", @\"motd_response\", @\"socket_closed\",\n                                @\"channel_mode_list_change\", @\"msg_services\", @\"stats\", @\"statslinkinfo\", @\"statscommands\", @\"statscline\",\n                                @\"statsnline\", @\"statsiline\", @\"statskline\", @\"statsqline\", @\"statsyline\", @\"statsbline\", @\"statsgline\", @\"statstline\",\n                                @\"statseline\", @\"statsvline\", @\"statslline\", @\"statsuptime\", @\"statsoline\", @\"statshline\", @\"statssline\", @\"statsuline\",\n                                @\"statsdebug\", @\"spamfilter\", @\"endofstats\", @\"inviting_to_channel\", @\"error\", @\"too_fast\", @\"no_bots\",\n                                @\"wallops\", @\"logged_in_as\", @\"sasl_fail\", @\"sasl_too_long\", @\"sasl_aborted\", @\"sasl_already\",\n                                @\"you_are_operator\", @\"btn_metadata_set\", @\"sasl_success\", @\"version\", @\"channel_name_change\",\n                                @\"cap_ls\", @\"cap_list\", @\"cap_new\", @\"cap_del\", @\"cap_req\",@\"cap_ack\",@\"cap_nak\",@\"cap_raw\",@\"cap_invalid\",\n                                @\"newsflash\", @\"invited\", @\"server_snomask\", @\"codepage\", @\"logged_out\", @\"nick_locked\", @\"info_response\", @\"generic_server_info\",\n                                @\"unknown_umode\", @\"bad_ping\", @\"cap_raw\", @\"rehashed_config\", @\"knock\", @\"bad_channel_mask\", @\"kill_deny\",\n                                @\"chan_own_priv_needed\", @\"not_for_halfops\", @\"chan_forbidden\", @\"starircd_welcome\", @\"zurna_motd\",\n                                @\"ambiguous_error_message\", @\"list_usage\", @\"list_syntax\", @\"who_syntax\", @\"text\", @\"admin_info\",\n                                @\"sqline_nick\", @\"user_chghost\", @\"loaded_module\", @\"unloaded_module\", @\"invite_notify\", @\"help\"]) {\n            [parserMap setObject:msg forKey:type];\n        }\n        \n        for(NSString *type in @[@\"too_many_channels\", @\"no_such_channel\", @\"bad_channel_name\",\n                                @\"no_such_nick\", @\"invalid_nick_change\", @\"chan_privs_needed\",\n                                @\"accept_exists\", @\"banned_from_channel\", @\"oper_only\",\n                                @\"no_nick_change\", @\"no_messages_from_non_registered\", @\"not_registered\",\n                                @\"already_registered\", @\"too_many_targets\", @\"no_such_server\",\n                                @\"unknown_command\", @\"help_not_found\", @\"accept_full\",\n                                @\"accept_not\", @\"nick_collision\", @\"nick_too_fast\", @\"need_registered_nick\",\n                                @\"save_nick\", @\"unknown_mode\", @\"user_not_in_channel\",\n                                @\"need_more_params\", @\"users_dont_match\", @\"users_disabled\",\n                                @\"invalid_operator_password\", @\"flood_warning\", @\"privs_needed\",\n                                @\"operator_fail\", @\"not_on_channel\", @\"ban_on_chan\",\n                                @\"cannot_send_to_chan\", @\"cant_send_to_user\", @\"user_on_channel\", @\"no_nick_given\",\n                                @\"no_text_to_send\", @\"no_origin\", @\"only_servers_can_change_mode\",\n                                @\"silence\", @\"no_channel_topic\", @\"invite_only_chan\", @\"channel_full\", @\"channel_key_set\",\n                                @\"blocked_channel\",@\"unknown_error\",@\"channame_in_use\",@\"pong\",\n                                @\"monitor_full\",@\"mlock_restricted\",@\"cannot_do_cmd\",@\"secure_only_chan\",\n                                @\"cannot_change_chan_mode\",@\"knock_delivered\",@\"too_many_knocks\",\n                                @\"chan_open\",@\"knock_on_chan\",@\"knock_disabled\",@\"cannotknock\",@\"ownmode\",\n                                @\"nossl\",@\"redirect_error\",@\"invalid_flood\",@\"join_flood\",@\"metadata_limit\",\n                                @\"metadata_targetinvalid\",@\"metadata_nomatchingkey\",@\"metadata_keyinvalid\",\n                                @\"metadata_keynotset\",@\"metadata_keynopermission\",@\"metadata_toomanysubs\",@\"invalid_nick\",@\"fail\"]) {\n            [parserMap setObject:alert forKey:type];\n        }\n        \n        NSDictionary *broadcastMap = @{    @\"bad_channel_key\":@(kIRCEventBadChannelKey),\n                                           @\"channel_query\":@(kIRCEventChannelQuery),\n                                           @\"open_buffer\":@(kIRCEventOpenBuffer),\n                                           @\"ban_list\":@(kIRCEventBanList),\n                                           @\"accept_list\":@(kIRCEventAcceptList),\n                                           @\"quiet_list\":@(kIRCEventQuietList),\n                                           @\"ban_exception_list\":@(kIRCEventBanExceptionList),\n                                           @\"invite_list\":@(kIRCEventInviteList),\n                                           @\"names_reply\":@(kIRCEventNamesList),\n                                           @\"whois_response\":@(kIRCEventWhois),\n                                           @\"list_response_fetching\":@(kIRCEventListResponseFetching),\n                                           @\"list_response_toomany\":@(kIRCEventListResponseTooManyChannels),\n                                           @\"list_response\":@(kIRCEventListResponse),\n                                           @\"map_list\":@(kIRCEventServerMap),\n                                           @\"who_special_response\":@(kIRCEventWhoSpecialResponse),\n                                           @\"modules_list\":@(kIRCEventModulesList),\n                                           @\"links_response\":@(kIRCEventLinksResponse),\n                                           @\"whowas_response\":@(kIRCEventWhoWas),\n                                           @\"trace_response\":@(kIRCEventTraceResponse),\n                                           @\"export_finished\":@(kIRCEventLogExportFinished),\n                                           @\"chanfilter_list\":@(kIRCEventChanFilterList),\n                                           @\"text\":@(kIRCEventTextList)\n                                           };\n        void (^broadcast)(IRCCloudJSONObject *object, BOOL backlog) = ^(IRCCloudJSONObject *object, BOOL backlog) {\n            if(!backlog && !self->_resuming)\n                [self postObject:object forEvent:[[broadcastMap objectForKey:object.type] intValue]];\n        };\n\n        for(NSString *type in broadcastMap.allKeys) {\n            [parserMap setObject:broadcast forKey:type];\n        }\n        \n        self->_parserMap = parserMap;\n    }\n    return self;\n}\n\n-(void)_processPendingEdits:(BOOL)backlog {\n    NSArray *pending;\n    @synchronized (self) {\n        pending = self->_pendingEdits;\n        self->_pendingEdits = [[NSMutableArray alloc] init];\n    }\n    for(IRCCloudJSONObject *object in pending) {\n        NSString *type = object.type;\n        \n        if([type isEqualToString:@\"empty_msg\"]) {\n            NSDictionary *entities = [object objectForKey:@\"entities\"];\n            //NSLog(@\"empty_msg entities: %@\", object);\n            if([entities objectForKey:@\"delete\"]) {\n                BOOL found = NO;\n                NSString *msgId = [entities objectForKey:@\"delete\"];\n                if(msgId.length) {\n                    Event *e = [[EventsDataSource sharedInstance] message:msgId buffer:object.bid];\n                    if(e && [e hasSameAccount:[object objectForKey:@\"from_account\"]]) {\n                        e.deleted = YES;\n                        found = YES;\n                    }\n                }\n                if(found) {\n                    if(!backlog && !self->_resuming)\n                        [self postObject:object forEvent:kIRCEventMessageChanged];\n                } else {\n                    [self->_pendingEdits addObject:object];\n                }\n            } else if([entities objectForKey:@\"edit\"]) {\n                BOOL found = NO;\n                NSString *msgId = [entities objectForKey:@\"edit\"];\n                if(msgId.length) {\n                    Event *e = [[EventsDataSource sharedInstance] message:msgId buffer:object.bid];\n                    if(e) {\n                        if(object.eid >= e.lastEditEID && [e hasSameAccount:[object objectForKey:@\"from_account\"]]) {\n                            if([[entities objectForKey:@\"edit_text\"] isKindOfClass:NSString.class]) {\n                                e.msg = [entities objectForKey:@\"edit_text\"];\n                                e.edited = YES;\n                                NSMutableDictionary *d = e.entities.mutableCopy;\n                                [d removeObjectForKey:@\"mentions\"];\n                                [d removeObjectForKey:@\"mention_data\"];\n                                e.entities = d;\n                            }\n                            NSMutableDictionary *d = e.entities.mutableCopy;\n                            [d setValuesForKeysWithDictionary:entities];\n                            e.entities = d;\n                            e.lastEditEID = object.eid;\n                            e.formatted = nil;\n                            e.formattedMsg = nil;\n                        }\n                        found = YES;\n                    }\n                }\n                if(found) {\n                    if(!backlog && !self->_resuming)\n                        [self postObject:object forEvent:kIRCEventMessageChanged];\n                } else {\n                    [self->_pendingEdits addObject:object];\n                }\n            }\n        } else if([type isEqualToString:@\"redact\"]) {\n            BOOL found = NO;\n            NSString *msgId = [object objectForKey:@\"redact_msgid\"];\n            if(msgId.length) {\n                Event *e = [[EventsDataSource sharedInstance] message:msgId buffer:object.bid];\n                if(e) {\n                    e.redacted = YES;\n                    e.redactedReason = [object objectForKey:@\"reason\"];\n                    found = YES;\n                }\n            }\n            if(found) {\n                if(!backlog && !self->_resuming)\n                    [self postObject:object forEvent:kIRCEventMessageChanged];\n            } else {\n                [self->_pendingEdits addObject:object];\n            }\n        }\n    }\n    CLS_LOG(@\"Queued pending edits: %lu\", (unsigned long)self->_pendingEdits.count);\n}\n\n//Adapted from http://stackoverflow.com/a/17057553/1406639\n-(kIRCCloudReachability)reachable {\n    SCNetworkReachabilityFlags flags;\n    if(self->_reachabilityValid && SCNetworkReachabilityGetFlags(self->_reachability, &flags)) {\n        if((flags & kSCNetworkReachabilityFlagsReachable) == 0) {\n            // if target host is not reachable\n            return kIRCCloudUnreachable;\n        }\n        \n        if((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) {\n            // if target host is reachable and no connection is required\n            return kIRCCloudReachable;\n        }\n        \n        \n        if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) {\n            // ... and the connection is on-demand (or on-traffic) if the\n            //     calling application is using the CFSocketStream or higher APIs\n            \n            if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) {\n                // ... and no [user] intervention is needed\n                return kIRCCloudReachable;\n            }\n        }\n        \n        if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) {\n            // ... but WWAN connections are OK if the calling application\n            //     is using the CFNetwork (CFSocketStream?) APIs.\n            return kIRCCloudReachable;\n        }\n        return kIRCCloudUnreachable;\n    }\n    return kIRCCloudUnknown;\n}\n\n-(BOOL)isWifi {\n    SCNetworkReachabilityFlags flags;\n    if(self->_reachabilityValid && SCNetworkReachabilityGetFlags(self->_reachability, &flags)) {\n        return (flags & kSCNetworkReachabilityFlagsIsWWAN) != kSCNetworkReachabilityFlagsIsWWAN;\n    }\n    return NO;\n}\n\nstatic void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) {\n    static BOOL firstTime = YES;\n    static int lastType = TYPE_UNKNOWN;\n    int type = TYPE_UNKNOWN;\n    [NetworkConnection sharedInstance].reachabilityValid = YES;\n    kIRCCloudReachability reachable = [[NetworkConnection sharedInstance] reachable];\n    kIRCCloudState state = [NetworkConnection sharedInstance].state;\n    CLS_LOG(@\"IRCCloud state: %i Reconnect timestamp: %f Reachable: %i lastType: %i\", state, [NetworkConnection sharedInstance].reconnectTimestamp, reachable, lastType);\n    \n    if(flags & kSCNetworkReachabilityFlagsIsWWAN)\n        type = TYPE_WWAN;\n    else if (flags & kSCNetworkReachabilityFlagsReachable)\n        type = TYPE_WIFI;\n    else\n        type = TYPE_UNKNOWN;\n\n    if(!firstTime && type != lastType && state != kIRCCloudStateDisconnected) {\n        CLS_LOG(@\"IRCCloud became unreachable, disconnecting websocket\");\n        SCNetworkReachabilityRef r = [NetworkConnection sharedInstance].reachability;\n        [NetworkConnection sharedInstance].reachability = nil;\n        [[NetworkConnection sharedInstance] performSelectorOnMainThread:@selector(disconnect) withObject:nil waitUntilDone:YES];\n        [NetworkConnection sharedInstance].reachability = r;\n        [NetworkConnection sharedInstance].reconnectTimestamp = -1;\n        state = kIRCCloudStateDisconnected;\n        [[NetworkConnection sharedInstance] performSelectorInBackground:@selector(serialize) withObject:nil];\n    }\n    \n    lastType = type;\n    firstTime = NO;\n    \n    if(reachable == kIRCCloudReachable && state == kIRCCloudStateDisconnected && [NetworkConnection sharedInstance].reconnectTimestamp != 0 && [[NetworkConnection sharedInstance].session length]) {\n        CLS_LOG(@\"IRCCloud server became reachable, connecting\");\n        [[NetworkConnection sharedInstance] performSelectorOnMainThread:@selector(_connect) withObject:nil waitUntilDone:YES];\n    } else if(reachable == kIRCCloudUnreachable && state == kIRCCloudStateConnected) {\n        CLS_LOG(@\"IRCCloud server became unreachable, disconnecting\");\n        SCNetworkReachabilityRef r = [NetworkConnection sharedInstance].reachability;\n        [NetworkConnection sharedInstance].reachability = nil;\n        [[NetworkConnection sharedInstance] performSelectorOnMainThread:@selector(disconnect) withObject:nil waitUntilDone:YES];\n        [NetworkConnection sharedInstance].reachability = r;\n        [[NetworkConnection sharedInstance] performSelectorInBackground:@selector(serialize) withObject:nil];\n    }\n    if(reachable == kIRCCloudUnreachable) {\n        [[NetworkConnection sharedInstance] performSelectorOnMainThread:@selector(cancelIdleTimer) withObject:nil waitUntilDone:YES];\n        [NetworkConnection sharedInstance].reconnectTimestamp = -1;\n    }\n    [[NetworkConnection sharedInstance] performSelectorOnMainThread:@selector(_postConnectivityChange) withObject:nil waitUntilDone:YES];\n}\n\n-(void)_connect {\n    [self connect:self->_notifier];\n}\n\n-(void)login:(NSString *)email password:(NSString *)password token:(NSString *)token handler:(IRCCloudAPIResultHandler)handler {\n    [self _postRequest:@\"/chat/login\" args:@{@\"email\":email, @\"password\":password, @\"token\":token} handler:handler];\n}\n\n-(void)login:(NSURL *)accessLink handler:(IRCCloudAPIResultHandler)handler {\n    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:accessLink];\n    [request setHTTPShouldHandleCookies:NO];\n    [request setValue:_userAgent forHTTPHeaderField:@\"User-Agent\"];\n    \n    [self _performDataTaskRequest:request handler:handler];\n}\n\n-(void)signup:(NSString *)email password:(NSString *)password realname:(NSString *)realname token:(NSString *)token handler:(IRCCloudAPIResultHandler)handler {\n    [self _postRequest:@\"/chat/signup\" args:@{@\"realname\":realname, @\"email\":email, @\"password\":password, @\"token\":token} handler:handler];\n}\n\n-(void)requestPasswordReset:(NSString *)email token:(NSString *)token handler:(IRCCloudAPIResultHandler)handler {\n    return [self _postRequest:@\"/chat/request-password-reset\" args:@{@\"email\":email, @\"mobile\":@\"1\", @\"token\":token} handler:handler];\n}\n\n-(void)requestAccessLink:(NSString *)email token:(NSString *)token handler:(IRCCloudAPIResultHandler)handler {\n    return [self _postRequest:@\"/chat/request-access-link\" args:@{@\"email\":email, @\"mobile\":@\"1\", @\"token\":token} handler:handler];\n}\n\n//From: http://stackoverflow.com/questions/1305225/best-way-to-serialize-a-nsdata-into-an-hexadeximal-string\n-(NSString *)dataToHex:(NSData *)data {\n    /* Returns hexadecimal string of NSData. Empty string if data is empty.   */\n    \n    const unsigned char *dataBuffer = (const unsigned char *)[data bytes];\n    \n    if (!dataBuffer)\n        return [NSString string];\n    \n    NSUInteger          dataLength  = [data length];\n    NSMutableString     *hexString  = [NSMutableString stringWithCapacity:(dataLength * 2)];\n    \n    for (int i = 0; i < dataLength; ++i)\n        [hexString appendString:[NSString stringWithFormat:@\"%02x\", (unsigned int)dataBuffer[i]]];\n    \n    return [NSString stringWithString:hexString];\n}\n\n-(void)registerAPNs:(NSData *)token fcm:(NSString *)fcm handler:(IRCCloudAPIResultHandler)handler {\n#if !defined(DEBUG) && !defined(EXTENSION)\n    [self _postRequest:@\"/apn-register\" args:@{@\"device_id\":[self dataToHex:token], @\"fcm_token\":fcm} handler:handler];\n#endif\n}\n\n-(void)unregisterAPNs:(NSData *)token fcm:(NSString *)fcm session:(NSString *)session handler:(IRCCloudAPIResultHandler)handler {\n#ifndef EXTENSION\n    [self _postRequest:@\"/apn-unregister\" args:@{@\"device_id\":[self dataToHex:token], @\"fcm_token\":fcm, @\"session\":session} handler:handler];\n#endif\n}\n\n-(void)requestAuthTokenWithHandler:(IRCCloudAPIResultHandler)handler {\n    [self _postRequest:@\"/chat/auth-formtoken\" args:@{} handler:handler];\n}\n\n-(void)_performDataTaskRequest:(NSURLRequest *)request handler:(IRCCloudAPIResultHandler)resultHandler {\n    NSURLSessionDataTask* task = [_urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n        if(resultHandler) {\n            if(!error && data) {\n                NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];\n                if(dict)\n                    resultHandler([[IRCCloudJSONObject alloc] initWithDictionary:dict]);\n                else\n                    resultHandler(nil);\n            } else {\n                CLS_LOG(@\"Request to %@ failed with error: %@\", request.URL, error);\n                resultHandler(nil);\n            }\n        }\n    }];\n    [task resume];\n}\n\n-(void)_get:(NSURL *)url handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(![NSThread isMainThread]) {\n        CLS_LOG(@\"*** _get called on wrong thread\");\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self _get:url handler:resultHandler];\n        }];\n    } else {\n        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];\n        [request setHTTPShouldHandleCookies:NO];\n        [request setValue:_userAgent forHTTPHeaderField:@\"User-Agent\"];\n        if(self.session.length > 1 && [url.scheme isEqualToString:@\"https\"] && ([url.host isEqualToString:IRCCLOUD_HOST] || [url.host hasSuffix:@\".irccloud.com\"]))\n            [request setValue:[NSString stringWithFormat:@\"session=%@\",self.session] forHTTPHeaderField:@\"Cookie\"];\n        \n        [self _performDataTaskRequest:request handler:resultHandler];\n    }\n}\n\n-(void)requestConfigurationWithHandler:(IRCCloudAPIResultHandler)handler {\n    CLS_LOG(@\"Requesting configuration\");\n    [self _get:[NSURL URLWithString:[NSString stringWithFormat:@\"https://%@/config\", IRCCLOUD_HOST]] handler:^(IRCCloudJSONObject *object) {\n        if(object) {\n            self->_config = object.dictionary;\n        }\n        \n        [self _configLoaded];\n        \n        if(handler)\n            handler(object);\n    }];\n}\n\n-(void)updateAPIHost:(NSString *)host {\n    if([host hasPrefix:@\"http://\"])\n        host = [host substringFromIndex:7];\n    if([host hasPrefix:@\"https://\"])\n        host = [host substringFromIndex:8];\n    if([host hasSuffix:@\"/\"])\n        host = [host substringToIndex:host.length - 1];\n    \n    [[NSUserDefaults standardUserDefaults] setObject:host forKey:@\"host\"];\n    [[NSUserDefaults standardUserDefaults] synchronize];\n\n    IRCCLOUD_HOST = host;\n    CLS_LOG(@\"API Host: %@\", IRCCLOUD_HOST);\n}\n\n-(void)_configLoaded {\n#ifdef ENTERPRISE\n    if(![[self->_config objectForKey:@\"enterprise\"] isKindOfClass:[NSDictionary class]])\n        self->_globalMsg = [NSString stringWithFormat:@\"Some features, such as push notifications, may not work as expected. Please download the standard IRCCloud app from the App Store: %@\", [self->_config objectForKey:@\"ios_app\"]];\n#endif\n    \n    if(self->_config) {\n        self.fileURITemplate = [CSURITemplate URITemplateWithString:[self->_config objectForKey:@\"file_uri_template\"] error:nil];\n        self.pasteURITemplate = [CSURITemplate URITemplateWithString:[self->_config objectForKey:@\"pastebin_uri_template\"] error:nil];\n        self.avatarURITemplate = [CSURITemplate URITemplateWithString:[self->_config objectForKey:@\"avatar_uri_template\"] error:nil];\n        self.avatarRedirectURITemplate = [CSURITemplate URITemplateWithString:[self->_config objectForKey:@\"avatar_redirect_uri_template\"] error:nil];\n\n        [self updateAPIHost:[self->_config objectForKey:@\"api_host\"]];\n    }\n}\n\n-(void)propertiesForFile:(NSString *)fileID handler:(IRCCloudAPIResultHandler)handler {\n    [self _get:[NSURL URLWithString:[NSString stringWithFormat:@\"https://%@/file/json/%@\", IRCCLOUD_HOST, fileID]] handler:handler];\n}\n\n-(void)getFiles:(int)page handler:(IRCCloudAPIResultHandler)handler {\n    [self _get:[NSURL URLWithString:[NSString stringWithFormat:@\"https://%@/chat/files?page=%i\", IRCCLOUD_HOST, page]] handler:handler];\n}\n\n-(void)getPastebins:(int)page handler:(IRCCloudAPIResultHandler)handler {\n    [self _get:[NSURL URLWithString:[NSString stringWithFormat:@\"https://%@/chat/pastebins?page=%i\", IRCCLOUD_HOST, page]] handler:handler];\n}\n\n-(void)getLogExportsWithHandler:(IRCCloudAPIResultHandler)handler {\n    [self _get:[NSURL URLWithString:[NSString stringWithFormat:@\"https://%@/chat/log-exports\", IRCCLOUD_HOST]] handler:handler];\n}\n\n-(int)_sendRequest:(NSString *)method args:(NSDictionary *)args handler:(IRCCloudAPIResultHandler)resultHandler {\n    @synchronized(self->_writer) {\n        if(self->_state == kIRCCloudStateConnected || [method isEqualToString:@\"auth\"]) {\n            NSMutableDictionary *dict = args?[[NSMutableDictionary alloc] initWithDictionary:args]:[[NSMutableDictionary alloc] init];\n            [dict setObject:method forKey:@\"_method\"];\n            if(![method isEqualToString:@\"auth\"])\n                [dict setObject:@(++_lastReqId) forKey:@\"_reqid\"];\n            [self->_socket sendText:[self->_writer stringWithObject:dict]];\n            if(resultHandler)\n                [self->_resultHandlers setObject:resultHandler forKey:@(self->_lastReqId)];\n            return _lastReqId;\n        } else {\n            CLS_LOG(@\"Discarding request '%@' on disconnected socket\", method);\n            return -1;\n        }\n    }\n}\n\n-(void)_postRequest:(NSString *)path args:(NSDictionary *)args handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(![NSThread isMainThread]) {\n        CLS_LOG(@\"*** _postRequest called on wrong thread\");\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self _postRequest:path args:args handler:resultHandler];\n        }];\n    } else {\n        NSMutableString *body = [[NSMutableString alloc] init];\n        \n        for (NSString *key in args.allKeys) {\n            if(body.length)\n                [body appendString:@\"&\"];\n            [body appendFormat:@\"%@=%@\",key,[[args objectForKey:key] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@\"\\\"#%<>[\\\\]^`{|}+&\"].invertedSet]];\n        }\n        \n        if(self.session.length > 1 && ![args objectForKey:@\"session\"])\n            [body appendFormat:@\"&session=%@\", self.session];\n        \n        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@\"https://%@%@\", IRCCLOUD_HOST, path]]];\n        [request setHTTPShouldHandleCookies:NO];\n        [request setValue:_userAgent forHTTPHeaderField:@\"User-Agent\"];\n        if([args objectForKey:@\"token\"])\n            [request setValue:[args objectForKey:@\"token\"] forHTTPHeaderField:@\"x-auth-formtoken\"];\n        if([args objectForKey:@\"session\"])\n            [request setValue:[NSString stringWithFormat:@\"session=%@\",[args objectForKey:@\"session\"]] forHTTPHeaderField:@\"Cookie\"];\n        else if(self.session.length > 1)\n            [request setValue:[NSString stringWithFormat:@\"session=%@\",self.session] forHTTPHeaderField:@\"Cookie\"];\n        [request setHTTPMethod:@\"POST\"];\n        [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];\n\n        [self _performDataTaskRequest:request handler:resultHandler];\n    }\n}\n\n-(void)_donateSendIntent:(NSString *)message to:(NSString *)to cid:(int)cid  image:(INImage *)img {\n    if (@available(iOS 14.0, *)) {\n        INPerson *person = [[INPerson alloc] initWithPersonHandle:[[INPersonHandle alloc] initWithValue:to type:INPersonHandleTypeUnknown] nameComponents:nil displayName:to image:img contactIdentifier:nil customIdentifier:[NSString stringWithFormat:@\"irccloud://%i/%@\", cid, to]];\n\n        INSendMessageIntent *intent = [[INSendMessageIntent alloc] initWithRecipients:@[person] outgoingMessageType:INOutgoingMessageTypeOutgoingMessageText content:nil speakableGroupName:nil conversationIdentifier:[NSString stringWithFormat:@\"irccloud://%i/%@\", cid, to] serviceName:nil sender:nil attachments:nil];\n        \n        INInteraction *interaction = [[INInteraction alloc] initWithIntent:intent response:nil];\n        [interaction donateInteractionWithCompletion:^(NSError *error) {\n            if(error) {\n                NSLog(@\"Intent donation failed: %@\", error);\n            }\n        }];\n    }\n}\n\n-(void)_donateSendIntent:(NSString *)message to:(NSString *)to cid:(int)cid {\n    if (@available(iOS 14.0, *)) {\n        if(!to || !to.length || [to isEqualToString:@\"*\"])\n            return;\n        \n        Buffer *b = [[BuffersDataSource sharedInstance] getBufferWithName:to server:cid];\n        if(b) {\n            Avatar *a = [[Avatar alloc] init];\n            a.nick = a.displayName = to;\n            \n            if([b.type isEqualToString:@\"channel\"]) {\n                [self _donateSendIntent:message to:to cid:cid image:[INImage imageWithUIImage:[a getImage:512 isSelf:NO isChannel:YES]]];\n            } else {\n                NSURL *url = [[AvatarsDataSource sharedInstance] URLforBid:b.bid];\n                if(!url) {\n                    User *u = [[UsersDataSource sharedInstance] getUser:to cid:cid];\n                    if(u) {\n                        Event *e = [[Event alloc] init];\n                        e.cid = cid;\n                        e.bid = b.bid;\n                        e.hostmask = u.hostmask;\n                        e.from = to;\n                        e.type = @\"buffer_msg\";\n                        \n                        url = [e avatar:512];\n                    }\n                }\n                \n                if(url) {\n                    UIImage *img = [[ImageCache sharedInstance] imageForURL:url];\n                    if(img) {\n                        [self _donateSendIntent:message to:to cid:cid image:[INImage imageWithURL:[[ImageCache sharedInstance] pathForURL:url]]];\n                        return;\n                    } else if([[ImageCache sharedInstance] isValidURL:url]) {\n                        [[ImageCache sharedInstance] fetchURL:url completionHandler:^(BOOL success) {\n                            if(success) {\n                                [self _donateSendIntent:message to:to cid:cid image:[INImage imageWithURL:[[ImageCache sharedInstance] pathForURL:url]]];\n                            } else {\n                                [self _donateSendIntent:message to:to cid:cid image:[INImage imageWithUIImage:[a getImage:512 isSelf:NO isChannel:NO]]];\n                            }\n                        }];\n                        return;\n                    }\n                }\n                [self _donateSendIntent:message to:to cid:cid image:[INImage imageWithUIImage:[a getImage:512 isSelf:NO isChannel:NO]]];\n            }\n        }\n    }\n}\n\n-(void)POSTsay:(NSString *)message to:(NSString *)to cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(to) {\n        [self _donateSendIntent:message to:to cid:cid];\n        [self _postRequest:@\"/chat/say\" args:@{@\"msg\":message, @\"to\":to, @\"cid\":[@(cid) stringValue]} handler:resultHandler];\n    } else {\n        [self _postRequest:@\"/chat/say\" args:@{@\"msg\":message, @\"to\":@\"*\", @\"cid\":[@(cid) stringValue]} handler:resultHandler];\n    }\n}\n\n-(int)say:(NSString *)message to:(NSString *)to cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(!message)\n        message = @\"\";\n    if(to) {\n        [self _donateSendIntent:message to:to cid:cid];\n        return [self _sendRequest:@\"say\" args:@{@\"cid\":@(cid), @\"msg\":message, @\"to\":to} handler:resultHandler];\n    } else {\n        return [self _sendRequest:@\"say\" args:@{@\"cid\":@(cid), @\"msg\":message, @\"to\":@\"*\"} handler:resultHandler];\n    }\n}\n\n-(void)POSTreply:(NSString *)message to:(NSString *)to cid:(int)cid msgid:(NSString *)msgid handler:(IRCCloudAPIResultHandler)handler {\n    if(!message)\n        message = @\"\";\n    [self _postRequest:@\"/chat/reply\" args:@{@\"cid\":[@(cid) stringValue], @\"reply\":message, @\"to\":to, @\"msgid\":msgid} handler:handler];\n}\n\n-(int)reply:(NSString *)message to:(NSString *)to cid:(int)cid msgid:(NSString *)msgid handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(!message)\n        message = @\"\";\n    return [self _sendRequest:@\"reply\" args:@{@\"cid\":@(cid), @\"reply\":message, @\"to\":to, @\"msgid\":msgid} handler:resultHandler];\n}\n\n-(int)heartbeat:(int)selectedBuffer cids:(NSArray *)cids bids:(NSArray *)bids lastSeenEids:(NSArray *)lastSeenEids handler:(IRCCloudAPIResultHandler)resultHandler {\n    @synchronized(self->_writer) {\n        NSMutableDictionary *heartbeat = [[NSMutableDictionary alloc] init];\n        for(int i = 0; i < cids.count; i++) {\n            NSMutableDictionary *d = [heartbeat objectForKey:[NSString stringWithFormat:@\"%@\",[cids objectAtIndex:i]]];\n            if(!d) {\n                d = [[NSMutableDictionary alloc] init];\n                [heartbeat setObject:d forKey:[NSString stringWithFormat:@\"%@\",[cids objectAtIndex:i]]];\n            }\n            [d setObject:[lastSeenEids objectAtIndex:i] forKey:[NSString stringWithFormat:@\"%@\",[bids objectAtIndex:i]]];\n        }\n        NSString *seenEids = [self->_writer stringWithObject:heartbeat];\n        [__userInfoLock lock];\n        NSMutableDictionary *d = self->_userInfo.mutableCopy;\n        [d setObject:@(selectedBuffer) forKey:@\"last_selected_bid\"];\n        self->_userInfo = d;\n        [__userInfoLock unlock];\n        return [self _sendRequest:@\"heartbeat\" args:@{@\"selectedBuffer\":@(selectedBuffer), @\"seenEids\":seenEids} handler:resultHandler];\n    }\n}\n-(int)heartbeat:(int)selectedBuffer cid:(int)cid bid:(int)bid lastSeenEid:(NSTimeInterval)lastSeenEid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self heartbeat:selectedBuffer cids:@[@(cid)] bids:@[@(bid)] lastSeenEids:@[@(lastSeenEid)] handler:resultHandler];\n}\n\n-(void)POSTheartbeat:(int)selectedBuffer cids:(NSArray *)cids bids:(NSArray *)bids lastSeenEids:(NSArray *)lastSeenEids handler:(IRCCloudAPIResultHandler)handler {\n    @synchronized(self->_writer) {\n        NSMutableDictionary *heartbeat = [[NSMutableDictionary alloc] init];\n        for(int i = 0; i < cids.count; i++) {\n            NSMutableDictionary *d = [heartbeat objectForKey:[NSString stringWithFormat:@\"%@\",[cids objectAtIndex:i]]];\n            if(!d) {\n                d = [[NSMutableDictionary alloc] init];\n                [heartbeat setObject:d forKey:[NSString stringWithFormat:@\"%@\",[cids objectAtIndex:i]]];\n            }\n            [d setObject:[lastSeenEids objectAtIndex:i] forKey:[NSString stringWithFormat:@\"%@\",[bids objectAtIndex:i]]];\n        }\n        NSString *seenEids = [self->_writer stringWithObject:heartbeat];\n        [self _postRequest:@\"/chat/heartbeat\" args:@{@\"selectedBuffer\":[@(selectedBuffer) stringValue], @\"seenEids\":seenEids} handler:handler];\n    }\n}\n\n-(void)POSTheartbeat:(int)selectedBuffer cid:(int)cid bid:(int)bid lastSeenEid:(NSTimeInterval)lastSeenEid handler:(IRCCloudAPIResultHandler)handler {\n    [self POSTheartbeat:selectedBuffer cids:@[@(cid)] bids:@[@(bid)] lastSeenEids:@[@(lastSeenEid)] handler:handler];\n}\n\n-(int)join:(NSString *)channel key:(NSString *)key cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(key.length) {\n        return [self _sendRequest:@\"join\" args:@{@\"cid\":@(cid), @\"channel\":channel, @\"key\":key} handler:resultHandler];\n    } else {\n        return [self _sendRequest:@\"join\" args:@{@\"cid\":@(cid), @\"channel\":channel} handler:resultHandler];\n    }\n}\n\n-(int)part:(NSString *)channel msg:(NSString *)msg cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(msg.length) {\n        return [self _sendRequest:@\"part\" args:@{@\"cid\":@(cid), @\"channel\":channel, @\"msg\":msg} handler:resultHandler];\n    } else {\n        return [self _sendRequest:@\"part\" args:@{@\"cid\":@(cid), @\"channel\":channel} handler:resultHandler];\n    }\n}\n\n-(int)kick:(NSString *)nick chan:(NSString *)chan msg:(NSString *)msg cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self say:[NSString stringWithFormat:@\"/kick %@ %@\",nick,(msg.length)?msg:@\"\"] to:chan cid:cid handler:resultHandler];\n}\n\n-(int)mode:(NSString *)mode chan:(NSString *)chan cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self say:[NSString stringWithFormat:@\"/mode %@ %@\",chan,mode] to:chan cid:cid handler:resultHandler];\n}\n\n-(int)invite:(NSString *)nick chan:(NSString *)chan cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self say:[NSString stringWithFormat:@\"/invite %@ %@\",nick,chan] to:chan cid:cid handler:resultHandler];\n}\n\n-(int)archiveBuffer:(int)bid cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"archive-buffer\" args:@{@\"cid\":@(cid),@\"id\":@(bid)} handler:resultHandler];\n}\n\n-(int)unarchiveBuffer:(int)bid cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"unarchive-buffer\" args:@{@\"cid\":@(cid),@\"id\":@(bid)} handler:resultHandler];\n}\n\n-(int)deleteBuffer:(int)bid cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"delete-buffer\" args:@{@\"cid\":@(cid),@\"id\":@(bid)} handler:resultHandler];\n}\n\n-(int)deleteServer:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"delete-connection\" args:@{@\"cid\":@(cid)} handler:(IRCCloudAPIResultHandler)resultHandler];\n}\n\n-(int)changePassword:(NSString *)password newPassword:(NSString *)newPassword handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"change-password\" args:@{@\"password\":password,@\"newPassword\":newPassword} handler:resultHandler];\n}\n\n-(int)deleteAccount:(NSString *)password handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"delete-account\" args:@{@\"password\":password} handler:resultHandler];\n}\n\n\n-(int)addServer:(NSString *)hostname port:(int)port ssl:(int)ssl netname:(NSString *)netname nick:(NSString *)nick realname:(NSString *)realname serverPass:(NSString *)serverPass nickservPass:(NSString *)nickservPass joinCommands:(NSString *)joinCommands channels:(NSString *)channels handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"add-server\" args:@{\n                                                   @\"hostname\":hostname?hostname:@\"\",\n                                                   @\"port\":@(port),\n                                                   @\"ssl\":[NSString stringWithFormat:@\"%i\",ssl],\n                                                   @\"netname\":netname?netname:@\"\",\n                                                   @\"nickname\":nick?nick:@\"\",\n                                                   @\"realname\":realname?realname:@\"\",\n                                                   @\"server_pass\":serverPass?serverPass:@\"\",\n                                                   @\"nspass\":nickservPass?nickservPass:@\"\",\n                                                   @\"joincommands\":joinCommands?joinCommands:@\"\",\n                                                   @\"channels\":channels?channels:@\"\"} handler:resultHandler];\n}\n\n-(int)editServer:(int)cid hostname:(NSString *)hostname port:(int)port ssl:(int)ssl netname:(NSString *)netname nick:(NSString *)nick realname:(NSString *)realname serverPass:(NSString *)serverPass nickservPass:(NSString *)nickservPass joinCommands:(NSString *)joinCommands handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"edit-server\" args:@{\n                                                    @\"hostname\":hostname?hostname:@\"\",\n                                                    @\"port\":@(port),\n                                                    @\"ssl\":[NSString stringWithFormat:@\"%i\",ssl],\n                                                    @\"netname\":netname?netname:@\"\",\n                                                    @\"nickname\":nick?nick:@\"\",\n                                                    @\"realname\":realname?realname:@\"\",\n                                                    @\"server_pass\":serverPass?serverPass:@\"\",\n                                                    @\"nspass\":nickservPass?nickservPass:@\"\",\n                                                    @\"joincommands\":joinCommands?joinCommands:@\"\",\n                                                    @\"cid\":@(cid)} handler:resultHandler];\n}\n\n-(int)ignore:(NSString *)mask cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"ignore\" args:@{@\"cid\":@(cid),@\"mask\":mask} handler:resultHandler];\n}\n\n-(int)unignore:(NSString *)mask cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"unignore\" args:@{@\"cid\":@(cid),@\"mask\":mask} handler:resultHandler];\n}\n\n-(int)setPrefs:(NSString *)prefs handler:(IRCCloudAPIResultHandler)resultHandler {\n#ifdef DEBUG\nif([[NSProcessInfo processInfo].arguments containsObject:@\"-ui_testing\"]) {\n    self->_prefs = [NSJSONSerialization JSONObjectWithData:[prefs dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:nil];\n    [self postObject:nil forEvent:kIRCEventUserInfo];\n    resultHandler([[IRCCloudJSONObject alloc] initWithDictionary:@{@\"success\":@YES}]);\n    return 1;\n} else {\n#endif\n    self->_prefs = nil;\n    return [self _sendRequest:@\"set-prefs\" args:@{@\"prefs\":prefs} handler:resultHandler];\n#ifdef DEBUG\n}\n#endif\n}\n\n-(int)setRealname:(NSString *)realname highlights:(NSString *)highlights autoaway:(BOOL)autoaway handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"user-settings\" args:@{\n                                                      @\"realname\":realname,\n                                                      @\"hwords\":highlights,\n                                                      @\"autoaway\":autoaway?@\"1\":@\"0\"} handler:resultHandler];\n}\n\n-(int)changeEmail:(NSString *)email password:(NSString *)password handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"change-password\" args:@{\n                                                      @\"email\":email,\n                                                      @\"password\":password} handler:resultHandler];\n}\n\n-(int)ns_help_register:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"ns-help-register\" args:@{@\"cid\":@(cid)} handler:resultHandler];\n}\n\n-(int)setNickservPass:(NSString *)nspass cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"set-nspass\" args:@{@\"cid\":@(cid),@\"nspass\":nspass} handler:resultHandler];\n}\n\n-(int)whois:(NSString *)nick server:(NSString *)server cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(server.length) {\n        return [self _sendRequest:@\"whois\" args:@{@\"cid\":@(cid), @\"nick\":nick, @\"server\":server} handler:resultHandler];\n    } else {\n        return [self _sendRequest:@\"whois\" args:@{@\"cid\":@(cid), @\"nick\":nick} handler:resultHandler];\n    }\n}\n\n-(int)topic:(NSString *)topic chan:(NSString *)chan cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"topic\" args:@{@\"cid\":@(cid),@\"channel\":chan,@\"topic\":topic} handler:resultHandler];\n}\n\n-(int)back:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"back\" args:@{@\"cid\":@(cid)} handler:resultHandler];\n}\n\n-(int)resendVerifyEmailWithHandler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"resend-verify-email\" args:nil handler:resultHandler];\n}\n\n-(int)disconnect:(int)cid msg:(NSString *)msg handler:(IRCCloudAPIResultHandler)resultHandler {\n    CLS_LOG(@\"Disconnecting cid%i\", cid);\n    if(msg.length)\n        return [self _sendRequest:@\"disconnect\" args:@{@\"cid\":@(cid), @\"msg\":msg} handler:resultHandler];\n    else\n        return [self _sendRequest:@\"disconnect\" args:@{@\"cid\":@(cid)} handler:resultHandler];\n}\n\n-(int)reconnect:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    CLS_LOG(@\"Reconnecting cid%i\", cid);\n    int reqid = [self _sendRequest:@\"reconnect\" args:@{@\"cid\":@(cid)} handler:resultHandler];\n    if(reqid > 0) {\n        Server *s = [self->_servers getServer:cid];\n        if(s) {\n            s.status = @\"queued\";\n            [self postObject:@{@\"cid\":@(cid)} forEvent:kIRCEventConnectionLag];\n        }\n    }\n    return reqid;\n}\n\n-(int)reorderConnections:(NSString *)cids handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"reorder-connections\" args:@{@\"cids\":cids} handler:resultHandler];\n}\n\n-(void)finalizeUpload:(NSString *)uploadID filename:(NSString *)filename originalFilename:(NSString *)originalFilename avatar:(BOOL)avatar orgId:(int)orgId cid:(int)cid handler:(IRCCloudAPIResultHandler)handler {\n    if(avatar) {\n        if(cid) {\n            [self _postRequest:@\"/chat/upload-finalise\" args:@{@\"id\":uploadID, @\"filename\":filename, @\"original_filename\":originalFilename, @\"type\":@\"avatar\", @\"cid\":[NSString stringWithFormat:@\"%i\", cid]} handler:handler];\n        } else if(orgId == -1) {\n            [self _postRequest:@\"/chat/upload-finalise\" args:@{@\"id\":uploadID, @\"filename\":filename, @\"original_filename\":originalFilename, @\"type\":@\"avatar\", @\"primary\":@\"1\"} handler:handler];\n        } else {\n            [self _postRequest:@\"/chat/upload-finalise\" args:@{@\"id\":uploadID, @\"filename\":filename, @\"original_filename\":originalFilename, @\"type\":@\"avatar\", @\"org\":[NSString stringWithFormat:@\"%i\", orgId]} handler:handler];\n        }\n    } else {\n        [self _postRequest:@\"/chat/upload-finalise\" args:@{@\"id\":uploadID, @\"filename\":filename, @\"original_filename\":originalFilename} handler:handler];\n    }\n}\n\n-(int)deleteFile:(NSString *)fileID handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"delete-file\" args:@{@\"file\":fileID} handler:resultHandler];\n}\n\n-(int)deleteMessage:(NSString *)msgId cid:(int)cid to:(NSString *)to handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"delete-message\" args:@{@\"cid\":@(cid), @\"to\":to, @\"msgid\":msgId} handler:resultHandler];\n}\n\n-(int)editMessage:(NSString *)msgId cid:(int)cid to:(NSString *)to msg:(NSString *)msg handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"edit-message\" args:@{@\"cid\":@(cid), @\"to\":to, @\"msgid\":msgId, @\"edit\":msg} handler:resultHandler];\n}\n\n-(int)redact:(NSString *)msgId cid:(int)cid to:(NSString *)to reason:(NSString *)reason handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"redact-message\" args:@{@\"cid\":@(cid), @\"to\":to, @\"msgid\":msgId, @\"reason\":reason} handler:resultHandler];\n}\n\n-(int)paste:(NSString *)name contents:(NSString *)contents extension:(NSString *)extension handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(name.length) {\n        return [self _sendRequest:@\"paste\" args:@{@\"name\":name, @\"contents\":contents, @\"extension\":extension} handler:resultHandler];\n    } else {\n        return [self _sendRequest:@\"paste\" args:@{@\"contents\":contents, @\"extension\":extension} handler:resultHandler];\n    }\n}\n\n-(int)deletePaste:(NSString *)pasteID handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"delete-pastebin\" args:@{@\"id\":pasteID} handler:resultHandler];\n}\n\n-(int)editPaste:(NSString *)pasteID name:(NSString *)name contents:(NSString *)contents extension:(NSString *)extension handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(name.length) {\n        return [self _sendRequest:@\"edit-pastebin\" args:@{@\"id\":pasteID, @\"name\":name, @\"body\":contents, @\"extension\":extension} handler:resultHandler];\n    } else {\n        return [self _sendRequest:@\"edit-pastebin\" args:@{@\"id\":pasteID, @\"body\":contents, @\"extension\":extension} handler:resultHandler];\n    }\n}\n\n-(int)exportLog:(NSString *)timezone cid:(int)cid bid:(int)bid handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(cid > 0) {\n        if(bid > 0) {\n            return [self _sendRequest:@\"export-log\" args:@{@\"cid\":@(cid), @\"bid\":@(bid), @\"timezone\":timezone} handler:resultHandler];\n        } else {\n            return [self _sendRequest:@\"export-log\" args:@{@\"cid\":@(cid), @\"timezone\":timezone} handler:resultHandler];\n        }\n    } else {\n        return [self _sendRequest:@\"export-log\" args:@{@\"timezone\":timezone} handler:resultHandler];\n    }\n}\n\n-(int)renameChannel:(NSString *)name cid:(int)cid bid:(int)bid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"rename-channel\" args:@{@\"cid\":@(cid), @\"id\":@(bid), @\"name\":name} handler:resultHandler];\n}\n\n-(int)renameConversation:(NSString *)name cid:(int)cid bid:(int)bid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"rename-conversation\" args:@{@\"cid\":@(cid), @\"id\":@(bid), @\"name\":name} handler:resultHandler];\n}\n\n-(int)setAvatar:(NSString *)avatarId orgId:(int)orgId handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(orgId == -1) {\n        if(avatarId)\n            return [self _sendRequest:@\"set-avatar\" args:@{@\"id\":avatarId, @\"primary\":@\"1\"} handler:resultHandler];\n        else\n            return [self _sendRequest:@\"set-avatar\" args:@{@\"clear\":@\"1\", @\"primary\":@\"1\"} handler:resultHandler];\n    } else {\n        if(avatarId)\n            return [self _sendRequest:@\"set-avatar\" args:@{@\"id\":avatarId, @\"org\":@(orgId)} handler:resultHandler];\n        else\n            return [self _sendRequest:@\"set-avatar\" args:@{@\"clear\":@\"1\", @\"org\":@(orgId)} handler:resultHandler];\n    }\n}\n\n-(int)setAvatar:(NSString *)avatarId cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    if(avatarId)\n        return [self _sendRequest:@\"set-avatar\" args:@{@\"id\":avatarId, @\"cid\":@(cid)} handler:resultHandler];\n    else\n        return [self _sendRequest:@\"set-avatar\" args:@{@\"clear\":@\"1\", @\"cid\":@(cid)} handler:resultHandler];\n}\n\n-(int)setNetworkName:(NSString *)name cid:(int)cid handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"set-netname\" args:@{@\"cid\":@(cid), @\"netname\":name} handler:resultHandler];\n}\n\n-(int)typing:(NSString *)value cid:(int)cid to:(NSString *)to handler:(IRCCloudAPIResultHandler)resultHandler {\n    return [self _sendRequest:@\"typing\" args:@{@\"cid\":@(cid), @\"to\":to, @\"value\":value} handler:resultHandler];\n}\n\n-(void)_createJSONParser {\n    self->_parser = [SBJson5Parser multiRootParserWithBlock:^(id item, BOOL *stop) {\n        [self parse:item backlog:NO];\n    } errorHandler:^(NSError *error) {\n        CLS_LOG(@\"JSON ERROR: %@\", error);\n        self->_streamId = nil;\n        self->_highestEID = 0;\n    }];\n}\n\n-(void)connect:(BOOL)notifier {\n    @synchronized(self) {\n        if(self->_mock) {\n            self->_reconnectTimestamp = -1;\n            self->_state = kIRCCloudStateConnected;\n            self->_ready = YES;\n            return;\n        }\n        \n        if(IRCCLOUD_HOST == nil || IRCCLOUD_HOST.length < 1) {\n            CLS_LOG(@\"Not connecting, no host\");\n            return;\n        }\n        \n        if(_session.length < 1) {\n            CLS_LOG(@\"Not connecting, no session\");\n            return;\n        }\n        \n        [self->_idleTimer invalidate];\n        self->_idleTimer = nil;\n\n        if(self->_socket) {\n            CLS_LOG(@\"Discarding previous socket\");\n            WebSocket *s = self->_socket;\n            self->_socket = nil;\n            s.delegate = nil;\n            [s close];\n        }\n        \n        if(!_reachability || !_reachabilityValid) {\n            if(self->_reachability)\n                CFRelease(self->_reachability);\n            self->_reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [IRCCLOUD_HOST cStringUsingEncoding:NSUTF8StringEncoding]);\n            SCNetworkReachabilitySetCallback(self->_reachability, ReachabilityCallback, NULL);\n            SCNetworkReachabilityScheduleWithRunLoop(self->_reachability, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);\n        } else {\n            kIRCCloudReachability reachability = [self reachable];\n            if(self->_reachabilityValid && reachability != kIRCCloudReachable) {\n                CLS_LOG(@\"IRCCloud is unreachable\");\n                self->_reconnectTimestamp = -1;\n                self->_state = kIRCCloudStateDisconnected;\n                if(reachability == kIRCCloudUnreachable)\n                    [self performSelectorOnMainThread:@selector(_postConnectivityChange) withObject:nil waitUntilDone:YES];\n                self->_ready = YES;\n                return;\n            }\n        }\n        \n        @synchronized (self->_oobQueue) {\n            if(self->_oobQueue.count) {\n                CLS_LOG(@\"Cancelling pending OOB requests\");\n                for(OOBFetcher *fetcher in _oobQueue) {\n                    [fetcher cancel];\n                }\n                [self->_oobQueue removeAllObjects];\n                self->_streamId = nil;\n                self->_highestEID = 0;\n            }\n        }\n        \n        self->_notifier = notifier;\n        self->_state = kIRCCloudStateConnecting;\n        self->_idleInterval = 20;\n        self->_accrued = 0;\n        self->_currentCount = 0;\n        self->_totalCount = 0;\n        self->_reconnectTimestamp = -1;\n        self->_resuming = NO;\n        self->_ready = NO;\n        self->_firstEID = 0;\n        __socketPaused = NO;\n        self->_lastReqId = 1;\n        [self->_resultHandlers removeAllObjects];\n        \n        [self performSelectorOnMainThread:@selector(_postConnectivityChange) withObject:nil waitUntilDone:YES];\n        \n        [self requestConfigurationWithHandler:^(IRCCloudJSONObject *result) {\n            if(result) {\n                NSString *url = [NSString stringWithFormat:@\"wss://%@%@\",[result objectForKey:@\"socket_host\"],IRCCLOUD_PATH];\n                if(self->_highestEID > 0 && self->_streamId.length) {\n                    url = [url stringByAppendingFormat:@\"?since_id=%.0lf&stream_id=%@\", self->_highestEID, self->_streamId];\n                }\n                if(notifier) {\n                    if([url rangeOfString:@\"?\"].location == NSNotFound)\n                        url = [url stringByAppendingFormat:@\"?notifier=1\"];\n                    else\n                        url = [url stringByAppendingFormat:@\"&notifier=1\"];\n                }\n                if([url rangeOfString:@\"?\"].location == NSNotFound)\n                    url = [url stringByAppendingFormat:@\"?exclude_archives=1\"];\n                else\n                    url = [url stringByAppendingFormat:@\"&exclude_archives=1\"];\n\n                SCNetworkReachabilityFlags flags;\n                BOOL success = SCNetworkReachabilityGetFlags(self->_reachability, &flags);\n                if(success && flags & kSCNetworkReachabilityFlagsIsWWAN) {\n                    CTTelephonyNetworkInfo *telephonyInfo = [[CTTelephonyNetworkInfo alloc] init];\n                    int limit = 50;\n                    NSString *radioType = telephonyInfo.serviceCurrentRadioAccessTechnology.allValues.firstObject;\n                    if([radioType isEqualToString:CTRadioAccessTechnologyGPRS] || [radioType isEqualToString:CTRadioAccessTechnologyEdge]) {\n                        limit = 25;\n                    } else if ([radioType isEqualToString:CTRadioAccessTechnologyLTE]) {\n                        limit = 100;\n                    }\n                    if([url rangeOfString:@\"?\"].location == NSNotFound)\n                        url = [url stringByAppendingFormat:@\"?limit=%i\", limit];\n                    else\n                        url = [url stringByAppendingFormat:@\"&limit=%i\", limit];\n                }\n                \n                CLS_LOG(@\"Connecting: %@\", url);\n                WebSocketConnectConfig* config = [WebSocketConnectConfig configWithURLString:url origin:[NSString stringWithFormat:@\"https://%@\", [result objectForKey:@\"socket_host\"]] protocols:nil\n                                                                                     headers:[@[[HandshakeHeader headerWithValue:_userAgent forKey:@\"User-Agent\"]] mutableCopy]\n                                                                           verifySecurityKey:YES extensions:@[@\"x-webkit-deflate-frame\"]];\n                self->_socket = [WebSocket webSocketWithConfig:config delegate:self];\n                [self->_socket performSelectorOnMainThread:@selector(open) withObject:nil waitUntilDone:YES];\n            } else {\n                CLS_LOG(@\"Unable to load configuration\");\n                [self fail];\n            }\n        }];\n    }\n}\n\n-(void)cancelPendingBacklogRequests {\n    @synchronized (self->_oobQueue) {\n        for(OOBFetcher *fetcher in _oobQueue.copy) {\n            if(fetcher.bid > 0) {\n                [fetcher cancel];\n                [self->_oobQueue removeObject:fetcher];\n            }\n        }\n    }\n}\n\n-(void)disconnect {\n    CLS_LOG(@\"Closing websocket\");\n    if(self->_reachability) {\n        CFRelease(self->_reachability);\n        self->_reachability = nil;\n        self->_reachabilityValid = NO;\n    }\n    @synchronized (self->_oobQueue) {\n        if(self->_oobQueue.count) {\n            for(OOBFetcher *fetcher in _oobQueue) {\n                [fetcher cancel];\n            }\n            [self->_oobQueue removeAllObjects];\n            self->_streamId = nil;\n            self->_highestEID = 0;\n        }\n    }\n    self->_reconnectTimestamp = 0;\n    [self performSelectorOnMainThread:@selector(cancelIdleTimer) withObject:nil waitUntilDone:YES];\n    self->_state = kIRCCloudStateDisconnected;\n    [self performSelectorOnMainThread:@selector(_postConnectivityChange) withObject:nil waitUntilDone:YES];\n    [self->_socket performSelectorOnMainThread:@selector(close) withObject:nil waitUntilDone:YES];\n    self->_socket = nil;\n    for(Buffer *b in [self->_buffers getBuffers]) {\n        b.typingIndicators = nil;\n        if(!b.scrolledUp && [self->_events highlightStateForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type] == 0) {\n            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n                [self->_events pruneEventsForBuffer:b.bid maxSize:50];\n            });\n        }\n    }\n}\n\n-(void)clearPrefs {\n    self->_prefs = nil;\n    [__userInfoLock lock];\n    self->_userInfo = nil;\n    [__userInfoLock unlock];\n}\n\n-(void)webSocketDidOpen:(WebSocket *)socket {\n    if(socket == self->_socket && self.session != nil) {\n        CLS_LOG(@\"Socket connected\");\n        self->_idleInterval = 20;\n        self->_reconnectTimestamp = -1;\n        [self _sendRequest:@\"auth\" args:@{@\"cookie\":self.session} handler:nil];\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self _postConnectivityChange];\n        }];\n    } else {\n        CLS_LOG(@\"Socket connected, but it wasn't the active socket\");\n    }\n}\n\n-(void)fail {\n    if(self->_session) {\n        [self clearOOB];\n        self->_failCount++;\n        if(self->_failCount < 4)\n            self->_idleInterval = self->_failCount;\n        else if(self->_failCount < 10)\n            self->_idleInterval = 10;\n        else\n            self->_idleInterval = 30;\n        self->_reconnectTimestamp = -1;\n        CLS_LOG(@\"Fail count: %i will reconnect in %f seconds\", _failCount, _idleInterval);\n        [self performSelectorOnMainThread:@selector(scheduleIdleTimer) withObject:nil waitUntilDone:YES];\n    }\n}\n\n-(void)webSocket:(WebSocket *)socket didClose:(NSUInteger) aStatusCode message:(NSString*) aMessage error:(NSError*) aError {\n    if(socket == self->_socket) {\n        CLS_LOG(@\"Status Code: %lu\", (unsigned long)aStatusCode);\n        CLS_LOG(@\"Close Message: %@\", aMessage);\n        CLS_LOG(@\"Error: errorDesc=%@, failureReason=%@, code=%li, domain=%@\", [aError localizedDescription], [aError localizedFailureReason], (long)aError.code, aError.domain);\n        self->_state = kIRCCloudStateDisconnected;\n        __socketPaused = NO;\n        if(aStatusCode == WebSocketCloseStatusProtocolError) {\n            self->_streamId = nil;\n            self->_highestEID = 0;\n        }\n        if([aError.domain isEqualToString:@\"kCFStreamErrorDomainNetDB\"])\n            _reconnectTimestamp = 0;\n        if(_reconnectTimestamp != 0) {\n            [self fail];\n        } else {\n            CLS_LOG(@\"reconnecting is disabled\");\n            [self performSelectorOnMainThread:@selector(cancelIdleTimer) withObject:nil waitUntilDone:YES];\n            [self serialize];\n        }\n        [self performSelectorOnMainThread:@selector(_postConnectivityChange) withObject:nil waitUntilDone:YES];\n    } else {\n        CLS_LOG(@\"Socket closed, but it wasn't the active socket\");\n    }\n}\n\n-(void)webSocket:(WebSocket *)socket didReceiveError: (NSError*) aError {\n    if(socket == self->_socket) {\n        CLS_LOG(@\"Error: errorDesc=%@, failureReason=%@, code=%li, domain=%@\", [aError localizedDescription], [aError localizedFailureReason], (long)aError.code, aError.domain);\n        self->_state = kIRCCloudStateDisconnected;\n        __socketPaused = NO;\n        if([self reachable] && _reconnectTimestamp != 0) {\n            [self fail];\n        }\n        [self performSelectorOnMainThread:@selector(_postConnectivityChange) withObject:nil waitUntilDone:YES];\n    } else {\n        CLS_LOG(@\"Socket received error, but it wasn't the active socket\");\n    }\n}\n\n-(void)webSocket:(WebSocket *)socket didReceiveTextMessage:(NSString*)aMessage {\n    if(socket == self->_socket) {\n        if(aMessage) {\n            while(__socketPaused) { //GCD uses a thread pool and can't guarantee NSLock will be locked and unlocked on the same thread, so here's an ugly hack instead\n                [NSThread sleepForTimeInterval:0.05];\n            }\n            [self->_parser parse:[aMessage dataUsingEncoding:NSUTF8StringEncoding]];\n        }\n    } else {\n        CLS_LOG(@\"Got event for inactive socket\");\n    }\n}\n\n- (void)webSocket:(WebSocket *)socket didReceiveBinaryMessage: (NSData*) aMessage {\n    if(socket == self->_socket) {\n        if(aMessage) {\n            while(__socketPaused) {\n                [NSThread sleepForTimeInterval:0.05];\n            }\n            [self->_parser parse:aMessage];\n        }\n    } else {\n        CLS_LOG(@\"Got event for inactive socket\");\n    }\n}\n\n-(void)postObject:(id)object forEvent:(kIRCEvent)event {\n    if(self->_accrued == 0) {\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudEventNotification object:object userInfo:@{kIRCCloudEventKey:[NSNumber numberWithInt:event]}];\n        }];\n    }\n}\n\n-(void)_postLoadingProgress:(NSNumber *)progress {\n    static NSNumber *lastProgress = nil;\n    if(!lastProgress || (int)(lastProgress.floatValue * 100) != (int)(progress.floatValue * 100))\n        [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudBacklogProgressNotification object:progress];\n    lastProgress = progress;\n}\n\n-(void)_postConnectivityChange {\n    [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudConnectivityNotification object:nil userInfo:nil];\n}\n\n-(NSDictionary *)prefs {\n    @synchronized(self) {\n        if(!_prefs && self.userInfo && [[self.userInfo objectForKey:@\"prefs\"] isKindOfClass:[NSString class]] && [[self.userInfo objectForKey:@\"prefs\"] length]) {\n            NSError *error;\n            self->_prefs = [NSJSONSerialization JSONObjectWithData:[[self.userInfo objectForKey:@\"prefs\"] dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];\n            if(error) {\n                CLS_LOG(@\"Prefs parse error: %@\", error);\n                CLS_LOG(@\"JSON string: %@\", [self.userInfo objectForKey:@\"prefs\"]);\n            }\n        }\n        return _prefs;\n    }\n}\n\n-(void)parse:(NSDictionary *)dict backlog:(BOOL)backlog {\n    if(![dict isKindOfClass:[NSDictionary class]])\n        return;\n    @synchronized(self->_parserMap) {\n        NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];\n        if(backlog)\n            self->_totalCount++;\n        if([NSThread currentThread].isMainThread)\n            CLS_LOG(@\"WARNING: Parsing on main thread\");\n        [self performSelectorOnMainThread:@selector(cancelIdleTimer) withObject:nil waitUntilDone:YES];\n        if(self->_accrued > 0) {\n            [self performSelectorOnMainThread:@selector(_postLoadingProgress:) withObject:@(((float)_totalCount++ / (float)_accrued)) waitUntilDone:NO];\n        }\n        IRCCloudJSONObject *object = [[IRCCloudJSONObject alloc] initWithDictionary:dict];\n        if(object.type) {\n            //NSLog(@\"New event (backlog: %i resuming: %i highestEID: %f) (%@) %@\", backlog, _resuming, _highestEID, object.type, object);\n            if((backlog || _accrued > 0) && object.bid > -1 && object.bid != self->_currentBid && object.eid > 0) {\n                if(!backlog) {\n                    if(self->_firstEID == 0) {\n                        self->_firstEID = object.eid;\n                        if(object.eid > _highestEID) {\n                            CLS_LOG(@\"Backlog gap detected, purging cache\");\n                            [self->_events clear];\n                            self->_highestEID = 0;\n                            self->_streamId = nil;\n                            self->_pendingEdits = [[NSMutableArray alloc] init];\n                            [self performSelectorOnMainThread:@selector(disconnect) withObject:nil waitUntilDone:NO];\n                            self->_state = kIRCCloudStateDisconnected;\n                            [self performSelectorOnMainThread:@selector(fail) withObject:nil waitUntilDone:NO];\n                            return;\n                        } else {\n                            CLS_LOG(@\"First EID matched\");\n                        }\n                    }\n                }\n                self->_currentBid = object.bid;\n                self->_currentCount = 0;\n            }\n            void (^block)(IRCCloudJSONObject *o, BOOL backlog) = [self->_parserMap objectForKey:object.type];\n            if(block != nil) {\n                block(object,backlog);\n            } else {\n                CLS_LOG(@\"Unhandled type: %@\", object.type);\n            }\n            if(backlog || _accrued > 0) {\n                if(self->_numBuffers > 1 && (object.bid > -1 || [object.type isEqualToString:@\"backlog_complete\"]) && ![object.type isEqualToString:@\"makebuffer\"] && ![object.type isEqualToString:@\"channel_init\"]) {\n                    if(object.bid != self->_currentBid) {\n                        self->_currentBid = object.bid;\n                        self->_currentCount = 0;\n                    }\n                    [self performSelectorOnMainThread:@selector(_postLoadingProgress:) withObject:@(((float)_totalBuffers + (float)_currentCount/100.0f)/ (float)_numBuffers) waitUntilDone:NO];\n                    self->_currentCount++;\n                }\n            }\n            if(!backlog && [object objectForKey:@\"reqid\"]) {\n                IRCCloudAPIResultHandler handler = [self->_resultHandlers objectForKey:@([[object objectForKey:@\"reqid\"] intValue])];\n                if(handler) {\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        handler(object);\n                    }];\n                }\n            }\n            if([NSDate timeIntervalSinceReferenceDate] - start > _longestEventTime) {\n                self->_longestEventTime = [NSDate timeIntervalSinceReferenceDate] - start;\n                self->_longestEventType = object.type;\n            }\n        } else {\n            if([object objectForKey:@\"success\"] && ![[object objectForKey:@\"success\"] boolValue] && [object objectForKey:@\"message\"]) {\n                CLS_LOG(@\"Failure: %@\", object);\n                if([[object objectForKey:@\"message\"] isEqualToString:@\"invalid_nick\"]) {\n                    [self postObject:object forEvent:kIRCEventAlert];\n                } else if([[object objectForKey:@\"message\"] isEqualToString:@\"auth\"]) {\n                    [self postObject:object forEvent:kIRCEventAuthFailure];\n                    if([[object objectForKey:@\"_reqid\"] intValue] == 0)\n                        [self logout];\n                } else if([[object objectForKey:@\"message\"] isEqualToString:@\"set_shard\"]) {\n                    if([object objectForKey:@\"websocket_path\"])\n                        IRCCLOUD_PATH = [object objectForKey:@\"websocket_path\"];\n                    if([object objectForKey:@\"api_host\"])\n                        [self updateAPIHost:[object objectForKey:@\"api_host\"]];\n                    [self setSession:[object objectForKey:@\"cookie\"]];\n                    [[NSUserDefaults standardUserDefaults] setObject:IRCCLOUD_PATH forKey:@\"path\"];\n                    [[NSUserDefaults standardUserDefaults] synchronize];\n#ifdef ENTERPRISE\n                    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n                    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n                    [d setObject:IRCCLOUD_HOST forKey:@\"host\"];\n                    [d setObject:IRCCLOUD_PATH forKey:@\"path\"];\n                    [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"uploadsAvailable\"] forKey:@\"uploadsAvailable\"];\n                    [d synchronize];\n                    [self disconnect];\n                    [self connect:NO];\n                } else if([self->_resultHandlers objectForKey:@([[object objectForKey:@\"_reqid\"] intValue])]) {\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        ((IRCCloudAPIResultHandler)[self->_resultHandlers objectForKey:@([[object objectForKey:@\"_reqid\"] intValue])])(object);\n                    }];\n                } else if(backlog) {\n                    [self _backlogFailed:nil];\n                }\n            } else if([object objectForKey:@\"success\"]) {\n                if([self->_resultHandlers objectForKey:@([[object objectForKey:@\"_reqid\"] intValue])])\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        ((IRCCloudAPIResultHandler)[self->_resultHandlers objectForKey:@([[object objectForKey:@\"_reqid\"] intValue])])(object);\n                    }];\n            }\n        }\n        if(!backlog && _reconnectTimestamp != 0)\n            [self performSelectorOnMainThread:@selector(scheduleIdleTimer) withObject:nil waitUntilDone:YES];\n    }\n}\n\n-(void)cancelIdleTimer {\n    if(![NSThread currentThread].isMainThread)\n        CLS_LOG(@\"WARNING: cancel idle timer called outside of main thread\");\n    \n    [self->_idleTimer invalidate];\n    self->_idleTimer = nil;\n    self->_reconnectTimestamp = -1;\n}\n\n-(void)scheduleIdleTimer {\n    if(![NSThread currentThread].isMainThread)\n        CLS_LOG(@\"WARNING: schedule idle timer called outside of main thread\");\n    [self->_idleTimer invalidate];\n    self->_idleTimer = nil;\n    if(self->_reconnectTimestamp == 0)\n        return;\n    \n    if(self->_idleInterval > 0) {\n        self->_idleTimer = [NSTimer scheduledTimerWithTimeInterval:self->_idleInterval target:self selector:@selector(_idle) userInfo:nil repeats:NO];\n        self->_reconnectTimestamp = [[NSDate date] timeIntervalSince1970] + _idleInterval;\n    }\n}\n\n+(BOOL)shouldReconnect {\n#ifdef EXTENSION\n    return NO;\n#else\n    if (@available(iOS 14.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp) {\n            return YES;\n        }\n    }\n    return [UIApplication sharedApplication].applicationState != UIApplicationStateBackground;\n#endif\n}\n\n-(void)_idle {\n    self->_reconnectTimestamp = 0;\n    self->_idleTimer = nil;\n    [self->_socket performSelectorOnMainThread:@selector(close) withObject:nil waitUntilDone:YES];\n    self->_state = kIRCCloudStateDisconnected;\n#ifndef EXTENSION\n    if([NetworkConnection shouldReconnect]) {\n        CLS_LOG(@\"Websocket idle time exceeded, reconnecting...\");\n        [self connect:self->_notifier];\n    } else {\n        CLS_LOG(@\"Websocket idle time exceeded in the background...\");\n    }\n#endif\n}\n\n-(void)requestBacklogForBuffer:(int)bid server:(int)cid completion:(void (^)(BOOL))completionHandler {\n    [self requestBacklogForBuffer:bid server:cid beforeId:-1 completion:completionHandler];\n}\n\n-(void)requestBacklogForBuffer:(int)bid server:(int)cid beforeId:(NSTimeInterval)eid completion:(void (^)(BOOL))completionHandler {\n    NSString *URL = nil;\n    if(eid > 0)\n        URL = [NSString stringWithFormat:@\"https://%@/chat/backlog?cid=%i&bid=%i&beforeid=%.0lf\", IRCCLOUD_HOST, cid, bid, eid];\n    else\n        URL = [NSString stringWithFormat:@\"https://%@/chat/backlog?cid=%i&bid=%i\", IRCCLOUD_HOST, cid, bid];\n    OOBFetcher *fetcher = [self fetchOOB:URL];\n    fetcher.bid = bid;\n    fetcher.completionHandler = completionHandler;\n}\n\n-(void)requestArchives:(int)cid {\n    @synchronized(self->_oobQueue) {\n        NSString *url = [NSString stringWithFormat:@\"https://%@/chat/archives?cid=%i\", IRCCLOUD_HOST, cid];\n        NSArray *fetchers = self->_oobQueue.copy;\n        for(OOBFetcher *fetcher in fetchers) {\n            if([fetcher.url isEqualToString:url]) {\n                CLS_LOG(@\"Ignoring duplicate archives request\");\n                return;\n            }\n        }\n        OOBFetcher *fetcher = [self fetchOOB:url];\n        fetcher.bid = -1;\n    }\n}\n\n-(OOBFetcher *)fetchOOB:(NSString *)url {\n    @synchronized(self->_oobQueue) {\n        NSArray *fetchers = self->_oobQueue.copy;\n        for(OOBFetcher *fetcher in fetchers) {\n            if([fetcher.url isEqualToString:url]) {\n                CLS_LOG(@\"Cancelling previous OOB request\");\n                [fetcher cancel];\n                [self->_oobQueue removeObject:fetcher];\n            }\n        }\n        OOBFetcher *fetcher = [[OOBFetcher alloc] initWithURL:url];\n        [self->_oobQueue addObject:fetcher];\n        if(self->_oobQueue.count == 1) {\n            [self->_queue addOperationWithBlock:^{\n                @autoreleasepool {\n                    CLS_LOG(@\"Starting OOB fetcher\");\n                    [fetcher start];\n                }\n            }];\n        } else {\n            CLS_LOG(@\"OOB Request has been queued\");\n        }\n        return fetcher;\n    }\n}\n\n-(void)clearOOB {\n    @synchronized(self->_oobQueue) {\n        NSMutableArray *oldQueue = self->_oobQueue;\n        self->_oobQueue = [[NSMutableArray alloc] init];\n        for(OOBFetcher *fetcher in oldQueue) {\n            [fetcher cancel];\n        }\n    }\n}\n\n-(void)_backlogStarted:(NSNotification *)notification {\n    self->_OOBStartTime = [NSDate timeIntervalSinceReferenceDate];\n    self->_longestEventTime = 0;\n    self->_longestEventType = nil;\n    if(self->_awayOverride.count)\n        CLS_LOG(@\"Caught %lu self_back events\", (unsigned long)_awayOverride.count);\n    self->_currentBid = -1;\n    self->_currentCount = 0;\n    self->_totalCount = 0;\n}\n\n-(void)_backlogCompleted:(NSNotification *)notification {\n    if(self->_OOBStartTime) {\n        NSTimeInterval total = [NSDate timeIntervalSinceReferenceDate] - _OOBStartTime;\n        CLS_LOG(@\"OOB processed %i events in %f seconds (%f seconds / event)\", _totalCount, total, total / (double)_totalCount);\n        CLS_LOG(@\"Longest event: %@ (%f seconds)\", _longestEventType, _longestEventTime);\n        self->_OOBStartTime = 0;\n        self->_longestEventTime = 0;\n        self->_longestEventType = nil;\n    }\n    self->_failCount = 0;\n    self->_accrued = 0;\n    self->_resuming = NO;\n    self->_awayOverride = nil;\n    self->_reconnectTimestamp = [[NSDate date] timeIntervalSince1970] + _idleInterval;\n    [self performSelectorOnMainThread:@selector(scheduleIdleTimer) withObject:nil waitUntilDone:NO];\n    OOBFetcher *fetcher = notification.object;\n    CLS_LOG(@\"Backlog finished for bid: %i\", fetcher.bid);\n    if(fetcher.bid > 0) {\n        [self->_buffers getBuffer:fetcher.bid].deferred = 0;\n        [self->_buffers updateTimeout:0 buffer:fetcher.bid];\n    } else {\n        self->_ready = YES;\n        CLS_LOG(@\"I now have %lu servers with %lu buffers\", (unsigned long)[self->_servers count], (unsigned long)[self->_buffers count]);\n        if(fetcher.bid == -1) {\n            [self->_buffers purgeInvalidBIDs];\n            [self->_channels purgeInvalidChannels];\n            CLS_LOG(@\"I now have %lu servers with %lu buffers\", (unsigned long)[self->_servers count], (unsigned long)[self->_buffers count]);\n        }\n        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n            for(Buffer *b in [self->_buffers getBuffers]) {\n                if(!b.scrolledUp && [self->_events highlightStateForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type] == 0) {\n                        [self->_events pruneEventsForBuffer:b.bid maxSize:101];\n                }\n                [self->_notifications removeNotificationsForBID:b.bid olderThan:b.last_seen_eid];\n            }\n            [NetworkConnection sync];\n        });\n        self->_numBuffers = 0;\n        __socketPaused = NO;\n    }\n    CLS_LOG(@\"I downloaded %i events\", _totalCount);\n    @synchronized (self->_oobQueue) {\n        [self->_oobQueue removeObject:fetcher];\n\n        if(fetcher.bid == -1 && self->_oobQueue.count > 0) {\n            [self->_queue addOperationWithBlock:^{\n                if(self->_oobQueue.count > 0 && ((OOBFetcher *)[self->_oobQueue objectAtIndex:0]).bid == -1) {\n                    CLS_LOG(@\"Starting next queued OOB fetcher\");\n                    [(OOBFetcher *)[self->_oobQueue objectAtIndex:0] start];\n                }\n            }];\n        }\n    }\n    [self->_notifications updateBadgeCount];\n    [self _processPendingEdits:NO];\n    if([self->_servers count]) {\n        [self performSelectorOnMainThread:@selector(_scheduleTimedoutBuffers) withObject:nil waitUntilDone:YES];\n    }\n    [self _serializeSoon];\n}\n\n-(void)_serializeUserInfo {\n    [__serializeLock lock];\n    NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"stream\"];\n    [__userInfoLock lock];\n    NSMutableDictionary *stream = [self->_userInfo mutableCopy];\n    if(self->_streamId)\n        [stream setObject:self->_streamId forKey:@\"streamId\"];\n    else\n        [stream removeObjectForKey:@\"streamId\"];\n    if(self->_config)\n        [stream setObject:self->_config forKey:@\"config\"];\n    else\n        [stream removeObjectForKey:@\"config\"];\n    [stream setObject:@(self->_highestEID) forKey:@\"highestEID\"];\n    \n    NSError* error = nil;\n    [[NSKeyedArchiver archivedDataWithRootObject:stream requiringSecureCoding:YES error:&error] writeToFile:cacheFile atomically:YES];\n    if(error)\n        CLS_LOG(@\"Error archiving: %@\", error);\n\n    [__userInfoLock unlock];\n    [[NSURL fileURLWithPath:cacheFile] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL];\n    [__serializeLock unlock];\n}\n\n-(void)_serializeSoon {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        if(self->_serializeTimer)\n            [self->_serializeTimer invalidate];\n        \n        self->_serializeTimer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(serialize) userInfo:nil repeats:NO];\n    }];\n}\n\n-(void)serialize {\n#ifndef EXTENSION\n    __block BOOL __interrupt = NO;\n    UIBackgroundTaskIdentifier background_task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^ {\n        CLS_LOG(@\"NetworkConnection serialize task expired\");\n        __interrupt = YES;\n    }];\n    [__serializeLock lock];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"cacheVersion\"];\n    [[NSUserDefaults standardUserDefaults] synchronize];\n    if(!__interrupt)\n        [self->_avatars serialize];\n    if(!__interrupt)\n        [self->_servers serialize];\n    if(!__interrupt)\n        [self->_buffers serialize];\n    if(!__interrupt)\n        [self->_channels serialize];\n    if(!__interrupt)\n        [self->_users serialize];\n    if(!__interrupt)\n        [self->_events serialize];\n    if(!__interrupt)\n        [self->_notifications serialize];\n    [__serializeLock unlock];\n    if(!__interrupt)\n        [self _serializeUserInfo];\n    [__serializeLock lock];\n    [[NSUserDefaults standardUserDefaults] setObject:[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleVersion\"] forKey:@\"cacheVersion\"];\n#ifdef ENTERPRISE\n    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n    [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"cacheVersion\"] forKey:@\"cacheVersion\"];\n    [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"fontSize\"] forKey:@\"fontSize\"];\n    [d synchronize];\n    if(!__interrupt)\n        [NetworkConnection sync];\n    [_serializeTimer invalidate];\n    _serializeTimer = nil;\n    [__serializeLock unlock];\n    [[UIApplication sharedApplication] endBackgroundTask: background_task];\n#endif\n}\n\n-(void)_backlogFailed:(NSNotification *)notification {\n    self->_accrued = 0;\n    self->_awayOverride = nil;\n    self->_reconnectTimestamp = [[NSDate date] timeIntervalSince1970] + _idleInterval;\n    [self performSelectorOnMainThread:@selector(scheduleIdleTimer) withObject:nil waitUntilDone:NO];\n    if(notification) {\n        @synchronized (self->_oobQueue) {\n            [self->_oobQueue removeObject:notification.object];\n        }\n    }\n    if(notification && [(OOBFetcher *)notification.object bid] > 0) {\n        CLS_LOG(@\"Backlog download failed, rescheduling timed out buffers\");\n        [self _scheduleTimedoutBuffers];\n    } else {\n        CLS_LOG(@\"Initial backlog download failed\");\n        [self disconnect];\n        __socketPaused = NO;\n        self->_state = kIRCCloudStateDisconnected;\n        self->_streamId = nil;\n        self->_highestEID = 0;\n        [self fail];\n        [self performSelectorOnMainThread:@selector(_postConnectivityChange) withObject:nil waitUntilDone:YES];\n    }\n}\n\n-(void)_scheduleTimedoutBuffers {\n    [self->_queue addOperationWithBlock:^{\n        for(Buffer *buffer in [self->_buffers getBuffers]) {\n            if(buffer.timeout > 0) {\n                if([buffer.type isEqualToString:@\"channel\"] && buffer.timeout == 0) {\n                    if(![self->_channels channelForBuffer:buffer.bid])\n                        continue;\n                }\n                CLS_LOG(@\"Requesting backlog for buffer: %@\", buffer.name);\n                [self requestBacklogForBuffer:buffer.bid server:buffer.cid completion:nil];\n            }\n        }\n        @synchronized (self->_oobQueue) {\n            if(self->_oobQueue.count > 0) {\n                [self->_queue addOperationWithBlock:^{\n                    if(self->_oobQueue.count > 0 && ((OOBFetcher *)[self->_oobQueue objectAtIndex:0]).bid > 0) {\n                        CLS_LOG(@\"Starting fetcher for timed-out bid%i\", ((OOBFetcher *)[self->_oobQueue objectAtIndex:0]).bid);\n                        [(OOBFetcher *)[self->_oobQueue objectAtIndex:0] start];\n                    }\n                }];\n            }\n        }\n    }];\n}\n\n-(void)_logout:(NSString *)session {\n#ifndef EXTENSION\n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"APNs\"] && [[NSUserDefaults standardUserDefaults] objectForKey:@\"FCM\"]) {\n        [self unregisterAPNs:[[NSUserDefaults standardUserDefaults] objectForKey:@\"APNs\"] fcm:[[NSUserDefaults standardUserDefaults] objectForKey:@\"FCM\"] session:session handler:^(IRCCloudJSONObject *result) {\n            CLS_LOG(@\"Unregister result: %@\", result);\n        }];\n    }\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"APNs\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"FCM\"];\n    [[FIRMessaging messaging] deleteDataWithCompletion:^(NSError *error) {\n        if(error)\n            CLS_LOG(@\"Unable to delete Firebase ID: %@\", error);\n    }];\n    IRCCLOUD_HOST = @\"api.irccloud.com\";\n    [self _postRequest:@\"/chat/logout\" args:@{@\"session\":session} handler:nil];\n#endif\n}\n\n-(void)logout {\n    CLS_LOG(@\"Logging out\");\n    self->_reconnectTimestamp = 0;\n    self->_streamId = nil;\n    [__userInfoLock lock];\n    self->_userInfo = @{};\n    [__userInfoLock unlock];\n    self->_highestEID = 0;\n    NSString *s = self.session;\n    SecItemDelete((__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword),  kSecClass, [NSBundle mainBundle].bundleIdentifier, kSecAttrService, nil]);\n    self->_session = nil;\n    [self disconnect];\n    if(s)\n        [self _logout:s];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"host\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"path\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"uploadsAvailable\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"theme\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"logs_cache\"];\n    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"last_uid\"];\n    [[NSUserDefaults standardUserDefaults] synchronize];\n    [UIColor setTheme:@\"dawn\"];\n    [self clearPrefs];\n    [self->_servers clear];\n    [self->_buffers clear];\n    [self->_users clear];\n    [self->_channels clear];\n    [self->_events clear];\n    [self->_avatars invalidate];\n    [self->_avatars removeAllURLs];\n    self->_pendingEdits = [[NSMutableArray alloc] init];\n    [self serialize];\n    [NetworkConnection sync];\n#ifndef EXTENSION\n    [[UIApplication sharedApplication] unregisterForRemoteNotifications];\n    NSURL *caches = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] objectAtIndex:0];\n    for(NSURL *file in [[NSFileManager defaultManager] contentsOfDirectoryAtURL:caches includingPropertiesForKeys:nil options:0 error:nil]) {\n        [[NSFileManager defaultManager] removeItemAtURL:file error:nil];\n    }\n#ifdef ENTERPRISE\n    NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.enterprise.share\"];\n#else\n    NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.share\"];\n#endif\n    for(NSURL *file in [[NSFileManager defaultManager] contentsOfDirectoryAtURL:sharedcontainer includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsHiddenFiles error:nil]) {\n        if(![file.absoluteString hasSuffix:@\"/\"]) {\n            CLS_LOG(@\"Removing: %@\", file);\n            [[NSFileManager defaultManager] removeItemAtURL:file error:nil];\n        }\n    }\n    [[ImageCache sharedInstance] purge];\n#endif\n    [self cancelIdleTimer];\n}\n\n-(NSString *)session {\n    if(self->_mock)\n        return @\"__mock_session__\";\n    \n    if(self->_session) {\n        self->_keychainFailCount = 0;\n        return _session;\n    }\n    \n    @synchronized (self) {\n        CFDataRef data = nil;\n#ifdef ENTERPRISE\n        OSStatus err = SecItemCopyMatching((__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword),  kSecClass, @\"com.irccloud.enterprise\", kSecAttrService, kCFBooleanTrue, kSecReturnData, nil], (CFTypeRef*)&data);\n#else\n        OSStatus err = SecItemCopyMatching((__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword),  kSecClass, @\"com.irccloud.IRCCloud\", kSecAttrService, kCFBooleanTrue, kSecReturnData, nil], (CFTypeRef*)&data);\n#endif\n        if(!err) {\n            self->_keychainFailCount = 0;\n            self->_session = [[NSString alloc] initWithData:CFBridgingRelease(data) encoding:NSUTF8StringEncoding];\n            if(self->_session.length <= 1) {\n                CLS_LOG(@\"Removing invalid session\");\n                [self setSession:nil];\n            }\n            return _session;\n        } else {\n            self->_keychainFailCount++;\n            if(self->_keychainFailCount < 10 && err != errSecItemNotFound) {\n                CLS_LOG(@\"Error fetching session: %i, trying again\", (int)err);\n                return self.session;\n            } else {\n                if(err == errSecItemNotFound)\n                    CLS_LOG(@\"Session key not found\");\n                else\n                    CLS_LOG(@\"Error fetching session: %i\", (int)err);\n                self->_keychainFailCount = 0;\n                return nil;\n            }\n        }\n    }\n}\n\n-(void)setSession:(NSString *)session {\n    @synchronized (self) {\n#ifdef ENTERPRISE\n        SecItemDelete((__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword),  kSecClass, @\"com.irccloud.enterprise\", kSecAttrService, nil]);\n        if(session)\n            SecItemAdd((__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword),  kSecClass, @\"com.irccloud.enterprise\", kSecAttrService, [session dataUsingEncoding:NSUTF8StringEncoding], kSecValueData, (__bridge id)(kSecAttrAccessibleAlways), kSecAttrAccessible, nil], NULL);\n#else\n        SecItemDelete((__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword),  kSecClass, @\"com.irccloud.IRCCloud\", kSecAttrService, nil]);\n        if(session)\n            SecItemAdd((__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword),  kSecClass, @\"com.irccloud.IRCCloud\", kSecAttrService, [session dataUsingEncoding:NSUTF8StringEncoding], kSecValueData, (__bridge id)(kSecAttrAccessibleAfterFirstUnlock), kSecAttrAccessible, nil], NULL);\n#endif\n        self->_session = session;\n    }\n}\n\n-(BOOL)notifier {\n    return _notifier;\n}\n\n-(void)setNotifier:(BOOL)notifier {\n    self->_notifier = notifier;\n    if(self->_state == kIRCCloudStateConnected && !notifier) {\n        CLS_LOG(@\"Upgrading websocket\");\n        [self _sendRequest:@\"upgrade_notifier\" args:nil handler:nil];\n    }\n}\n\n-(NSDictionary *)userInfo {\n    [__userInfoLock lock];\n    NSDictionary *d = self->_userInfo;\n    [__userInfoLock unlock];\n    return d;\n}\n\n-(void)setUserInfo:(NSDictionary *)userInfo {\n  [__userInfoLock lock];\n  self->_userInfo = userInfo;\n  [__userInfoLock unlock];\n}\n\n-(void)setLastSelectedBID:(int)bid {\n  [__userInfoLock lock];\n  NSMutableDictionary *d = self->_userInfo.mutableCopy;\n  [d setObject:@(bid) forKey:@\"last_selected_bid\"];\n  self->_userInfo = d;\n  [__userInfoLock unlock];\n  \n}\n\n-(void)sendFeedbackReport:(UIViewController *)delegate {\n    CLS_LOG(@\"Feedback Requested\");\n    NSString *version = [NSString stringWithFormat:@\"%@ (%@)\",[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"], [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleVersion\"]];\n    NSMutableString *report = [[NSMutableString alloc] initWithFormat:\n@\"Briefly describe the issue below:\\n\\\n\\n\\\n\\n\\\n\\n\\\n==========\\n\\\nUID: %@\\n\\\nApp Version: %@\\n\\\nOS Version: %@\\n\\\nDevice type: %@\\n\\\nNetwork type: %@\\n\",\n                               [[NetworkConnection sharedInstance].userInfo objectForKey:@\"id\"],version,[UIDevice currentDevice].systemVersion,[UIDevice currentDevice].model,[NetworkConnection sharedInstance].isWifi ? @\"Wi-Fi\" : @\"Mobile\"];\n    [report appendString:@\"==========\\nPrefs:\\n\"];\n    [report appendFormat:@\"%@\\n\", [[NetworkConnection sharedInstance] prefs]];\n    [report appendString:@\"==========\\nNSUserDefaults:\\n\"];\n    NSMutableDictionary *d = [NSUserDefaults standardUserDefaults].dictionaryRepresentation.mutableCopy;\n    [d removeObjectForKey:@\"logs_cache\"];\n    [d removeObjectForKey:@\"AppleITunesStoreItemKinds\"];\n    [report appendFormat:@\"%@\\n\", d];\n\n#ifdef ENTERPRISE\n    NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.enterprise.share\"];\n#else\n    NSURL *sharedcontainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@\"group.com.irccloud.share\"];\n#endif\n    if(sharedcontainer) {\n        fflush(stderr);\n        NSURL *logfile = [[[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] objectAtIndex:0] URLByAppendingPathComponent:@\"log.txt\"];\n        \n        [report appendString:@\"==========\\nConsole log:\\n\"];\n        [report appendFormat:@\"%@\\n\", [NSString stringWithContentsOfURL:logfile encoding:NSUTF8StringEncoding error:nil]];\n    }\n    \n    if(report.length) {\n        MFMailComposeViewController *mfmc = [MFMailComposeViewController canSendMail] ? [[MFMailComposeViewController alloc] init] : nil;\n        if(mfmc) {\n            mfmc.mailComposeDelegate = (UIViewController<MFMailComposeViewControllerDelegate> *)delegate;\n            [mfmc setToRecipients:@[@\"team@irccloud.com\"]];\n            [mfmc setSubject:@\"IRCCloud for iOS\"];\n            [mfmc setMessageBody:report isHTML:NO];\n            if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                mfmc.modalPresentationStyle = UIModalPresentationPageSheet;\n            else\n                mfmc.modalPresentationStyle = UIModalPresentationCurrentContext;\n            [delegate presentViewController:mfmc animated:YES completion:nil];\n        } else {\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Email Unavailable\" message:@\"Email is not configured on this device.  Please copy the report to the clipboard and send it to team@irccloud.com.\" preferredStyle:UIAlertControllerStyleAlert];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Copy to Clipboard\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                UIPasteboard *pb = [UIPasteboard generalPasteboard];\n                [pb setValue:report forPasteboardType:(NSString *)kUTTypeUTF8PlainText];\n            }]];\n            [delegate presentViewController:alert animated:YES completion:nil];\n        }\n    }\n\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/NickCompletionView.h",
    "content": "//\n//  NickCompletionView.h\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n\n@protocol NickCompletionViewDelegate<NSObject>\n-(void)nickSelected:(NSString *)nick;\n@end\n\n@interface NickCompletionView : UIView<UIInputViewAudioFeedback,UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout> {\n    UICollectionView *_collectionView;\n    NSArray *_suggestions;\n    UIFont *_font;\n    NSInteger _selection;\n}\n@property (readonly) UIFont *font;\n@property (assign) id<NickCompletionViewDelegate> completionDelegate;\n@property NSInteger selection;\n-(void)setSuggestions:(NSArray *)suggestions;\n-(NSUInteger)count;\n-(NSString *)suggestion;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/NickCompletionView.m",
    "content": "//\n//  NickCompletionView.m\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import \"NickCompletionView.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"ColorFormatter.h\"\n\n@interface NickCompletionCell : UICollectionViewCell {\n    UILabel *_label;\n}\n@property (readonly)UILabel *label;\n@end\n\n@implementation NickCompletionCell\n-(instancetype)initWithFrame:(CGRect)frame {\n    self = [super initWithFrame:frame];\n    if (self) {\n        self->_label = [[UILabel alloc] init];\n        self->_label.textAlignment = NSTextAlignmentCenter;\n        self->_label.textColor = [UIColor bufferTextColor];\n        [self.contentView addSubview:self->_label];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n    self->_label.frame = self.bounds;\n}\n\n-(void)setSelected:(BOOL)selected {\n    self.contentView.backgroundColor = selected ? [UIColor selectedBufferBackgroundColor] : [UIColor clearColor];\n    self->_label.textColor = selected ? [UIColor selectedBufferTextColor] : [UIColor bufferTextColor];\n}\n@end\n\n@implementation NickCompletionView\n\n- (id)initWithFrame:(CGRect)frame {\n    self = [super initWithFrame:frame];\n    if (self) {\n        self->_selection = -1;\n        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];\n        layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;\n        layout.sectionInset = UIEdgeInsetsMake(0, 6, 0, 6);\n        layout.minimumInteritemSpacing = 0;\n        layout.minimumLineSpacing = 0;\n        self->_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];\n        self->_collectionView.dataSource = self;\n        self->_collectionView.delegate = self;\n        [self->_collectionView registerClass:NickCompletionCell.class forCellWithReuseIdentifier:@\"NickCompletionCell\"];\n        self->_collectionView.translatesAutoresizingMaskIntoConstraints = NO;\n        self->_collectionView.layer.masksToBounds = YES;\n        self->_collectionView.layer.cornerRadius = 4;\n        self->_collectionView.allowsSelection = YES;\n        self->_collectionView.allowsMultipleSelection = NO;\n        self->_collectionView.scrollEnabled = NO;\n        [self addSubview:self->_collectionView];\n        [self addConstraints:@[\n                               [NSLayoutConstraint constraintWithItem:self->_collectionView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0f constant:1.0f],\n                               [NSLayoutConstraint constraintWithItem:self->_collectionView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-1.0f],\n                               [NSLayoutConstraint constraintWithItem:self->_collectionView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0f constant:1.0f],\n                               [NSLayoutConstraint constraintWithItem:self->_collectionView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:-1.0f]\n                               ]];\n        [self setSuggestions:@[]];\n    }\n    return self;\n}\n\n-(CGSize)intrinsicContentSize {\n    return CGSizeMake(self.bounds.size.width, 36);\n}\n\n-(void)setSuggestions:(NSArray *)suggestions {\n    self->_suggestions = suggestions;\n    self->_selection = -1;\n    self->_font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];\n    \n    CGFloat width = 0;\n    for(NSString *s in _suggestions) {\n        width += [s sizeWithAttributes:@{NSFontAttributeName:self->_font}].width + 12;\n        if(width > self.bounds.size.width)\n            break;\n    }\n    \n    if(width < self.bounds.size.width)\n        self->_collectionView.contentInset = UIEdgeInsetsMake(0, ((self.bounds.size.width - width) / 2) - 4, 0, 0);\n    else\n        self->_collectionView.contentInset = UIEdgeInsetsZero;\n    self->_collectionView.scrollEnabled = width > self.bounds.size.width;\n\n    self.backgroundColor = [UIColor bufferBorderColor];\n    self->_collectionView.backgroundColor = [UIColor bufferBackgroundColor];\n    [self->_collectionView reloadData];\n}\n\n-(NSString *)suggestion {\n    if(self->_selection == -1 || _selection >= self->_suggestions.count)\n        return nil;\n    NSString *suggestion = [self->_suggestions objectAtIndex:self->_selection];\n    if([suggestion rangeOfString:@\"\\u00a0(\"].location != NSNotFound) {\n        NSUInteger nickIndex = [suggestion rangeOfString:@\"(\" options:NSBackwardsSearch].location;\n        suggestion = [suggestion substringWithRange:NSMakeRange(nickIndex + 1, suggestion.length - nickIndex - 2)];\n    }\n    \n    return suggestion;\n}\n\n-(NSUInteger)count {\n    return _suggestions.count;\n}\n\n-(NSInteger)selection {\n    return _selection;\n}\n\n-(void)setSelection:(NSInteger)selection {\n    self->_selection = selection;\n    [self->_collectionView selectItemAtIndexPath:[NSIndexPath indexPathForRow:selection inSection:0] animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];\n}\n\n-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {\n    return 1;\n}\n\n- (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {\n    return _suggestions.count;\n}\n\n- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {\n    NickCompletionCell *cell = [self->_collectionView dequeueReusableCellWithReuseIdentifier:@\"NickCompletionCell\" forIndexPath:indexPath];\n    cell.label.font = self->_font;\n    cell.label.text = [self->_suggestions objectAtIndex:indexPath.row];\n    return cell;\n}\n\n-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {\n    return CGSizeMake([[self->_suggestions objectAtIndex:indexPath.row] sizeWithAttributes:@{NSFontAttributeName:self->_font}].width + 12, _collectionView.frame.size.height - 1);\n}\n\n-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {\n    [[UIDevice currentDevice] playInputClick];\n    self->_selection = indexPath.row;\n    [self->_completionDelegate nickSelected:self.suggestion];\n}\n\n-(BOOL)enableInputClicksWhenVisible {\n    return YES;\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/NotificationsDataSource.h",
    "content": "//\n//  NotificationsDataSource.h\n//\n//  Copyright (C) 2015 IRCCloud, Ltd.\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#import <Foundation/Foundation.h>\n#import \"EventsDataSource.h\"\n\n@interface NotificationsDataSource : NSObject {\n    NSMutableDictionary *_notifications;\n}\n+(NotificationsDataSource *)sharedInstance;\n-(void)serialize;\n-(void)clear;\n-(void)notify:(NSString *)alert category:(NSString *)category cid:(int)cid bid:(int)bid eid:(NSTimeInterval)eid;\n-(void)removeNotificationsForBID:(int)bid olderThan:(NSTimeInterval)eid;\n-(void)updateBadgeCount;\n-(id)getNotification:(NSTimeInterval)eid bid:(int)bid;\n-(void)alert:(NSString *)alertBody title:(NSString *)title category:(NSString *)category userInfo:(NSDictionary *)userInfo;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/NotificationsDataSource.m",
    "content": "//\n//  NotificationsDataSource.m\n//\n//  Copyright (C) 2015 IRCCloud, Ltd.\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#import <UserNotifications/UserNotifications.h>\n#import \"NotificationsDataSource.h\"\n#import \"BuffersDataSource.h\"\n#import \"EventsDataSource.h\"\n#import \"NetworkConnection.h\"\n\n@implementation NotificationsDataSource\n+(NotificationsDataSource *)sharedInstance {\n    static NotificationsDataSource *sharedInstance;\n    \n    @synchronized(self) {\n        if(!sharedInstance)\n            sharedInstance = [[NotificationsDataSource alloc] init];\n        \n        return sharedInstance;\n    }\n    return nil;\n}\n\n-(id)init {\n    self = [super init];\n    if(self) {\n        if(!_notifications)\n            self->_notifications = [[NSMutableDictionary alloc] init];\n    }\n    return self;\n}\n\n-(void)serialize {\n    return;\n}\n\n-(void)clear {\n    @synchronized(self->_notifications) {\n        CLS_LOG(@\"Clearing badge count\");\n        [self->_notifications removeAllObjects];\n#ifndef EXTENSION\n        [UIApplication sharedApplication].applicationIconBadgeNumber = 1;\n        [UIApplication sharedApplication].applicationIconBadgeNumber = 0;\n        [[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications];\n#endif\n    }\n}\n\n-(void)notify:(NSString *)alert category:(NSString *)category cid:(int)cid bid:(int)bid eid:(NSTimeInterval)eid {\n#ifndef EXTENSION\n#if TARGET_IPHONE_SIMULATOR\n    UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];\n    content.title = @\"IRCCloud\";\n    content.body = alert;\n    Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:bid];\n    content.userInfo = @{@\"d\": @[@(cid), @(bid), @(eid)], @\"aps\":@{@\"alert\":@{@\"loc-args\":@[b.name, b.name, b.name, b.name]}}};\n    content.categoryIdentifier = category;\n    content.threadIdentifier = [NSString stringWithFormat:@\"%i-%i\", cid, bid];\n    \n    UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:[@(eid) stringValue] content:content trigger:nil];\n    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];\n#endif\n#endif\n}\n\n-(void)alert:(NSString *)alertBody title:(NSString *)title category:(NSString *)category userInfo:(NSDictionary *)userInfo {\n    UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];\n    content.title = title?title:@\"IRCCloud\";\n    content.body = alertBody;\n    content.userInfo = userInfo;\n    content.categoryIdentifier = category;\n    content.sound = [UNNotificationSound soundNamed:@\"a.caf\"];\n    \n    UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:[@([NSDate date].timeIntervalSince1970) stringValue] content:content trigger:nil];\n    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];\n}\n\n\n-(void)removeNotificationsForBID:(int)bid olderThan:(NSTimeInterval)eid {\n#ifndef EXTENSION\n    @synchronized(self->_notifications) {\n        if(![[self->_notifications objectForKey:@(bid)] count])\n            [self->_notifications removeObjectForKey:@(bid)];\n    }\n#endif\n}\n\n-(id)getNotification:(NSTimeInterval)eid bid:(int)bid {\n#ifndef EXTENSION\n    @synchronized(self->_notifications) {\n        NSArray *ns = [NSArray arrayWithArray:[self->_notifications objectForKey:@(bid)]];\n        for(UNNotification *n in ns) {\n            NSArray *d = [n.request.content.userInfo objectForKey:@\"d\"];\n            if([[d objectAtIndex:1] intValue] == bid && [[d objectAtIndex:2] doubleValue] == eid) {\n                return n;\n            }\n        }\n    }\n#endif\n    return nil;\n}\n\n-(void)updateBadgeCount {\n#ifndef EXTENSION\n    __block BOOL __interrupt = NO;\n    UIBackgroundTaskIdentifier background_task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^ {\n        CLS_LOG(@\"NotificationsDataSource updateBadgeCount task expired\");\n        __interrupt = YES;\n    }];\n    [[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray *notifications) {\n        NSUInteger count = 0;\n        NSArray *buffers = [[BuffersDataSource sharedInstance] getBuffers];\n        NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n        NSMutableArray *identifiers = [[NSMutableArray alloc] init];\n        NSMutableSet *dirtyBuffers = [[NSMutableSet alloc] init];\n        \n        if(__interrupt)\n            return;\n        \n        for(Buffer *b in buffers) {\n            if(b.extraHighlights)\n                [dirtyBuffers addObject:b];\n            b.extraHighlights = 0;\n        }\n        \n        for(UNNotification *n in notifications) {\n            NSArray *d = [n.request.content.userInfo objectForKey:@\"d\"];\n            Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:[[d objectAtIndex:1] intValue]];\n            NSTimeInterval eid = [[d objectAtIndex:2] doubleValue];\n            if((!b && [NetworkConnection sharedInstance].state == kIRCCloudStateConnected && [NetworkConnection sharedInstance].ready) || eid <= b.last_seen_eid) {\n                if(!b)\n                    CLS_LOG(@\"Removing eid%f because bid%i doesn't exist\", eid, [[d objectAtIndex:1] intValue]);\n                else\n                    CLS_LOG(@\"Removing eid%f because bid%i.last_seen_eid = %f\", eid, [[d objectAtIndex:1] intValue], b.last_seen_eid);\n                [identifiers addObject:n.request.identifier];\n            } else if(b && ![[EventsDataSource sharedInstance] event:eid buffer:b.bid]) {\n                b.extraHighlights++;\n                [dirtyBuffers addObject:b];\n                CLS_LOG(@\"bid%i has notification eid%.0f that's not in the loaded backlog, extraHighlights: %i\", b.bid, eid, b.extraHighlights);\n            }\n\n            if(__interrupt)\n                break;\n        }\n        \n        if(identifiers.count > 0)\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:identifiers];\n            }];\n        \n        for(Buffer *b in buffers) {\n            int highlights = [[EventsDataSource sharedInstance] highlightCountForBuffer:b.bid lastSeenEid:b.last_seen_eid type:b.type];\n            if([b.type isEqualToString:@\"conversation\"] && [[[prefs objectForKey:@\"buffer-disableTrackUnread\"] objectForKey:[NSString stringWithFormat:@\"%i\",b.bid]] intValue] == 1)\n                highlights = 0;\n            count += highlights;\n            if(__interrupt)\n                break;\n        }\n\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            if([UIApplication sharedApplication].applicationIconBadgeNumber != count)\n                CLS_LOG(@\"Setting iOS icon badge to %lu\", (unsigned long)count);\n            [UIApplication sharedApplication].applicationIconBadgeNumber = count;\n            [[NSNotificationCenter defaultCenter] postNotificationName:kIRCCloudEventNotification object:dirtyBuffers userInfo:@{kIRCCloudEventKey:[NSNumber numberWithInt:kIRCEventRefresh]}];\n            [[UIApplication sharedApplication] endBackgroundTask: background_task];\n        }];\n    }];\n#endif\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/PastebinEditorViewController.h",
    "content": "//\n//  PastebinEditorViewController.h\n//\n//  Copyright (C) 2015 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"BuffersDataSource.h\"\n\n@interface PastebinEditorViewController : UITableViewController<UITextFieldDelegate,UITextViewDelegate> {\n    UITextField *_filename;\n    UITextView *_message;\n    UITextView *_text;\n    int _sayreqid;\n    Buffer *_buffer;\n    NSString *_pasteID;\n    UISegmentedControl *_type;\n    UILabel *_messageFooter;\n}\n+(NSString *)pastebinType:(NSString *)extension;\n-(id)initWithBuffer:(Buffer *)buffer;\n-(id)initWithPasteID:(NSString *)pasteID;\n@property NSString *extension;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/PastebinEditorViewController.m",
    "content": "//\n//  PastebinEditorViewController.m\n//\n//  Copyright (C) 2015 IRCCloud, Ltd.\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#import \"PastebinEditorViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"CSURITemplate.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"AppDelegate.h\"\n\n@interface PastebinTypeViewController : UITableViewController {\n    NSArray *_pastebinTypes;\n    NSString *_selected;\n}\n@property PastebinEditorViewController *delegate;\n@end\n\n@implementation PastebinTypeViewController\n\n-(id)init {\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        self.navigationItem.title = @\"Mode\";\n        self->_pastebinTypes = @[\n            @{@\"name\": @\"ABAP\", @\"extension\": @\"abap\"},\n            @{@\"name\": @\"ABC\", @\"extension\": @\"abc\"},\n            @{@\"name\": @\"ActionScript\", @\"extension\": @\"as\"},\n            @{@\"name\": @\"ADA\", @\"extension\": @\"ada\"},\n            @{@\"name\": @\"Apache Conf\", @\"extension\": @\"htaccess\"},\n            @{@\"name\": @\"AsciiDoc\", @\"extension\": @\"asciidoc\"},\n            @{@\"name\": @\"Assembly x86\", @\"extension\": @\"asm\"},\n            @{@\"name\": @\"AutoHotKey\", @\"extension\": @\"ahk\"},\n            @{@\"name\": @\"BatchFile\", @\"extension\": @\"bat\"},\n            @{@\"name\": @\"Bro\", @\"extension\": @\"bro\"},\n            @{@\"name\": @\"C and C++\", @\"extension\": @\"cpp\"},\n            @{@\"name\": @\"C9Search\", @\"extension\": @\"c9search_results\"},\n            @{@\"name\": @\"Cirru\", @\"extension\": @\"cirru\"},\n            @{@\"name\": @\"Clojure\", @\"extension\": @\"clj\"},\n            @{@\"name\": @\"Cobol\", @\"extension\": @\"CBL\"},\n            @{@\"name\": @\"CoffeeScript\", @\"extension\": @\"coffee\"},\n            @{@\"name\": @\"ColdFusion\", @\"extension\": @\"cfm\"},\n            @{@\"name\": @\"C#\", @\"extension\": @\"cs\"},\n            @{@\"name\": @\"Csound Document\", @\"extension\": @\"csd\"},\n            @{@\"name\": @\"Csound\", @\"extension\": @\"orc\"},\n            @{@\"name\": @\"Csound Score\", @\"extension\": @\"sco\"},\n            @{@\"name\": @\"CSS\", @\"extension\": @\"css\"},\n            @{@\"name\": @\"Curly\", @\"extension\": @\"curly\"},\n            @{@\"name\": @\"D\", @\"extension\": @\"d\"},\n            @{@\"name\": @\"Dart\", @\"extension\": @\"dart\"},\n            @{@\"name\": @\"Diff\", @\"extension\": @\"diff\"},\n            @{@\"name\": @\"Dockerfile\", @\"extension\": @\"Dockerfile\"},\n            @{@\"name\": @\"Dot\", @\"extension\": @\"dot\"},\n            @{@\"name\": @\"Drools\", @\"extension\": @\"drl\"},\n            @{@\"name\": @\"Dummy\", @\"extension\": @\"dummy\"},\n            @{@\"name\": @\"DummySyntax\", @\"extension\": @\"dummy\"},\n            @{@\"name\": @\"Eiffel\", @\"extension\": @\"e\"},\n            @{@\"name\": @\"EJS\", @\"extension\": @\"ejs\"},\n            @{@\"name\": @\"Elixir\", @\"extension\": @\"ex\"},\n            @{@\"name\": @\"Elm\", @\"extension\": @\"elm\"},\n            @{@\"name\": @\"Erlang\", @\"extension\": @\"erl\"},\n            @{@\"name\": @\"Forth\", @\"extension\": @\"frt\"},\n            @{@\"name\": @\"Fortran\", @\"extension\": @\"f\"},\n            @{@\"name\": @\"FreeMarker\", @\"extension\": @\"ftl\"},\n            @{@\"name\": @\"Gcode\", @\"extension\": @\"gcode\"},\n            @{@\"name\": @\"Gherkin\", @\"extension\": @\"feature\"},\n            @{@\"name\": @\"Gitignore\", @\"extension\": @\"gitignore\"},\n            @{@\"name\": @\"Glsl\", @\"extension\": @\"glsl\"},\n            @{@\"name\": @\"Gobstones\", @\"extension\": @\"gbs\"},\n            @{@\"name\": @\"Go\", @\"extension\": @\"go\"},\n            @{@\"name\": @\"GraphQLSchema\", @\"extension\": @\"gql\"},\n            @{@\"name\": @\"Groovy\", @\"extension\": @\"groovy\"},\n            @{@\"name\": @\"HAML\", @\"extension\": @\"haml\"},\n            @{@\"name\": @\"Handlebars\", @\"extension\": @\"hbs\"},\n            @{@\"name\": @\"Haskell\", @\"extension\": @\"hs\"},\n            @{@\"name\": @\"Haskell Cabal\", @\"extension\": @\"cabal\"},\n            @{@\"name\": @\"haXe\", @\"extension\": @\"hx\"},\n            @{@\"name\": @\"Hjson\", @\"extension\": @\"hjson\"},\n            @{@\"name\": @\"HTML\", @\"extension\": @\"html\"},\n            @{@\"name\": @\"HTML (Elixir)\", @\"extension\": @\"eex\"},\n            @{@\"name\": @\"HTML (Ruby)\", @\"extension\": @\"erb\"},\n            @{@\"name\": @\"INI\", @\"extension\": @\"ini\"},\n            @{@\"name\": @\"Io\", @\"extension\": @\"io\"},\n            @{@\"name\": @\"Jack\", @\"extension\": @\"jack\"},\n            @{@\"name\": @\"Jade\", @\"extension\": @\"jade\"},\n            @{@\"name\": @\"Java\", @\"extension\": @\"java\"},\n            @{@\"name\": @\"JavaScript\", @\"extension\": @\"js\"},\n            @{@\"name\": @\"JSON\", @\"extension\": @\"json\"},\n            @{@\"name\": @\"JSONiq\", @\"extension\": @\"jq\"},\n            @{@\"name\": @\"JSP\", @\"extension\": @\"jsp\"},\n            @{@\"name\": @\"JSSM\", @\"extension\": @\"jssm\"},\n            @{@\"name\": @\"JSX\", @\"extension\": @\"jsx\"},\n            @{@\"name\": @\"Julia\", @\"extension\": @\"jl\"},\n            @{@\"name\": @\"Kotlin\", @\"extension\": @\"kt\"},\n            @{@\"name\": @\"LaTeX\", @\"extension\": @\"tex\"},\n            @{@\"name\": @\"LESS\", @\"extension\": @\"less\"},\n            @{@\"name\": @\"Liquid\", @\"extension\": @\"liquid\"},\n            @{@\"name\": @\"Lisp\", @\"extension\": @\"lisp\"},\n            @{@\"name\": @\"LiveScript\", @\"extension\": @\"ls\"},\n            @{@\"name\": @\"LogiQL\", @\"extension\": @\"logic\"},\n            @{@\"name\": @\"LSL\", @\"extension\": @\"lsl\"},\n            @{@\"name\": @\"Lua\", @\"extension\": @\"lua\"},\n            @{@\"name\": @\"LuaPage\", @\"extension\": @\"lp\"},\n            @{@\"name\": @\"Lucene\", @\"extension\": @\"lucene\"},\n            @{@\"name\": @\"Makefile\", @\"extension\": @\"Makefile\"},\n            @{@\"name\": @\"Markdown\", @\"extension\": @\"md\"},\n            @{@\"name\": @\"Mask\", @\"extension\": @\"mask\"},\n            @{@\"name\": @\"MATLAB\", @\"extension\": @\"matlab\"},\n            @{@\"name\": @\"Maze\", @\"extension\": @\"mz\"},\n            @{@\"name\": @\"MEL\", @\"extension\": @\"mel\"},\n            @{@\"name\": @\"MUSHCode\", @\"extension\": @\"mc\"},\n            @{@\"name\": @\"MySQL\", @\"extension\": @\"mysql\"},\n            @{@\"name\": @\"Nix\", @\"extension\": @\"nix\"},\n            @{@\"name\": @\"NSIS\", @\"extension\": @\"nsi\"},\n            @{@\"name\": @\"Objective-C\", @\"extension\": @\"m\"},\n            @{@\"name\": @\"OCaml\", @\"extension\": @\"ml\"},\n            @{@\"name\": @\"Pascal\", @\"extension\": @\"pas\"},\n            @{@\"name\": @\"Perl\", @\"extension\": @\"pl\"},\n            @{@\"name\": @\"pgSQL\", @\"extension\": @\"pgsql\"},\n            @{@\"name\": @\"PHP\", @\"extension\": @\"php\"},\n            @{@\"name\": @\"Pig\", @\"extension\": @\"pig\"},\n            @{@\"name\": @\"Plain Text\", @\"extension\": @\"txt\"},\n            @{@\"name\": @\"Powershell\", @\"extension\": @\"ps1\"},\n            @{@\"name\": @\"Praat\", @\"extension\": @\"praat\"},\n            @{@\"name\": @\"Prolog\", @\"extension\": @\"plg\"},\n            @{@\"name\": @\"Properties\", @\"extension\": @\"properties\"},\n            @{@\"name\": @\"Protobuf\", @\"extension\": @\"proto\"},\n            @{@\"name\": @\"Python\", @\"extension\": @\"py\"},\n            @{@\"name\": @\"R\", @\"extension\": @\"r\"},\n            @{@\"name\": @\"Razor\", @\"extension\": @\"cshtml\"},\n            @{@\"name\": @\"RDoc\", @\"extension\": @\"Rd\"},\n            @{@\"name\": @\"Red\", @\"extension\": @\"red\"},\n            @{@\"name\": @\"RHTML\", @\"extension\": @\"Rhtml\"},\n            @{@\"name\": @\"RST\", @\"extension\": @\"rst\"},\n            @{@\"name\": @\"Ruby\", @\"extension\": @\"rb\"},\n            @{@\"name\": @\"Rust\", @\"extension\": @\"rs\"},\n            @{@\"name\": @\"SASS\", @\"extension\": @\"sass\"},\n            @{@\"name\": @\"SCAD\", @\"extension\": @\"scad\"},\n            @{@\"name\": @\"Scala\", @\"extension\": @\"scala\"},\n            @{@\"name\": @\"Scheme\", @\"extension\": @\"scm\"},\n            @{@\"name\": @\"SCSS\", @\"extension\": @\"scss\"},\n            @{@\"name\": @\"SH\", @\"extension\": @\"sh\"},\n            @{@\"name\": @\"SJS\", @\"extension\": @\"sjs\"},\n            @{@\"name\": @\"Smarty\", @\"extension\": @\"smarty\"},\n            @{@\"name\": @\"snippets\", @\"extension\": @\"snippets\"},\n            @{@\"name\": @\"Soy Template\", @\"extension\": @\"soy\"},\n            @{@\"name\": @\"Space\", @\"extension\": @\"space\"},\n            @{@\"name\": @\"SQL\", @\"extension\": @\"sql\"},\n            @{@\"name\": @\"SQLServer\", @\"extension\": @\"sqlserver\"},\n            @{@\"name\": @\"Stylus\", @\"extension\": @\"styl\"},\n            @{@\"name\": @\"SVG\", @\"extension\": @\"svg\"},\n            @{@\"name\": @\"Swift\", @\"extension\": @\"swift\"},\n            @{@\"name\": @\"Tcl\", @\"extension\": @\"tcl\"},\n            @{@\"name\": @\"Tex\", @\"extension\": @\"tex\"},\n            @{@\"name\": @\"Textile\", @\"extension\": @\"textile\"},\n            @{@\"name\": @\"Toml\", @\"extension\": @\"toml\"},\n            @{@\"name\": @\"TSX\", @\"extension\": @\"tsx\"},\n            @{@\"name\": @\"Twig\", @\"extension\": @\"twig\"},\n            @{@\"name\": @\"Typescript\", @\"extension\": @\"ts\"},\n            @{@\"name\": @\"Vala\", @\"extension\": @\"vala\"},\n            @{@\"name\": @\"VBScript\", @\"extension\": @\"vbs\"},\n            @{@\"name\": @\"Velocity\", @\"extension\": @\"vm\"},\n            @{@\"name\": @\"Verilog\", @\"extension\": @\"v\"},\n            @{@\"name\": @\"VHDL\", @\"extension\": @\"vhd\"},\n            @{@\"name\": @\"Wollok\", @\"extension\": @\"wlk\"},\n            @{@\"name\": @\"XML\", @\"extension\": @\"xml\"},\n            @{@\"name\": @\"XQuery\", @\"extension\": @\"xq\"},\n            @{@\"name\": @\"YAML\", @\"extension\": @\"yaml\"},\n            @{@\"name\": @\"Django\", @\"extension\": @\"html\"},\n        ];\n    }\n    return self;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return _pastebinTypes.count;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"pastebintypecell\"];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"pastebintypecell\"];\n    \n    cell.textLabel.text = [[self->_pastebinTypes objectAtIndex:indexPath.row] objectForKey:@\"name\"];\n    cell.accessoryType = [_selected isEqualToString:cell.textLabel.text]?UITableViewCellAccessoryCheckmark:UITableViewCellAccessoryNone;\n    \n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    _delegate.extension = [[self->_pastebinTypes objectAtIndex:indexPath.row] objectForKey:@\"extension\"];\n    _selected = [[self->_pastebinTypes objectAtIndex:indexPath.row] objectForKey:@\"name\"];\n    [self.tableView reloadData];\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        [self.navigationController popViewControllerAnimated:YES];\n    }];\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    _selected = [PastebinEditorViewController pastebinType:_delegate.extension];\n}\n\n@end\n\n\n@interface PastebinEditorCell : UITableViewCell\n\n@end\n\n@implementation PastebinEditorCell\n- (void) layoutSubviews {\n    [super layoutSubviews];\n    self.textLabel.frame = CGRectMake(self.textLabel.frame.origin.x, self.textLabel.frame.origin.y, self.frame.size.width - self.textLabel.frame.origin.x, self.textLabel.frame.size.height);\n}\n@end\n\nNSDictionary *__pastebinTypeMap = nil;\n\n@implementation PastebinEditorViewController\n\n+(NSString *)pastebinType:(NSString *)extension {\n    if(extension.length) {\n        if (!__pastebinTypeMap) {\n            __pastebinTypeMap = @{\n                @\"ABAP\": [NSRegularExpression regularExpressionWithPattern:@\"abap\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"ABC\": [NSRegularExpression regularExpressionWithPattern:@\"abc\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"ActionScript\": [NSRegularExpression regularExpressionWithPattern:@\"as\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"ADA\": [NSRegularExpression regularExpressionWithPattern:@\"ada|adb\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Apache Conf\": [NSRegularExpression regularExpressionWithPattern:@\"^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"AsciiDoc\": [NSRegularExpression regularExpressionWithPattern:@\"asciidoc|adoc\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Assembly x86\": [NSRegularExpression regularExpressionWithPattern:@\"asm|a\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"AutoHotKey\": [NSRegularExpression regularExpressionWithPattern:@\"ahk\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"BatchFile\": [NSRegularExpression regularExpressionWithPattern:@\"bat|cmd\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Bro\": [NSRegularExpression regularExpressionWithPattern:@\"bro\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"C and C++\": [NSRegularExpression regularExpressionWithPattern:@\"cpp|c|cc|cxx|h|hh|hpp|ino\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"C9Search\": [NSRegularExpression regularExpressionWithPattern:@\"c9search_results\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Cirru\": [NSRegularExpression regularExpressionWithPattern:@\"cirru|cr\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Clojure\": [NSRegularExpression regularExpressionWithPattern:@\"clj|cljs\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Cobol\": [NSRegularExpression regularExpressionWithPattern:@\"CBL|COB\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"CoffeeScript\": [NSRegularExpression regularExpressionWithPattern:@\"coffee|cf|cson|^Cakefile\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"ColdFusion\": [NSRegularExpression regularExpressionWithPattern:@\"cfm\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"C#\": [NSRegularExpression regularExpressionWithPattern:@\"cs\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Csound Document\": [NSRegularExpression regularExpressionWithPattern:@\"csd\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Csound\": [NSRegularExpression regularExpressionWithPattern:@\"orc\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Csound Score\": [NSRegularExpression regularExpressionWithPattern:@\"sco\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"CSS\": [NSRegularExpression regularExpressionWithPattern:@\"css\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Curly\": [NSRegularExpression regularExpressionWithPattern:@\"curly\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"D\": [NSRegularExpression regularExpressionWithPattern:@\"d|di\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Dart\": [NSRegularExpression regularExpressionWithPattern:@\"dart\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Diff\": [NSRegularExpression regularExpressionWithPattern:@\"diff|patch\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Dockerfile\": [NSRegularExpression regularExpressionWithPattern:@\"^Dockerfile\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Dot\": [NSRegularExpression regularExpressionWithPattern:@\"dot\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Drools\": [NSRegularExpression regularExpressionWithPattern:@\"drl\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Dummy\": [NSRegularExpression regularExpressionWithPattern:@\"dummy\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"DummySyntax\": [NSRegularExpression regularExpressionWithPattern:@\"dummy\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Eiffel\": [NSRegularExpression regularExpressionWithPattern:@\"e|ge\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"EJS\": [NSRegularExpression regularExpressionWithPattern:@\"ejs\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Elixir\": [NSRegularExpression regularExpressionWithPattern:@\"ex|exs\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Elm\": [NSRegularExpression regularExpressionWithPattern:@\"elm\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Erlang\": [NSRegularExpression regularExpressionWithPattern:@\"erl|hrl\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Forth\": [NSRegularExpression regularExpressionWithPattern:@\"frt|fs|ldr|fth|4th\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Fortran\": [NSRegularExpression regularExpressionWithPattern:@\"f|f90\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"FreeMarker\": [NSRegularExpression regularExpressionWithPattern:@\"ftl\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Gcode\": [NSRegularExpression regularExpressionWithPattern:@\"gcode\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Gherkin\": [NSRegularExpression regularExpressionWithPattern:@\"feature\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Gitignore\": [NSRegularExpression regularExpressionWithPattern:@\"^.gitignore\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Glsl\": [NSRegularExpression regularExpressionWithPattern:@\"glsl|frag|vert\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Gobstones\": [NSRegularExpression regularExpressionWithPattern:@\"gbs\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Go\": [NSRegularExpression regularExpressionWithPattern:@\"go\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"GraphQLSchema\": [NSRegularExpression regularExpressionWithPattern:@\"gql\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Groovy\": [NSRegularExpression regularExpressionWithPattern:@\"groovy\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"HAML\": [NSRegularExpression regularExpressionWithPattern:@\"haml\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Handlebars\": [NSRegularExpression regularExpressionWithPattern:@\"hbs|handlebars|tpl|mustache\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Haskell\": [NSRegularExpression regularExpressionWithPattern:@\"hs\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Haskell Cabal\": [NSRegularExpression regularExpressionWithPattern:@\"cabal\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"haXe\": [NSRegularExpression regularExpressionWithPattern:@\"hx\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Hjson\": [NSRegularExpression regularExpressionWithPattern:@\"hjson\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"HTML\": [NSRegularExpression regularExpressionWithPattern:@\"html|htm|xhtml|vue|we|wpy\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"HTML (Elixir)\": [NSRegularExpression regularExpressionWithPattern:@\"eex|html.eex\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"HTML (Ruby)\": [NSRegularExpression regularExpressionWithPattern:@\"erb|rhtml|html.erb\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"INI\": [NSRegularExpression regularExpressionWithPattern:@\"ini|conf|cfg|prefs\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Io\": [NSRegularExpression regularExpressionWithPattern:@\"io\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Jack\": [NSRegularExpression regularExpressionWithPattern:@\"jack\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Jade\": [NSRegularExpression regularExpressionWithPattern:@\"jade|pug\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Java\": [NSRegularExpression regularExpressionWithPattern:@\"java\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"JavaScript\": [NSRegularExpression regularExpressionWithPattern:@\"js|jsm|jsx\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"JSON\": [NSRegularExpression regularExpressionWithPattern:@\"json\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"JSONiq\": [NSRegularExpression regularExpressionWithPattern:@\"jq\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"JSP\": [NSRegularExpression regularExpressionWithPattern:@\"jsp\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"JSSM\": [NSRegularExpression regularExpressionWithPattern:@\"jssm|jssm_state\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"JSX\": [NSRegularExpression regularExpressionWithPattern:@\"jsx\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Julia\": [NSRegularExpression regularExpressionWithPattern:@\"jl\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Kotlin\": [NSRegularExpression regularExpressionWithPattern:@\"kt|kts\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"LaTeX\": [NSRegularExpression regularExpressionWithPattern:@\"tex|latex|ltx|bib\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"LESS\": [NSRegularExpression regularExpressionWithPattern:@\"less\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Liquid\": [NSRegularExpression regularExpressionWithPattern:@\"liquid\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Lisp\": [NSRegularExpression regularExpressionWithPattern:@\"lisp\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"LiveScript\": [NSRegularExpression regularExpressionWithPattern:@\"ls\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"LogiQL\": [NSRegularExpression regularExpressionWithPattern:@\"logic|lql\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"LSL\": [NSRegularExpression regularExpressionWithPattern:@\"lsl\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Lua\": [NSRegularExpression regularExpressionWithPattern:@\"lua\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"LuaPage\": [NSRegularExpression regularExpressionWithPattern:@\"lp\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Lucene\": [NSRegularExpression regularExpressionWithPattern:@\"lucene\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Makefile\": [NSRegularExpression regularExpressionWithPattern:@\"^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Markdown\": [NSRegularExpression regularExpressionWithPattern:@\"md|markdown\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Mask\": [NSRegularExpression regularExpressionWithPattern:@\"mask\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"MATLAB\": [NSRegularExpression regularExpressionWithPattern:@\"matlab\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Maze\": [NSRegularExpression regularExpressionWithPattern:@\"mz\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"MEL\": [NSRegularExpression regularExpressionWithPattern:@\"mel\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"MUSHCode\": [NSRegularExpression regularExpressionWithPattern:@\"mc|mush\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"MySQL\": [NSRegularExpression regularExpressionWithPattern:@\"mysql\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Nix\": [NSRegularExpression regularExpressionWithPattern:@\"nix\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"NSIS\": [NSRegularExpression regularExpressionWithPattern:@\"nsi|nsh\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Objective-C\": [NSRegularExpression regularExpressionWithPattern:@\"m|mm\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"OCaml\": [NSRegularExpression regularExpressionWithPattern:@\"ml|mli\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Pascal\": [NSRegularExpression regularExpressionWithPattern:@\"pas|p\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Perl\": [NSRegularExpression regularExpressionWithPattern:@\"pl|pm\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"pgSQL\": [NSRegularExpression regularExpressionWithPattern:@\"pgsql\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"PHP\": [NSRegularExpression regularExpressionWithPattern:@\"php|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp|module\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Pig\": [NSRegularExpression regularExpressionWithPattern:@\"pig\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Powershell\": [NSRegularExpression regularExpressionWithPattern:@\"ps1\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Praat\": [NSRegularExpression regularExpressionWithPattern:@\"praat|praatscript|psc|proc\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Prolog\": [NSRegularExpression regularExpressionWithPattern:@\"plg|prolog\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Properties\": [NSRegularExpression regularExpressionWithPattern:@\"properties\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Protobuf\": [NSRegularExpression regularExpressionWithPattern:@\"proto\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Python\": [NSRegularExpression regularExpressionWithPattern:@\"py\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"R\": [NSRegularExpression regularExpressionWithPattern:@\"r\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Razor\": [NSRegularExpression regularExpressionWithPattern:@\"cshtml|asp\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"RDoc\": [NSRegularExpression regularExpressionWithPattern:@\"Rd\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Red\": [NSRegularExpression regularExpressionWithPattern:@\"red|reds\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"RHTML\": [NSRegularExpression regularExpressionWithPattern:@\"Rhtml\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"RST\": [NSRegularExpression regularExpressionWithPattern:@\"rst\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Ruby\": [NSRegularExpression regularExpressionWithPattern:@\"rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Rust\": [NSRegularExpression regularExpressionWithPattern:@\"rs\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"SASS\": [NSRegularExpression regularExpressionWithPattern:@\"sass\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"SCAD\": [NSRegularExpression regularExpressionWithPattern:@\"scad\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Scala\": [NSRegularExpression regularExpressionWithPattern:@\"scala\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Scheme\": [NSRegularExpression regularExpressionWithPattern:@\"scm|sm|rkt|oak|scheme\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"SCSS\": [NSRegularExpression regularExpressionWithPattern:@\"scss\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"SH\": [NSRegularExpression regularExpressionWithPattern:@\"sh|bash|^.bashrc\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"SJS\": [NSRegularExpression regularExpressionWithPattern:@\"sjs\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Smarty\": [NSRegularExpression regularExpressionWithPattern:@\"smarty|tpl\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"snippets\": [NSRegularExpression regularExpressionWithPattern:@\"snippets\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Soy Template\": [NSRegularExpression regularExpressionWithPattern:@\"soy\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Space\": [NSRegularExpression regularExpressionWithPattern:@\"space\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"SQL\": [NSRegularExpression regularExpressionWithPattern:@\"sql\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"SQLServer\": [NSRegularExpression regularExpressionWithPattern:@\"sqlserver\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Stylus\": [NSRegularExpression regularExpressionWithPattern:@\"styl|stylus\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"SVG\": [NSRegularExpression regularExpressionWithPattern:@\"svg\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Swift\": [NSRegularExpression regularExpressionWithPattern:@\"swift\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Tcl\": [NSRegularExpression regularExpressionWithPattern:@\"tcl\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Tex\": [NSRegularExpression regularExpressionWithPattern:@\"tex\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Plain Text\": [NSRegularExpression regularExpressionWithPattern:@\"txt\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Textile\": [NSRegularExpression regularExpressionWithPattern:@\"textile\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Toml\": [NSRegularExpression regularExpressionWithPattern:@\"toml\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"TSX\": [NSRegularExpression regularExpressionWithPattern:@\"tsx\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Twig\": [NSRegularExpression regularExpressionWithPattern:@\"twig|swig\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Typescript\": [NSRegularExpression regularExpressionWithPattern:@\"ts|typescript|str\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Vala\": [NSRegularExpression regularExpressionWithPattern:@\"vala\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"VBScript\": [NSRegularExpression regularExpressionWithPattern:@\"vbs|vb\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Velocity\": [NSRegularExpression regularExpressionWithPattern:@\"vm\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Verilog\": [NSRegularExpression regularExpressionWithPattern:@\"v|vh|sv|svh\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"VHDL\": [NSRegularExpression regularExpressionWithPattern:@\"vhd|vhdl\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Wollok\": [NSRegularExpression regularExpressionWithPattern:@\"wlk|wpgm|wtest\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"XML\": [NSRegularExpression regularExpressionWithPattern:@\"xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"XQuery\": [NSRegularExpression regularExpressionWithPattern:@\"xq\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"YAML\": [NSRegularExpression regularExpressionWithPattern:@\"yaml|yml\" options:NSRegularExpressionCaseInsensitive error:nil],\n                @\"Django\": [NSRegularExpression regularExpressionWithPattern:@\"html\" options:NSRegularExpressionCaseInsensitive error:nil],\n            };\n        }\n        \n        NSRange range = NSMakeRange(0, extension.length);\n        for(NSString *type in __pastebinTypeMap.allKeys) {\n            NSRegularExpression *regex = [__pastebinTypeMap objectForKey:type];\n            NSArray *matches = [regex matchesInString:extension options:NSMatchingAnchored range:range];\n            for(NSTextCheckingResult *result in matches) {\n                if(result.range.location == 0 && result.range.length == range.length) {\n                    return type;\n                }\n            }\n        }\n    }\n    return @\"Plain Text\";\n}\n\n-(id)initWithBuffer:(Buffer *)buffer {\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        self.navigationItem.title = @\"Text Snippet\";\n        if(buffer)\n            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@\"Send\" style:UIBarButtonItemStyleDone target:self action:@selector(sendButtonPressed:)];\n        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];\n        self->_buffer = buffer;\n        self->_sayreqid = -1;\n        \n        self->_type = [[UISegmentedControl alloc] initWithItems:@[@\"Snippet\", @\"Messages\"]];\n        self->_type.selectedSegmentIndex = 0;\n        [self->_type addTarget:self action:@selector(_typeToggled) forControlEvents:UIControlEventValueChanged];\n        self.navigationItem.titleView = self->_type;\n    }\n    return self;\n}\n\n-(void)_typeToggled {\n    [self.tableView reloadData];\n    [self textViewDidChange:self->_text];\n}\n\n-(id)initWithPasteID:(NSString *)pasteID {\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        self.navigationItem.title = @\"Text Snippet\";\n        self->_pasteID = pasteID;\n        self->_sayreqid = -1;\n        UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n        [spinny startAnimating];\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinny];\n    }\n    return self;\n}\n\n-(void)_fetchPaste {\n    NSString *url = [[NetworkConnection sharedInstance].pasteURITemplate relativeStringWithVariables:@{@\"id\":self->_pasteID, @\"type\":@\"json\"} error:nil];\n    url = [url stringByReplacingOccurrencesOfString:@\"https://www.irccloud.com/\" withString:[NSString stringWithFormat:@\"https://%@/\", IRCCLOUD_HOST]];\n\n    [[[NetworkConnection sharedInstance].urlSession dataTaskWithURL:[NSURL URLWithString:url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n        if (error) {\n            CLS_LOG(@\"Error fetching pastebin. Error %li : %@\", (long)error.code, error.userInfo);\n        } else {\n            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];\n            self->_text.text = [dict objectForKey:@\"body\"];\n            self->_filename.text = [dict objectForKey:@\"name\"];\n            self->_text.editable = self->_filename.enabled = YES;\n            self->_extension = [dict objectForKey:@\"extension\"];\n            [self.tableView reloadData];\n        }\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@\"Save\" style:UIBarButtonItemStyleDone target:self action:@selector(sendButtonPressed:)];\n    }] resume];\n}\n\n-(void)sendButtonPressed:(id)sender {\n    [self.tableView endEditing:YES];\n    UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n    [spinny startAnimating];\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinny];\n\n    if(self->_type.selectedSegmentIndex == 1) {\n        if(self->_message.text.length) {\n            self->_buffer.draft = [NSString stringWithFormat:@\"%@ %@\", _message.text, _text.text];\n        } else {\n            self->_buffer.draft = self->_text.text;\n        }\n        self->_sayreqid = [[NetworkConnection sharedInstance] say:self->_buffer.draft to:self->_buffer.name cid:self->_buffer.cid handler:^(IRCCloudJSONObject *result) {\n            if(![[result objectForKey:@\"success\"] boolValue]) {\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:[NSString stringWithFormat:@\"Failed to send message: %@\", [result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n                self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@\"Save\" style:UIBarButtonItemStyleDone target:self action:@selector(sendButtonPressed:)];\n            }\n        }];\n    } else {\n        if(!_extension.length)\n            self->_extension = @\"txt\";\n        \n        IRCCloudAPIResultHandler pasteHandler = ^(IRCCloudJSONObject *result) {\n            if([[result objectForKey:@\"success\"] boolValue]) {\n                if(self->_pasteID) {\n                    [self.tableView endEditing:YES];\n                    [self.navigationController popViewControllerAnimated:YES];\n                } else {\n                    if(self->_message.text.length) {\n                        self->_buffer.draft = [NSString stringWithFormat:@\"%@ %@\", self->_message.text, [result objectForKey:@\"url\"]];\n                    } else {\n                        self->_buffer.draft = [result objectForKey:@\"url\"];\n                    }\n                    self->_sayreqid = [[NetworkConnection sharedInstance] say:self->_buffer.draft to:self->_buffer.name cid:self->_buffer.cid handler:^(IRCCloudJSONObject *result) {\n                        if(![result objectForKey:@\"success\"]) {\n                            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:[NSString stringWithFormat:@\"Failed to send message: %@\", [result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                            [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                            [self presentViewController:alert animated:YES completion:nil];\n                        }\n                    }];\n                }\n            } else {\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to save snippet, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n                self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:self->_pasteID?@\"Save\":@\"Send\" style:UIBarButtonItemStyleDone target:self action:@selector(sendButtonPressed:)];\n            }\n        };\n        \n        if(self->_pasteID)\n            [[NetworkConnection sharedInstance] editPaste:self->_pasteID name:self->_filename.text contents:self->_text.text extension:self->_extension handler:pasteHandler];\n        else\n            [[NetworkConnection sharedInstance] paste:self->_filename.text contents:self->_text.text extension:self->_extension handler:pasteHandler];\n    }\n}\n\n-(void)cancelButtonPressed:(id)sender {\n    [self.tableView endEditing:YES];\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    [self.tableView reloadData];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    Event *e;\n    \n    switch(event) {\n        case kIRCEventBufferMsg:\n            e = notification.object;\n            if(self->_sayreqid > 0 && e.bid == self->_buffer.bid && (e.reqId == self->_sayreqid || (e.isSelf && [e.from isEqualToString:self->_buffer.name]))) {\n                self->_buffer.draft = @\"\";\n                [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                    [self.tableView endEditing:YES];\n                    [self dismissViewControllerAnimated:YES completion:nil];\n                    self->_buffer.draft = @\"\";\n                    [((AppDelegate *)[UIApplication sharedApplication].delegate).mainViewController clearText];\n                }];\n            }\n            break;\n        default:\n            break;\n    }\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    \n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n\n    self->_filename = [[UITextField alloc] initWithFrame:CGRectZero];\n    self->_filename.text = @\"\";\n    self->_filename.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_filename.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    self->_filename.autocorrectionType = UITextAutocorrectionTypeNo;\n    self->_filename.adjustsFontSizeToFitWidth = YES;\n    self->_filename.returnKeyType = UIReturnKeyDone;\n    self->_filename.enabled = !_pasteID;\n    self->_filename.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    [self->_filename addTarget:self action:@selector(filenameChanged) forControlEvents:UIControlEventEditingChanged];\n    \n    self->_message = [[UITextView alloc] initWithFrame:CGRectZero];\n    self->_message.text = @\"\";\n    self->_message.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_message.backgroundColor = [UIColor clearColor];\n    self->_message.returnKeyType = UIReturnKeyDone;\n    self->_message.delegate = self;\n    self->_message.font = self->_filename.font;\n    self->_message.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    self->_message.keyboardAppearance = [UITextField appearance].keyboardAppearance;\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"autoCaps\"]) {\n        self->_message.autocapitalizationType = UITextAutocapitalizationTypeSentences;\n    } else {\n        self->_message.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    }\n\n    self->_messageFooter = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 32)];\n    self->_messageFooter.backgroundColor = [UIColor clearColor];\n    self->_messageFooter.textColor = [UILabel appearanceWhenContainedInInstancesOfClasses:@[UITableViewHeaderFooterView.class]].textColor;\n    self->_messageFooter.textAlignment = NSTextAlignmentCenter;\n    self->_messageFooter.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    self->_messageFooter.numberOfLines = 0;\n    self->_messageFooter.adjustsFontSizeToFitWidth = YES;\n    \n    self->_text = [[UITextView alloc] initWithFrame:CGRectZero];\n    self->_text.backgroundColor = [UIColor clearColor];\n    self->_text.font = self->_filename.font;\n    self->_text.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_text.delegate = self;\n    self->_text.editable = !_pasteID;\n    self->_text.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    self->_text.text = self->_buffer.draft;\n    self->_text.keyboardAppearance = [UITextField appearance].keyboardAppearance;\n    if([[NSUserDefaults standardUserDefaults] boolForKey:@\"autoCaps\"]) {\n        self->_text.autocapitalizationType = UITextAutocapitalizationTypeSentences;\n    } else {\n        self->_text.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    }\n    [self textViewDidChange:self->_text];\n    \n    if(self->_pasteID)\n        [self _fetchPaste];\n}\n\n- (void)textViewDidBeginEditing:(UITextView *)textView {\n    if(textView == self->_message)\n        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];\n}\n\n- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {\n    if(textView != self->_text && [text isEqualToString:@\"\\n\"]) {\n        [self.tableView endEditing:YES];\n        return NO;\n    }\n    return YES;\n}\n\n-(void)textViewDidChange:(UITextView *)textView {\n    self.navigationItem.rightBarButtonItem.enabled = (self->_text.text.length > 0);\n    if(textView == self->_text) {\n        int count = 0;\n        NSArray *lines = [self->_text.text componentsSeparatedByString:@\"\\n\"];\n        for (NSString *line in lines) {\n            count += ceil((float)line.length / 1080.0f);\n        }\n        if(self->_type.selectedSegmentIndex == 1)\n            self->_messageFooter.text = [NSString stringWithFormat:@\"Text will be sent as %i message%@\", count, (count == 1)?@\"\":@\"s\"];\n        else\n            self->_messageFooter.text = @\"Text snippets are visible to anyone with the URL but are not publicly listed or indexed.\";\n    }\n}\n\n-(void)filenameChanged {\n    if([self->_filename.text rangeOfString:@\".\"].location != NSNotFound) {\n        NSString *extension = [self->_filename.text substringFromIndex:[self->_filename.text rangeOfString:@\".\" options:NSBackwardsSearch].location + 1];\n        if(extension.length)\n            self->_extension = extension;\n        else if(!_extension.length)\n            self->_extension = @\"txt\";\n        [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:2]] withRowAnimation:UITableViewRowAnimationNone];\n    }\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    if(indexPath.section == 0)\n        return 160;\n    else if(indexPath.section == 3)\n        return 64;\n    else\n        return UITableViewAutomaticDimension;\n}\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    if(self->_pasteID)\n        return 3;\n    else if(self->_type.selectedSegmentIndex == 0)\n        return 4;\n    else\n        return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return 1;\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {\n    switch (section) {\n        case 0:\n            return nil;\n        case 1:\n            return @\"File name (optional)\";\n        case 2:\n            return @\"Syntax Highlighting Mode\";\n        case 3:\n            return @\"Message (optional)\";\n    }\n    return nil;\n}\n\n-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {\n    if(section == 0) {\n        CGRect frame = self->_messageFooter.frame;\n        frame.origin.x = self.view.window.safeAreaInsets.left;\n        self->_messageFooter.frame = frame;\n        return _messageFooter;\n    }\n    return nil;\n}\n\n-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {\n    if(section == 0) {\n        return 32;\n    }\n    return 0;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSUInteger row = indexPath.row;\n    NSString *identifier = [NSString stringWithFormat:@\"pastecell-%li-%li\", (long)indexPath.section, (long)indexPath.row];\n    PastebinEditorCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];\n    \n    if(!cell)\n        cell = [[PastebinEditorCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];\n    \n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    cell.accessoryView = nil;\n    cell.accessoryType = UITableViewCellAccessoryNone;\n    cell.textLabel.text = nil;\n\n    switch(indexPath.section) {\n        case 0:\n            [self->_text removeFromSuperview];\n            self->_text.frame = CGRectInset(cell.contentView.bounds, 4, 4);\n            [cell.contentView addSubview:self->_text];\n            break;\n        case 1:\n            [self->_filename removeFromSuperview];\n            self->_filename.frame = CGRectInset(cell.contentView.bounds, 4, 4);\n            [cell.contentView addSubview:self->_filename];\n            break;\n        case 2:\n            cell.textLabel.text = [PastebinEditorViewController pastebinType:self->_extension];\n            break;\n        case 3:\n            [self->_message removeFromSuperview];\n            self->_message.frame = CGRectInset(cell.contentView.bounds, 4, 4);\n            [cell.contentView addSubview:self->_message];\n            break;\n    }\n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [self.tableView deselectRowAtIndexPath:indexPath animated:NO];\n    [self.tableView endEditing:YES];\n    \n    if(indexPath.section == 2) {\n        PastebinTypeViewController *vc = [[PastebinTypeViewController alloc] init];\n        vc.delegate = self;\n        \n        [self.navigationController pushViewController:vc animated:YES];\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/PastebinViewController.h",
    "content": "//\n//  PastebinViewController.h\n//\n//  Copyright (C) 2015 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import <WebKit/WebKit.h>\n#import \"OpenInChromeController.h\"\n\n@interface PastebinViewController : UIViewController<UIPopoverPresentationControllerDelegate,WKNavigationDelegate> {\n    IBOutlet WKWebView *_webView;\n    IBOutlet UIToolbar *_toolbar;\n    IBOutlet UIActivityIndicatorView *_activity;\n    NSString *_url;\n    UISwitch *_lineNumbers;\n    NSString *_pasteID;\n    BOOL _ownPaste;\n    OpenInChromeController *_chrome;\n}\n-(void)setUrl:(NSURL *)url;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/PastebinViewController.m",
    "content": "//\n//  PastebinViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <MobileCoreServices/UTCoreTypes.h>\n#import <SafariServices/SafariServices.h>\n#import <Twitter/Twitter.h>\n#import \"PastebinViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"OpenInChromeController.h\"\n#import \"OpenInFirefoxControllerObjC.h\"\n#import \"AppDelegate.h\"\n#import \"PastebinEditorViewController.h\"\n#import \"UIColor+IRCCloud.h\"\n@import Firebase;\n\n@implementation PastebinViewController\n\n-(void)setUrl:(NSURL *)url {\n    self->_url = url.absoluteString;\n    \n    if([self->_url rangeOfString:@\"?\"].location != NSNotFound) {\n        self->_url = [self->_url substringToIndex:[self->_url rangeOfString:@\"?\"].location];\n    }\n\n    NSRegularExpression *regexExpression = [NSRegularExpression regularExpressionWithPattern:@\"/pastebin/([^/.&?]+)\" options:0 error:NULL];\n    NSRange range = NSMakeRange(0, self->_url.length);\n    NSTextCheckingResult *r = [regexExpression firstMatchInString:self->_url options:0 range:range];\n    if(r.numberOfRanges == 2)\n        self->_pasteID = [self->_url substringWithRange:[r rangeAtIndex:1]];\n}\n\n\n- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {\n    NSURL *url = [NSURL URLWithString:self->_url];\n    \n    return @[\n                              [UIPreviewAction actionWithTitle:@\"Copy URL\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                                  UIPasteboard *pb = [UIPasteboard generalPasteboard];\n                                  [pb setValue:self->_url forPasteboardType:(NSString *)kUTTypeUTF8PlainText];\n                              }],\n                              [UIPreviewAction actionWithTitle:@\"Share\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                                  UIApplication *app = [UIApplication sharedApplication];\n                                  AppDelegate *appDelegate = (AppDelegate *)app.delegate;\n                                  MainViewController *mainViewController = [appDelegate mainViewController];\n                                  \n                                  [UIColor clearTheme];\n                                  UIActivityViewController *activityController = [URLHandler activityControllerForItems:@[url] type:@\"Pastebin\"];\n                                  activityController.popoverPresentationController.sourceView = mainViewController.slidingViewController.view;\n                                  [mainViewController.slidingViewController presentViewController:activityController animated:YES completion:nil];\n                              }],\n                              [UIPreviewAction actionWithTitle:@\"Open in Browser\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                                  if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Chrome\"] && [[OpenInChromeController sharedInstance] openInChrome:url\n                                                                                                                                                                          withCallbackURL:[NSURL URLWithString:\n#ifdef ENTERPRISE\n                                                                                                                                                                                           @\"irccloud-enterprise://\"\n#else\n                                                                                                                                                                                           @\"irccloud://\"\n#endif\n                                                                                                                                                                                           ]\n                                                                                                                                                                             createNewTab:NO])\n                                      return;\n                                  else if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Firefox\"] && [[OpenInFirefoxControllerObjC sharedInstance] openInFirefox:url])\n                                      return;\n                                  else\n                                      [[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n                              }]\n                              ];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [self->_activity startAnimating];\n    self->_lineNumbers.enabled = NO;\n    self->_lineNumbers.on = YES;\n    [self _fetch];\n    [self didMoveToParentViewController:nil];\n}\n\n-(void)viewDidLoad {\n    [super viewDidLoad];\n    \n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(_doneButtonPressed)];\n    self->_chrome = [[OpenInChromeController alloc] init];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n\n    self->_lineNumbers = [[UISwitch alloc] initWithFrame:CGRectZero];\n    self->_lineNumbers.on = YES;\n    [self->_lineNumbers addTarget:self action:@selector(_toggleLineNumbers) forControlEvents:UIControlEventValueChanged];\n    \n    self->_lineNumbers.enabled = NO;\n    [self->_lineNumbers sizeToFit];\n    \n    self->_webView.opaque = NO;\n    self->_webView.backgroundColor = [UIColor contentBackgroundColor];\n    self->_webView.scrollView.scrollsToTop = YES;\n    self->_webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;\n    self->_webView.navigationDelegate = self;\n    \n    self.view.backgroundColor = [UIColor contentBackgroundColor];\n    \n    if([UIColor isDarkTheme]) {\n        self.navigationController.view.backgroundColor = [UIColor navBarColor];\n        self->_activity.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;\n        [self->_toolbar setBackgroundImage:[UIColor navBarBackgroundImage] forToolbarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];\n        [self->_toolbar setTintColor:[UIColor navBarSubheadingColor]];\n    } else {\n        self.navigationController.view.backgroundColor = [UIColor navBarColor];\n        self->_activity.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;\n    }\n}\n\n-(void)didMoveToParentViewController:(UIViewController *)parent {\n    CGRect frame = self->_webView.frame;\n    if(self.navigationController.navigationBarHidden) {\n        self->_toolbar.hidden = YES;\n        frame.size.height = self.view.frame.size.height - _webView.frame.origin.y;\n    } else {\n        self->_toolbar.hidden = NO;\n        frame.size.height = self.view.frame.size.height - _webView.frame.origin.y - _toolbar.frame.size.height;\n    }\n    self->_webView.frame = frame;\n}\n\n-(void)_fetch {\n    if([self->_url hasPrefix:[NSString stringWithFormat:@\"https://%@/pastebin/\", IRCCLOUD_HOST]] || [self->_url hasPrefix:@\"https://www.irccloud.com/pastebin/\"]) {\n        [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;\n        [[NSURLCache sharedURLCache] removeAllCachedResponses];\n        NSString *url = [[NetworkConnection sharedInstance].pasteURITemplate relativeStringWithVariables:@{@\"id\":self->_pasteID, @\"type\":@\"json\"} error:nil];\n        url = [url stringByReplacingOccurrencesOfString:@\"https://www.irccloud.com/\" withString:[NSString stringWithFormat:@\"https://%@/\", IRCCLOUD_HOST]];\n        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];\n        [request setHTTPShouldHandleCookies:NO];\n        [request setValue:[NSString stringWithFormat:@\"session=%@\",NetworkConnection.sharedInstance.session] forHTTPHeaderField:@\"Cookie\"];\n\n        [[[NetworkConnection sharedInstance].urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n            if (error) {\n                CLS_LOG(@\"Error fetching pastebin. Error %li : %@\", (long)error.code, error.userInfo);\n            } else {\n                NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];\n                self->_ownPaste = [[dict objectForKey:@\"own_paste\"] intValue] == 1;\n            }\n            NSURL *url = [NSURL URLWithString:[self->_url stringByAppendingFormat:@\"?mobile=ios&version=%@&theme=%@&own_paste=%@\", [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"], [UIColor currentTheme], self->_ownPaste ? @\"1\" : @\"0\"]];\n            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];\n            [request setHTTPShouldHandleCookies:NO];\n            \n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [self->_webView loadRequest:request];\n\n                if(self->_ownPaste) {\n                    [self->_toolbar setItems:@[[[UIBarButtonItem alloc] initWithTitle:@\"Line Numbers\" style:UIBarButtonItemStylePlain target:self action:@selector(_toggleLineNumbersSwitch)],\n                                               [[UIBarButtonItem alloc] initWithCustomView:self->_lineNumbers],\n                                               [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],\n                                               [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:@selector(_editPaste)],\n                                               [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],\n                                               [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(_removePaste)],\n                                               [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],\n                                               [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(shareButtonPressed:)]\n                                               ]];\n                } else {\n                    [self->_toolbar setItems:@[[[UIBarButtonItem alloc] initWithTitle:@\"Line Numbers\" style:UIBarButtonItemStylePlain target:self action:@selector(_toggleLineNumbersSwitch)],\n                                               [[UIBarButtonItem alloc] initWithCustomView:self->_lineNumbers],\n                                               [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],\n                                               [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(shareButtonPressed:)]\n                                               ]];\n                    \n                }\n            }];\n        }] resume];\n    }\n}\n\n-(void)_doneButtonPressed {\n    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)_toggleLineNumbers {\n    if(self->_lineNumbers.enabled) {\n        if(self->_lineNumbers.on) {\n            [self->_webView evaluateJavaScript:@\"window.PASTEVIEW.$el.toggleClass('nolinenums', true);\" completionHandler:nil];\n            [self->_webView evaluateJavaScript:@\"window.PASTEVIEW.ace.renderer.setShowGutter(true);\" completionHandler:nil];\n        } else {\n            [self->_webView evaluateJavaScript:@\"window.PASTEVIEW.$el.toggleClass('nolinenums', false);\" completionHandler:nil];\n            [self->_webView evaluateJavaScript:@\"window.PASTEVIEW.ace.renderer.setShowGutter(false);\" completionHandler:nil];\n        }\n    }\n}\n\n-(void)_toggleLineNumbersSwitch {\n    if(self->_lineNumbers.enabled) {\n        [self->_lineNumbers setOn:!_lineNumbers.on animated:YES];\n        [self _toggleLineNumbers];\n    }\n}\n\n-(void)_removePaste {\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Delete Snippet\" message:@\"Are you sure you want to delete this text snippet?\" preferredStyle:UIAlertControllerStyleAlert];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {\n        [[NetworkConnection sharedInstance] deletePaste:self->_pasteID handler:nil];\n        if(self.navigationController.viewControllers.count == 1)\n            [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];\n        else\n            [self.navigationController popViewControllerAnimated:YES];\n    }]];\n    [self presentViewController:alert animated:YES completion:nil];\n}\n\n-(void)_editPaste {\n    [self.navigationController pushViewController:[[PastebinEditorViewController alloc] initWithPasteID:self->_pasteID] animated:YES];\n    [self->_webView loadHTMLString:@\"\" baseURL:nil];\n}\n\n-(IBAction)shareButtonPressed:(id)sender {\n    [UIColor clearTheme];\n    UIActivityViewController *activityController = [URLHandler activityControllerForItems:@[[NSURL URLWithString:self->_url]] type:@\"Pastebin\"];\n    activityController.popoverPresentationController.delegate = self;\n    activityController.popoverPresentationController.barButtonItem = sender;\n    [self presentViewController:activityController animated:YES completion:nil];\n}\n\n-(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {\n    if(([error.domain isEqualToString:@\"WebKitErrorDomain\"] && error.code == 102) || ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled))\n        return;\n    CLS_LOG(@\"Error: %@\", error);\n    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;\n    [self->_activity stopAnimating];\n}\n\n-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {\n    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;\n}\n\n-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {\n    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;\n}\n\n-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {\n    if([navigationAction.request.URL.scheme isEqualToString:@\"hide-spinner\"]) {\n        [self->_activity stopAnimating];\n        self->_lineNumbers.enabled = YES;\n        decisionHandler(WKNavigationActionPolicyCancel);\n    } else if(([navigationAction.request.URL.host isEqualToString:IRCCLOUD_HOST] || [navigationAction.request.URL.host isEqualToString:@\"www.irccloud.com\"]) && [navigationAction.request.URL.path hasPrefix:@\"/pastebin/\"]) {\n        decisionHandler(WKNavigationActionPolicyAllow);\n    } else {\n        decisionHandler(WKNavigationActionPolicyCancel);\n        if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Chrome\"] && [[OpenInChromeController sharedInstance] openInChrome:navigationAction.request.URL\n                                                                                                                                                withCallbackURL:[NSURL URLWithString:\n#ifdef ENTERPRISE\n                                                                                                                                                                 @\"irccloud-enterprise://\"\n#else\n                                                                                                                                                                 @\"irccloud://\"\n#endif\n                                                                                                                                                                 ]\n                                                                                                                                                   createNewTab:NO])\n            return;\n        else if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Firefox\"] && [[OpenInFirefoxControllerObjC sharedInstance] openInFirefox:navigationAction.request.URL])\n            return;\n        else\n            [[UIApplication sharedApplication] openURL:navigationAction.request.URL options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n    }\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/PastebinsTableViewController.h",
    "content": "//\n//  PastebinsTableViewController.h\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n\n@protocol PastebinsTableViewDelegate<NSObject>\n-(void)pastebinsTableViewControllerDidSelectFile:(NSDictionary *)file message:(NSString *)message;\n@end\n\n@interface PastebinsTableViewController : UITableViewController {\n    int _pages;\n    NSArray *_pastes;\n    BOOL _canLoadMore;\n    id<PastebinsTableViewDelegate> _delegate;\n    UIView *_footerView;\n    NSDictionary *_selectedPaste;\n    NSMutableDictionary *_extensions;\n}\n@property id<PastebinsTableViewDelegate> delegate;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/PastebinsTableViewController.m",
    "content": "//\n//  PastebinsTableViewController.m\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import \"PastebinsTableViewController.h\"\n#import \"ColorFormatter.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"NetworkConnection.h\"\n#import \"PastebinViewController.h\"\n#import \"PastebinEditorViewController.h\"\n\n#define MAX_LINES 6\n\n@interface PastebinsTableCell : UITableViewCell {\n    UILabel *_name;\n    UILabel *_date;\n    UILabel *_text;\n}\n@property (readonly) UILabel *name,*date,*text;\n@end\n\n@implementation PastebinsTableCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self->_name = [[UILabel alloc] init];\n        self->_name.backgroundColor = [UIColor clearColor];\n        self->_name.textColor = [UITableViewCell appearance].textLabelColor;\n        self->_name.font = [UIFont boldSystemFontOfSize:FONT_SIZE];\n        self->_name.textAlignment = NSTextAlignmentLeft;\n        [self.contentView addSubview:self->_name];\n        \n        self->_date = [[UILabel alloc] init];\n        self->_date.backgroundColor = [UIColor clearColor];\n        self->_date.textColor = [UITableViewCell appearance].textLabelColor;\n        self->_date.font = [UIFont systemFontOfSize:FONT_SIZE];\n        self->_date.textAlignment = NSTextAlignmentRight;\n        [self.contentView addSubview:self->_date];\n        \n        self->_text = [[UILabel alloc] init];\n        self->_text.backgroundColor = [UIColor clearColor];\n        self->_text.textColor = [UITableViewCell appearance].detailTextLabelColor;\n        self->_text.font = [UIFont systemFontOfSize:FONT_SIZE];\n        self->_text.lineBreakMode = NSLineBreakByTruncatingTail;\n        self->_text.numberOfLines = 0;\n        [self.contentView addSubview:self->_text];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n    [super layoutSubviews];\n    \n    CGRect frame = [self.contentView bounds];\n    frame.origin.x = 16;\n    frame.origin.y = 8;\n    frame.size.width -= 20;\n    frame.size.height -= 16;\n    \n    [self->_date sizeToFit];\n    self->_date.frame = CGRectMake(frame.origin.x, frame.origin.y + frame.size.height - FONT_SIZE - 6, _date.frame.size.width, FONT_SIZE + 6);\n\n    if(self->_name.text.length) {\n        self->_name.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width - 4, FONT_SIZE + 6);\n        self->_text.frame = CGRectMake(frame.origin.x, _name.frame.origin.y + _name.frame.size.height, frame.size.width, frame.size.height - _date.frame.size.height - _name.frame.size.height);\n    } else {\n        self->_text.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height - _date.frame.size.height);\n    }\n}\n\n-(void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n@end\n\n@implementation PastebinsTableViewController\n\n-(instancetype)init {\n    self = [super initWithStyle:UITableViewStylePlain];\n    if(self) {\n        self.navigationItem.title = @\"Text Snippets\";\n        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editButtonPressed:)];\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)];\n        self->_extensions = [[NSMutableDictionary alloc] init];\n    }\n    return self;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.tableView.backgroundColor = [[UITableViewCell appearance] backgroundColor];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n\n    self->_footerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,64,64)];\n    self->_footerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n    UIActivityIndicatorView *a = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n    a.center = self->_footerView.center;\n    a.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;\n    [a startAnimating];\n    [self->_footerView addSubview:a];\n    \n    self.tableView.tableFooterView = self->_footerView;\n    self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;\n    self->_pages = 0;\n    self->_pastes = nil;\n    self->_canLoadMore = YES;\n    [self _loadMore];\n}\n\n-(void)editButtonPressed:(id)sender {\n    [self.tableView setEditing:!self.tableView.isEditing animated:YES];\n    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:self.tableView.isEditing?UIBarButtonSystemItemCancel:UIBarButtonSystemItemEdit target:self action:@selector(editButtonPressed:)];\n}\n\n-(void)doneButtonPressed:(id)sender {\n    [self.tableView endEditing:YES];\n    [self dismissViewControllerAnimated:YES completion:nil];\n    self->_pastes = nil;\n    self->_canLoadMore = NO;\n}\n\n-(void)setFooterView:(UIView *)v {\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        self.tableView.tableFooterView = v;\n    }];\n}\n\n-(void)_loadMore {\n    [[NetworkConnection sharedInstance] getPastebins:++_pages handler:^(IRCCloudJSONObject *d) {\n        if([[d objectForKey:@\"success\"] boolValue]) {\n            CLS_LOG(@\"Loaded pastebin list for page %i\", self->_pages);\n            if(self->_pastes)\n                self->_pastes = [self->_pastes arrayByAddingObjectsFromArray:[d objectForKey:@\"pastebins\"]];\n            else\n                self->_pastes = [d objectForKey:@\"pastebins\"];\n            \n            self->_canLoadMore = self->_pastes.count < [[d objectForKey:@\"total\"] intValue];\n            [self setFooterView:self->_canLoadMore?self->_footerView:nil];\n            if(!self->_pastes.count) {\n                CLS_LOG(@\"Pastebin list is empty\");\n                UILabel *fail = [[UILabel alloc] init];\n                fail.text = @\"\\nYou haven't created any\\ntext snippets yet.\\n\";\n                fail.numberOfLines = 3;\n                fail.textAlignment = NSTextAlignmentCenter;\n                fail.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n                fail.textColor = [UIColor messageTextColor];\n                [fail sizeToFit];\n                [self setFooterView:fail];\n            }\n        } else {\n            CLS_LOG(@\"Failed to load pastebin list for page %i: %@\", self->_pages, d);\n            self->_canLoadMore = NO;\n            UILabel *fail = [[UILabel alloc] init];\n            fail.text = @\"\\nUnable to load snippet.\\nPlease try again later.\\n\";\n            fail.numberOfLines = 4;\n            fail.textAlignment = NSTextAlignmentCenter;\n            fail.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n            fail.textColor = [UIColor messageTextColor];\n            [fail sizeToFit];\n            [self setFooterView:fail];\n            return;\n        }\n\n        [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];\n    }];\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n- (NSString *)fileType:(NSString *)extension {\n    if([self->_extensions objectForKey:extension.lowercaseString])\n        return [self->_extensions objectForKey:extension.lowercaseString];\n    \n    NSString *type = [PastebinEditorViewController pastebinType:extension];\n    [self->_extensions setObject:type forKey:extension.lowercaseString];\n    return type;\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return _pastes.count;\n}\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    return FONT_SIZE + 24 + ([[[self->_pastes objectAtIndex:indexPath.row] objectForKey:@\"body\"] boundingRectWithSize:CGRectMake(0,0,self.tableView.frame.size.width - 26,(FONT_SIZE + 4) * MAX_LINES).size options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:FONT_SIZE]} context:nil].size.height) + ([[[self->_pastes objectAtIndex:indexPath.row] objectForKey:@\"name\"] length]?(FONT_SIZE + 6):0);\n}\n\n-(void)scrollViewDidScroll:(UIScrollView *)scrollView {\n    if(self->_pastes.count && _canLoadMore) {\n        NSArray *rows = [self.tableView indexPathsForRowsInRect:UIEdgeInsetsInsetRect(self.tableView.bounds, self.tableView.contentInset)];\n        \n        if([[rows lastObject] row] >= self->_pastes.count - 5) {\n            self->_canLoadMore = NO;\n            [self _loadMore];\n        }\n    }\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    PastebinsTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"pastebincell\"];\n    if(!cell)\n        cell = [[PastebinsTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"pastebincell\"];\n\n    NSDictionary *pastebin = [self->_pastes objectAtIndex:indexPath.row];\n    \n    NSString *date = nil;\n    double seconds = [[NSDate date] timeIntervalSince1970] - [[pastebin objectForKey:@\"date\"] doubleValue];\n    double minutes = seconds / 60.0;\n    double hours = minutes / 60.0;\n    double days = hours / 24.0;\n    double months = days / 31.0;\n    double years = months / 12.0;\n    \n    if(years >= 1) {\n        if(years - (int)years > 0.5)\n            years++;\n        \n        if((int)years == 1)\n            date = [NSString stringWithFormat:@\"%i year ago\", (int)years];\n        else\n            date = [NSString stringWithFormat:@\"%i years ago\", (int)years];\n    } else if(months >= 1) {\n        if(months - (int)months > 0.5)\n            months++;\n        \n        if((int)months == 1)\n            date = [NSString stringWithFormat:@\"%i month ago\", (int)months];\n        else\n            date = [NSString stringWithFormat:@\"%i months ago\", (int)months];\n    } else if(days >= 1) {\n        if(days - (int)days > 0.5)\n            days++;\n        \n        if((int)days == 1)\n            date = [NSString stringWithFormat:@\"%i day ago\", (int)days];\n        else\n            date = [NSString stringWithFormat:@\"%i days ago\", (int)days];\n    } else if(hours >= 1) {\n        if(hours - (int)hours > 0.5)\n            hours++;\n        \n        if((int)hours < 2)\n            date = [NSString stringWithFormat:@\"%i hour ago\", (int)hours];\n        else\n            date = [NSString stringWithFormat:@\"%i hours ago\", (int)hours];\n    } else if(minutes >= 1) {\n        if(minutes - (int)minutes > 0.5)\n            minutes++;\n        \n        if((int)minutes == 1)\n            date = [NSString stringWithFormat:@\"%i minute ago\", (int)minutes];\n        else\n            date = [NSString stringWithFormat:@\"%i minutes ago\", (int)minutes];\n    } else {\n        if((int)seconds == 1)\n            date = [NSString stringWithFormat:@\"%i second ago\", (int)seconds];\n        else\n            date = [NSString stringWithFormat:@\"%i seconds ago\", (int)seconds];\n    }\n\n    cell.name.text = [pastebin objectForKey:@\"name\"];\n    cell.date.text = [NSString stringWithFormat:@\"%@ • %@ line%@ • %@\", date, [pastebin objectForKey:@\"lines\"], ([[pastebin objectForKey:@\"lines\"] intValue] == 1)?@\"\":@\"s\", [self fileType:[pastebin objectForKey:@\"extension\"]]];\n    cell.text.text = [pastebin objectForKey:@\"body\"];\n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;\n    [cell layoutSubviews];\n    \n    return cell;\n}\n\n- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {\n    return YES;\n}\n\n- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {\n    if (editingStyle == UITableViewCellEditingStyleDelete) {\n        [[NetworkConnection sharedInstance] deletePaste:[[self->_pastes objectAtIndex:indexPath.row] objectForKey:@\"id\"] handler:^(IRCCloudJSONObject *result) {\n            if([[result objectForKey:@\"success\"] boolValue]) {\n                CLS_LOG(@\"Pastebin deleted successfully\");\n            } else {\n                CLS_LOG(@\"Error deleting pastebin: %@\", result);\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to delete snippet, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n                self->_pages = 0;\n                self->_pastes = nil;\n                self->_canLoadMore = YES;\n                [self _loadMore];\n            }\n        }];\n        NSMutableArray *a = self->_pastes.mutableCopy;\n        [a removeObjectAtIndex:indexPath.row];\n        self->_pastes = [NSArray arrayWithArray:a];\n        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];\n        if(!_pastes.count) {\n            UILabel *fail = [[UILabel alloc] init];\n            fail.text = @\"\\nYou haven't created any text snippets yet.\\n\";\n            fail.numberOfLines = 3;\n            fail.textAlignment = NSTextAlignmentCenter;\n            fail.autoresizingMask = UIViewAutoresizingFlexibleWidth;\n            [fail sizeToFit];\n            self.tableView.tableFooterView = fail;\n        }\n        [self scrollViewDidScroll:self.tableView];\n    }\n}\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    self->_selectedPaste = [self->_pastes objectAtIndex:indexPath.row];\n    if(self->_selectedPaste) {\n        NSString *url = [[NetworkConnection sharedInstance].pasteURITemplate relativeStringWithVariables:self->_selectedPaste error:nil];\n        url = [url stringByAppendingFormat:@\"?id=%@\", [self->_selectedPaste objectForKey:@\"id\"]];\n        PastebinViewController *c = [[UIStoryboard storyboardWithName:@\"MainStoryboard\" bundle:nil] instantiateViewControllerWithIdentifier:@\"PastebinViewController\"];\n        [c setUrl:[NSURL URLWithString:url]];\n        [self.navigationController pushViewController:c animated:YES];\n    }\n    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/PinReorderViewController.h",
    "content": "//\n//  PinReorderViewController.h\n//\n//  Copyright (C) 2020 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n\n@interface PinReorderViewController : UITableViewController {\n    NSMutableArray *buffers;\n    NSMutableDictionary *nameCounts;\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/PinReorderViewController.m",
    "content": "//\n//  PinReorderViewController.m\n//\n//  Copyright (C) 2020 IRCCloud, Ltd.\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#import \"PinReorderViewController.h\"\n#import \"BuffersDataSource.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"NetworkConnection.h\"\n#import \"FontAwesome.h\"\n\n@interface ReorderCell : UITableViewCell {\n    UILabel *_icon;\n}\n@property (readonly) UILabel *icon;\n@end\n\n@implementation PinReorderViewController\n\n- (id)initWithStyle:(UITableViewStyle)style {\n    self = [super initWithStyle:style];\n    if (self) {\n        self.navigationItem.title = @\"Pinned Channels\";\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)];\n    }\n    return self;\n}\n\n-(void)dealloc {\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n- (void)doneButtonPressed:(id)sender {\n    NSMutableDictionary *mutablePrefs = [[NetworkConnection sharedInstance] prefs].mutableCopy;\n    [mutablePrefs setObject:buffers forKey:@\"pinnedBuffers\"];\n    SBJson5Writer *writer = [[SBJson5Writer alloc] init];\n    NSString *json = [writer stringWithObject:mutablePrefs];\n\n    [[NetworkConnection sharedInstance] setPrefs:json handler:^(IRCCloudJSONObject *result) {\n        if([[result objectForKey:@\"success\"] boolValue]) {\n            [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];\n        } else {\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to save settings, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n            [self presentViewController:alert animated:YES completion:nil];\n        }\n    }];\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.tableView.separatorColor = [UIColor clearColor];\n    self.tableView.editing = YES;\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refresh) name:kIRCCloudBacklogCompletedNotification object:nil];\n    [self refresh];\n}\n\n-(void)refresh {\n    NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n    if([[prefs objectForKey:@\"pinnedBuffers\"] isKindOfClass:NSArray.class] && [(NSArray *)[prefs objectForKey:@\"pinnedBuffers\"] count] > 0) {\n        buffers = ((NSArray *)[prefs objectForKey:@\"pinnedBuffers\"]).mutableCopy;\n    } else {\n        buffers = [[NSMutableArray alloc] init];\n    }\n    nameCounts = [[NSMutableDictionary alloc] init];\n    for(NSNumber *bid in buffers) {\n        Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:bid.intValue];\n        if(b) {\n            int count = [[nameCounts objectForKey:b.displayName] intValue];\n            [nameCounts setObject:@(count + 1) forKey:b.displayName];\n        }\n    }\n    [self.tableView reloadData];\n}\n\n- (void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    switch(event) {\n        case kIRCEventUserInfo:\n            [self refresh];\n            break;\n        default:\n            break;\n    }\n}\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return [buffers count];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    ReorderCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"reordercell\"];\n    if(!cell)\n        cell = [[ReorderCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"reordercell\"];\n\n    Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:[[buffers objectAtIndex:indexPath.row] intValue]];\n    NSString *name = b.displayName;\n    if([[nameCounts objectForKey:b.displayName] intValue] > 1) {\n        Server *s = [[ServersDataSource sharedInstance] getServer:b.cid];\n        if(s) {\n            NSString *serverName = s.name;\n            if(!serverName || serverName.length == 0)\n                serverName = s.hostname;\n\n            name = [name stringByAppendingFormat:@\" (%@)\", serverName];\n        }\n    }\n    \n    cell.textLabel.text = name;\n    cell.icon.text = nil;\n    if([b.type isEqualToString:@\"channel\"]) {\n        Channel *channel = [[ChannelsDataSource sharedInstance] channelForBuffer:b.bid];\n        if(channel) {\n            if(channel.key || (b.serverIsSlack && !b.isMPDM && [channel hasMode:@\"s\"]))\n                cell.icon.text = FA_LOCK;\n        }\n    }\n\n    \n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    return cell;\n}\n\n- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {\n    NSNumber *bid = [buffers objectAtIndex:fromIndexPath.row];\n    [buffers removeObjectAtIndex:fromIndexPath.row];\n    if (toIndexPath.row >= buffers.count) {\n        [buffers addObject:bid];\n    } else {\n        [buffers insertObject:bid atIndex:toIndexPath.row];\n    }\n}\n\n- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {\n    return UITableViewCellEditingStyleNone;\n}\n\n/*\n// Override to support conditional rearranging of the table view.\n- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    // Return NO if you do not want the item to be re-orderable.\n    return YES;\n}\n*/\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/SamlLoginViewController.h",
    "content": "//\n//  SamlLoginViewController.h\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n#import <WebKit/WebKit.h>\n\n@interface SamlLoginViewController : UIViewController<WKNavigationDelegate> {\n    WKWebView *_webView;\n    UIActivityIndicatorView *_activity;\n    NSURL *_url;\n}\n-(id)initWithURL:(NSString *)url;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/SamlLoginViewController.m",
    "content": "//\n//  SamlLoginViewController.m\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import \"SamlLoginViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"AppDelegate.h\"\n\n@implementation SamlLoginViewController\n\n- (id)initWithURL:(NSString *)url {\n    self = [super init];\n    if (self) {\n        self->_url = [NSURL URLWithString:url];\n    }\n    return self;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];\n    if (cookies != nil && cookies.count > 0) {\n        for (NSHTTPCookie *cookie in cookies) {\n            [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];\n        }\n        [[NSUserDefaults standardUserDefaults] synchronize];\n    }\n    self->_activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];\n    self->_activity.hidesWhenStopped = YES;\n    [self->_activity startAnimating];\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self->_activity];\n\n    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];\n    if (@available(iOS 14.0, *)) {\n        WKWebpagePreferences *prefs = [[WKWebpagePreferences alloc] init];\n        prefs.allowsContentJavaScript = YES;\n        config.defaultWebpagePreferences = prefs;\n    } else {\n        WKPreferences *prefs = [[WKPreferences alloc] init];\n        prefs.javaScriptEnabled = YES;\n        config.preferences = prefs;\n    }\n\n    self->_webView = [[WKWebView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width, self.view.frame.size.height) configuration:config];\n    self->_webView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;\n    self->_webView.navigationDelegate = self;\n    [self->_webView loadRequest:[NSURLRequest requestWithURL:self->_url]];\n    [self.view addSubview:self->_webView];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [self.view endEditing:YES];\n    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;\n}\n\n-(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {\n    CLS_LOG(@\"Error: %@\", error);\n    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;\n    [self->_activity stopAnimating];\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];\n}\n\n-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {\n    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self->_activity];\n    [self->_activity startAnimating];\n}\n\n-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {\n    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;\n    [self->_activity stopAnimating];\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];\n}\n\n-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {\n    [self.view endEditing:YES];\n    if([navigationAction.request.URL.host isEqualToString:IRCCLOUD_HOST] && [navigationAction.request.URL.path isEqualToString:@\"/\"]) {\n        [[WKWebsiteDataStore defaultDataStore].httpCookieStore getAllCookies:^(NSArray *cookies) {\n                    if (cookies != nil && cookies.count > 0) {\n                        for (NSHTTPCookie *cookie in cookies) {\n                            if([cookie.name isEqualToString:@\"session\"]) {\n                                [NetworkConnection sharedInstance].session = cookie.value;\n                                [[NSUserDefaults standardUserDefaults] setObject:IRCCLOUD_HOST forKey:@\"host\"];\n                                [[NSUserDefaults standardUserDefaults] setObject:IRCCLOUD_PATH forKey:@\"path\"];\n                                [[NSUserDefaults standardUserDefaults] synchronize];\n#ifdef ENTERPRISE\n                                NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n                                NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n                                [d setObject:IRCCLOUD_HOST forKey:@\"host\"];\n                                [d setObject:IRCCLOUD_PATH forKey:@\"path\"];\n                                [d synchronize];\n                                [self.presentingViewController dismissViewControllerAnimated:YES completion:^{\n                                    [((AppDelegate *)([UIApplication sharedApplication].delegate)) showMainView:YES];\n                                }];\n                            }\n                            [[WKWebsiteDataStore defaultDataStore].httpCookieStore deleteCookie:cookie completionHandler:nil];\n                        }\n                        [[NSUserDefaults standardUserDefaults] synchronize];\n                    }\n                    decisionHandler(WKNavigationActionPolicyCancel);\n        }];\n        return;\n    }\n    decisionHandler(WKNavigationActionPolicyAllow);\n}\n\n- (void)cancelButtonPressed:(id)sender {\n    [self->_webView stopLoading];\n    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;\n    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/SendMessageIntentHandler.h",
    "content": "//\n//  SendMessageIntentHandler.h\n//\n//  Copyright (C) 2022 IRCCloud, Ltd.\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#import <Intents/Intents.h>\n#import \"FileUploader.h\"\n\n@interface SendMessageIntentHandler : NSObject <INSendMessageIntentHandling,FileUploaderDelegate> {\n    FileUploader *_fileUploader;\n    void (^_completion)(INSendMessageIntentResponse * _Nonnull);\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/SendMessageIntentHandler.m",
    "content": "//\n//  SendMessageIntentHandler.m\n//\n//  Copyright (C) 2022 IRCCloud, Ltd.\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#import <AVFoundation/AVFoundation.h>\n#import <MobileCoreServices/MobileCoreServices.h>\n#import <IntentsUI/IntentsUI.h>\n#import \"SendMessageIntentHandler.h\"\n#import \"AvatarsDataSource.h\"\n#import \"NetworkConnection.h\"\n#import \"ImageCache.h\"\n\n@interface INSendMessageAttachment (FileAttachments)\n@property INFile *file;\n@end\n\n@implementation SendMessageIntentHandler\n-(instancetype)init {\n    self = [super init];\n\n    if(self) {\n        self->_fileUploader = [[FileUploader alloc] init];\n        self->_fileUploader.delegate = self;\n    }\n    \n    return self;\n}\n\n-(INSendMessageRecipientResolutionResult *)resolvePerson:(INPerson *)person {\n    if(person && [person.customIdentifier hasPrefix:@\"irccloud://\"]) {\n        INPersonResolutionResult *result = [INPersonResolutionResult successWithResolvedPerson:person];\n        return [[INSendMessageRecipientResolutionResult alloc] initWithPersonResolutionResult:result];\n    } else if (person.displayName) {\n        NSMutableArray *matches = [[NSMutableArray alloc] init];\n        NSArray *buffers = [BuffersDataSource sharedInstance].getBuffers;\n        NSString *personName = person.displayName.lowercaseString;\n        for(Buffer *b in buffers) {\n            if([personName isEqualToString:b.name.lowercaseString]) {\n                Server *s = [[ServersDataSource sharedInstance] getServer:b.cid];\n                if(![s.status isEqualToString:@\"connected_ready\"])\n                    continue;\n                \n                NSString *serverName = s.name;\n                if(!serverName.length)\n                    serverName = s.hostname;\n                \n                BOOL exists = NO;\n                for(INPerson *p in matches) {\n                    if([p.customIdentifier isEqualToString:[NSString stringWithFormat:@\"irccloud://%i/%@\", s.cid, b.name]]) {\n                        exists = YES;\n                        break;\n                    }\n                }\n                if(exists)\n                    continue;\n\n                INImage *img = nil;\n                if([b.type isEqualToString:@\"conversation\"]) {\n                    NSURL *url = [[AvatarsDataSource sharedInstance] URLforBid:b.bid];\n                    if(!url) {\n                        User *u = [[UsersDataSource sharedInstance] getUser:b.name cid:b.cid];\n                        if(u) {\n                            Event *e = [[Event alloc] init];\n                            e.cid = b.cid;\n                            e.bid = b.bid;\n                            e.hostmask = u.hostmask;\n                            e.from = b.name;\n                            e.type = @\"buffer_msg\";\n                            \n                            url = [e avatar:512];\n                        }\n                    }\n                    \n                    if(url && [[ImageCache sharedInstance] imageForURL:url]) {\n                        img = [INImage imageWithURL:[[ImageCache sharedInstance] pathForURL:url]];\n                    }\n                }\n\n                if(!img) {\n                    Avatar *a = [[Avatar alloc] init];\n                    a.nick = a.displayName = b.name;\n                    img = [INImage imageWithUIImage:[a getImage:512 isSelf:NO]];\n                }\n                [matches addObject:[[INPerson alloc] initWithPersonHandle:[[INPersonHandle alloc] initWithValue:b.name type:INPersonHandleTypeUnknown] nameComponents:nil displayName:[NSString stringWithFormat:@\"%@ (%@)\", b.name, serverName] image:img contactIdentifier:nil customIdentifier:[NSString stringWithFormat:@\"irccloud://%i/%@\", b.cid, b.name]]];\n            }\n        }\n        NSArray *servers = [ServersDataSource sharedInstance].getServers;\n        for(Server *s in servers) {\n            if(![s.status isEqualToString:@\"connected_ready\"])\n                continue;\n            User *u = [[UsersDataSource sharedInstance] getUser:personName cid:s.cid];\n            if(u) {\n                BOOL exists = NO;\n                for(INPerson *p in matches) {\n                    if([p.customIdentifier isEqualToString:[NSString stringWithFormat:@\"irccloud://%i/%@\", s.cid, u.nick]]) {\n                        exists = YES;\n                        break;\n                    }\n                }\n                if(exists)\n                    continue;\n                \n                NSString *serverName = s.name;\n                if(!serverName.length)\n                    serverName = s.hostname;\n                \n                INImage *img = nil;\n                Event *e = [[Event alloc] init];\n                e.hostmask = u.hostmask;\n                e.from = u.nick;\n                e.type = @\"buffer_msg\";\n                NSURL *url = [e avatar:512];\n                if(url && [[ImageCache sharedInstance] imageForURL:url]) {\n                    img = [INImage imageWithURL:[[ImageCache sharedInstance] pathForURL:url]];\n                }\n\n                if(!img) {\n                    Avatar *a = [[Avatar alloc] init];\n                    a.nick = a.displayName = u.nick;\n                    img = [INImage imageWithUIImage:[a getImage:512 isSelf:NO]];\n                }\n                [matches addObject:[[INPerson alloc] initWithPersonHandle:[[INPersonHandle alloc] initWithValue:u.nick type:INPersonHandleTypeUnknown] nameComponents:nil displayName:[NSString stringWithFormat:@\"%@ (%@)\", u.display_name, serverName] image:img contactIdentifier:nil customIdentifier:[NSString stringWithFormat:@\"irccloud://%i/%@\", s.cid, u.nick]]];\n            }\n        }\n        NSLog(@\"Matches: %@\", matches);\n        if(matches.count == 1) {\n            INPersonResolutionResult *result = [INPersonResolutionResult successWithResolvedPerson:matches.firstObject];\n            return [[INSendMessageRecipientResolutionResult alloc] initWithPersonResolutionResult:result];\n        } else if(matches.count) {\n            INPersonResolutionResult *result = [INPersonResolutionResult disambiguationWithPeopleToDisambiguate:matches];\n            return [[INSendMessageRecipientResolutionResult alloc] initWithPersonResolutionResult:result];\n        }\n    }\n    return [INSendMessageRecipientResolutionResult unsupportedForReason:INSendMessageRecipientUnsupportedReasonNoHandleForLabel];\n}\n\n-(void)resolveRecipientsForSendMessage:(INSendMessageIntent *)intent completion:(void (^)(NSArray<INSendMessageRecipientResolutionResult *> * _Nonnull))completion {\n    NSLog(@\"Resolve intent: %@\", intent);\n    NSMutableArray *results;\n    \n    if(intent.recipients.count) {\n        results = [[NSMutableArray alloc] init];\n        \n        for(INPerson *person in intent.recipients) {\n            [results addObject:[self resolvePerson:person]];\n        }\n    } else {\n        results = @[[INSendMessageRecipientResolutionResult needsValue]].mutableCopy;\n    }\n    completion(results);\n}\n\n-(void)resolveContentForSendMessage:(INSendMessageIntent *)intent withCompletion:(void (^)(INStringResolutionResult * _Nonnull))completion {\n    if (@available(iOS 14.0, *)) {\n        if(intent.attachments.count > 1) {\n            completion([INStringResolutionResult unsupported]);\n            return;\n        } else if(intent.attachments.count == 1) {\n            completion([INStringResolutionResult successWithResolvedString:intent.content]);\n            return;\n        }\n    }\n\n    if(intent.content.length)\n        completion([INStringResolutionResult successWithResolvedString:intent.content]);\n    else\n        completion([INStringResolutionResult needsValue]);\n    \n}\n\n-(void)confirmSendMessage:(INSendMessageIntent *)intent completion:(void (^)(INSendMessageIntentResponse * _Nonnull))completion {\n    NSLog(@\"Confirm intent: %@\", intent);\n    int code = INSendMessageIntentResponseCodeReady;\n    for(INPerson *person in intent.recipients) {\n        if(![person.customIdentifier hasPrefix:@\"irccloud://\"]) {\n            code = INSendMessageIntentResponseCodeFailure;\n        }\n    }\n    completion([[INSendMessageIntentResponse alloc] initWithCode:code userActivity:nil]);\n}\n\n-(void)handleSendMessage:(INSendMessageIntent *)intent completion:(void (^)(INSendMessageIntentResponse * _Nonnull))completion {\n    NSLog(@\"Send intent: %@\", intent);\n    __block int code = INSendMessageIntentResponseCodeSuccess;\n    __block int responseCount = 0;\n\n    if(@available(iOS 14.0, *)) {\n        if(intent.attachments.count) {\n            NSMutableArray *to = [[NSMutableArray alloc] init];\n            for(INPerson *person in intent.recipients) {\n                NSString *ident = [person.customIdentifier substringFromIndex:11];\n                NSUInteger sep = [ident rangeOfString:@\"/\"].location;\n                [to addObject:@{@\"cid\":@([ident substringToIndex:sep].intValue), @\"to\":[ident substringFromIndex:sep + 1]}];\n            }\n            _completion = completion;\n            \n            INSendMessageAttachment *attachment = intent.attachments.firstObject;\n            INFile *file = attachment.audioMessageFile ? attachment.audioMessageFile : attachment.file;\n            if(file && file.data && file.data.length) {\n                _fileUploader = [[FileUploader alloc] init];\n                _fileUploader.delegate = self;\n                _fileUploader.to = to;\n                [_fileUploader setFilename:file.filename message:intent.content];\n                [_fileUploader uploadFile:file.filename UTI:CFBridgingRelease(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef _Nonnull)(file.typeIdentifier), kUTTagClassMIMEType)) data:file.data];\n            } else {\n                _completion([[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeFailure userActivity:nil]);\n            }\n            return;\n        }\n    }\n    \n    for(INPerson *person in intent.recipients) {\n        NSString *ident = [person.customIdentifier substringFromIndex:11];\n        NSUInteger sep = [ident rangeOfString:@\"/\"].location;\n        int cid = [ident substringToIndex:sep].intValue;\n        NSString *to = [ident substringFromIndex:sep + 1];\n\n        [[NetworkConnection sharedInstance] POSTsay:intent.content to:to cid:cid handler:^(IRCCloudJSONObject *result) {\n            if(![[result objectForKey:@\"success\"] boolValue]) {\n                CLS_LOG(@\"Message failed to send: %@\", result);\n                code = INSendMessageIntentResponseCodeFailure;\n            }\n            \n            if(++responseCount == intent.recipients.count)\n                completion([[INSendMessageIntentResponse alloc] initWithCode:code userActivity:nil]);\n        }];\n    }\n}\n\n- (void)fileUploadDidFail:(NSString *)reason {\n    NSLog(@\"File upload failed: %@\", reason);\n    _completion([[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeFailure userActivity:nil]);\n}\n\n- (void)fileUploadDidFinish {\n    NSLog(@\"File upload finished\");\n    _completion([[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeSuccess userActivity:nil]);\n}\n\n- (void)fileUploadProgress:(float)progress {\n}\n\n- (void)fileUploadTooLarge {\n    _completion([[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeFailure userActivity:nil]);\n}\n\n- (void)fileUploadWasCancelled {\n    _completion([[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeFailure userActivity:nil]);\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ServerReorderViewController.h",
    "content": "//\n//  ServerReorderViewController.h\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n\n@interface ServerReorderViewController : UITableViewController {\n    NSMutableArray *servers;\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ServerReorderViewController.m",
    "content": "//\n//  ServerReorderViewController.m\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import \"ServerReorderViewController.h\"\n#import \"ServersDataSource.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"NetworkConnection.h\"\n#import \"FontAwesome.h\"\n\n@interface ReorderCell : UITableViewCell {\n    UILabel *_icon;\n}\n@property (readonly) UILabel *icon;\n@end\n\nUIImage *__tintedReorderImage = nil;\n\n@implementation ReorderCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if(self) {\n        self->_icon = [[UILabel alloc] initWithFrame:CGRectMake(0,14,16,16)];\n        self->_icon.textColor = [UITableViewCell appearance].textLabelColor;\n        self->_icon.textAlignment = NSTextAlignmentCenter;\n        self->_icon.font = [UIFont fontWithName:@\"FontAwesome\" size:self.textLabel.font.pointSize];\n        [self.contentView addSubview:self->_icon];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n    [super layoutSubviews];\n    CGRect frame = self.contentView.bounds;\n    frame.origin.x = 10;\n    frame.size.width -= 20;\n    self.contentView.frame = frame;\n    self.textLabel.frame = CGRectMake(frame.origin.x + 16,0,frame.size.width - 22,frame.size.height);\n}\n\n- (void)setEditing:(BOOL)editing animated:(BOOL)animated {\n    [super setEditing:editing animated:animated];\n    \n    for(UIView *v in self.subviews) {\n        if([v isKindOfClass:NSClassFromString(@\"UITableViewCellReorderControl\")]) {\n            for(UIView *v1 in v.subviews) {\n                if([v1 isKindOfClass:UIImageView.class]) {\n                    UIImageView *iv = (UIImageView *)v1;\n                    if(__tintedReorderImage == nil) {\n                        __tintedReorderImage = [iv.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];\n                    }\n                    iv.image = __tintedReorderImage;\n                    iv.tintColor = [UIColor bufferTextColor];\n                }\n            }\n        }\n    }\n}\n@end\n\n@implementation ServerReorderViewController\n\n- (id)initWithStyle:(UITableViewStyle)style {\n    self = [super initWithStyle:style];\n    if (self) {\n        self.navigationItem.title = @\"Connections\";\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)];\n    }\n    return self;\n}\n\n-(void)dealloc {\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n- (void)doneButtonPressed:(id)sender {\n    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.tableView.separatorColor = [UIColor clearColor];\n    self.tableView.editing = YES;\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refresh) name:kIRCCloudBacklogCompletedNotification object:nil];\n    [self refresh];\n}\n\n-(void)refresh {\n    servers = [[ServersDataSource sharedInstance] getServers].mutableCopy;\n    [self.tableView reloadData];\n}\n\n- (void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    switch(event) {\n        case kIRCEventMakeServer:\n        case kIRCEventReorderConnections:\n        case kIRCEventConnectionDeleted:\n            [self refresh];\n            break;\n        default:\n            break;\n    }\n}\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return [servers count];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    ReorderCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"reordercell\"];\n    if(!cell)\n        cell = [[ReorderCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"reordercell\"];\n\n    Server *s = [servers objectAtIndex:indexPath.row];\n    \n    if(s.name.length)\n        cell.textLabel.text = s.name;\n    else\n        cell.textLabel.text = s.hostname;\n    \n    cell.icon.text = (s.ssl > 0)?FA_SHIELD:FA_GLOBE;\n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    return cell;\n}\n\n- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {\n    Server *s = [servers objectAtIndex:fromIndexPath.row];\n    [servers removeObjectAtIndex:fromIndexPath.row];\n    if (toIndexPath.row >= servers.count) {\n        [servers addObject:s];\n    } else {\n        [servers insertObject:s atIndex:toIndexPath.row];\n    }\n    \n    NSString *cids = @\"\";\n    for(int i = 0; i < servers.count; i++) {\n        s = [servers objectAtIndex:i];\n        s.order = i + 1;\n        if(cids.length)\n            cids = [cids stringByAppendingString:@\",\"];\n        cids = [cids stringByAppendingFormat:@\"%i\", s.cid];\n    }\n    [[NetworkConnection sharedInstance] reorderConnections:cids handler:^(IRCCloudJSONObject *result) {\n        if(![[result objectForKey:@\"success\"] boolValue]) {\n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:[NSString stringWithFormat:@\"Unable to reorder connections: %@. Please try again shortly.\", [result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:nil]];\n            [self presentViewController:alert animated:YES completion:nil];\n        }\n    }];\n}\n\n- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {\n    return UITableViewCellEditingStyleNone;\n}\n\n/*\n// Override to support conditional rearranging of the table view.\n- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    // Return NO if you do not want the item to be re-orderable.\n    return YES;\n}\n*/\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ServersDataSource.h",
    "content": "//\n//  ServersDataSource.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import \"Ignore.h\"\n\n@interface Server : NSObject<NSSecureCoding> {\n    int _cid;\n    NSString *_name;\n    NSString *_hostname;\n    NSString *_ircserver;\n    int _port;\n    NSString *_nick;\n    NSString *_from;\n    NSString *_status;\n    int _ssl;\n    NSString *_realname;\n    NSString *_server_pass;\n    NSString *_server_realname;\n    NSString *_nickserv_pass;\n    NSString *_join_commands;\n    NSDictionary *_fail_info;\n    NSString *_away;\n    NSString *_usermask;\n    NSString *_mode;\n    NSMutableDictionary *_isupport;\n    NSArray *_ignores;\n    NSString *_CHANTYPES;\n    NSDictionary *_PREFIX;\n    int _order;\n    NSString *_MODE_OPER, *_MODE_OWNER, *_MODE_ADMIN, *_MODE_OP, *_MODE_HALFOP, *_MODE_VOICED;\n    int _deferred_archives;\n    Ignore *_ignore;\n    int _orgId;\n    NSString *_avatar;\n    NSString *_avatarURL;\n    int _avatars_supported;\n    int _slack;\n    NSArray *_caps;\n    NSString *_account;\n    NSMutableDictionary *_collapsed;\n    BOOL _blocksEdits;\n    BOOL _blocksReplies;\n    BOOL _blocksReactions;\n    BOOL _blocksDeletes;\n    BOOL _blocksTyping;\n}\n@property (assign) int cid, port, ssl, order, deferred_archives, orgId, avatars_supported, slack;\n@property (copy) NSString *name, *hostname, *nick, *status, *realname, *server_pass, *nickserv_pass, *join_commands, *away, *usermask, *mode, *CHANTYPES, *MODE_OPER, *MODE_OWNER, *MODE_ADMIN, *MODE_OP, *MODE_HALFOP, *MODE_VOICED, *server_realname, *ircserver, *avatar, *avatarURL, *from, *account;\n@property (copy) NSDictionary *fail_info, *PREFIX;\n@property (copy) NSDictionary *isupport;\n@property (copy) NSArray *caps;\n@property (strong) NSMutableDictionary *collapsed;\n@property (readonly) Ignore *ignore;\n@property (assign) BOOL blocksEdits, blocksReplies, blocksReactions, blocksDeletes, blocksTyping;\n-(NSComparisonResult)compare:(Server *)aServer;\n-(NSArray *)ignores;\n-(void)setIgnores:(NSArray *)ignores;\n-(BOOL)isSlack;\n-(NSString *)slackBaseURL;\n-(BOOL)clientTagDeny:(NSString *)tagName;\n-(BOOL)hasMessageTags;\n-(BOOL)hasLabels;\n-(BOOL)hasRedaction;\n@end\n\n@interface ServersDataSource : NSObject {\n    NSMutableArray *_servers;\n}\n+(ServersDataSource *)sharedInstance;\n-(void)serialize;\n-(void)clear;\n-(void)addServer:(Server *)server;\n-(NSArray *)getServers;\n-(Server *)getServer:(int)cid;\n-(Server *)getServer:(NSString *)hostname port:(int)port;\n-(Server *)getServer:(NSString *)hostname SSL:(BOOL)ssl;\n-(void)removeServer:(int)cid;\n-(void)removeAllDataForServer:(int)cid;\n-(NSUInteger)count;\n-(void)updateNick:(NSString *)nick server:(int)cid;\n-(void)updateStatus:(NSString *)status failInfo:(NSDictionary *)failInfo server:(int)cid;\n-(void)updateAway:(NSString *)away server:(int)cid;\n-(void)updateUsermask:(NSString *)usermask server:(int)cid;\n-(void)updateMode:(NSString *)mode server:(int)cid;\n-(void)updateIsupport:(NSDictionary *)isupport server:(int)cid;\n-(void)updateIgnores:(NSArray *)ignores server:(int)cid;\n-(void)updateUserModes:(NSString *)modes server:(int)cid;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/ServersDataSource.m",
    "content": "//\n//  ServersDataSource.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import \"ServersDataSource.h\"\n#import \"BuffersDataSource.h\"\n#import \"ChannelsDataSource.h\"\n#import \"UsersDataSource.h\"\n#import \"EventsDataSource.h\"\n\n@implementation Server\n+ (BOOL)supportsSecureCoding {\n    return YES;\n}\n\n-(id)init {\n    self = [super init];\n    if(self) {\n        self->_MODE_OPER = @\"Y\";\n        self->_MODE_OWNER = @\"q\";\n        self->_MODE_ADMIN = @\"a\";\n        self->_MODE_OP = @\"o\";\n        self->_MODE_HALFOP = @\"h\";\n        self->_MODE_VOICED = @\"v\";\n        self->_ignore = [[Ignore alloc] init];\n    }\n    return self;\n}\n-(NSComparisonResult)compare:(Server *)aServer {\n    if(aServer.order > _order)\n        return NSOrderedAscending;\n    else if(aServer.order < _order)\n        return NSOrderedDescending;\n    else if(aServer.cid > _cid)\n        return NSOrderedAscending;\n    else if(aServer.cid < _cid)\n        return NSOrderedDescending;\n    else\n        return NSOrderedSame;\n}\n-(NSString *)description {\n    return [NSString stringWithFormat:@\"{cid: %i, name: %@, hostname: %@, port: %i}\", _cid, _name, _hostname, _port];\n}\n-(void)encodeWithCoder:(NSCoder *)aCoder {\n    encodeInt(self->_cid);\n    encodeObject(self->_name);\n    encodeObject(self->_hostname);\n    encodeInt(self->_port);\n    encodeObject(self->_nick);\n    encodeObject(self->_status);\n    encodeInt(self->_ssl);\n    encodeObject(self->_realname);\n    encodeObject(self->_join_commands);\n    encodeObject(self->_fail_info);\n    encodeObject(self->_away);\n    encodeObject(self->_usermask);\n    encodeObject(self->_mode);\n    encodeObject(self->_isupport);\n    encodeObject(self->_ignores);\n    encodeObject(self->_CHANTYPES);\n    encodeObject(self->_PREFIX);\n    encodeInt(self->_order);\n    encodeObject(self->_MODE_OPER);\n    encodeObject(self->_MODE_OWNER);\n    encodeObject(self->_MODE_ADMIN);\n    encodeObject(self->_MODE_OP);\n    encodeObject(self->_MODE_HALFOP);\n    encodeObject(self->_MODE_VOICED);\n    encodeObject(self->_ircserver);\n    encodeInt(self->_orgId);\n    encodeObject(self->_avatar);\n    encodeInt(self->_avatars_supported);\n    encodeObject(self->_account);\n}\n-(id)initWithCoder:(NSCoder *)aDecoder {\n    self = [super init];\n    if(self) {\n        decodeInt(self->_cid);\n        decodeObjectOfClass(NSString.class, self->_name);\n        decodeObjectOfClass(NSString.class, self->_hostname);\n        decodeInt(self->_port);\n        decodeObjectOfClass(NSString.class, self->_nick);\n        decodeObjectOfClass(NSString.class, self->_status);\n        decodeInt(self->_ssl);\n        decodeObjectOfClass(NSString.class, self->_realname);\n        decodeObjectOfClass(NSString.class, self->_join_commands);\n        NSSet *set = [NSSet setWithObjects:NSDictionary.class, NSArray.class, NSMutableArray.class, NSString.class, NSNumber.class, NSNull.class, nil];\n        decodeObjectOfClasses(set, self->_fail_info);\n        decodeObjectOfClass(NSString.class, self->_away);\n        decodeObjectOfClass(NSString.class, self->_usermask);\n        decodeObjectOfClass(NSString.class, self->_mode);\n        set = [NSSet setWithObjects:NSDictionary.class, NSArray.class, NSMutableArray.class, NSString.class, NSNumber.class, NSNull.class, nil];\n        decodeObjectOfClasses(set, self->_isupport);\n        self->_isupport = self->_isupport.mutableCopy;\n        [NSSet setWithObjects:NSArray.class, NSMutableArray.class, NSString.class, nil];\n        decodeObjectOfClasses(set, self->_ignores);\n        decodeObjectOfClass(NSString.class, self->_CHANTYPES);\n        set = [NSSet setWithObjects:NSDictionary.class, NSArray.class, NSMutableArray.class, NSString.class, NSNumber.class, NSNull.class, nil];\n        decodeObjectOfClasses(set, self->_PREFIX);\n        decodeInt(self->_order);\n        decodeObjectOfClass(NSString.class, self->_MODE_OPER);\n        decodeObjectOfClass(NSString.class, self->_MODE_OWNER);\n        decodeObjectOfClass(NSString.class, self->_MODE_ADMIN);\n        decodeObjectOfClass(NSString.class, self->_MODE_OP);\n        decodeObjectOfClass(NSString.class, self->_MODE_HALFOP);\n        decodeObjectOfClass(NSString.class, self->_MODE_VOICED);\n        decodeObjectOfClass(NSString.class, self->_ircserver);\n        decodeInt(self->_orgId);\n        decodeObjectOfClass(NSString.class, self->_avatar);\n        decodeInt(self->_avatars_supported);\n        decodeObjectOfClass(NSString.class, self->_account);\n        self->_ignore = [[Ignore alloc] init];\n        [self->_ignore setIgnores:self->_ignores];\n    }\n    return self;\n}\n-(NSArray *)ignores {\n    return _ignores;\n}\n-(void)setIgnores:(NSArray *)ignores {\n    self->_ignores = ignores;\n    [self->_ignore setIgnores:self->_ignores];\n}\n\n-(BOOL)isSlack {\n    return _slack || [self->_hostname hasSuffix:@\".slack.com\"] || [self->_ircserver hasSuffix:@\".slack.com\"];\n}\n\n-(NSString *)slackBaseURL {\n    NSString *host = self->_hostname;\n    if(![host hasSuffix:@\".slack.com\"])\n        host = self->_ircserver;\n    if([host hasSuffix:@\".slack.com\"])\n        return [NSString stringWithFormat:@\"https://%@\", host];\n    return nil;\n}\n\n-(BOOL)clientTagDeny:(NSString *)tagName {\n    if([[self->_isupport objectForKey:@\"CLIENTTAGDENY\"] isKindOfClass:[NSString class]]) {\n        BOOL denied = NO;\n        NSArray *tags = [[self->_isupport objectForKey:@\"CLIENTTAGDENY\"] componentsSeparatedByString:@\",\"];\n        for(NSString *tag in tags) {\n            if([tag isEqualToString:@\"*\"] || [tag isEqualToString:tagName])\n                denied = YES;\n            if([tag isEqualToString:[NSString stringWithFormat:@\"-%@\", tagName]])\n                denied = NO;\n        }\n        return denied;\n    }\n    return NO;\n}\n\n-(BOOL)hasMessageTags {\n    return [self->_caps containsObject:@\"message-tags\"];\n}\n\n-(BOOL)hasRedaction {\n    return [self->_caps containsObject:@\"draft/message-redaction\"];\n}\n\n-(BOOL)hasLabels {\n    return [self->_caps containsObject:@\"labeled-response\"] ||  [self->_caps containsObject:@\"draft/labeled-response\"] ||  [self->_caps containsObject:@\"draft/labeled-response-0.2\"];\n}\n\n@end\n\n@implementation ServersDataSource\n+(ServersDataSource *)sharedInstance {\n    static ServersDataSource *sharedInstance;\n\t\n    @synchronized(self) {\n        if(!sharedInstance)\n            sharedInstance = [[ServersDataSource alloc] init];\n\t\t\n        return sharedInstance;\n    }\n\treturn nil;\n}\n\n-(id)init {\n    self = [super init];\n    if(self) {\n        [NSKeyedArchiver setClassName:@\"IRCCloud.Server\" forClass:Server.class];\n        [NSKeyedUnarchiver setClass:Server.class forClassName:@\"IRCCloud.Server\"];\n\n        if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"cacheVersion\"] isEqualToString:[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleVersion\"]]) {\n            NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"servers\"];\n            \n            @try {\n                NSError* error = nil;\n                self->_servers = [[NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:NSDictionary.class, NSArray.class, Server.class,NSString.class,NSNumber.class, nil] fromData:[NSData dataWithContentsOfFile:cacheFile] error:&error] mutableCopy];\n                if(error)\n                    @throw [NSException exceptionWithName:@\"NSError\" reason:error.debugDescription userInfo:@{ @\"NSError\" : error }];\n            } @catch(NSException *e) {\n                CLS_LOG(@\"Exception: %@\", e);\n                [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n                [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"cacheVersion\"];\n                [[BuffersDataSource sharedInstance] clear];\n                [[ChannelsDataSource sharedInstance] clear];\n                [[EventsDataSource sharedInstance] clear];\n                [[UsersDataSource sharedInstance] clear];\n            }\n        }\n        if(!_servers)\n            self->_servers = [[NSMutableArray alloc] init];\n    }\n    return self;\n}\n\n-(void)serialize {\n    NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"servers\"];\n    \n    NSArray *servers;\n    @synchronized(self->_servers) {\n        servers = [self->_servers copy];\n    }\n    \n    @synchronized(self) {\n        @try {\n            NSError* error = nil;\n            [[NSKeyedArchiver archivedDataWithRootObject:servers requiringSecureCoding:YES error:&error] writeToFile:cacheFile atomically:YES];\n            if(error)\n                CLS_LOG(@\"Error archiving: %@\", error);\n            [[NSURL fileURLWithPath:cacheFile] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL];\n        }\n        @catch (NSException *exception) {\n            [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n        }\n    }\n}\n\n-(void)clear {\n    @synchronized(self->_servers) {\n        [self->_servers removeAllObjects];\n    }\n}\n\n-(void)addServer:(Server *)server {\n    @synchronized(self->_servers) {\n        [self->_servers addObject:server];\n    }\n}\n\n-(NSArray *)getServers {\n    @synchronized(self->_servers) {\n        return [self->_servers sortedArrayUsingSelector:@selector(compare:)];\n    }\n}\n\n-(Server *)getServer:(int)cid {\n    NSArray *copy;\n    @synchronized(self->_servers) {\n        copy = self->_servers.copy;\n    }\n    for(Server *server in copy) {\n        if(server.cid == cid)\n            return server;\n    }\n    return nil;\n}\n\n-(Server *)getServer:(NSString *)hostname port:(int)port {\n    NSArray *copy;\n    @synchronized(self->_servers) {\n        copy = self->_servers.copy;\n    }\n    for(Server *server in copy) {\n        if([server.hostname isEqualToString:hostname] && (port == -1 || server.port == port))\n            return server;\n    }\n    return nil;\n}\n\n-(Server *)getServer:(NSString *)hostname SSL:(BOOL)ssl {\n    NSArray *copy;\n    @synchronized(self->_servers) {\n        copy = self->_servers.copy;\n    }\n    for(Server *server in copy) {\n        if([server.hostname isEqualToString:hostname] && ((ssl == YES && server.ssl > 0) || (ssl == NO && server.ssl == 0)))\n            return server;\n    }\n    return nil;\n}\n\n-(void)removeServer:(int)cid {\n    @synchronized(self->_servers) {\n        Server *server = [self getServer:cid];\n        if(server)\n            [self->_servers removeObject:server];\n    }\n}\n\n-(void)removeAllDataForServer:(int)cid {\n    Server *server = [self getServer:cid];\n    if(server) {\n        for(Buffer *b in [[BuffersDataSource sharedInstance] getBuffersForServer:cid]) {\n            [[BuffersDataSource sharedInstance] removeAllDataForBuffer:b.bid];\n        }\n        @synchronized(self->_servers) {\n            [self->_servers removeObject:server];\n        }\n    }\n}\n\n-(NSUInteger)count {\n    @synchronized(self->_servers) {\n        return _servers.count;\n    }\n}\n\n-(void)updateNick:(NSString *)nick server:(int)cid {\n    Server *server = [self getServer:cid];\n    if(server)\n        server.nick = nick;\n}\n\n-(void)updateStatus:(NSString *)status failInfo:(NSDictionary *)failInfo server:(int)cid {\n    Server *server = [self getServer:cid];\n    if(server) {\n        server.status = status;\n        server.fail_info = failInfo;\n    }\n}\n\n-(void)updateAway:(NSString *)away server:(int)cid {\n    Server *server = [self getServer:cid];\n    if(server)\n        server.away = away;\n}\n\n-(void)updateUsermask:(NSString *)usermask server:(int)cid {\n    Server *server = [self getServer:cid];\n    if(server)\n        server.usermask = usermask;\n}\n\n-(void)updateMode:(NSString *)mode server:(int)cid {\n    Server *server = [self getServer:cid];\n    if(server)\n        server.mode = mode;\n}\n\n-(void)updateIsupport:(NSDictionary *)isupport server:(int)cid {\n    Server *server = [self getServer:cid];\n    if(server) {\n        if([isupport isKindOfClass:[NSDictionary class]]) {\n            NSMutableDictionary *d = [[NSMutableDictionary alloc] initWithDictionary:server.isupport];\n            [d addEntriesFromDictionary:isupport];\n            server.isupport = d;\n        } else {\n            server.isupport = [[NSMutableDictionary alloc] init];\n        }\n\n        if([[server.isupport objectForKey:@\"PREFIX\"] isKindOfClass:[NSDictionary class]])\n            server.PREFIX = [server.isupport objectForKey:@\"PREFIX\"];\n        else\n            server.PREFIX = nil;\n        if([[server.isupport objectForKey:@\"CHANTYPES\"] isKindOfClass:[NSString class]])\n            server.CHANTYPES = [server.isupport objectForKey:@\"CHANTYPES\"];\n        else\n            server.CHANTYPES = nil;\n        \n        for(Buffer *b in [[BuffersDataSource sharedInstance] getBuffersForServer:cid]) {\n            b.chantypes = server.CHANTYPES;\n        }\n        \n        server.blocksTyping = [server clientTagDeny:@\"typing\"];\n        server.blocksReplies = [server clientTagDeny:@\"reply\"] && [server clientTagDeny:@\"draft/reply\"];\n        server.blocksReactions = server.blocksReplies || [server clientTagDeny:@\"draft/react\"];\n        server.blocksEdits = [server clientTagDeny:@\"draft/edit\"] || [server clientTagDeny:@\"draft/edit-text\"];\n        server.blocksDeletes = [server clientTagDeny:@\"draft/delete\"];\n    }\n}\n\n-(void)updateIgnores:(NSArray *)ignores server:(int)cid {\n    Server *server = [self getServer:cid];\n    if(server)\n        server.ignores = ignores;\n}\n\n-(void)updateUserModes:(NSString *)modes server:(int)cid {\n    if([modes isKindOfClass:[NSString class]] && modes.length) {\n        Server *server = [self getServer:cid];\n        if(server) {\n            if([[modes.lowercaseString substringToIndex:1] isEqualToString:[server.isupport objectForKey:@\"OWNER\"]]) {\n                server.MODE_OWNER = [modes substringToIndex:1];\n                if([server.MODE_OWNER.lowercaseString isEqualToString:server.MODE_OPER.lowercaseString])\n                    server.MODE_OPER = @\"\";\n            }\n        }\n    }\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/SettingsViewController.h",
    "content": "//\n//  SettingsViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n\n@interface FontSizeCell : UITableViewCell {\n    UILabel *_small;\n    UILabel *_large;\n    UILabel *_fontSample;\n    UISlider *_fontSize;\n}\n@property (readonly) UILabel *fontSample;\n-(void)setFontSize:(UISlider *)fontSize;\n@end\n\n@interface SettingsViewController : UITableViewController<UITextFieldDelegate,UITextViewDelegate> {\n    UITextField *_email;\n    UITextField *_name;\n    UITextView *_highlights;\n    UISwitch *_autoaway;\n    UISwitch *_24hour;\n    UISwitch *_seconds;\n    UISwitch *_symbols;\n    UISwitch *_colors;\n    UISwitch *_screen;\n    UISwitch *_autoCaps;\n    UISwitch *_emocodes;\n    UISwitch *_saveToCameraRoll;\n    UISwitch *_notificationSound;\n    UISwitch *_tabletMode;\n    UISwitch *_pastebin;\n    UISwitch *_mono;\n    UISwitch *_hideJoinPart;\n    UISwitch *_expandJoinPart;\n    UISwitch *_notifyAll;\n    UISwitch *_showUnread;\n    UISwitch *_markAsRead;\n    UISwitch *_oneLine;\n    UISwitch *_noRealName;\n    UISwitch *_timeLeft;\n    UISwitch *_avatarsOff;\n    UISwitch *_browserWarning;\n    UISwitch *_compact;\n    UISwitch *_imageViewer;\n    UISwitch *_videoViewer;\n    UISwitch *_disableInlineFiles;\n    UISwitch *_disableBigEmoji;\n    UISwitch *_inlineWifiOnly;\n    UISwitch *_defaultSound;\n    UISwitch *_notificationPreviews;\n    UISwitch *_thirdPartyNotificationPreviews;\n    UISwitch *_disableCodeSpan;\n    UISwitch *_disableCodeBlock;\n    UISwitch *_disableQuote;\n    UISwitch *_inlineImages;\n    UISwitch *_clearFormattingAfterSending;\n    UISwitch *_avatarImages;\n    UISwitch *_colorizeMentions;\n    UISwitch *_hiddenMembers;\n    UISwitch *_muteNotifications;\n    UISwitch *_noColor;\n    UISwitch *_disableTypingStatus;\n    UISwitch *_showDeleted;\n    NSString *_version;\n    UISlider *_fontSize;\n    NSString *_oldTheme;\n    NSArray *_data;\n    FontSizeCell *_fontSizeCell;\n}\n@property BOOL scrollToNotifications;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/SettingsViewController.m",
    "content": "//\n//  SettingsViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <SafariServices/SafariServices.h>\n#import \"SettingsViewController.h\"\n#import \"NetworkConnection.h\"\n#import \"LicenseViewController.h\"\n#import \"AppDelegate.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"OpenInChromeController.h\"\n#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n#import \"ColorFormatter.h\"\n#import \"OpenInChromeController.h\"\n#import \"OpenInFirefoxControllerObjC.h\"\n#import \"AvatarsDataSource.h\"\n#import \"AvatarsTableViewController.h\"\n@import Firebase;\n\n@interface BrowserViewController : UITableViewController {\n    NSMutableArray *_browsers;\n}\n@end\n\n@implementation BrowserViewController\n\n-(id)init {\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        self.navigationItem.title = @\"Browser\";\n        self->_browsers = [[NSMutableArray alloc] init];\n        if([SFSafariViewController class] && !((AppDelegate *)([UIApplication sharedApplication].delegate)).isOnVisionOS)\n            [self->_browsers addObject:@\"IRCCloud\"];\n        [self->_browsers addObject:@\"Safari\"];\n        if([[OpenInChromeController sharedInstance] isChromeInstalled])\n            [self->_browsers addObject:@\"Chrome\"];\n        if([[OpenInFirefoxControllerObjC sharedInstance] isFirefoxInstalled])\n            [self->_browsers addObject:@\"Firefox\"];\n    }\n    return self;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return _browsers.count;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"browserservicecell\"];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"browserservicecell\"];\n    \n    cell.textLabel.text = [self->_browsers objectAtIndex:indexPath.row];\n    cell.accessoryType = [[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:[self->_browsers objectAtIndex:indexPath.row]]?UITableViewCellAccessoryCheckmark:UITableViewCellAccessoryNone;\n    \n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    \n    [[NSUserDefaults standardUserDefaults] setObject:[self->_browsers objectAtIndex:indexPath.row] forKey:@\"browser\"];\n    [[NSUserDefaults standardUserDefaults] synchronize];\n    [tableView reloadData];\n    [self.navigationController popViewControllerAnimated:YES];\n}\n\n@end\n\n@implementation FontSizeCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        \n        self->_small = [[UILabel alloc] init];\n        self->_small.font = [UIFont boldSystemFontOfSize:FONT_MIN];\n        self->_small.lineBreakMode = NSLineBreakByCharWrapping;\n        self->_small.textAlignment = NSTextAlignmentCenter;\n        self->_small.numberOfLines = 0;\n        self->_small.text = @\"Aa\";\n        self->_small.textColor = [[UITableViewCell appearance] textLabelColor];\n        [self.contentView addSubview:self->_small];\n        \n        self->_large = [[UILabel alloc] init];\n        self->_large.font = [UIFont systemFontOfSize:FONT_MAX];\n        self->_large.lineBreakMode = NSLineBreakByCharWrapping;\n        self->_large.textAlignment = NSTextAlignmentCenter;\n        self->_large.numberOfLines = 0;\n        self->_large.text = @\"Aa\";\n        self->_large.textColor = [[UITableViewCell appearance] textLabelColor];\n        [self.contentView addSubview:self->_large];\n        \n        self->_fontSample = [[UILabel alloc] initWithFrame:CGRectZero];\n        self->_fontSample.textAlignment = NSTextAlignmentCenter;\n        self->_fontSample.text = @\"Example\";\n        [self.contentView addSubview:self->_fontSample];\n    }\n    return self;\n}\n\n-(void)setFontSize:(UISlider *)fontSize {\n    [self->_fontSize removeFromSuperview];\n    self->_fontSize = fontSize;\n    \n    [self.contentView addSubview:self->_fontSize];\n}\n\n-(void)layoutSubviews {\n    [super layoutSubviews];\n    \n    CGRect frame = CGRectInset([self.contentView bounds], 6, 6);\n    \n    self->_small.frame = CGRectMake(frame.origin.x, frame.origin.y, 32, frame.size.height/2);\n    self->_large.frame = CGRectMake(frame.origin.x + frame.size.width - 32, frame.origin.y, 32, frame.size.height/2);\n    [self->_fontSize sizeToFit];\n    self->_fontSize.frame = CGRectMake(frame.origin.x + 32, 0, frame.size.width - 64 - frame.origin.x, _fontSize.frame.size.height/2);\n    CGPoint p = self->_fontSize.center;\n    p.y = self.contentView.center.y/2;\n    self->_fontSize.center = p;\n    self->_fontSample.frame = CGRectMake(frame.origin.x, frame.origin.y + frame.size.height / 2, frame.size.width, frame.size.height / 2);\n}\n\n-(void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n@end\n\n@interface PhotoSizeViewController : UITableViewController\n@end\n\n@implementation PhotoSizeViewController\n\n-(id)init {\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        self.navigationItem.title = @\"Photo Size\";\n    }\n    return self;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return 4;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"photosizecell\"];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"photosizecell\"];\n    \n    cell.accessoryType = UITableViewCellAccessoryNone;\n    \n    switch(indexPath.row) {\n        case 0:\n            cell.textLabel.text = @\"Small\";\n            if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"photoSize\"] intValue] == 512)\n                cell.accessoryType = UITableViewCellAccessoryCheckmark;\n            break;\n        case 1:\n            cell.textLabel.text = @\"Medium\";\n            if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"photoSize\"] intValue] == 1024)\n                cell.accessoryType = UITableViewCellAccessoryCheckmark;\n            break;\n        case 2:\n            cell.textLabel.text = @\"Large\";\n            if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"photoSize\"] intValue] == 2048)\n                cell.accessoryType = UITableViewCellAccessoryCheckmark;\n            break;\n        case 3:\n            cell.textLabel.text = @\"Original\";\n            if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"photoSize\"] intValue] == -1)\n                cell.accessoryType = UITableViewCellAccessoryCheckmark;\n            break;\n    }\n    \n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    switch(indexPath.row) {\n        case 0:\n            [[NSUserDefaults standardUserDefaults] setObject:@(512) forKey:@\"photoSize\"];\n            break;\n        case 1:\n            [[NSUserDefaults standardUserDefaults] setObject:@(1024) forKey:@\"photoSize\"];\n            break;\n        case 2:\n            [[NSUserDefaults standardUserDefaults] setObject:@(2048) forKey:@\"photoSize\"];\n            break;\n        case 3:\n            [[NSUserDefaults standardUserDefaults] setObject:@(-1) forKey:@\"photoSize\"];\n            break;\n    }\n    [[NSUserDefaults standardUserDefaults] synchronize];\n    [tableView reloadData];\n    [self.navigationController popViewControllerAnimated:YES];\n}\n\n@end\n\n@interface ThemesViewController : UITableViewController {\n    NSArray *_themes;\n    NSArray *_themePreviews;\n}\n@end\n\n@implementation ThemesViewController\n\n-(id)init {\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if (self) {\n        self.navigationItem.title = @\"Theme\";\n        if (@available(iOS 13, *)) {\n            self->_themes = @[@\"Automatic\", @\"Dawn\", @\"Dusk\", @\"Tropic\", @\"Emerald\", @\"Sand\", @\"Rust\", @\"Orchid\", @\"Ash\", @\"Midnight\"];\n        } else {\n            self->_themes = @[@\"Dawn\", @\"Dusk\", @\"Tropic\", @\"Emerald\", @\"Sand\", @\"Rust\", @\"Orchid\", @\"Ash\", @\"Midnight\"];\n        }\n\n        NSMutableArray *previews = [[NSMutableArray alloc] init];\n        \n        if (@available(iOS 13, *)) {\n            UIView *v = [[UIView alloc] initWithFrame:CGRectZero];\n            if([UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark) {\n                v.backgroundColor = [UIColor blackColor];\n            } else {\n                v.backgroundColor = [UIColor colorWithRed:0.851 green:0.906 blue:1 alpha:1];\n            }\n            v.layer.borderColor = [UIColor blackColor].CGColor;\n            v.layer.borderWidth = 1.0f;\n            [previews addObject:v];\n        }\n        \n        UIView *v = [[UIView alloc] initWithFrame:CGRectZero];\n        v.backgroundColor = [UIColor colorWithRed:0.851 green:0.906 blue:1 alpha:1];\n        v.layer.borderColor = [UIColor blackColor].CGColor;\n        v.layer.borderWidth = 1.0f;\n        [previews addObject:v];\n        \n        v = [[UIView alloc] initWithFrame:CGRectZero];\n        v.backgroundColor = [UIColor colorWithRed:0 green:0.4 blue:0.8 alpha:1];\n        v.layer.borderColor = [UIColor blackColor].CGColor;\n        v.layer.borderWidth = 1.0f;\n        [previews addObject:v];\n        \n        v = [[UIView alloc] initWithFrame:CGRectZero];\n        v.backgroundColor = [UIColor colorWithRed:0 green:0.8 blue:0.8 alpha:1];\n        v.layer.borderColor = [UIColor blackColor].CGColor;\n        v.layer.borderWidth = 1.0f;\n        [previews addObject:v];\n        \n        v = [[UIView alloc] initWithFrame:CGRectZero];\n        v.backgroundColor = [UIColor colorWithRed:0.133 green:0.8 blue:0 alpha:1];\n        v.layer.borderColor = [UIColor blackColor].CGColor;\n        v.layer.borderWidth = 1.0f;\n        [previews addObject:v];\n        \n        v = [[UIView alloc] initWithFrame:CGRectZero];\n        v.backgroundColor = [UIColor colorWithRed:0.8 green:0.6 blue:0 alpha:1];\n        v.layer.borderColor = [UIColor blackColor].CGColor;\n        v.layer.borderWidth = 1.0f;\n        [previews addObject:v];\n        \n        v = [[UIView alloc] initWithFrame:CGRectZero];\n        v.backgroundColor = [UIColor colorWithRed:0.8 green:0 blue:0 alpha:1];\n        v.layer.borderColor = [UIColor blackColor].CGColor;\n        v.layer.borderWidth = 1.0f;\n        [previews addObject:v];\n        \n        v = [[UIView alloc] initWithFrame:CGRectZero];\n        v.backgroundColor = [UIColor colorWithRed:0.8 green:0 blue:0.612 alpha:1];\n        v.layer.borderColor = [UIColor blackColor].CGColor;\n        v.layer.borderWidth = 1.0f;\n        [previews addObject:v];\n        \n        v = [[UIView alloc] initWithFrame:CGRectZero];\n        v.backgroundColor = [UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:1];\n        v.layer.borderColor = [UIColor blackColor].CGColor;\n        v.layer.borderWidth = 1.0f;\n        [previews addObject:v];\n        \n        v = [[UIView alloc] initWithFrame:CGRectZero];\n        v.backgroundColor = [UIColor blackColor];\n        v.layer.borderColor = [UIColor blackColor].CGColor;\n        v.layer.borderWidth = 1.0f;\n        [previews addObject:v];\n        \n        self->_themePreviews = previews;\n        \n        self.tableView.separatorInset = UIEdgeInsetsMake(0, 40, 0, 0);\n    }\n    return self;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return _themes.count;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"themecell\"];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"themecell\"];\n\n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    cell.textLabel.text = [self->_themes objectAtIndex:indexPath.row];\n    if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"theme\"] isEqualToString:[[self->_themes objectAtIndex:indexPath.row] lowercaseString]] || (![[NSUserDefaults standardUserDefaults] objectForKey:@\"theme\"] && indexPath.row == 0))\n        cell.accessoryType = UITableViewCellAccessoryCheckmark;\n    else\n        cell.accessoryType = UITableViewCellAccessoryNone;\n    \n    UIView *v = [self->_themePreviews objectAtIndex:indexPath.row];\n    [v removeFromSuperview];\n    v.frame = CGRectMake(self.view.window.safeAreaInsets.left?-12:8,cell.contentView.frame.size.height / 2 - 12,24,24);\n    v.layer.cornerRadius = v.frame.size.width / 2;\n    [cell.contentView addSubview:v];\n    \n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [[NSUserDefaults standardUserDefaults] setObject:[[self->_themes objectAtIndex:indexPath.row] lowercaseString] forKey:@\"theme\"];\n    [[NSUserDefaults standardUserDefaults] synchronize];\n    [UIColor setTheme];\n    [[EventsDataSource sharedInstance] reformat];\n    [tableView reloadData];\n    UIView *v = self.navigationController.view.superview;\n    [self.navigationController.view removeFromSuperview];\n    [v addSubview: self.navigationController.view];\n    [self.navigationController.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    self.navigationController.view.backgroundColor = [UIColor navBarColor];\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    if (@available(iOS 13.0, *)) {\n        UINavigationBarAppearance *a = [[UINavigationBarAppearance alloc] init];\n        a.backgroundImage = [UIColor navBarBackgroundImage];\n        a.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor navBarHeadingColor]};\n        self.navigationController.navigationBar.standardAppearance = a;\n        self.navigationController.navigationBar.compactAppearance = a;\n        self.navigationController.navigationBar.scrollEdgeAppearance = a;\n        if (@available(iOS 15.0, *)) {\n#if !TARGET_OS_MACCATALYST\n            self.navigationController.navigationBar.compactScrollEdgeAppearance = a;\n#endif\n        }\n    }\n\n    [self.navigationController setNeedsStatusBarAppearanceUpdate];\n}\n@end\n\n@implementation SettingsViewController\n\n- (id)initWithStyle:(UITableViewStyle)style {\n    self = [super initWithStyle:style];\n    if (self) {\n        self.navigationItem.title = @\"Settings\";\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveButtonPressed:)];\n        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];\n        self->_oldTheme = [[NSUserDefaults standardUserDefaults] objectForKey:@\"theme\"];\n    }\n    return self;\n}\n\n-(void)saveButtonPressed:(id)sender {\n    [self.tableView endEditing:YES];\n    \n    if(sender && [NetworkConnection sharedInstance].userInfo && [[NetworkConnection sharedInstance].userInfo objectForKey:@\"email\"] && ![self->_email.text isEqualToString:[[NetworkConnection sharedInstance].userInfo objectForKey:@\"email\"]]) {\n        [self.view endEditing:YES];\n        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Change Your Email Address\" message:@\"Please enter your current password to confirm this change\" preferredStyle:UIAlertControllerStyleAlert];\n        \n        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n        [alert addAction:[UIAlertAction actionWithTitle:@\"Confirm\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n            if(((UITextField *)[alert.textFields objectAtIndex:0]).text.length) {\n                UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n                [spinny startAnimating];\n                self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinny];\n                \n                [[NetworkConnection sharedInstance] changeEmail:self->_email.text password:((UITextField *)[alert.textFields objectAtIndex:0]).text handler:^(IRCCloudJSONObject *result) {\n                    if([[result objectForKey:@\"success\"] boolValue]) {\n                        [self saveButtonPressed:nil];\n                    } else {\n                        if([[result objectForKey:@\"message\"] isEqualToString:@\"oldpassword\"]) {\n                            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Incorrect password, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                            [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                            [self presentViewController:alert animated:YES completion:nil];\n                        } else {\n                            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to save settings, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                            [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                            [self presentViewController:alert animated:YES completion:nil];\n                        }\n                    }\n                }];\n            }\n        }]];\n        \n        [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n            textField.secureTextEntry = YES;\n            textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n        }];\n        \n        [self presentViewController:alert animated:YES completion:nil];\n    } else {\n        UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n        [spinny startAnimating];\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinny];\n        NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithDictionary:[[NetworkConnection sharedInstance] prefs]];\n        \n        [prefs setObject:[NSNumber numberWithBool:self->_24hour.isOn] forKey:@\"time-24hr\"];\n        [prefs setObject:[NSNumber numberWithBool:self->_seconds.isOn] forKey:@\"time-seconds\"];\n        [prefs setObject:[NSNumber numberWithBool:self->_symbols.isOn] forKey:@\"mode-showsymbol\"];\n        [prefs setObject:[NSNumber numberWithBool:self->_colors.isOn] forKey:@\"nick-colors\"];\n        [prefs setObject:[NSNumber numberWithBool:self->_colorizeMentions.isOn] forKey:@\"mention-colors\"];\n        [prefs setObject:[NSNumber numberWithBool:!_emocodes.isOn] forKey:@\"emoji-disableconvert\"];\n        [prefs setObject:[NSNumber numberWithBool:!_pastebin.isOn] forKey:@\"pastebin-disableprompt\"];\n        if([prefs objectForKey:@\"font\"]) {\n            if(self->_mono.isOn)\n                [prefs setObject:@\"mono\" forKey:@\"font\"];\n            else if([[prefs objectForKey:@\"font\"] isEqualToString:@\"mono\"])\n                [prefs setObject:@\"sans\" forKey:@\"font\"];\n        } else {\n            [prefs setObject:self->_mono.isOn?@\"mono\":@\"sans\" forKey:@\"font\"];\n        }\n        [prefs setObject:[NSNumber numberWithBool:!_hideJoinPart.isOn] forKey:@\"hideJoinPart\"];\n        [prefs setObject:[NSNumber numberWithBool:!_expandJoinPart.isOn] forKey:@\"expandJoinPart\"];\n        [prefs setObject:[NSNumber numberWithBool:self->_notifyAll.isOn] forKey:@\"notifications-all\"];\n        [prefs setObject:[NSNumber numberWithBool:!_showUnread.isOn] forKey:@\"disableTrackUnread\"];\n        [prefs setObject:[NSNumber numberWithBool:self->_markAsRead.isOn] forKey:@\"enableReadOnSelect\"];\n        [prefs setObject:[NSNumber numberWithBool:self->_compact.isOn] forKey:@\"ascii-compact\"];\n        [prefs setObject:[NSNumber numberWithBool:!_disableInlineFiles.isOn] forKey:@\"files-disableinline\"];\n        [prefs setObject:[NSNumber numberWithBool:self->_inlineImages.isOn] forKey:@\"inlineimages\"];\n        [prefs setObject:[NSNumber numberWithBool:!_disableBigEmoji.isOn] forKey:@\"emoji-nobig\"];\n        [prefs setObject:[NSNumber numberWithBool:!_disableCodeSpan.isOn] forKey:@\"chat-nocodespan\"];\n        [prefs setObject:[NSNumber numberWithBool:!_disableCodeBlock.isOn] forKey:@\"chat-nocodeblock\"];\n        [prefs setObject:[NSNumber numberWithBool:!_disableQuote.isOn] forKey:@\"chat-noquote\"];\n        [prefs setObject:[NSNumber numberWithBool:_muteNotifications.isOn] forKey:@\"notifications-mute\"];\n        [prefs setObject:[NSNumber numberWithBool:!_noColor.isOn] forKey:@\"chat-nocolor\"];\n        [prefs setObject:[NSNumber numberWithBool:!_disableTypingStatus.isOn] forKey:@\"disableTypingStatus\"];\n        [prefs setObject:[NSNumber numberWithBool:_showDeleted.isOn] forKey:@\"chat-deleted-show\"];\n\n        SBJson5Writer *writer = [[SBJson5Writer alloc] init];\n        NSString *json = [writer stringWithObject:prefs];\n        \n        [[NetworkConnection sharedInstance] setRealname:self->_name.text highlights:self->_highlights.text autoaway:self->_autoaway.isOn handler:^(IRCCloudJSONObject *result) {\n            if([[result objectForKey:@\"success\"] boolValue]) {\n                [[NetworkConnection sharedInstance] setPrefs:json handler:^(IRCCloudJSONObject *result) {\n                    if([[result objectForKey:@\"success\"] boolValue]) {\n                        [self.tableView endEditing:YES];\n                        [self dismissViewControllerAnimated:YES completion:nil];\n                    } else {\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to save settings, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                        [self presentViewController:alert animated:YES completion:nil];\n                        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveButtonPressed:)];\n                    }\n                }];\n            } else {\n                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error\" message:@\"Unable to save settings, please try again.\" preferredStyle:UIAlertControllerStyleAlert];\n                [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                [self presentViewController:alert animated:YES completion:nil];\n                self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveButtonPressed:)];\n            }\n        }];\n        \n        [[NSUserDefaults standardUserDefaults] setBool:self->_screen.on forKey:@\"keepScreenOn\"];\n        [[NSUserDefaults standardUserDefaults] setBool:self->_autoCaps.on forKey:@\"autoCaps\"];\n        [[NSUserDefaults standardUserDefaults] setBool:self->_saveToCameraRoll.on forKey:@\"saveToCameraRoll\"];\n        [[NSUserDefaults standardUserDefaults] setBool:self->_notificationSound.on forKey:@\"notificationSound\"];\n        [[NSUserDefaults standardUserDefaults] setBool:self->_tabletMode.on forKey:@\"tabletMode\"];\n        [[NSUserDefaults standardUserDefaults] setFloat:ceilf(self->_fontSize.value) forKey:@\"fontSize\"];\n        [[NSUserDefaults standardUserDefaults] setBool:!_oneLine.isOn forKey:@\"chat-oneline\"];\n        [[NSUserDefaults standardUserDefaults] setBool:!_noRealName.isOn forKey:@\"chat-norealname\"];\n        [[NSUserDefaults standardUserDefaults] setBool:!_timeLeft.isOn forKey:@\"time-left\"];\n        [[NSUserDefaults standardUserDefaults] setBool:!_avatarsOff.isOn forKey:@\"avatars-off\"];\n        [[NSUserDefaults standardUserDefaults] setBool:!_browserWarning.isOn forKey:@\"warnBeforeLaunchingBrowser\"];\n        [[NSUserDefaults standardUserDefaults] setBool:!_imageViewer.isOn forKey:@\"imageViewer\"];\n        [[NSUserDefaults standardUserDefaults] setBool:!_videoViewer.isOn forKey:@\"videoViewer\"];\n        [[NSUserDefaults standardUserDefaults] setBool:!_inlineWifiOnly.isOn forKey:@\"inlineWifiOnly\"];\n        [[NSUserDefaults standardUserDefaults] setBool:self->_defaultSound.isOn forKey:@\"defaultSound\"];\n        [[NSUserDefaults standardUserDefaults] setBool:!_notificationPreviews.isOn forKey:@\"disableNotificationPreviews\"];\n        [[NSUserDefaults standardUserDefaults] setBool:self->_thirdPartyNotificationPreviews.isOn forKey:@\"thirdPartyNotificationPreviews\"];\n        [[NSUserDefaults standardUserDefaults] setBool:self->_clearFormattingAfterSending.isOn forKey:@\"clearFormattingAfterSending\"];\n        [[NSUserDefaults standardUserDefaults] setBool:self->_avatarImages.isOn forKey:@\"avatarImages\"];\n        [[NSUserDefaults standardUserDefaults] setBool:!_hiddenMembers.isOn forKey:@\"hiddenMembers\"];\n        [[NSUserDefaults standardUserDefaults] synchronize];\n    \n#ifdef ENTERPRISE\n        NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n        NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n        [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"photoSize\"] forKey:@\"photoSize\"];\n        [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"uploadsAvailable\"] forKey:@\"uploadsAvailable\"];\n        [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"imageService\"] forKey:@\"imageService\"];\n        [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"fontSize\"] forKey:@\"fontSize\"];\n        [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"defaultSound\"] forKey:@\"defaultSound\"];\n        [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"disableNotificationPreviews\"] forKey:@\"disableNotificationPreviews\"];\n        [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"thirdPartyNotificationPreviews\"] forKey:@\"thirdPartyNotificationPreviews\"];\n        [d synchronize];\n        \n        if([ColorFormatter shouldClearFontCache]) {\n            [ColorFormatter clearFontCache];\n            [ColorFormatter loadFonts];\n        }\n        [[EventsDataSource sharedInstance] clearFormattingCache];\n        [[AvatarsDataSource sharedInstance] invalidate];\n        \n        [((AppDelegate *)[UIApplication sharedApplication].delegate).mainViewController viewWillAppear:YES];\n//#if TARGET_OS_MACCATALYST\n        //[(AppDelegate *)UIApplication.sharedApplication.delegate closeWindow:self.view.window];\n//#endif\n    }\n}\n\n-(void)cancelButtonPressed:(id)sender {\n    [self.tableView endEditing:YES];\n#ifdef ENTERPRISE\n    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n    [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"photoSize\"] forKey:@\"photoSize\"];\n    [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"uploadsAvailable\"] forKey:@\"uploadsAvailable\"];\n    [d setObject:[[NSUserDefaults standardUserDefaults] objectForKey:@\"imageService\"] forKey:@\"imageService\"];\n    [d synchronize];\n    [[NSUserDefaults standardUserDefaults] setObject:self->_oldTheme forKey:@\"theme\"];\n    [[NSUserDefaults standardUserDefaults] synchronize];\n    [UIColor setTheme:self->_oldTheme];\n    if([ColorFormatter shouldClearFontCache]) {\n        [ColorFormatter clearFontCache];\n        [ColorFormatter loadFonts];\n    }\n    [[EventsDataSource sharedInstance] clearFormattingCache];\n    [[AvatarsDataSource sharedInstance] invalidate];\n    [[EventsDataSource sharedInstance] reformat];\n//#if TARGET_OS_MACCATALYST\n//    [(AppDelegate *)UIApplication.sharedApplication.delegate closeWindow:self.view.window];\n//#else\n    UIView *v = self.navigationController.view.superview;\n    [self.navigationController.view removeFromSuperview];\n    [v addSubview: self.navigationController.view];\n    [self.navigationController.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    self.navigationController.view.backgroundColor = [UIColor navBarColor];\n    if (@available(iOS 13.0, *)) {\n        UINavigationBarAppearance *a = [[UINavigationBarAppearance alloc] init];\n        a.backgroundImage = [UIColor navBarBackgroundImage];\n        a.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor navBarHeadingColor]};\n        self.navigationController.navigationBar.standardAppearance = a;\n        self.navigationController.navigationBar.compactAppearance = a;\n        self.navigationController.navigationBar.scrollEdgeAppearance = a;\n        if (@available(iOS 15.0, *)) {\n#if !TARGET_OS_MACCATALYST\n            self.navigationController.navigationBar.compactScrollEdgeAppearance = a;\n#endif\n        }\n    }\n    [self dismissViewControllerAnimated:YES completion:nil];\n//#endif\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    self->_email.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_name.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_highlights.textColor = [UITableViewCell appearance].detailTextLabelColor;\n    self->_email.frame = CGRectMake(0, 0, self.tableView.frame.size.width / 3, 22);\n    self->_name.frame = CGRectMake(0, 0, self.tableView.frame.size.width / 3, 22);\n    [self refresh];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)handleEvent:(NSNotification *)notification {\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    \n    switch(event) {\n        case kIRCEventUserInfo:\n            [self setFromPrefs];\n            [self refresh];\n            break;\n        default:\n            break;\n    }\n}\n\n-(NSString *)accountMsg:(NSString *)msg {\n    if([msg isEqualToString:@\"oldpassword\"]) {\n        msg = @\"Current password incorrect\";\n    } else if([msg isEqualToString:@\"bad_pass\"]) {\n        msg = @\"Incorrect password, please try again\";\n    } else if([msg isEqualToString:@\"rate_limited\"]) {\n        msg = @\"Rate limited, try again in a few minutes\";\n    } else if([msg isEqualToString:@\"newpassword\"] || [msg isEqualToString:@\"password_error\"]) {\n        msg = @\"Invalid password, please try again\";\n    } else if([msg isEqualToString:@\"last_admin_cant_leave\"]) {\n        msg = @\"You can’t delete your account as the last admin of a team.  Please transfer ownership before continuing.\";\n    }\n    return msg;\n}\n\n-(void)refresh {\n    BOOL isCatalyst = NO;\n    if (@available(iOS 13.0, *)) {\n        isCatalyst = [NSProcessInfo processInfo].macCatalystApp;\n    }\n    \n    NSArray *account;\n#ifdef ENTERPRISE\n    if([[[NetworkConnection sharedInstance].config objectForKey:@\"auth_mechanism\"] isEqualToString:@\"internal\"]) {\n#endif\n        account = @[\n                    @{@\"title\":@\"Email Address\", @\"accessory\":self->_email},\n                    @{@\"title\":@\"Full Name\", @\"accessory\":self->_name},\n                    @{@\"title\":@\"Auto Away\", @\"accessory\":self->_autoaway},\n#ifndef ENTERPRISE\n                    @{@\"title\":@\"Public Avatar\", @\"value\":@\"\", @\"selected\":^{\n                        AvatarsTableViewController *atv = [[AvatarsTableViewController alloc] initWithServer:-1];\n                        [self.navigationController pushViewController:atv animated:YES];\n                    }},\n                    @{@\"title\":@\"Avatars FAQ\", @\"selected\":^{[(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:[NSURL URLWithString:@\"https://www.irccloud.com/faq#faq-avatars\"]];}},\n#endif\n                    @{@\"title\":@\"Change Password\", @\"selected\":^{\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Change Password\" message:nil preferredStyle:UIAlertControllerStyleAlert];\n                        \n                        [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n                            textField.placeholder = @\"Current Password\";\n                            textField.textContentType = UITextContentTypePassword;\n                            textField.secureTextEntry = YES;\n                            textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n                        }];\n                        \n                        [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n                            textField.placeholder = @\"New Password\";\n                            textField.textContentType = UITextContentTypeNewPassword;\n                            textField.secureTextEntry = YES;\n                            textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n                        }];\n                        \n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Change Password\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                            UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n                            [spinny startAnimating];\n                            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinny];\n\n                            [[NetworkConnection sharedInstance] changePassword:[alert.textFields objectAtIndex:0].text newPassword:[alert.textFields objectAtIndex:0].text handler:^(IRCCloudJSONObject *result) {\n                                if([[result objectForKey:@\"success\"] boolValue]) {\n                                    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveButtonPressed:)];\n                                    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Password Changed\" message:@\"Your password has been successfully updated and all your other sessions have been logged out\" preferredStyle:UIAlertControllerStyleAlert];\n                                    [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                                    [self presentViewController:alert animated:YES completion:nil];\n                                } else {\n                                    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error Changing Password\" message:[self accountMsg:[result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                                    [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                                    [self presentViewController:alert animated:YES completion:nil];\n                                    CLS_LOG(@\"Password not changed: %@\", [result objectForKey:@\"message\"]);\n                                    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveButtonPressed:)];\n                                }\n                            }];\n                        }]];\n                        \n                        [self presentViewController:alert animated:YES completion:nil];\n                        \n                    }},\n                    @{@\"title\":@\"Delete Account\", @\"selected\":^{\n                        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Delete Account\" message:@\"Re-enter your password to confirm\" preferredStyle:UIAlertControllerStyleAlert];\n                        \n                        [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n                            textField.placeholder = @\"Password\";\n                            textField.secureTextEntry = YES;\n                            textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n                        }];\n\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n                        [alert addAction:[UIAlertAction actionWithTitle:@\"Delete\" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {\n                            UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[UIColor activityIndicatorViewStyle]];\n                            [spinny startAnimating];\n                            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinny];\n                            \n                            [[NetworkConnection sharedInstance] deleteAccount:[alert.textFields objectAtIndex:0].text handler:^(IRCCloudJSONObject *result) {\n                                if([[result objectForKey:@\"success\"] boolValue]) {\n                                    [self.tableView endEditing:YES];\n                                    [self dismissViewControllerAnimated:YES completion:nil];\n                                } else {\n                                    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Error Deleting Account\" message:[self accountMsg:[result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                                    [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n                                    [self presentViewController:alert animated:YES completion:nil];\n                                    CLS_LOG(@\"Account not deleted: %@\", [result objectForKey:@\"message\"]);\n                                    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveButtonPressed:)];\n                                }\n                            }];\n                        }]];\n                        \n                        [self presentViewController:alert animated:YES completion:nil];\n                        \n                    }}\n                    ];\n        \n#ifdef ENTERPRISE\n    } else {\n        account = @[\n                    @{@\"title\":@\"Full Name\", @\"accessory\":self->_name},\n                    @{@\"title\":@\"Auto Away\", @\"accessory\":self->_autoaway},\n                    ];\n    }\n#endif\n    \n    NSString *imageSize;\n    switch([[[NSUserDefaults standardUserDefaults] objectForKey:@\"photoSize\"] intValue]) {\n        case 512:\n            imageSize = @\"Small\";\n            break;\n        case 1024:\n            imageSize = @\"Medium\";\n            break;\n        case 2048:\n            imageSize = @\"Large\";\n            break;\n        default:\n            imageSize = @\"Original\";\n            break;\n    }\n    \n    NSMutableArray *device = [[NSMutableArray alloc] init];\n    [device addObject:@{@\"title\":@\"Theme\", @\"value\":[[NSUserDefaults standardUserDefaults] objectForKey:@\"theme\"]?[[[NSUserDefaults standardUserDefaults] objectForKey:@\"theme\"] capitalizedString]:@\"Dawn\", @\"selected\":^{ [self.navigationController pushViewController:[[ThemesViewController alloc] init] animated:YES]; }}];\n    [device addObject:@{@\"title\":@\"Monospace Font\", @\"accessory\":self->_mono}];\n    [device addObject:@{@\"title\":@\"Prevent Auto-Lock\", @\"accessory\":self->_screen}];\n    [device addObject:@{@\"title\":@\"Auto-capitalization\", @\"accessory\":self->_autoCaps}];\n    if(!isCatalyst)\n        [device addObject:@{@\"title\":@\"Preferred Browser\", @\"value\":[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"], @\"selected\":^{ [self.navigationController pushViewController:[[BrowserViewController alloc] init] animated:YES]; }}];\n    if([[UIDevice currentDevice] isBigPhone] || [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {\n        [device addObject:@{@\"title\":@\"Show Sidebars In Landscape\", @\"accessory\":self->_tabletMode}];\n        [device addObject:@{@\"title\":@\"Always show channel members\", @\"accessory\":self->_hiddenMembers}];\n    }\n    [device addObject:@{@\"title\":@\"Ask To Post A Snippet\", @\"accessory\":self->_pastebin}];\n    if(!isCatalyst) {\n        [device addObject:@{@\"title\":@\"Open Images in Browser\", @\"accessory\":self->_imageViewer}];\n        [device addObject:@{@\"title\":@\"Open Videos in Browser\", @\"accessory\":self->_videoViewer}];\n        [device addObject:@{@\"title\":@\"Retry Failed Images in Browser\", @\"accessory\":self->_browserWarning}];\n    }\n    \n    NSMutableArray *photos = [[NSMutableArray alloc] init];\n    if(!isCatalyst) {\n        [photos addObject:@{@\"title\":@\"Save to Camera Roll\", @\"accessory\":self->_saveToCameraRoll}];\n    }\n    [photos addObject:@{@\"title\":@\"Image Size\", @\"value\":imageSize, @\"selected\":^{[self.navigationController pushViewController:[[PhotoSizeViewController alloc] init] animated:YES];}}];\n\n    NSMutableArray *notifications = [[NSMutableArray alloc] init];\n    [notifications addObject:@{@\"title\":@\"Default Alert Sound\", @\"accessory\":self->_defaultSound}];\n    [notifications addObject:@{@\"title\":@\"Preview Uploaded Files\", @\"accessory\":self->_notificationPreviews}];\n    [notifications addObject:@{@\"title\":@\"Preview External URLs\", @\"accessory\":self->_thirdPartyNotificationPreviews}];\n    [notifications addObject:@{@\"title\":@\"Notify On All Messages\", @\"accessory\":self->_notifyAll}];\n    [notifications addObject:@{@\"title\":@\"Show Unread Indicators\", @\"accessory\":self->_showUnread}];\n    [notifications addObject:@{@\"title\":@\"Mark As Read Automatically\", @\"accessory\":self->_markAsRead}];\n#ifndef ENTERPRISE\n    [notifications addObject:@{@\"title\":@\"Mute Notifications\", @\"accessory\":self->_muteNotifications}];\n#endif\n    \n    self->_data = @[\n              @{@\"title\":@\"Account\", @\"items\":account},\n              @{@\"title\":@\"Highlight Words\", @\"items\":@[\n                        @{@\"configure\":^(UITableViewCell *cell) {\n                            cell.textLabel.text = nil;\n                            [self->_highlights removeFromSuperview];\n                            self->_highlights.frame = CGRectInset(cell.contentView.bounds, 4, 4);\n                            [cell.contentView addSubview:self->_highlights];\n                        }, @\"style\":@(UITableViewCellStyleDefault)}\n                        ]},\n              @{@\"title\":@\"Message Layout\", @\"items\":@[\n                         @{@\"title\":@\"Nicknames on Separate Line\", @\"accessory\":self->_oneLine},\n                         @{@\"title\":@\"Show Real Names\", @\"accessory\":self->_noRealName},\n                         @{@\"title\":@\"Right Hand Side Timestamps\", @\"accessory\":self->_timeLeft},\n                         @{@\"title\":@\"User Icons\", @\"accessory\":self->_avatarsOff},\n#ifndef ENTERPRISE\n                         @{@\"title\":@\"Avatars\", @\"accessory\":self->_avatarImages},\n#endif\n                         @{@\"title\":@\"Compact Spacing\", @\"accessory\":self->_compact},\n                         @{@\"title\":@\"24-Hour Clock\", @\"accessory\":self->_24hour},\n                         @{@\"title\":@\"Show Seconds\", @\"accessory\":self->_seconds},\n                         @{@\"title\":@\"Usermode Symbols\", @\"accessory\":self->_symbols, @\"subtitle\":@\"@, +, etc.\"},\n                         @{@\"title\":@\"Colourise Nicknames\", @\"accessory\":self->_colors},\n                         @{@\"title\":@\"Colourise Mentions\", @\"accessory\":self->_colorizeMentions},\n                         @{@\"title\":@\"Convert :emocodes: to Emoji\", @\"accessory\":self->_emocodes, @\"subtitle\":@\":thumbsup: → 👍\"},\n                         @{@\"title\":@\"Enlarge Emoji Messages\", @\"accessory\":self->_disableBigEmoji},\n                         ]},\n              @{@\"title\":@\"Chat & Embeds\", @\"items\":@[\n                        @{@\"title\":@\"Show Joins, Parts, Quits\", @\"accessory\":self->_hideJoinPart},\n                        @{@\"title\":@\"Collapse Joins, Parts, Quits\", @\"accessory\":self->_expandJoinPart},\n                        @{@\"title\":@\"Embed Uploaded Files\", @\"accessory\":self->_disableInlineFiles},\n                        @{@\"title\":@\"Embed External Media\", @\"accessory\":self->_inlineImages},\n                        @{@\"title\":@\"Embed Using Mobile Data\", @\"accessory\":self->_inlineWifiOnly},\n                        @{@\"title\":@\"Format inline code\", @\"accessory\":self->_disableCodeSpan},\n                        @{@\"title\":@\"Format code blocks\", @\"accessory\":self->_disableCodeBlock},\n                        @{@\"title\":@\"Format quoted text\", @\"accessory\":self->_disableQuote},\n                        @{@\"title\":@\"Format colours\", @\"accessory\":self->_noColor},\n                        @{@\"title\":@\"Clear colours after sending\", @\"accessory\":self->_clearFormattingAfterSending},\n                        @{@\"title\":@\"Share typing status\", @\"accessory\":self->_disableTypingStatus},\n                        @{@\"title\":@\"Show deleted messages\", @\"accessory\":self->_showDeleted},\n                        ]},\n              @{@\"title\":@\"Device\", @\"items\":device},\n              @{@\"title\":@\"Notifications\", @\"items\":notifications},\n              @{@\"title\":@\"Font Size\", @\"items\":@[\n                        @{@\"special\":^UITableViewCell *(UITableViewCell *cell, NSString *identifier) {\n                            self->_fontSizeCell.fontSample.textColor = [UIColor messageTextColor];\n                            [self monoToggled:nil];\n                            return self->_fontSizeCell;\n                        }}\n                        ]},\n              @{@\"title\":@\"Photo Sharing\", @\"items\":photos},\n              @{@\"title\":@\"About\", @\"items\":@[\n                        @{@\"title\":@\"Feedback Channel\", @\"selected\":^{[self dismissViewControllerAnimated:YES completion:^{\n                            [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:[NSURL URLWithString:@\"irc://irc.irccloud.com/%23feedback\"]];\n                        }];}},\n#ifndef ENTERPRISE\n                        @{@\"title\":@\"Become a Beta Tester\", @\"selected\":^{\n                            [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:[NSURL URLWithString:@\"https://testflight.apple.com/join/MApr7Une\"]];}},\n#endif\n                        @{@\"title\":@\"FAQ\", @\"selected\":^{\n                            [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:[NSURL URLWithString:@\"https://www.irccloud.com/faq\"]];}},\n                        @{@\"title\":@\"Version History\", @\"selected\":^{\n                            [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:[NSURL URLWithString:@\"https://github.com/irccloud/ios/releases\"]];}},\n                        @{@\"title\":@\"Open-Source Licenses\", @\"selected\":^{[self.navigationController pushViewController:[[LicenseViewController alloc] init] animated:YES];}},\n                        @{@\"title\":@\"Version\", @\"subtitle\":self->_version}\n                        ]}\n              ];\n    \n    [self.tableView reloadData];\n    if(self.scrollToNotifications) {\n        self.scrollToNotifications = NO;\n        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:device.count - 1 inSection:4] atScrollPosition:UITableViewScrollPositionTop animated:NO];\n    }\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    \n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n\n    self->_email = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width / 3, 22)];\n    self->_email.text = @\"\";\n    self->_email.textAlignment = NSTextAlignmentRight;\n    self->_email.autocapitalizationType = UITextAutocapitalizationTypeNone;\n    self->_email.autocorrectionType = UITextAutocorrectionTypeNo;\n    self->_email.keyboardType = UIKeyboardTypeEmailAddress;\n    self->_email.adjustsFontSizeToFitWidth = YES;\n    self->_email.returnKeyType = UIReturnKeyDone;\n    self->_email.delegate = self;\n    \n    self->_name = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width / 3, 22)];\n    self->_name.text = @\"\";\n    self->_name.textAlignment = NSTextAlignmentRight;\n    self->_name.autocapitalizationType = UITextAutocapitalizationTypeWords;\n    self->_name.autocorrectionType = UITextAutocorrectionTypeNo;\n    self->_name.keyboardType = UIKeyboardTypeDefault;\n    self->_name.adjustsFontSizeToFitWidth = YES;\n    self->_name.returnKeyType = UIReturnKeyDone;\n    self->_name.delegate = self;\n    \n    self->_autoaway = [[UISwitch alloc] init];\n    _24hour = [[UISwitch alloc] init];\n    self->_seconds = [[UISwitch alloc] init];\n    self->_symbols = [[UISwitch alloc] init];\n    self->_colors = [[UISwitch alloc] init];\n    self->_screen = [[UISwitch alloc] init];\n    self->_autoCaps = [[UISwitch alloc] init];\n    self->_emocodes = [[UISwitch alloc] init];\n    self->_saveToCameraRoll = [[UISwitch alloc] init];\n    self->_notificationSound = [[UISwitch alloc] init];\n    self->_tabletMode = [[UISwitch alloc] init];\n    self->_pastebin = [[UISwitch alloc] init];\n    self->_mono = [[UISwitch alloc] init];\n    [self->_mono addTarget:self action:@selector(monoToggled:) forControlEvents:UIControlEventValueChanged];\n    self->_hideJoinPart = [[UISwitch alloc] init];\n    [self->_hideJoinPart addTarget:self action:@selector(hideJoinPartToggled:) forControlEvents:UIControlEventValueChanged];\n    self->_expandJoinPart = [[UISwitch alloc] init];\n    self->_notifyAll = [[UISwitch alloc] init];\n    self->_showUnread = [[UISwitch alloc] init];\n    self->_markAsRead = [[UISwitch alloc] init];\n    self->_oneLine = [[UISwitch alloc] init];\n    [self->_oneLine addTarget:self action:@selector(oneLineToggled:) forControlEvents:UIControlEventValueChanged];\n    self->_noRealName = [[UISwitch alloc] init];\n    self->_timeLeft = [[UISwitch alloc] init];\n    self->_avatarsOff = [[UISwitch alloc] init];\n    [self->_avatarsOff addTarget:self action:@selector(oneLineToggled:) forControlEvents:UIControlEventValueChanged];\n    self->_browserWarning = [[UISwitch alloc] init];\n    self->_compact = [[UISwitch alloc] init];\n    self->_imageViewer = [[UISwitch alloc] init];\n    self->_videoViewer = [[UISwitch alloc] init];\n    self->_disableInlineFiles = [[UISwitch alloc] init];\n    self->_disableBigEmoji = [[UISwitch alloc] init];\n    self->_inlineWifiOnly = [[UISwitch alloc] init];\n    self->_defaultSound = [[UISwitch alloc] init];\n    self->_notificationPreviews = [[UISwitch alloc] init];\n    [self->_notificationPreviews addTarget:self action:@selector(notificationPreviewsToggled:) forControlEvents:UIControlEventValueChanged];\n    self->_thirdPartyNotificationPreviews = [[UISwitch alloc] init];\n    [self->_thirdPartyNotificationPreviews addTarget:self action:@selector(thirdPartyNotificationPreviewsToggled:) forControlEvents:UIControlEventValueChanged];\n    self->_disableCodeSpan = [[UISwitch alloc] init];\n    self->_disableCodeBlock = [[UISwitch alloc] init];\n    self->_disableQuote = [[UISwitch alloc] init];\n    self->_inlineImages = [[UISwitch alloc] init];\n    [self->_inlineImages addTarget:self action:@selector(thirdPartyNotificationPreviewsToggled:) forControlEvents:UIControlEventValueChanged];\n    self->_clearFormattingAfterSending = [[UISwitch alloc] init];\n    self->_avatarImages = [[UISwitch alloc] init];\n    self->_colorizeMentions = [[UISwitch alloc] init];\n    self->_hiddenMembers = [[UISwitch alloc] init];\n    self->_muteNotifications = [[UISwitch alloc] init];\n    self->_noColor = [[UISwitch alloc] init];\n    self->_disableTypingStatus = [[UISwitch alloc] init];\n    self->_showDeleted = [[UISwitch alloc] init];\n\n    self->_highlights = [[UITextView alloc] initWithFrame:CGRectZero];\n    self->_highlights.text = @\"\";\n    self->_highlights.backgroundColor = [UIColor clearColor];\n    self->_highlights.returnKeyType = UIReturnKeyDone;\n    self->_highlights.delegate = self;\n    self->_highlights.font = self->_email.font;\n    self->_highlights.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    self->_highlights.keyboardAppearance = [UITextField appearance].keyboardAppearance;\n\n    self->_version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"];\n#ifdef BRAND_NAME\n    self->_version = [self->_version stringByAppendingFormat:@\"-%@\", BRAND_NAME];\n#endif\n#ifndef APPSTORE\n    self->_version = [self->_version stringByAppendingFormat:@\" (%@)\", [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleVersion\"]];\n#endif\n    \n    self->_fontSize = [[UISlider alloc] init];\n    self->_fontSize.minimumValue = FONT_MIN;\n    self->_fontSize.maximumValue = FONT_MAX;\n    self->_fontSize.continuous = YES;\n    [self->_fontSize addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];\n    \n    self->_fontSizeCell = [[FontSizeCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil];\n    self->_fontSizeCell.fontSize = self->_fontSize;\n    \n    [self setFromPrefs];\n    [self refresh];\n}\n\n-(void)setFromPrefs {\n    NSDictionary *userInfo = [NetworkConnection sharedInstance].userInfo;\n    NSDictionary *prefs = [[NetworkConnection sharedInstance] prefs];\n    \n    if([[userInfo objectForKey:@\"name\"] isKindOfClass:[NSString class]] && [[userInfo objectForKey:@\"name\"] length])\n        self->_name.text = [userInfo objectForKey:@\"name\"];\n    else\n        self->_name.text = @\"\";\n    \n    if([[userInfo objectForKey:@\"email\"] isKindOfClass:[NSString class]] && [[userInfo objectForKey:@\"email\"] length])\n        self->_email.text = [userInfo objectForKey:@\"email\"];\n    else\n        self->_email.text = @\"\";\n    \n    if([[userInfo objectForKey:@\"autoaway\"] isKindOfClass:[NSNumber class]]) {\n        self->_autoaway.on = [[userInfo objectForKey:@\"autoaway\"] boolValue];\n    }\n    \n    if([[userInfo objectForKey:@\"highlights\"] isKindOfClass:[NSArray class]] && [(NSArray *)[userInfo objectForKey:@\"highlights\"] count])\n        self->_highlights.text = [[userInfo objectForKey:@\"highlights\"] componentsJoinedByString:@\", \"];\n    else if([[userInfo objectForKey:@\"highlights\"] isKindOfClass:[NSString class]] && [[userInfo objectForKey:@\"highlights\"] length])\n        self->_highlights.text = [userInfo objectForKey:@\"highlights\"];\n    else\n        self->_highlights.text = @\"\";\n    \n    if([[prefs objectForKey:@\"time-24hr\"] isKindOfClass:[NSNumber class]]) {\n        _24hour.on = [[prefs objectForKey:@\"time-24hr\"] boolValue];\n    } else {\n        _24hour.on = NO;\n    }\n    \n    if([[prefs objectForKey:@\"time-seconds\"] isKindOfClass:[NSNumber class]]) {\n        self->_seconds.on = [[prefs objectForKey:@\"time-seconds\"] boolValue];\n    } else {\n        self->_seconds.on = NO;\n    }\n    \n    if([[prefs objectForKey:@\"mode-showsymbol\"] isKindOfClass:[NSNumber class]]) {\n        self->_symbols.on = [[prefs objectForKey:@\"mode-showsymbol\"] boolValue];\n    } else {\n        self->_symbols.on = NO;\n    }\n    \n    if([[prefs objectForKey:@\"nick-colors\"] isKindOfClass:[NSNumber class]]) {\n        self->_colors.on = [[prefs objectForKey:@\"nick-colors\"] boolValue];\n    } else {\n        self->_colors.on = NO;\n    }\n    \n    if([[prefs objectForKey:@\"mention-colors\"] isKindOfClass:[NSNumber class]]) {\n        self->_colorizeMentions.on = [[prefs objectForKey:@\"mention-colors\"] boolValue];\n    } else {\n        self->_colorizeMentions.on = NO;\n    }\n    \n    if([[prefs objectForKey:@\"emoji-disableconvert\"] isKindOfClass:[NSNumber class]]) {\n        self->_emocodes.on = ![[prefs objectForKey:@\"emoji-disableconvert\"] boolValue];\n    } else {\n        self->_emocodes.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"pastebin-disableprompt\"] isKindOfClass:[NSNumber class]]) {\n        self->_pastebin.on = ![[prefs objectForKey:@\"pastebin-disableprompt\"] boolValue];\n    } else {\n        self->_pastebin.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"hideJoinPart\"] isKindOfClass:[NSNumber class]]) {\n        self->_hideJoinPart.on = ![[prefs objectForKey:@\"hideJoinPart\"] boolValue];\n    } else {\n        self->_hideJoinPart.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"expandJoinPart\"] isKindOfClass:[NSNumber class]]) {\n        self->_expandJoinPart.on = ![[prefs objectForKey:@\"expandJoinPart\"] boolValue];\n    } else {\n        self->_expandJoinPart.on = YES;\n    }\n    \n    self->_expandJoinPart.enabled = self->_hideJoinPart.on;\n    \n    if([[prefs objectForKey:@\"font\"] isKindOfClass:[NSString class]]) {\n        self->_mono.on = [[prefs objectForKey:@\"font\"] isEqualToString:@\"mono\"];\n    } else {\n        self->_mono.on = NO;\n    }\n    \n    if([[prefs objectForKey:@\"notifications-all\"] isKindOfClass:[NSNumber class]]) {\n        self->_notifyAll.on = [[prefs objectForKey:@\"notifications-all\"] boolValue];\n    } else {\n        self->_notifyAll.on = NO;\n    }\n    \n    if([[prefs objectForKey:@\"disableTrackUnread\"] isKindOfClass:[NSNumber class]]) {\n        self->_showUnread.on = ![[prefs objectForKey:@\"disableTrackUnread\"] boolValue];\n    } else {\n        self->_showUnread.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"enableReadOnSelect\"] isKindOfClass:[NSNumber class]]) {\n        self->_markAsRead.on = [[prefs objectForKey:@\"enableReadOnSelect\"] boolValue];\n    } else {\n        self->_markAsRead.on = NO;\n    }\n    \n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"chat-oneline\"]) {\n        self->_oneLine.on = ![[NSUserDefaults standardUserDefaults] boolForKey:@\"chat-oneline\"];\n    } else {\n        self->_oneLine.on = YES;\n    }\n    \n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"chat-norealname\"]) {\n        self->_noRealName.on = ![[NSUserDefaults standardUserDefaults] boolForKey:@\"chat-norealname\"];\n    } else {\n        self->_noRealName.on = YES;\n    }\n    \n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"time-left\"]) {\n        self->_timeLeft.on = ![[NSUserDefaults standardUserDefaults] boolForKey:@\"time-left\"];\n    } else {\n        self->_timeLeft.on = YES;\n    }\n    \n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"avatars-off\"]) {\n        self->_avatarsOff.on = ![[NSUserDefaults standardUserDefaults] boolForKey:@\"avatars-off\"];\n    } else {\n        self->_avatarsOff.on = YES;\n    }\n    \n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"warnBeforeLaunchingBrowser\"]) {\n        self->_browserWarning.on = ![[NSUserDefaults standardUserDefaults] boolForKey:@\"warnBeforeLaunchingBrowser\"];\n    } else {\n        self->_browserWarning.on = YES;\n    }\n    \n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"inlineWifiOnly\"]) {\n        self->_inlineWifiOnly.on = ![[NSUserDefaults standardUserDefaults] boolForKey:@\"inlineWifiOnly\"];\n    } else {\n        self->_inlineWifiOnly.on = YES;\n    }\n    \n    if([[NSUserDefaults standardUserDefaults] objectForKey:@\"hiddenMembers\"]) {\n        self->_hiddenMembers.on = ![[NSUserDefaults standardUserDefaults] boolForKey:@\"hiddenMembers\"];\n    } else {\n        self->_hiddenMembers.on = YES;\n    }\n    \n    if(self->_oneLine.on) {\n        self->_noRealName.enabled = YES;\n        if(self->_avatarsOff.on) {\n            self->_timeLeft.enabled = NO;\n            self->_timeLeft.on = YES;\n        } else {\n            self->_timeLeft.enabled = YES;\n        }\n    } else {\n        self->_noRealName.enabled = NO;\n        self->_timeLeft.enabled = YES;\n    }\n    \n    if([[prefs objectForKey:@\"ascii-compact\"] isKindOfClass:[NSNumber class]]) {\n        self->_compact.on = [[prefs objectForKey:@\"ascii-compact\"] boolValue];\n    } else {\n        self->_compact.on = NO;\n    }\n    \n    if([[prefs objectForKey:@\"files-disableinline\"] isKindOfClass:[NSNumber class]]) {\n        self->_disableInlineFiles.on = ![[prefs objectForKey:@\"files-disableinline\"] boolValue];\n    } else {\n        self->_disableInlineFiles.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"inlineimages\"] isKindOfClass:[NSNumber class]]) {\n        self->_inlineImages.on = [[prefs objectForKey:@\"inlineimages\"] boolValue];\n    } else {\n        self->_inlineImages.on = NO;\n    }\n    \n    if([[prefs objectForKey:@\"emoji-nobig\"] isKindOfClass:[NSNumber class]]) {\n        self->_disableBigEmoji.on = ![[prefs objectForKey:@\"emoji-nobig\"] boolValue];\n    } else {\n        self->_disableBigEmoji.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"chat-nocodespan\"] isKindOfClass:[NSNumber class]]) {\n        self->_disableCodeSpan.on = ![[prefs objectForKey:@\"chat-nocodespan\"] boolValue];\n    } else {\n        self->_disableCodeSpan.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"chat-nocodeblock\"] isKindOfClass:[NSNumber class]]) {\n        self->_disableCodeBlock.on = ![[prefs objectForKey:@\"chat-nocodeblock\"] boolValue];\n    } else {\n        self->_disableCodeBlock.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"chat-noquote\"] isKindOfClass:[NSNumber class]]) {\n        self->_disableQuote.on = ![[prefs objectForKey:@\"chat-noquote\"] boolValue];\n    } else {\n        self->_disableQuote.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"notifications-mute\"] isKindOfClass:[NSNumber class]]) {\n        self->_muteNotifications.on = [[prefs objectForKey:@\"notifications-mute\"] boolValue];\n    } else {\n        self->_muteNotifications.on = NO;\n    }\n    \n    if([[prefs objectForKey:@\"chat-nocolor\"] isKindOfClass:[NSNumber class]]) {\n        self->_noColor.on = ![[prefs objectForKey:@\"chat-nocolor\"] boolValue];\n    } else {\n        self->_noColor.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"disableTypingStatus\"] isKindOfClass:[NSNumber class]]) {\n        self->_disableTypingStatus.on = ![[prefs objectForKey:@\"disableTypingStatus\"] boolValue];\n    } else {\n        self->_disableTypingStatus.on = YES;\n    }\n    \n    if([[prefs objectForKey:@\"chat-deleted-show\"] isKindOfClass:[NSNumber class]]) {\n        self->_showDeleted.on = [[prefs objectForKey:@\"chat-deleted-show\"] boolValue];\n    } else {\n        self->_showDeleted.on = NO;\n    }\n    \n    self->_screen.on = [[NSUserDefaults standardUserDefaults] boolForKey:@\"keepScreenOn\"];\n    self->_autoCaps.on = [[NSUserDefaults standardUserDefaults] boolForKey:@\"autoCaps\"];\n    self->_saveToCameraRoll.on = [[NSUserDefaults standardUserDefaults] boolForKey:@\"saveToCameraRoll\"];\n    self->_notificationSound.on = [[NSUserDefaults standardUserDefaults] boolForKey:@\"notificationSound\"];\n    self->_tabletMode.on = [[NSUserDefaults standardUserDefaults] boolForKey:@\"tabletMode\"];\n    self->_fontSize.value = [[NSUserDefaults standardUserDefaults] floatForKey:@\"fontSize\"];\n    self->_imageViewer.on = ![[NSUserDefaults standardUserDefaults] boolForKey:@\"imageViewer\"];\n    self->_videoViewer.on = ![[NSUserDefaults standardUserDefaults] boolForKey:@\"videoViewer\"];\n    self->_defaultSound.on = [[NSUserDefaults standardUserDefaults] boolForKey:@\"defaultSound\"];\n    self->_notificationPreviews.on = ![[NSUserDefaults standardUserDefaults] boolForKey:@\"disableNotificationPreviews\"];\n    self->_thirdPartyNotificationPreviews.on = [[NSUserDefaults standardUserDefaults] boolForKey:@\"thirdPartyNotificationPreviews\"];\n    self->_clearFormattingAfterSending.on = [[NSUserDefaults standardUserDefaults] boolForKey:@\"clearFormattingAfterSending\"];\n    self->_avatarImages.on = [[NSUserDefaults standardUserDefaults] boolForKey:@\"avatarImages\"];\n}\n\n-(void)hideJoinPartToggled:(id)sender {\n    self->_expandJoinPart.enabled = self->_hideJoinPart.on;\n}\n\n-(void)oneLineToggled:(id)sender {\n    if(self->_oneLine.on) {\n        self->_noRealName.enabled = YES;\n        if(self->_avatarsOff.on) {\n            self->_timeLeft.enabled = NO;\n            self->_timeLeft.on = YES;\n        } else {\n            self->_timeLeft.enabled = YES;\n        }\n    } else {\n        self->_noRealName.enabled = NO;\n        self->_timeLeft.enabled = YES;\n    }\n}\n\n-(void)monoToggled:(id)sender {\n    if(self->_mono.on)\n        self->_fontSizeCell.fontSample.font = [UIFont fontWithName:@\"Hack\" size:self->_fontSize.value - 1];\n    else\n        self->_fontSizeCell.fontSample.font = [UIFont fontWithDescriptor:[UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody] size:self->_fontSize.value];\n}\n\n-(void)notificationPreviewsToggled:(id)sender {\n    self->_thirdPartyNotificationPreviews.enabled = self->_notificationPreviews.on;\n}\n\n-(void)thirdPartyNotificationPreviewsToggled:(UISwitch *)sender {\n    [self->_inlineImages addTarget:self action:@selector(thirdPartyNotificationPreviewsToggled:) forControlEvents:UIControlEventValueChanged];\n    if(sender.on) {\n        UIAlertController *ac = [UIAlertController alertControllerWithTitle:@\"Warning\" message:@\"External URLs may load insecurely and could result in your IP address being revealed to external site operators\" preferredStyle:UIAlertControllerStyleAlert];\n        \n        [ac addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {\n            sender.on = NO;\n        }]];\n\n        [ac addAction:[UIAlertAction actionWithTitle:@\"Enable\" style:UIAlertActionStyleDefault handler:nil]];\n\n        [self presentViewController:ac animated:YES completion:nil];\n    }\n}\n\n-(void)sliderChanged:(UISlider *)slider {\n    [slider setValue:(int)slider.value animated:NO];\n    [self monoToggled:nil];\n}\n\n- (void)textViewDidBeginEditing:(UITextView *)textView {\n    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];\n}\n\n- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {\n    if([text isEqualToString:@\"\\n\"]) {\n        [self.tableView endEditing:YES];\n        return NO;\n    }\n    return YES;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    if(indexPath.section == 1 || [[[self->_data objectAtIndex:indexPath.section] objectForKey:@\"title\"] isEqualToString:@\"Font Size\"])\n        return ([UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody].pointSize * 2) + 32;\n    else\n        return UITableViewAutomaticDimension;\n}\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return _data.count;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return [(NSArray *)[[self->_data objectAtIndex:section] objectForKey:@\"items\"] count];\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {\n    return [[self->_data objectAtIndex:section] objectForKey:@\"title\"];\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSString *identifier = [NSString stringWithFormat:@\"settingscell-%li-%li\", (long)indexPath.section, (long)indexPath.row];\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];\n    NSDictionary *item = [[[self->_data objectAtIndex:indexPath.section] objectForKey:@\"items\"] objectAtIndex:indexPath.row];\n    \n    if([item objectForKey:@\"special\"]) {\n        UITableViewCell *(^special)(UITableViewCell *cell, NSString *identifier) = [item objectForKey:@\"special\"];\n        return special(cell,identifier);\n    }\n\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:([item objectForKey:@\"subtitle\"])?UITableViewCellStyleSubtitle:UITableViewCellStyleValue1 reuseIdentifier:identifier];\n    \n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    cell.textLabel.text = [item objectForKey:@\"title\"];\n    cell.accessoryView = [item objectForKey:@\"accessory\"];\n    cell.accessoryType = [item objectForKey:@\"value\"]?UITableViewCellAccessoryDisclosureIndicator:UITableViewCellAccessoryNone;\n    cell.detailTextLabel.text = [item objectForKey:@\"value\"]?[item objectForKey:@\"value\"]:[item objectForKey:@\"subtitle\"];\n    \n    if([item objectForKey:@\"configure\"]) {\n        void (^configure)(UITableViewCell *cell) = [item objectForKey:@\"configure\"];\n        configure(cell);\n    }\n    \n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [self.tableView deselectRowAtIndexPath:indexPath animated:NO];\n    [self.tableView endEditing:YES];\n    NSDictionary *item = [[[self->_data objectAtIndex:indexPath.section] objectForKey:@\"items\"] objectAtIndex:indexPath.row];\n\n    if([item objectForKey:@\"selected\"]) {\n        void (^selected)(void) = [item objectForKey:@\"selected\"];\n        selected();\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/SpamViewController.h",
    "content": "//\n//  SpamViewController.h\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n\n@interface SpamViewController : UITableViewController {\n    int _cid;\n    NSArray *_buffers;\n    NSMutableArray *_buffersToDelete;\n    UILabel *_header;\n}\n-(id)initWithCid:(int)cid;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/SpamViewController.m",
    "content": "//\n//  SpamViewController.h\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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 \"SpamViewController.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"NetworkConnection.h\"\n\n@implementation SpamViewController\n\n- (id)initWithCid:(int)cid {\n    self = [super initWithStyle:UITableViewStyleGrouped];\n    if(self) {\n        self->_cid = cid;\n        self->_buffersToDelete = [[NSMutableArray alloc] init];\n        \n        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(deleteButtonPressed:)];\n    }\n    return self;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n\n    NSMutableArray *buffers = [[NSMutableArray alloc] init];\n    \n    for(Buffer *b in [[BuffersDataSource sharedInstance] getBuffersForServer:self->_cid]) {\n        if([b.type isEqualToString:@\"conversation\"] && !b.archived) {\n            [buffers addObject:b];\n            [self->_buffersToDelete addObject:b];\n        }\n    }\n    \n    self->_buffers = buffers;\n    \n    self->_header = [[UILabel alloc] init];\n    self->_header.frame = CGRectMake(8,0,self.tableView.frame.size.width - 16,64);\n    self->_header.text = @\"Uncheck any conversations you'd prefer to keep before continuing.\";\n    self->_header.numberOfLines = 0;\n    self->_header.lineBreakMode = NSLineBreakByWordWrapping;\n    self->_header.textAlignment = NSTextAlignmentCenter;\n    self->_header.textColor = [UIColor timestampColor];\n\n    [self.tableView reloadData];\n}\n\n- (void)cancelButtonPressed:(id)sender {\n    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];\n}\n\n- (void)deleteButtonPressed:(id)sender {\n    for(Buffer *b in _buffersToDelete) {\n        [[NetworkConnection sharedInstance] deleteBuffer:b.bid cid:b.cid handler:nil];\n    }\n    [self.presentingViewController dismissViewControllerAnimated:YES completion:^{\n        if(self->_buffersToDelete.count) {\n            Server *s = [[ServersDataSource sharedInstance] getServer:self->_cid];\n            \n            UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@\"%@ (%@:%i)\", s.name, s.hostname, s.port] message:[NSString stringWithFormat:@\"%lu conversations were deleted\", (unsigned long)self->_buffersToDelete.count] preferredStyle:UIAlertControllerStyleAlert];\n            [alert addAction:[UIAlertAction actionWithTitle:@\"Ok\" style:UIAlertActionStyleCancel handler:nil]];\n            [self presentViewController:alert animated:YES completion:nil];\n        }\n    }];\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n#pragma mark - Table view data source\n\n-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {\n    CGRect frame = self->_header.frame;\n    frame.origin.x = self.view.window.safeAreaInsets.left + 8;\n    self->_header.frame = frame;\n\n    return _header;\n}\n\n-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {\n    return _header.frame.size.height;\n}\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return _buffers.count;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"buffercell\"];\n    if(!cell)\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"buffercell\"];\n    \n    Buffer *b = [self->_buffers objectAtIndex:indexPath.row];\n    cell.textLabel.text = b.name;\n    \n    if([self->_buffersToDelete containsObject:b])\n        cell.accessoryType = UITableViewCellAccessoryCheckmark;\n    else\n        cell.accessoryType = UITableViewCellAccessoryNone;\n    \n    return cell;\n}\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    Buffer *b = [self->_buffers objectAtIndex:indexPath.row];\n    if([self->_buffersToDelete containsObject:b])\n        [self->_buffersToDelete removeObject:b];\n    else\n        [self->_buffersToDelete addObject:b];\n    \n    [self.tableView reloadData];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/SplashViewController.h",
    "content": "//\n//  SplashViewController.h\n//\n//  Copyright (C) 2015 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n\n@interface SplashViewController : UIViewController {\n    IBOutlet UIImageView *_logo;\n}\n-(void)animate:(UIImageView *)loginLogo;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/SplashViewController.m",
    "content": "//\n//  SplashViewController.h\n//\n//  Copyright (C) 2015 IRCCloud, Ltd.\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#import \"SplashViewController.h\"\n\n@interface SplashViewController ()\n\n@end\n\n@implementation SplashViewController\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self->_logo.center = CGPointMake(self.view.center.x, 39 + [UIApplication sharedApplication].statusBarFrame.size.height);\n}\n\n-(UIStatusBarStyle)preferredStatusBarStyle {\n    return UIStatusBarStyleLightContent;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n-(void)animate:(UIImageView *)loginLogo {\n    if(loginLogo) {\n        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@\"position.x\"];\n        [animation setFromValue:@(self->_logo.layer.position.x)];\n        [animation setToValue:@((self.view.bounds.size.width / 2) - 112)];\n        [animation setDuration:0.4];\n        [animation setTimingFunction:[CAMediaTimingFunction functionWithControlPoints:.17 :.89 :.32 :1.28]];\n        animation.removedOnCompletion = NO;\n        animation.fillMode = kCAFillModeForwards;\n        [self->_logo.layer addAnimation:animation forKey:nil];\n    } else {\n        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@\"position.x\"];\n        [animation setFromValue:@(self->_logo.layer.position.x)];\n        [animation setToValue:@(self.view.bounds.size.width + _logo.bounds.size.width)];\n        [animation setDuration:0.4];\n        [animation setTimingFunction:[CAMediaTimingFunction functionWithControlPoints:.8 :-.3 :.8 :-.3]];\n        animation.removedOnCompletion = NO;\n        animation.fillMode = kCAFillModeForwards;\n        [self->_logo.layer addAnimation:animation forKey:nil];\n    }\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/TextTableViewController.h",
    "content": "//\n//  TextTableViewController.h\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n#import \"ServersDataSource.h\"\n#import \"LinkLabel.h\"\n\n@interface TextTableViewController : UIViewController {\n    NSArray *_data;\n    Server *_server;\n    LinkLabel *tv;\n    UIScrollView *sv;\n    NSString *_type;\n    NSString *_placeholder;\n    NSString *_text;\n}\n@property Server *server;\n@property NSString *type, *placeholder;\n-(id)initWithData:(NSArray *)data;\n-(id)initWithText:(NSString *)text;\n-(void)appendData:(NSArray *)data;\n-(void)appendText:(NSString *)text;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/TextTableViewController.m",
    "content": "//\n//  TextTableViewController.h\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import \"TextTableViewController.h\"\n#import \"LinkLabel.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"ColorFormatter.h\"\n#import \"AppDelegate.h\"\n\n@implementation TextTableViewController\n\n- (id)initWithData:(NSArray *)data {\n    self = [super init];\n    if(self) {\n        self->_data = data;\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)];\n    }\n    return self;\n}\n\n- (id)initWithText:(NSString *)text {\n    self = [super init];\n    if(self) {\n        self->_text = text;\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)];\n    }\n    return self;\n}\n\n- (void)appendData:(NSArray *)data {\n    self->_data = [self->_data arrayByAddingObjectsFromArray:data];\n    [self refresh];\n}\n\n-(void)appendText:(NSString *)text {\n    if(self->_text)\n        self->_text = [self->_text stringByAppendingString:text];\n    else\n        self->_text = text;\n    \n    [self refresh];\n}\n\n\n- (void)doneButtonPressed:(id)sender {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n- (void)refresh {\n    NSString *text = self->_text;\n    if(!text) {\n        NSMutableString *mutableText = [[NSMutableString alloc] init];\n        \n        if(self->_data.count) {\n            for(id item in _data) {\n                NSString *s;\n                if([item isKindOfClass:[NSString class]]) {\n                    s = item;\n                } else if([item isKindOfClass:[NSArray class]]) {\n                    s = [(NSArray *)item componentsJoinedByString:@\"\\t\"];\n                } else {\n                    s = [item description];\n                }\n                [mutableText appendFormat:@\"%@\\n\", s];\n            }\n        } else {\n            if(self->_placeholder)\n                [mutableText appendString:self->_placeholder];\n        }\n        text = mutableText;\n    }\n    \n    NSArray *links;\n    tv.attributedText = [ColorFormatter format:text defaultColor:[UIColor messageTextColor] mono:YES linkify:YES server:self->_server links:&links];\n    tv.linkAttributes = [UIColor linkAttributes];\n    \n    for(NSTextCheckingResult *result in links) {\n        if(result.resultType == NSTextCheckingTypeLink) {\n            [tv addLinkWithTextCheckingResult:result];\n        } else {\n            NSString *url = [[tv.attributedText attributedSubstringFromRange:result.range] string];\n            if(![url hasPrefix:@\"irc\"]) {\n                url = [NSString stringWithFormat:@\"irc://%i/%@\", _server.cid, [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]];\n            }\n            [tv addLinkToURL:[NSURL URLWithString:[url stringByReplacingOccurrencesOfString:@\"#\" withString:@\"%23\"]] withRange:result.range];\n        }\n    }\n    \n    CGSize size = [tv.attributedText boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;\n    if(size.width < self.view.bounds.size.width)\n        size.width = self.view.bounds.size.width;\n    tv.frame = CGRectMake(0,0,size.width,size.height);\n    sv.contentSize = tv.bounds.size;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    tv = [[LinkLabel alloc] initWithFrame:CGRectZero];\n    tv.backgroundColor = [UIColor contentBackgroundColor];\n    tv.textColor = [UIColor messageTextColor];\n    tv.numberOfLines = 0;\n    \n    sv = [[UIScrollView alloc] initWithFrame:self.view.bounds];\n    sv.backgroundColor = [UIColor contentBackgroundColor];\n    sv.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;\n    [sv addSubview:tv];\n    \n    [self.view addSubview:sv];\n    \n    [self refresh];\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n/*\n#pragma mark - Navigation\n\n// In a storyboard-based application, you will often want to do a little preparation before navigation\n- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {\n    // Get the new view controller using [segue destinationViewController].\n    // Pass the selected object to the new view controller.\n}\n*/\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UIColor+IRCCloud.h",
    "content": "//\n//  UIColor+IRCCloud.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n\n#define IRC_COLOR_COUNT 99\n\n@interface UITableViewCell (IRCCloudAppearanceHax) <UIAppearance>\n@property (strong) UIColor *textLabelColor UI_APPEARANCE_SELECTOR;\n@property (strong) UIColor *detailTextLabelColor UI_APPEARANCE_SELECTOR;\n@end\n\n@interface UIColor (IRCCloud)\n+(void)setSafeInsets:(UIEdgeInsets)insets;\n+(UIColor *)colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation lightness:(CGFloat)brightness alpha:(CGFloat)alpha;\n+(BOOL)isDarkTheme;\n+(void)setTheme;\n+(void)setTheme:(NSString *)theme;\n+(void)clearTheme;\n+(void)setCurrentTraits:(UITraitCollection *)traitCollection;\n+(UIColor *)contentBackgroundColor;\n+(UIColor *)messageTextColor;\n+(UIColor *)opersGroupColor;\n+(UIColor *)ownersGroupColor;\n+(UIColor *)adminsGroupColor;\n+(UIColor *)opsGroupColor;\n+(UIColor *)halfopsGroupColor;\n+(UIColor *)voicedGroupColor;\n+(UIColor *)membersGroupColor;\n+(UIColor *)opersBorderColor;\n+(UIColor *)ownersBorderColor;\n+(UIColor *)adminsBorderColor;\n+(UIColor *)opsBorderColor;\n+(UIColor *)halfopsBorderColor;\n+(UIColor *)voicedBorderColor;\n+(UIColor *)membersBorderColor;\n+(UIColor *)opersHeadingColor;\n+(UIColor *)ownersHeadingColor;\n+(UIColor *)adminsHeadingColor;\n+(UIColor *)opsHeadingColor;\n+(UIColor *)halfopsHeadingColor;\n+(UIColor *)voicedHeadingColor;\n+(UIColor *)membersHeadingColor;\n+(UIColor *)memberListTextColor;\n+(UIColor *)memberListAwayTextColor;\n+(UIColor *)timestampColor;\n+(UIColor *)darkBlueColor;\n+(UIColor *)networkErrorBackgroundColor;\n+(UIColor *)networkErrorColor;\n+(UIColor *)colorFromHexString:(NSString *)hexString;\n+(UIColor *)mIRCColor:(int)color background:(BOOL)isBackground;\n+(int)mIRCColor:(UIColor *)color;\n+(UIColor *)errorBackgroundColor;\n+(UIColor *)statusBackgroundColor;\n+(UIColor *)selfBackgroundColor;\n+(UIColor *)highlightBackgroundColor;\n+(UIColor *)highlightTimestampColor;\n+(UIColor *)noticeBackgroundColor;\n+(UIColor *)timestampBackgroundColor;\n+(UIColor *)collapsedRowTextColor;\n+(UIColor *)collapsedRowNickColor;\n+(UIColor *)collapsedHeadingBackgroundColor;\n+(UIColor *)navBarColor;\n+(UIColor *)navBarHeadingColor;\n+(UIColor *)navBarSubheadingColor;\n+(UIImage *)navBarBackgroundImage;\n+(UIColor *)textareaTextColor;\n+(UIImage *)textareaBackgroundImage;\n+(UIColor *)textareaBackgroundColor;\n+(UIColor *)linkColor;\n+(UIColor *)lightLinkColor;\n+(UIColor *)serverBackgroundColor;\n+(UIColor *)bufferBackgroundColor;\n+(UIColor *)unreadBorderColor;\n+(UIColor *)highlightBorderColor;\n+(UIColor *)networkErrorBorderColor;\n+(UIColor *)bufferTextColor;\n+(UIColor *)inactiveBufferTextColor;\n+(UIColor *)unreadBufferTextColor;\n+(UIColor *)selectedBufferTextColor;\n+(UIColor *)selectedBufferBackgroundColor;\n+(UIColor *)bufferBorderColor;\n+(UIColor *)selectedBufferBorderColor;\n+(UIColor *)serverBorderColor;\n+(UIColor *)failedServerBorderColor;\n+(UIColor *)backlogDividerColor;\n+(UIColor *)chatterBarTextColor;\n+(UIColor *)chatterBarColor;\n+(UIColor *)awayBarTextColor;\n+(UIColor *)awayBarColor;\n+(UIColor *)connectionBarTextColor;\n+(UIColor *)connectionBarColor;\n+(UIColor *)connectionErrorBarTextColor;\n+(UIColor *)connectionErrorBarColor;\n+(UIColor *)buffersDrawerBackgroundColor;\n+(UIColor *)usersDrawerBackgroundColor;\n+(UIColor *)iPadBordersColor;\n+(UIColor *)unreadBlueColor;\n+(UIColor *)archivesHeadingTextColor;\n+(UIColor *)archivedChannelTextColor;\n+(UIColor *)archivedBufferTextColor;\n+(UIColor *)selectedArchivesHeadingColor;\n+(UIColor *)timestampTopBorderColor;\n+(UIColor *)timestampBottomBorderColor;\n+(UIActivityIndicatorViewStyle)activityIndicatorViewStyle;\n+(UIColor *)expandCollapseIndicatorColor;\n+(UIColor *)bufferHighlightColor;\n+(UIColor *)selectedBufferHighlightColor;\n+(UIColor *)archivedBufferHighlightColor;\n+(UIColor *)selectedArchivedBufferHighlightColor;\n+(UIColor *)selectedArchivedBufferBackgroundColor;\n+(UIColor *)socketClosedBackgroundColor;\n+(NSString *)currentTheme;\n+(NSString *)colorForNick:(NSString *)nick;\n+(NSDictionary *)linkAttributes;\n+(NSDictionary *)lightLinkAttributes;\n+(UIColor *)selfNickColor;\n-(NSString *)toHexString;\n+(UIColor *)codeSpanForegroundColor;\n+(UIColor *)codeSpanBackgroundColor;\n+(UIColor *)quoteBorderColor;\n+(UIColor *)unreadCollapsedColor;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UIColor+IRCCloud.m",
    "content": "//\n//  UIColor+IRCCloud.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"UIColor+IRCCloud.h\"\n#import \"ColorFormatter.h\"\n\nUIImage *__timestampBackgroundImage;\nUIImage *__navbarBackgroundImage;\nUIImage *__textareaBackgroundImage;\nUIImage *__buffersDrawerBackgroundImage;\nUIImage *__usersDrawerBackgroundImage;\nUIImage *__socketClosedBackgroundImage;\n\nUIColor *__contentBackgroundColor;\nUIColor *__messageTextColor;\nUIColor *__opersGroupColor;\nUIColor *__ownersGroupColor;\nUIColor *__adminsGroupColor;\nUIColor *__opsGroupColor;\nUIColor *__halfopsGroupColor;\nUIColor *__voicedGroupColor;\nUIColor *__membersGroupColor;\nUIColor *__opersBorderColor;\nUIColor *__ownersBorderColor;\nUIColor *__adminsBorderColor;\nUIColor *__opsBorderColor;\nUIColor *__halfopsBorderColor;\nUIColor *__voicedBorderColor;\nUIColor *__membersBorderColor;\nUIColor *__opersHeadingColor;\nUIColor *__ownersHeadingColor;\nUIColor *__adminsHeadingColor;\nUIColor *__opsHeadingColor;\nUIColor *__halfopsHeadingColor;\nUIColor *__voicedHeadingColor;\nUIColor *__membersHeadingColor;\nUIColor *__memberListTextColor;\nUIColor *__memberListAwayTextColor;\nUIColor *__timestampColor;\nUIColor *__darkBlueColor;\nUIColor *__networkErrorBackgroundColor;\nUIColor *__networkErrorColor;\nUIColor *__errorBackgroundColor;\nUIColor *__statusBackgroundColor;\nUIColor *__selfBackgroundColor;\nUIColor *__highlightBackgroundColor;\nUIColor *__highlightTimestampColor;\nUIColor *__noticeBackgroundColor;\nUIColor *__timestampBackgroundColor;\nUIColor *__newMsgsBackgroundColor;\nUIColor *__collapsedRowTextColor;\nUIColor *__collapsedRowNickColor;\nUIColor *__collapsedHeadingBackgroundColor;\nUIColor *__navBarColor;\nUIColor *__navBarHeadingColor;\nUIColor *__navBarSubheadingColor;\nUIColor *__navBarBorderColor;\nUIColor *__textareaTextColor;\nUIColor *__textareaBackgroundColor;\nUIColor *__linkColor;\nUIColor *__lightLinkColor;\nUIColor *__serverBackgroundColor;\nUIColor *__bufferBackgroundColor;\nUIColor *__unreadBorderColor;\nUIColor *__highlightBorderColor;\nUIColor *__networkErrorBorderColor;\nUIColor *__bufferTextColor;\nUIColor *__inactiveBufferTextColor;\nUIColor *__unreadBufferTextColor;\nUIColor *__selectedBufferTextColor;\nUIColor *__selectedBufferBackgroundColor;\nUIColor *__bufferBorderColor;\nUIColor *__selectedBufferBorderColor;\nUIColor *__backlogDividerColor;\nUIColor *__chatterBarTextColor;\nUIColor *__chatterBarColor;\nUIColor *__awayBarTextColor;\nUIColor *__awayBarColor;\nUIColor *__connectionBarTextColor;\nUIColor *__connectionBarColor;\nUIColor *__connectionErrorBarTextColor;\nUIColor *__connectionErrorBarColor;\nUIColor *__buffersDrawerBackgroundColor;\nUIColor *__usersDrawerBackgroundColor;\nUIColor *__iPadBordersColor;\nUIColor *__placeholderColor;\nUIColor *__unreadBlueColor;\nUIColor *__serverBorderColor;\nUIColor *__failedServerBorderColor;\nUIColor *__archivesHeadingTextColor;\nUIColor *__archivedChannelTextColor;\nUIColor *__archivedBufferTextColor;\nUIColor *__selectedArchivesHeadingColor;\nUIColor *__timestampTopBorderColor;\nUIColor *__timestampBottomBorderColor;\nUIColor *__expandCollapseIndicatorColor;\nUIColor *__bufferHighlightColor;\nUIColor *__selectedBufferHighlightColor;\nUIColor *__archivedBufferHighlightColor;\nUIColor *__selectedArchivedBufferHighlightColor;\nUIColor *__selectedArchivedBufferBackgroundColor;\nUIColor *__selfNickColor;\nUIColor *__socketClosedBarColor;\nUIColor *__codeSpanForegroundColor;\nUIColor *__codeSpanBackgroundColor;\nUIColor *__quoteBorderColor;\nUIColor *__unreadCollapsedColor;\n\nUIColor *__mIRCColors_BG[IRC_COLOR_COUNT];\nUIColor *__mIRCColors_FG[IRC_COLOR_COUNT];\n\nUIEdgeInsets __safeInsets;\n\nBOOL __color_theme_is_dark;\n\nNSString *__current_theme;\n\nBOOL __compact = NO;\n\nUITraitCollection *__currentTraitCollection;\n\n@implementation UITextField (IRCCloudAppearanceHax)\n-(void)setPlaceholder:(NSString *)placeholder {\n    [self setAttributedPlaceholder:[[NSAttributedString alloc] initWithString:placeholder?placeholder:@\"\" attributes:@{NSForegroundColorAttributeName:__placeholderColor}]];\n}\n@end\n\n@implementation UITableViewCell (IRCCloudAppearanceHax)\n- (UIColor *)textLabelColor {\n    return self.textLabel.textColor;\n}\n\n- (void)setTextLabelColor:(UIColor *)textLabelColor {\n    if(textLabelColor)\n        self.textLabel.textColor = textLabelColor;\n}\n\n- (UIColor *)detailTextLabelColor {\n    return self.detailTextLabel.textColor;\n}\n\n- (void)setDetailTextLabelColor:(UIColor *)detailTextLabelColor {\n    if(detailTextLabelColor)\n        self.detailTextLabel.textColor = detailTextLabelColor;\n}\n@end\n\n@implementation UIColor (IRCCloud)\n+(BOOL)isDarkTheme {\n    return __color_theme_is_dark;\n}\n\n+(UIColor *)colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation lightness:(CGFloat)light alpha:(CGFloat)alpha {\n    saturation *= (light < 0.5)?light:(1-light);\n    \n    return [UIColor colorWithHue:hue saturation:(2*saturation)/(light+saturation) brightness:light+saturation alpha:alpha];\n}\n\n+(NSString *)colorForNick:(NSString *)nick {\n    NSArray *light_colors = @[\n                              @\"b22222\",\n                              @\"d2691e\",\n                              @\"ff9166\",\n                              @\"fa8072\",\n                              @\"ff8c00\",\n                              @\"228b22\",\n                              @\"808000\",\n                              @\"b7b05d\",\n                              @\"8ebd2e\",\n                              @\"2ebd2e\",\n                              @\"82b482\",\n                              @\"37a467\",\n                              @\"57c8a1\",\n                              @\"1da199\",\n                              @\"579193\",\n                              @\"008b8b\",\n                              @\"00bfff\",\n                              @\"4682b4\",\n                              @\"1e90ff\",\n                              @\"4169e1\",\n                              @\"6a5acd\",\n                              @\"7b68ee\",\n                              @\"9400d3\",\n                              @\"8b008b\",\n                              @\"ba55d3\",\n                              @\"ff00ff\",\n                              @\"ff1493\",\n                              ];\n    NSArray *dark_colors = @[\n                             @\"deb887\",\n                             @\"ffd700\",\n                             @\"ff9166\",\n                             @\"fa8072\",\n                             @\"ff8c00\",\n                             @\"00ff00\",\n                             @\"ffff00\",\n                             @\"bdb76b\",\n                             @\"9acd32\",\n                             @\"32cd32\",\n                             @\"8fbc8f\",\n                             @\"3cb371\",\n                             @\"66cdaa\",\n                             @\"20b2aa\",\n                             @\"40e0d0\",\n                             @\"00ffff\",\n                             @\"00bfff\",\n                             @\"87ceeb\",\n                             @\"339cff\",\n                             @\"6495ed\",\n                             @\"b2a9e5\",\n                             @\"ff69b4\",\n                             @\"da70d6\",\n                             @\"ee82ee\",\n                             @\"d68fff\",\n                             @\"ff00ff\",\n                             @\"ffb6c1\"\n                             ];\n    NSArray *colors = __color_theme_is_dark?dark_colors:light_colors;\n    \n    // Normalise a bit\n    // typically ` and _ are used on the end alone\n    NSRegularExpression *r = [NSRegularExpression regularExpressionWithPattern:@\"[`_]+$\" options:NSRegularExpressionCaseInsensitive error:nil];\n    NSString *normalizedNick = [r stringByReplacingMatchesInString:[nick lowercaseString] options:0 range:NSMakeRange(0, nick.length) withTemplate:@\"\"];\n    // remove |<anything> from the end\n    r = [NSRegularExpression regularExpressionWithPattern:@\"\\\\|.*$\" options:NSRegularExpressionCaseInsensitive error:nil];\n    normalizedNick = [r stringByReplacingMatchesInString:normalizedNick options:0 range:NSMakeRange(0, normalizedNick.length) withTemplate:@\"\"];\n    \n    double hash = 0;\n    int32_t lHash = 0;\n    for(int i = 0; i < normalizedNick.length; i++) {\n        hash = [normalizedNick characterAtIndex:i] + (double)(lHash << 6) + (double)(lHash << 16) - hash;\n        lHash = [[NSNumber numberWithDouble:hash] intValue];\n    }\n        \n    return [colors objectAtIndex:(NSUInteger)llabs([[NSNumber numberWithDouble:hash] longLongValue] % (int)(colors.count))];\n}\n\n+(void)setSafeInsets:(UIEdgeInsets)insets {\n    __safeInsets = insets;\n}\n\n+(void)setTheme:(NSString *)theme {\n    if([theme isEqualToString:@\"automatic\"]) {\n        if (@available(iOS 13, *)) {\n            if(!__currentTraitCollection)\n                __currentTraitCollection = [UITraitCollection currentTraitCollection];\n            theme = (__currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) ? @\"midnight\" : @\"dawn\";\n        } else {\n            theme = @\"dawn\";\n        }\n    }\n\n    CLS_LOG(@\"Setting theme: %@\", theme);\n    \n    int i = 0;\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"FFFFFF\"]; //white\n    __mIRCColors_BG[i++] = [UIColor blackColor];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"000080\"]; //navy\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"008000\"]; //green\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"FF0000\"]; //red\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"800000\"]; //maroon\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"800080\"]; //purple\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"FFA500\"]; //orange\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"FFFF00\"]; //yellow\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"00FF00\"]; //lime\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"008080\"]; //teal\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"00FFFF\"]; //cyan\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"0000FF\"]; //blue\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"FF00FF\"]; //magenta\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"808080\"]; //grey\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"C0C0C0\"]; //silver\n    // http://anti.teamidiot.de/static/nei/*/extended_mirc_color_proposal.html\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"470000\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"472100\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"474700\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"324700\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"004700\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"00472c\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"004747\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"002747\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"000047\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"2e0047\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"470047\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"47002a\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"740000\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"743a00\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"747400\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"517400\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"007400\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"007449\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"007474\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"004074\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"000074\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"4b0074\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"740074\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"740045\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"b50000\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"b56300\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"b5b500\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"7db500\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"00b500\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"00b571\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"00b5b5\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"0063b5\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"0000b5\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"7500b5\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"b500b5\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"b5006b\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ff0000\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ff8c00\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ffff00\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"b2ff00\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"00ff00\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"00ffa0\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"00ffff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"008cff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"0000ff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"a500ff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ff00ff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ff0098\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ff5959\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ffb459\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ffff71\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"cfff60\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"6fff6f\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"65ffc9\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"6dffff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"59b4ff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"5959ff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"c459ff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ff66ff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ff59bc\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ff9c9c\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ffd39c\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ffff9c\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"e2ff9c\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"9cff9c\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"9cffdb\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"9cffff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"9cd3ff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"9c9cff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"dc9cff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ff9cff\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ff94d3\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"000000\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"131313\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"282828\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"363636\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"4d4d4d\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"656565\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"818181\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"9f9f9f\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"bcbcbc\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"e2e2e2\"];\n    __mIRCColors_BG[i++] = [UIColor colorFromHexString:@\"ffffff\"];\n\n    if([theme isEqualToString:@\"dawn\"] || theme == nil) {\n        __color_theme_is_dark = NO;\n        \n        __bufferTextColor = [UIColor colorWithRed:0.114 green:0.251 blue:1 alpha:1];\n        __inactiveBufferTextColor = [UIColor colorWithRed:0.612 green:0.78 blue:1 alpha:1];\n        __iPadBordersColor = [UIColor colorWithRed:0.404 green:0.624 blue:1 alpha:1];\n        __navBarSubheadingColor = [UIColor colorWithWhite:0.467 alpha:1.0];\n        __chatterBarTextColor = [UIColor colorWithRed:0 green:0.129 blue:0.475 alpha:1];\n        __linkColor = [UIColor colorWithRed:0.114 green:0.251 blue:1 alpha:1];\n        __highlightTimestampColor = [UIColor colorWithRed:0.376 green:0 blue:0 alpha:1];\n        __highlightBackgroundColor = [UIColor colorWithRed:0.753 green:0.859 blue:1 alpha:1];\n        __selfBackgroundColor = [UIColor colorWithRed:0.886 green:0.929 blue:1 alpha:1];\n        \n        __contentBackgroundColor = [UIColor whiteColor];\n        __messageTextColor = [UIColor colorWithWhite:0.2 alpha:1.0];\n        __serverBackgroundColor = [UIColor colorWithRed:0.949 green:0.969 blue:0.988 alpha:1];\n        __bufferBackgroundColor = [UIColor colorWithRed:0.851 green:0.906 blue:1 alpha:1];\n        __memberListTextColor = [UIColor colorWithWhite:0.133 alpha:1.0];\n        __memberListAwayTextColor = [UIColor colorWithWhite:0.667 alpha:1.0];\n        __timestampColor = [UIColor colorWithWhite:0.667 alpha:1.0];\n        __timestampBackgroundColor = [UIColor whiteColor];\n        __statusBackgroundColor = [UIColor colorWithRed:0.949 green:0.969 blue:0.988 alpha:1];\n        __noticeBackgroundColor = [UIColor colorWithRed:0.851 green:0.906 blue:1 alpha:1];\n        __collapsedRowTextColor = [UIColor colorWithWhite:0.686 alpha:1.0];\n        __collapsedRowNickColor = [UIColor colorWithWhite:0.33 alpha:1.0];\n        __collapsedHeadingBackgroundColor = [UIColor colorWithRed:0.949 green:0.969 blue:0.988 alpha:1];\n        __navBarColor = [UIColor colorWithRed:0.949 green:0.969 blue:0.988 alpha:1];\n        __navBarBorderColor = [UIColor colorWithRed:0.851 green:0.906 blue:1 alpha:1];\n        __textareaTextColor = [UIColor colorWithWhite:0.2 alpha:1.0];\n        __textareaBackgroundColor = __navBarSubheadingColor;\n        __navBarHeadingColor = [UIColor colorWithWhite:0.133 alpha:1.0];\n        __lightLinkColor = [UIColor colorWithWhite:0.667 alpha:1.0];\n        __unreadBufferTextColor = [UIColor colorWithRed:0.114 green:0.251 blue:1 alpha:1];\n        __selectedBufferTextColor = [UIColor whiteColor];\n        __selectedBufferBackgroundColor = [UIColor colorWithRed:0.118 green:0.447 blue:1 alpha:1];\n        __bufferBorderColor = [UIColor colorWithRed:0.702 green:0.812 blue:1 alpha:1];\n        __selectedBufferBorderColor = [UIColor colorWithRed:0.243 green:0.047 blue:1 alpha:1];\n        __serverBorderColor = [UIColor colorWithRed:0.851 green:0.906 blue:1 alpha:1];\n        __failedServerBorderColor = [UIColor colorWithRed:0.906 green:0.667 blue:0 alpha:1];\n        __backlogDividerColor = [UIColor colorWithRed:0.404 green:0.624 blue:1 alpha:1];\n        __chatterBarColor = [UIColor colorWithRed:0.85 green:0.91 blue:1.00 alpha:1.0];\n        __awayBarTextColor = [UIColor colorWithWhite:0.686 alpha:1.0];\n        __awayBarColor = [UIColor colorWithRed:0.949 green:0.969 blue:0.988 alpha:1];\n        __connectionBarTextColor = [UIColor colorWithRed:0.071 green:0.243 blue:0.573 alpha:1];\n        __connectionBarColor = [UIColor colorWithRed:0.851 green:0.906 blue:1 alpha:1];\n        __connectionErrorBarTextColor = [UIColor colorWithRed:0.388 green:0.157 blue:0 alpha:1];\n        __connectionErrorBarColor = [UIColor colorWithRed:0.973 green:0.875 blue:0.149 alpha:1];\n        __errorBackgroundColor = [UIColor colorWithRed:1 green:0.996 blue:0.914 alpha:1];\n        __archivesHeadingTextColor = [UIColor colorWithWhite:0.4 alpha:1.0];\n        __archivedChannelTextColor = [UIColor colorWithWhite:0.667 alpha:1.0];\n        __archivedBufferTextColor = [UIColor colorWithWhite:0.4 alpha:1.0];\n        __selectedArchivesHeadingColor = [UIColor colorWithRed:0.867 green:0.867 blue:0.867 alpha:1];\n        __timestampTopBorderColor = [UIColor colorWithRed:0.851 green:0.906 blue:1 alpha:1];\n        __timestampBottomBorderColor = [UIColor colorWithRed:0.851 green:0.906 blue:1 alpha:1];\n        __placeholderColor = [UIColor colorWithRed:0.78 green:0.78 blue:0.804 alpha:1];\n        __expandCollapseIndicatorColor = [UIColor colorWithRed:0.702 green:0.812 blue:1 alpha:1];\n        __bufferHighlightColor = [UIColor colorWithRed:0.776 green:0.855 blue:1 alpha:1];\n        __selectedBufferHighlightColor = [UIColor colorWithRed:0.118 green:0.447 blue:1 alpha:1];\n        __archivedBufferHighlightColor = [UIColor colorWithRed:0.776 green:0.855 blue:1 alpha:1];\n        __selectedArchivedBufferHighlightColor = [UIColor colorWithWhite:0.667 alpha:1];\n        __selectedArchivedBufferBackgroundColor = [UIColor colorWithWhite:0.667 alpha:1];\n        \n        __codeSpanForegroundColor = [UIColor colorWithWhite:0.33 alpha:1];\n        __codeSpanBackgroundColor = [UIColor colorWithWhite:1.0 alpha:1];\n        \n        __opersBorderColor = [UIColor colorWithRed:0.878 green:0.137 blue:0.02 alpha:1];\n        __ownersBorderColor = [UIColor colorWithRed:0.906 green:0.667 blue:0 alpha:1];\n        __adminsBorderColor = [UIColor colorWithRed:0.396 green:0 blue:0.647 alpha:1];\n        __opsBorderColor = [UIColor colorWithRed:0.729 green:0.09 blue:0.098 alpha:1];\n        __halfopsBorderColor = [UIColor colorWithRed:0.71 green:0.349 blue:0 alpha:1];\n        __voicedBorderColor = [UIColor colorWithRed:0.145 green:0.694 blue:0 alpha:1];\n        __membersBorderColor = [UIColor colorWithRed:0.114 green:0.251 blue:1 alpha:1];\n        \n        __opersGroupColor = [UIColor colorWithRed:1 green:1 blue:0.82 alpha:1];\n        __ownersGroupColor = [UIColor colorWithRed:1 green:1 blue:0.82 alpha:1];\n        __adminsGroupColor = [UIColor colorWithRed:0.929 green:0.8 blue:1 alpha:1];\n        __opsGroupColor = [UIColor colorWithRed:0.996 green:0.949 blue:0.949 alpha:1];\n        __halfopsGroupColor = [UIColor colorWithRed:1 green:0.98 blue:0.949 alpha:1];\n        __voicedGroupColor = [UIColor colorWithRed:0.957 green:1 blue:0.929 alpha:1];\n        __membersGroupColor = [UIColor colorWithRed:0.851 green:0.906 blue:1 alpha:1];\n        \n        __opersHeadingColor = [UIColor colorWithRed:0.878 green:0.137 blue:0.02 alpha:1];\n        __ownersHeadingColor = [UIColor colorWithRed:0.906 green:0.667 blue:0 alpha:1];\n        __adminsHeadingColor = [UIColor colorWithRed:0.396 green:0 blue:0.647 alpha:1];\n        __opsHeadingColor = [UIColor colorWithRed:0.729 green:0.09 blue:0.098 alpha:1];\n        __halfopsHeadingColor = [UIColor colorWithRed:0.71 green:0.349 blue:0 alpha:1];\n        __voicedHeadingColor = [UIColor colorWithRed:0.145 green:0.694 blue:0 alpha:1];\n        __membersHeadingColor = [UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:1];\n        \n        __selfNickColor = [UIColor colorWithRed:0.08 green:0.17 blue:0.26 alpha:1.0];\n        __socketClosedBarColor = __timestampColor;\n        __unreadCollapsedColor = [UIColor colorWithRed:0.34 green:0.64 blue:0.97 alpha:1.0];\n\n        [[UITableView appearance] setBackgroundColor:[UIColor colorWithRed:0.937 green:0.937 blue:0.957 alpha:1]];\n        [[UITableView appearance] setSeparatorColor:nil];\n        [[UITableViewCell appearance] setBackgroundColor:[UIColor whiteColor]];\n        [[UITableViewCell appearance] setSelectedBackgroundView:nil];\n        [[UITableViewCell appearance] setTextLabelColor:__messageTextColor];\n        [[UITableViewCell appearance] setDetailTextLabelColor:[UIColor colorWithRed:0.557 green:0.557 blue:0.576 alpha:1]];\n        [[UITableViewCell appearance] setTintColor:nil];\n        [[UILabel appearanceWhenContainedInInstancesOfClasses:@[UITableViewHeaderFooterView.class]] setTextColor:__messageTextColor];\n        [[UISwitch appearance] setOnTintColor:nil];\n        [[UISlider appearance] setTintColor:nil];\n        \n        [[UITextField appearance] setTintColor:nil];\n        [[UITextField appearance] setKeyboardAppearance:UIKeyboardAppearanceDefault];\n        \n        [[UITextView appearance] setTintColor:nil];\n        [[UITextView appearance] setTextColor:nil];\n        \n        [[UIScrollView appearance] setIndicatorStyle:UIScrollViewIndicatorStyleDefault];\n        \n        [[UITableViewCell appearanceWhenContainedInInstancesOfClasses:@[UIImagePickerController.class]] setBackgroundColor:nil];\n        [[UIScrollView appearanceWhenContainedInInstancesOfClasses:@[UIImagePickerController.class]] setIndicatorStyle:UIScrollViewIndicatorStyleDefault];\n        \n        [[UINavigationBar appearance] setBackgroundImage:[self navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: [self navBarHeadingColor]}];\n        [[UINavigationBar appearance] setTintColor:[UIColor colorWithRed:0 green:0.478 blue:1 alpha:1]];\n        if (@available(iOS 13.0, *)) {\n            UINavigationBarAppearance *a = [[UINavigationBarAppearance alloc] init];\n            a.backgroundImage = [self navBarBackgroundImage];\n            a.titleTextAttributes = @{NSForegroundColorAttributeName: [self navBarHeadingColor]};\n            [[UINavigationBar appearance] setStandardAppearance:a];\n            if (@available(iOS 15.0, *)) {\n                [[UINavigationBar appearance] setCompactAppearance:a];\n#if !TARGET_OS_MACCATALYST\n                [[UINavigationBar appearance] setCompactScrollEdgeAppearance:a];\n#endif\n            }\n            [[UINavigationBar appearance] setScrollEdgeAppearance:a];\n        }\n        \n        __mIRCColors_FG[0] = [UIColor colorFromHexString:@\"FFFFFF\"]; //white\n        __mIRCColors_FG[1] = [UIColor blackColor]; //black\n        __mIRCColors_FG[2] = __color_theme_is_dark?[UIColor colorFromHexString:@\"4682B4\"]:[UIColor colorFromHexString:@\"000080\"]; //steelblue or navy\n        __mIRCColors_FG[3] = __color_theme_is_dark?[UIColor colorFromHexString:@\"32CD32\"]:[UIColor colorFromHexString:@\"008000\"]; //limegreen or green\n        __mIRCColors_FG[4] = [UIColor colorFromHexString:@\"FF0000\"]; //red\n        __mIRCColors_FG[5] = __color_theme_is_dark?[UIColor colorFromHexString:@\"FA8072\"]:[UIColor colorFromHexString:@\"800000\"]; //salmon or maroon\n        __mIRCColors_FG[6] = __color_theme_is_dark?[UIColor colorFromHexString:@\"DA70D6\"]:[UIColor colorFromHexString:@\"800080\"]; //orchird or purple\n        __mIRCColors_FG[7] = [UIColor colorFromHexString:@\"FFA500\"]; //orange\n        __mIRCColors_FG[8] = [UIColor colorFromHexString:@\"FFFF00\"]; //yellow\n        __mIRCColors_FG[9] = [UIColor colorFromHexString:@\"00FF00\"]; //lime\n        __mIRCColors_FG[10] = __color_theme_is_dark?[UIColor colorFromHexString:@\"20B2AA\"]:[UIColor colorFromHexString:@\"008080\"]; //lightseagreen or teal\n        __mIRCColors_FG[11] = [UIColor colorFromHexString:@\"00FFFF\"]; //cyan\n        __mIRCColors_FG[12] = __color_theme_is_dark?[UIColor colorFromHexString:@\"00BFFF\"]:[UIColor colorFromHexString:@\"0000FF\"]; //deepskyblue or blue\n        __mIRCColors_FG[13] = [UIColor colorFromHexString:@\"FF00FF\"]; //magenta\n        __mIRCColors_FG[14] = [UIColor colorFromHexString:@\"808080\"]; //grey\n        __mIRCColors_FG[15] = [UIColor colorFromHexString:@\"C0C0C0\"]; //silver\n    } else {\n        UIColor *color_border1;\n        UIColor *color_border2;\n        UIColor *color_border3;\n        UIColor *color_border4;\n        UIColor *color_border5;\n        UIColor *color_border6;\n        UIColor *color_border7;\n        UIColor *color_border8;\n        UIColor *color_border9;\n        UIColor *color_border10;\n        UIColor *color_border11;\n        \n        UIColor *color_text1;\n        UIColor *color_text2;\n        UIColor *color_text3;\n        UIColor *color_text4;\n        UIColor *color_text5;\n        UIColor *color_text6;\n        UIColor *color_text7;\n        UIColor *color_text8;\n        UIColor *color_text9;\n        UIColor *color_text10;\n        UIColor *color_text11;\n        UIColor *color_text12;\n        \n        UIColor *color_background0;\n        UIColor *color_background1;\n        UIColor *color_background2;\n        UIColor *color_background3;\n        UIColor *color_background4;\n        UIColor *color_background5;\n        UIColor *color_background5a;\n        UIColor *color_background6;\n        UIColor *color_background6a;\n        UIColor *color_background7;\n        UIColor *color_background7a;\n        UIColor *color_background8;\n        \n        CGFloat hue = 210.0f/360.0f;\n        CGFloat saturation = 0.55f;\n        CGFloat selectedSaturation = 1.0f;\n        \n        if([theme isEqualToString:@\"ash\"] || [theme isEqualToString:@\"midnight\"]) {\n            hue = 210.0f/360.0f;\n            saturation = 0.0f;\n            selectedSaturation = 0.0f;\n        } else if([theme isEqualToString:@\"dusk\"]) {\n            hue = 210.0f/360.0f;\n            saturation = 0.55f;\n            selectedSaturation = 1.0f;\n        } else if([theme isEqualToString:@\"emerald\"]) {\n            hue = 110.0f/360.0f;\n            saturation = 0.55f;\n            selectedSaturation = 1.0f;\n        } else if([theme isEqualToString:@\"orchid\"]) {\n            hue = 314.0f/360.0f;\n            saturation = 0.55f;\n            selectedSaturation = 1.0f;\n        } else if([theme isEqualToString:@\"rust\"]) {\n            hue = 0.0f;\n            saturation = 0.55f;\n            selectedSaturation = 1.0f;\n        } else if([theme isEqualToString:@\"sand\"]) {\n            hue = 45.0f/360.0f;\n            saturation = 0.55f;\n            selectedSaturation = 1.0f;\n        } else if([theme isEqualToString:@\"tropic\"]) {\n            hue = 180.0f/360.0f;\n            saturation = 0.55f;\n            selectedSaturation = 0.0f;\n        }\n        \n        color_border1 = [UIColor colorWithHue:hue saturation:saturation lightness:0.55f alpha:1.0f];\n        color_border2 = [UIColor colorWithHue:hue saturation:saturation lightness:0.50f alpha:1.0f];\n        color_border3 = [UIColor colorWithHue:hue saturation:saturation lightness:0.45f alpha:1.0f];\n        color_border4 = [UIColor colorWithHue:hue saturation:saturation lightness:0.40f alpha:1.0f];\n        color_border5 = [UIColor colorWithHue:hue saturation:saturation lightness:0.35f alpha:1.0f];\n        color_border6 = [UIColor colorWithHue:hue saturation:saturation lightness:0.30f alpha:1.0f];\n        color_border7 = [UIColor colorWithHue:hue saturation:saturation lightness:0.25f alpha:1.0f];\n        color_border8 = [UIColor colorWithHue:hue saturation:saturation lightness:0.20f alpha:1.0f];\n        color_border9 = [UIColor colorWithHue:hue saturation:saturation lightness:0.15f alpha:1.0f];\n        color_border10 = [UIColor colorWithHue:hue saturation:saturation lightness:0.10f alpha:1.0f];\n        color_border11 = [UIColor colorWithHue:hue saturation:saturation lightness:0.05f alpha:1.0f];\n        \n        color_text1 = [UIColor colorWithHue:hue saturation:saturation lightness:1.0f alpha:1.0f];\n        color_text2 = [UIColor colorWithHue:hue saturation:saturation lightness:0.95f alpha:1.0f];\n        color_text3 = [UIColor colorWithHue:hue saturation:saturation lightness:0.90f alpha:1.0f];\n        color_text4 = [UIColor colorWithHue:hue saturation:saturation lightness:0.85f alpha:1.0f];\n        color_text5 = [UIColor colorWithHue:hue saturation:saturation lightness:0.80f alpha:1.0f];\n        color_text6 = [UIColor colorWithHue:hue saturation:saturation lightness:0.75f alpha:1.0f];\n        color_text7 = [UIColor colorWithHue:hue saturation:saturation lightness:0.70f alpha:1.0f];\n        color_text8 = [UIColor colorWithHue:hue saturation:saturation lightness:0.65f alpha:1.0f];\n        color_text9 = [UIColor colorWithHue:hue saturation:saturation lightness:0.60f alpha:1.0f];\n        color_text10 = [UIColor colorWithHue:hue saturation:saturation lightness:0.55f alpha:1.0f];\n        color_text11 = [UIColor colorWithHue:hue saturation:saturation lightness:0.50f alpha:1.0f];\n        color_text12 = [UIColor colorWithHue:hue saturation:saturation lightness:0.45f alpha:1.0f];\n        \n        color_background0 = [UIColor colorWithHue:hue saturation:saturation lightness:0.50f alpha:1.0f];\n        color_background1 = [UIColor colorWithHue:hue saturation:saturation lightness:0.45f alpha:1.0f];\n        color_background2 = [UIColor colorWithHue:hue saturation:saturation lightness:0.40f alpha:1.0f];\n        color_background3 = [UIColor colorWithHue:hue saturation:saturation lightness:0.35f alpha:1.0f];\n        color_background4 = [UIColor colorWithHue:hue saturation:saturation lightness:0.30f alpha:1.0f];\n        color_background5 = [UIColor colorWithHue:hue saturation:saturation lightness:0.25f alpha:1.0f];\n        color_background5a = [UIColor colorWithHue:hue saturation:saturation lightness:0.23f alpha:1.0f];\n        color_background6 = [UIColor colorWithHue:hue saturation:saturation lightness:0.20f alpha:1.0f];\n        color_background6a = [UIColor colorWithHue:hue saturation:saturation lightness:0.17f alpha:1.0f];\n        color_background7 = [UIColor colorWithHue:hue saturation:saturation lightness:0.15f alpha:1.0f];\n        color_background7a = [UIColor colorWithHue:hue saturation:saturation lightness:0.12f alpha:1.0f];\n        color_background8 = [UIColor colorWithHue:hue saturation:saturation lightness:0.10f alpha:1.0f];\n        \n        __color_theme_is_dark = YES;\n\n        __iPadBordersColor = color_background7;\n        __bufferTextColor = __navBarSubheadingColor = color_text4;\n        __inactiveBufferTextColor = __archivesHeadingTextColor = color_text9;\n        __chatterBarTextColor = color_text5;\n        __linkColor = color_text1;\n        __highlightTimestampColor = [UIColor colorWithRed:1 green:0.878 blue:0.878 alpha:1];\n        __highlightBackgroundColor = color_background5;\n        __selfBackgroundColor = color_background6;\n        \n        __contentBackgroundColor = color_background7;\n        __messageTextColor = color_text4;\n        __serverBackgroundColor = color_background6;\n        __bufferBackgroundColor = color_background4;\n        __memberListTextColor = color_text5;\n        __memberListAwayTextColor = color_text9;\n        __timestampColor = color_text10;\n        __timestampBackgroundColor = color_background6;\n        __statusBackgroundColor = color_background6a;\n        __noticeBackgroundColor = color_background5a;\n        __collapsedRowTextColor = color_text12;\n        __collapsedRowNickColor = color_text7;\n        __collapsedHeadingBackgroundColor = color_background6;\n        __navBarColor = color_background5;\n        __navBarBorderColor = color_border10;\n        __textareaTextColor = color_text3;\n        __textareaBackgroundColor = color_background3;\n        __navBarHeadingColor = color_text1;\n        __lightLinkColor = color_text9;\n        __unreadBufferTextColor = color_text2;\n        __selectedBufferTextColor = color_border8;\n        __selectedBufferBackgroundColor = color_text3;\n        __bufferBorderColor = __serverBorderColor = __failedServerBorderColor = color_border9;\n        __selectedBufferBorderColor = color_border4;\n        __backlogDividerColor = color_border1;\n        __chatterBarColor = color_background3;\n        __awayBarTextColor = color_text7;\n        __awayBarColor = color_background6;\n        __connectionBarTextColor = color_text4;\n        __connectionBarColor = color_background4;\n        __connectionErrorBarTextColor = color_text4;\n        __connectionErrorBarColor = color_background5;\n        __errorBackgroundColor = [UIColor colorWithRed:0.698 green:0.698 blue:0.204 alpha:1];\n        __archivedChannelTextColor = [UIColor colorWithWhite:0.667 alpha:1.0];\n        __archivedBufferTextColor = [UIColor colorWithWhite:0.667 alpha:1.0];\n        __selectedArchivesHeadingColor = [UIColor colorWithRed:0.867 green:0.867 blue:0.867 alpha:1];\n        __timestampTopBorderColor = color_border9;\n        __timestampBottomBorderColor = color_border6;\n        __placeholderColor = color_text12;\n        __expandCollapseIndicatorColor = color_text12;\n        __bufferHighlightColor = color_background5;\n        __selectedBufferHighlightColor = color_text4;\n        __archivedBufferHighlightColor = color_background5;\n        __selectedArchivedBufferHighlightColor = color_text6;\n        __selectedArchivedBufferBackgroundColor = color_text6;\n        __socketClosedBarColor = color_border5;\n        __codeSpanForegroundColor = color_text3;\n        __codeSpanBackgroundColor = color_background1;\n        __unreadCollapsedColor = color_background2;\n\n        __opersBorderColor = [UIColor colorWithHue:30.0/360.0 saturation:0.85 lightness:0.25 alpha:1.0];\n        __ownersBorderColor = [UIColor colorWithHue:47.0/360.0 saturation:0.68 lightness:0.25 alpha:1.0];\n        __adminsBorderColor = [UIColor colorWithHue:265.0/360.0 saturation:0.44 lightness:0.36 alpha:1.0];\n        __opsBorderColor = [UIColor colorWithHue:0 saturation:0.36 lightness:0.38 alpha:1.0];\n        __halfopsBorderColor = [UIColor colorWithHue:37.0/360.0 saturation:0.45 lightness:0.28 alpha:1.0];\n        __voicedBorderColor = [UIColor colorWithHue:85.0/360.0 saturation:1.0 lightness:0.17 alpha:1.0];\n        __membersBorderColor = [UIColor colorWithHue:221.0/360.0 saturation:0.55 lightness:0.23 alpha:1.0];\n\n        __opersGroupColor = [UIColor colorWithHue:27.0/360.0 saturation:0.64 lightness:0.16 alpha:1.0];\n        __ownersGroupColor = [UIColor colorWithHue:45.0/360.0 saturation:0.29 lightness:0.19 alpha:1.0];\n        __adminsGroupColor = [UIColor colorWithHue:276.0/360.0 saturation:0.27 lightness:0.15 alpha:1.0];\n        __opsGroupColor = [UIColor colorWithHue:0 saturation:0.42 lightness:0.19 alpha:1.0];\n        __halfopsGroupColor = [UIColor colorWithHue:37.0/360.0 saturation:0.26 lightness:0.17 alpha:1.0];\n        __voicedGroupColor = [UIColor colorWithHue:94.0/360.0 saturation:0.25 lightness:0.16 alpha:1.0];\n        __membersGroupColor = [UIColor colorWithHue:217.0/360.0 saturation:0.30 lightness:0.15 alpha:1.0];\n        \n        __opersHeadingColor = [UIColor colorWithRed:0.992 green:0.745 blue:0.706 alpha:1];\n        __ownersHeadingColor = [UIColor colorWithRed:1 green:0.922 blue:0.706 alpha:1];\n        __adminsHeadingColor = [UIColor colorWithRed:0.784 green:0.447 blue:1 alpha:1];\n        __opsHeadingColor = [UIColor colorWithRed:0.957 green:0.663 blue:0.667 alpha:1];\n        __halfopsHeadingColor = [UIColor colorWithRed:1 green:0.749 blue:0.51 alpha:1];\n        __voicedHeadingColor = [UIColor colorWithRed:0.6 green:1 blue:0.494 alpha:1];\n        __membersHeadingColor = [UIColor colorWithRed:0.533 green:0.698 blue:0.867 alpha:1];\n        \n        __selfNickColor = [UIColor whiteColor];\n        \n        __mIRCColors_FG[0] = [UIColor colorFromHexString:@\"FFFFFF\"]; //white\n        __mIRCColors_FG[1] = [UIColor blackColor]; //black\n        __mIRCColors_FG[2] = [UIColor colorFromHexString:@\"4682B4\"]; //steelblue\n        __mIRCColors_FG[3] = [UIColor colorFromHexString:@\"32CD32\"]; //limegreen\n        __mIRCColors_FG[4] = [UIColor colorFromHexString:@\"FF0000\"]; //red\n        __mIRCColors_FG[5] = [UIColor colorFromHexString:@\"FA8072\"]; //salmon\n        __mIRCColors_FG[6] = [UIColor colorFromHexString:@\"DA70D6\"]; //orchird\n        __mIRCColors_FG[7] = [UIColor colorFromHexString:@\"FFA500\"]; //orange\n        __mIRCColors_FG[8] = [UIColor colorFromHexString:@\"FFFF00\"]; //yellow\n        __mIRCColors_FG[9] = [UIColor colorFromHexString:@\"00FF00\"]; //lime\n        __mIRCColors_FG[10] = [UIColor colorFromHexString:@\"20B2AA\"]; //lightseagreen\n        __mIRCColors_FG[11] = [UIColor colorFromHexString:@\"00FFFF\"]; //cyan\n        __mIRCColors_FG[12] = [UIColor colorFromHexString:@\"00BFFF\"]; //deepskyblue\n        __mIRCColors_FG[13] = [UIColor colorFromHexString:@\"FF00FF\"]; //magenta\n        __mIRCColors_FG[14] = [UIColor colorFromHexString:@\"808080\"]; //grey\n        __mIRCColors_FG[15] = [UIColor colorFromHexString:@\"C0C0C0\"]; //silver\n        \n        if([theme isEqualToString:@\"midnight\"]) {\n            __contentBackgroundColor = [UIColor blackColor];\n            __buffersDrawerBackgroundColor = [UIColor blackColor];\n            __navBarColor = __textareaBackgroundColor = color_border9;\n            __navBarBorderColor = color_border10;\n            __bufferBorderColor = __bufferBackgroundColor = [UIColor blackColor];\n            __serverBorderColor = color_border10;\n            __serverBackgroundColor = color_border9;\n            __iPadBordersColor = color_border10;\n            \n            __highlightBackgroundColor = color_background6a;\n            __noticeBackgroundColor = color_background7;\n            __selfBackgroundColor = color_background7a;\n            __statusBackgroundColor = color_background8;\n            \n            __mIRCColors_FG[1] = [UIColor colorFromHexString:@\"222222\"];\n        }\n        \n        [[UITableView appearance] setBackgroundColor:__contentBackgroundColor];\n        [[UITableView appearance] setSeparatorColor:__navBarBorderColor];\n        [[UITableViewCell appearance] setBackgroundColor:__serverBackgroundColor];\n        UIView *v = [[UIView alloc]initWithFrame:CGRectZero];\n        v.backgroundColor = __contentBackgroundColor;\n        [[UITableViewCell appearance] setSelectedBackgroundView:v];\n        [[UITableViewCell appearance] setTextLabelColor:color_text4];\n        [[UITableViewCell appearance] setDetailTextLabelColor:color_text7];\n        [[UITableViewCell appearance] setTintColor:color_text7];\n        [[UILabel appearanceWhenContainedInInstancesOfClasses:@[UITableViewHeaderFooterView.class]] setTextColor:color_text8];\n        [[UISwitch appearance] setOnTintColor:color_text7];\n        [[UISlider appearance] setTintColor:color_text7];\n        \n        [[UITextField appearance] setTintColor:[self textareaTextColor]];\n        [[UITextField appearance] setKeyboardAppearance:UIKeyboardAppearanceDark];\n        \n        [[UITextView appearance] setTintColor:[self textareaTextColor]];\n        [[UITextView appearance] setTextColor:[self textareaTextColor]];\n        \n        [[UIScrollView appearance] setIndicatorStyle:UIScrollViewIndicatorStyleWhite];\n\n        [[UITableViewCell appearanceWhenContainedInInstancesOfClasses:@[UIImagePickerController.class]] setBackgroundColor:nil];\n        [[UIScrollView appearanceWhenContainedInInstancesOfClasses:@[UIImagePickerController.class]] setIndicatorStyle:UIScrollViewIndicatorStyleDefault];\n\n        [[UINavigationBar appearance] setBackgroundImage:[self navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n        [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: [self navBarHeadingColor]}];\n        [[UINavigationBar appearance] setTintColor:[UIColor navBarSubheadingColor]];\n        if (@available(iOS 13.0, *)) {\n            UINavigationBarAppearance *a = [[UINavigationBarAppearance alloc] init];\n            a.backgroundImage = [self navBarBackgroundImage];\n            a.titleTextAttributes = @{NSForegroundColorAttributeName: [self navBarHeadingColor]};\n            [[UINavigationBar appearance] setStandardAppearance:a];\n            if (@available(iOS 15.0, *)) {\n                [[UINavigationBar appearance] setCompactAppearance:a];\n#if !TARGET_OS_MACCATALYST\n                [[UINavigationBar appearance] setCompactScrollEdgeAppearance:a];\n#endif\n            }\n            [[UINavigationBar appearance] setScrollEdgeAppearance:a];\n        }\n    }\n    \n    __timestampBackgroundImage = nil;\n    __navbarBackgroundImage = nil;\n    __textareaBackgroundImage = nil;\n    __buffersDrawerBackgroundImage = nil;\n    __usersDrawerBackgroundImage = nil;\n    __socketClosedBackgroundImage = nil;\n    __unreadBlueColor = [UIColor colorWithRed:0.118 green:0.447 blue:1 alpha:1];\n    __quoteBorderColor = [UIColor colorWithWhite:0.87 alpha:1];\n\n    __current_theme = theme?theme:@\"dawn\";\n    \n    for(int i = 16; i < IRC_COLOR_COUNT; i++) {\n        __mIRCColors_FG[i] = __mIRCColors_BG[i];\n    }\n}\n\n+(void)clearTheme {\n    [[UITableView appearance] setBackgroundColor:nil];\n    [[UITableView appearance] setSeparatorColor:nil];\n    [[UITableViewCell appearance] setBackgroundColor:nil];\n    [[UITableViewCell appearance] setSelectedBackgroundView:nil];\n    [[UITableViewCell appearance] setTextLabelColor:nil];\n    [[UITableViewCell appearance] setDetailTextLabelColor:nil];\n    [[UITableViewCell appearance] setTintColor:nil];\n    [[UILabel appearanceWhenContainedInInstancesOfClasses:@[UITableViewHeaderFooterView.class]] setTextColor:nil];\n    [[UISwitch appearance] setOnTintColor:nil];\n    [[UISlider appearance] setTintColor:nil];\n    \n    [[UITextField appearance] setTintColor:nil];\n    [[UITextField appearance] setKeyboardAppearance:UIKeyboardAppearanceDefault];\n    \n    [[UITextView appearance] setTintColor:nil];\n    [[UITextView appearance] setTextColor:nil];\n    \n    [[UIScrollView appearance] setIndicatorStyle:UIScrollViewIndicatorStyleDefault];\n    \n    [[UITableViewCell appearanceWhenContainedInInstancesOfClasses:@[UIImagePickerController.class]] setBackgroundColor:nil];\n    [[UIScrollView appearanceWhenContainedInInstancesOfClasses:@[UIImagePickerController.class]] setIndicatorStyle:UIScrollViewIndicatorStyleDefault];\n    \n    [[UINavigationBar appearance] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];\n    [[UINavigationBar appearance] setTitleTextAttributes:nil];\n    [[UINavigationBar appearance] setTintColor:nil];\n}\n\n+(NSString *)currentTheme {\n    return __current_theme;\n}\n\n+(void)setCurrentTraits:(UITraitCollection *)traitCollection {\n    __currentTraitCollection = traitCollection;\n}\n\n+(void)setTheme {\n    [self setTheme:[[NSUserDefaults standardUserDefaults] objectForKey:@\"theme\"]];\n}\n\n+(UIColor *)contentBackgroundColor {\n    return __contentBackgroundColor;\n}\n\n+(UIColor *)messageTextColor {\n    return __messageTextColor;\n}\n\n+(UIColor *)opersGroupColor {\n    return __opersGroupColor;\n}\n+(UIColor *)ownersGroupColor {\n    return __ownersGroupColor;\n}\n+(UIColor *)adminsGroupColor {\n    return __adminsGroupColor;\n}\n+(UIColor *)opsGroupColor {\n    return __opsGroupColor;\n}\n+(UIColor *)halfopsGroupColor {\n    return __halfopsGroupColor;\n}\n+(UIColor *)voicedGroupColor {\n    return __voicedGroupColor;\n}\n+(UIColor *)membersGroupColor {\n    return __membersGroupColor;\n}\n+(UIColor *)opersBorderColor {\n    return __opersBorderColor;\n}\n+(UIColor *)ownersBorderColor {\n    return __ownersBorderColor;\n}\n+(UIColor *)adminsBorderColor {\n    return __adminsBorderColor;\n}\n+(UIColor *)opsBorderColor {\n    return __opsBorderColor;\n}\n+(UIColor *)halfopsBorderColor {\n    return __halfopsBorderColor;\n}\n+(UIColor *)voicedBorderColor {\n    return __voicedBorderColor;\n}\n+(UIColor *)membersBorderColor {\n    return __membersBorderColor;\n}\n+(UIColor *)opersHeadingColor {\n    return __opersHeadingColor;\n}\n+(UIColor *)ownersHeadingColor {\n    return __ownersHeadingColor;\n}\n+(UIColor *)adminsHeadingColor {\n    return __adminsHeadingColor;\n}\n+(UIColor *)opsHeadingColor {\n    return __opsHeadingColor;\n}\n+(UIColor *)halfopsHeadingColor {\n    return __halfopsHeadingColor;\n}\n+(UIColor *)voicedHeadingColor {\n    return __voicedHeadingColor;\n}\n+(UIColor *)membersHeadingColor {\n    return __membersHeadingColor;\n}\n+(UIColor *)memberListTextColor {\n    return __memberListTextColor;\n}\n+(UIColor *)memberListAwayTextColor {\n    return __memberListAwayTextColor;\n}\n+(UIColor *)timestampColor {\n    return __timestampColor;\n}\n+(UIColor *)darkBlueColor {\n    static UIColor *c = nil;\n    if(!c)\n        c = [UIColor colorWithRed:0.094 green:0.247 blue:0.553 alpha:1.0]; /*#183f8d*/\n    return c;\n}\n+(UIColor *)networkErrorBackgroundColor {\n    static UIColor *c = nil;\n    if(!c)\n        c = [UIColor colorWithRed:0.973 green:0.875 blue:0.149 alpha:1];\n    return c;\n}\n+(UIColor *)networkErrorColor {\n    static UIColor *c = nil;\n    if(!c)\n        c = [UIColor colorWithRed:0.388 green:0.157 blue:0 alpha:1];\n    return c;\n}\n+(UIColor *)serverBackgroundColor {\n    return __serverBackgroundColor;\n}\n+(UIColor *)bufferBackgroundColor {\n    return __bufferBackgroundColor;\n}\n+(UIColor *) colorFromHexString:(NSString *)hexString {\n    //From: http://stackoverflow.com/a/3805354\n    \n    NSString *cleanString = [hexString stringByReplacingOccurrencesOfString:@\"#\" withString:@\"\"];\n    if([cleanString length] == 3) {\n        cleanString = [NSString stringWithFormat:@\"%@%@%@%@%@%@\",\n                       [cleanString substringWithRange:NSMakeRange(0, 1)],[cleanString substringWithRange:NSMakeRange(0, 1)],\n                       [cleanString substringWithRange:NSMakeRange(1, 1)],[cleanString substringWithRange:NSMakeRange(1, 1)],\n                       [cleanString substringWithRange:NSMakeRange(2, 1)],[cleanString substringWithRange:NSMakeRange(2, 1)]];\n    }\n    if([cleanString length] == 6) {\n        cleanString = [cleanString stringByAppendingString:@\"ff\"];\n    }\n    \n    unsigned int baseValue;\n    [[NSScanner scannerWithString:cleanString] scanHexInt:&baseValue];\n    \n    float red = ((baseValue >> 24) & 0xFF)/255.0f;\n    float green = ((baseValue >> 16) & 0xFF)/255.0f;\n    float blue = ((baseValue >> 8) & 0xFF)/255.0f;\n    float alpha = ((baseValue >> 0) & 0xFF)/255.0f;\n    \n    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];\n}\n\n+(UIColor *)mIRCColor:(int)color background:(BOOL)isBackground {\n    if(color < IRC_COLOR_COUNT)\n        return isBackground?__mIRCColors_BG[color]:__mIRCColors_FG[color];\n    return nil;\n}\n\n//https://stackoverflow.com/a/8899384\n- (BOOL)isEqualToColor:(UIColor *)otherColor {\n    CGColorSpaceRef colorSpaceRGB = CGColorSpaceCreateDeviceRGB();\n    \n    UIColor *(^convertColorToRGBSpace)(UIColor*) = ^(UIColor *color) {\n        if (CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) == kCGColorSpaceModelMonochrome) {\n            const CGFloat *oldComponents = CGColorGetComponents(color.CGColor);\n            CGFloat components[4] = {oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]};\n            CGColorRef colorRef = CGColorCreate( colorSpaceRGB, components );\n            \n            UIColor *color = [UIColor colorWithCGColor:colorRef];\n            CGColorRelease(colorRef);\n            return color;\n        } else\n            return color;\n    };\n    \n    UIColor *selfColor = convertColorToRGBSpace(self);\n    otherColor = convertColorToRGBSpace(otherColor);\n    CGColorSpaceRelease(colorSpaceRGB);\n    \n    return [selfColor isEqual:otherColor];\n}\n\n+(int)mIRCColor:(UIColor *)color {\n    for(int i = 0; i < IRC_COLOR_COUNT; i++) {\n        if([color isEqualToColor:__mIRCColors_FG[i]] || [color isEqualToColor:__mIRCColors_BG[i]])\n            return i;\n    }\n    \n    return -1;\n}\n\n+(UIColor *)errorBackgroundColor {\n    return __errorBackgroundColor;\n}\n+(UIColor *)highlightBackgroundColor {\n    return __highlightBackgroundColor;\n}\n+(UIColor *)statusBackgroundColor {\n    return __statusBackgroundColor;\n}\n+(UIColor *)selfBackgroundColor {\n    return __selfBackgroundColor;\n}\n+(UIColor *)noticeBackgroundColor {\n    return __noticeBackgroundColor;\n}\n+(UIColor *)highlightTimestampColor {\n    return __highlightTimestampColor;\n}\n+(UIColor *)timestampBackgroundColor {\n    return __timestampBackgroundColor;\n}\n+(UIColor *)socketClosedBackgroundColor {\n    if(!__socketClosedBackgroundImage) {\n        float scaleFactor = [[UIScreen mainScreen] scale];\n        int width = [[UIScreen mainScreen] bounds].size.width;\n        int height = FONT_SIZE-2;\n        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();\n        CGContextRef context = CGBitmapContextCreate(NULL, width * scaleFactor, height * scaleFactor, 8, 4 * width * scaleFactor, colorSpace, (CGBitmapInfo)kCGImageAlphaNoneSkipFirst);\n        CGContextScaleCTM(context, scaleFactor, scaleFactor);\n        CGContextSetFillColorWithColor(context, [self contentBackgroundColor].CGColor);\n        CGContextFillRect(context, CGRectMake(0,0,width,height));\n        CGContextSetLineCap(context, kCGLineCapSquare);\n        CGContextSetStrokeColorWithColor(context, __socketClosedBarColor.CGColor);\n        CGContextSetLineWidth(context, 1.0);\n        CGContextMoveToPoint(context, 0.0, height / 2 - 1);\n        CGContextAddLineToPoint(context, width, height / 2 - 1);\n        CGContextMoveToPoint(context, 0.0, height / 2 + 1);\n        CGContextAddLineToPoint(context, width, height / 2 + 1);\n        CGContextStrokePath(context);\n        CGImageRef cgImage = CGBitmapContextCreateImage(context);\n        __socketClosedBackgroundImage = [UIImage imageWithCGImage:cgImage scale:scaleFactor orientation:UIImageOrientationUp];\n        CFRelease(cgImage);\n        CGContextRelease(context);\n        CGColorSpaceRelease(colorSpace);\n    }\n    return [UIColor colorWithPatternImage:__socketClosedBackgroundImage];\n}\n+(UIColor *)collapsedRowTextColor {\n    return __collapsedRowTextColor;\n}\n+(UIColor *)collapsedRowNickColor {\n    return __collapsedRowNickColor;\n}\n+(UIColor *)collapsedHeadingBackgroundColor {\n    return __collapsedHeadingBackgroundColor;\n}\n+(UIColor *)navBarColor {\n    return __navBarColor;\n}\n+(UIImage *)navBarBackgroundImage {\n    if(!__navbarBackgroundImage) {\n        float scaleFactor = [[UIScreen mainScreen] scale];\n        int width = [[UIScreen mainScreen] bounds].size.width;\n        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();\n        CGContextRef context = CGBitmapContextCreate(NULL, width * scaleFactor, 88 * scaleFactor, 8, 4 * width * scaleFactor, colorSpace, (CGBitmapInfo)kCGImageAlphaNoneSkipFirst);\n        CGContextScaleCTM(context, scaleFactor, scaleFactor);\n        CGContextSetFillColorWithColor(context, __navBarColor.CGColor);\n        CGContextFillRect(context, CGRectMake(0,0,width,88));\n        CGContextSetLineCap(context, kCGLineCapSquare);\n        CGContextSetStrokeColorWithColor(context, __navBarBorderColor.CGColor);\n        CGContextSetLineWidth(context, 4.0);\n        CGContextMoveToPoint(context, 0.0, 0.0);\n        CGContextAddLineToPoint(context, width, 0.0);\n        CGContextStrokePath(context);\n        CGImageRef cgImage = CGBitmapContextCreateImage(context);\n        __navbarBackgroundImage = [[UIImage imageWithCGImage:cgImage scale:scaleFactor orientation:UIImageOrientationUp] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 1, 0) resizingMode:UIImageResizingModeStretch];\n        CFRelease(cgImage);\n        CGContextRelease(context);\n        CGColorSpaceRelease(colorSpace);\n    }\n    return __navbarBackgroundImage;\n}\n+(UIColor *)textareaTextColor {\n    return __textareaTextColor;\n}\n+(UIColor *)textareaBackgroundColor {\n    return __textareaBackgroundColor;\n}\n+(UIImage *)textareaBackgroundImage {\n    if(!__textareaBackgroundImage) {\n        float scaleFactor = [[UIScreen mainScreen] scale];\n        int width = [[UIScreen mainScreen] bounds].size.width;\n        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();\n        CGContextRef context = CGBitmapContextCreate(NULL, width * scaleFactor, 44 * scaleFactor, 8, 4 * width * scaleFactor, colorSpace, (CGBitmapInfo)kCGImageAlphaNoneSkipFirst);\n        CGContextScaleCTM(context, scaleFactor, scaleFactor);\n        CGContextSetFillColorWithColor(context, __textareaBackgroundColor.CGColor);\n        CGContextFillRect(context, CGRectMake(0,0,width,44));\n        if(!__color_theme_is_dark) {\n            CGContextSetFillColorWithColor(context, __contentBackgroundColor.CGColor);\n            CGContextFillRect(context, CGRectMake(1,1,width-2,42));\n        }\n        CGImageRef cgImage = CGBitmapContextCreateImage(context);\n        __textareaBackgroundImage = [[UIImage imageWithCGImage:cgImage scale:scaleFactor orientation:UIImageOrientationUp] resizableImageWithCapInsets:UIEdgeInsetsMake(2, 2, 2, 2) resizingMode:UIImageResizingModeStretch];\n        CFRelease(cgImage);\n        CGContextRelease(context);\n        CGColorSpaceRelease(colorSpace);\n    }\n    return __textareaBackgroundImage;\n}\n+(UIColor *)navBarHeadingColor {\n    return __navBarHeadingColor;\n}\n+(UIColor *)navBarSubheadingColor {\n    return __navBarSubheadingColor;\n}\n+(UIColor *)linkColor {\n    return __linkColor;\n}\n+(UIColor *)lightLinkColor {\n    return __lightLinkColor;\n}\n+(UIColor *)unreadBorderColor {\n    static UIColor *c = nil;\n    if(!c)\n        c = [UIColor colorWithRed:0.071 green:0.243 blue:0.573 alpha:1];\n    return c;\n}\n+(UIColor *)highlightBorderColor {\n    static UIColor *c = nil;\n    if(!c)\n        c = [UIColor colorWithRed:0.824 green:0 blue:0.016 alpha:1];\n    return c;\n}\n+(UIColor *)networkErrorBorderColor{\n    static UIColor *c = nil;\n    if(!c)\n        c = [UIColor colorWithRed:0.859 green:0.702 blue:0 alpha:1];\n    return c;\n}\n+(UIColor *)bufferTextColor {\n    return __bufferTextColor;\n}\n+(UIColor *)inactiveBufferTextColor {\n    return __inactiveBufferTextColor;\n}\n+(UIColor *)unreadBufferTextColor {\n    return __unreadBufferTextColor;\n}\n+(UIColor *)selectedBufferTextColor {\n    return __selectedBufferTextColor;\n}\n+(UIColor *)selectedBufferBackgroundColor {\n    return __selectedBufferBackgroundColor;\n}\n+(UIColor *)bufferBorderColor {\n    return __bufferBorderColor;\n}\n+(UIColor *)selectedBufferBorderColor {\n    return __selectedBufferBorderColor;\n}\n+(UIColor *)backlogDividerColor {\n    return __backlogDividerColor;\n}\n+(UIColor *)chatterBarTextColor {\n    return __chatterBarTextColor;\n}\n+(UIColor *)chatterBarColor {\n    return __chatterBarColor;\n}\n+(UIColor *)awayBarTextColor {\n    return __awayBarTextColor;\n}\n+(UIColor *)awayBarColor {\n    return __awayBarColor;\n}\n+(UIColor *)connectionBarTextColor {\n    return __connectionBarTextColor;\n}\n+(UIColor *)connectionBarColor {\n    return __connectionBarColor;\n}\n+(UIColor *)connectionErrorBarTextColor {\n    return __connectionErrorBarTextColor;\n}\n+(UIColor *)connectionErrorBarColor {\n    return __connectionErrorBarColor;\n}\n+(UIColor *)buffersDrawerBackgroundColor {\n    if(!__buffersDrawerBackgroundImage) {\n        float scaleFactor = [[UIScreen mainScreen] scale];\n        int width = [[UIScreen mainScreen] bounds].size.width;\n        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();\n        CGContextRef context = CGBitmapContextCreate(NULL, width * scaleFactor, 16 * scaleFactor, 8, 4 * width * scaleFactor, colorSpace, (CGBitmapInfo)kCGImageAlphaNoneSkipFirst);\n        CGContextScaleCTM(context, scaleFactor, scaleFactor);\n        CGContextSetFillColorWithColor(context, [self bufferBackgroundColor].CGColor);\n        CGContextFillRect(context, CGRectMake(0,0,width,16));\n        CGContextSetLineCap(context, kCGLineCapSquare);\n        CGContextSetStrokeColorWithColor(context, [self bufferBorderColor].CGColor);\n        float borderWidth = 6.0;\n        borderWidth += __safeInsets.left;\n        CGContextSetLineWidth(context, borderWidth);\n        CGContextMoveToPoint(context, borderWidth / 2, 0.0);\n        CGContextAddLineToPoint(context, borderWidth / 2, 16.0);\n        CGContextStrokePath(context);\n        CGImageRef cgImage = CGBitmapContextCreateImage(context);\n        __buffersDrawerBackgroundImage = [[UIImage imageWithCGImage:cgImage scale:scaleFactor orientation:UIImageOrientationUp] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 6, 0, 0) resizingMode:UIImageResizingModeStretch];\n        CFRelease(cgImage);\n        CGContextRelease(context);\n        CGColorSpaceRelease(colorSpace);\n    }\n    return [UIColor colorWithPatternImage:__buffersDrawerBackgroundImage];\n}\n+(UIColor *)usersDrawerBackgroundColor {\n    if(!__color_theme_is_dark)\n        return [self membersGroupColor];\n    if(!__usersDrawerBackgroundImage) {\n        float scaleFactor = [[UIScreen mainScreen] scale];\n        int width = [[UIScreen mainScreen] bounds].size.width;\n        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();\n        CGContextRef context = CGBitmapContextCreate(NULL, width * scaleFactor, 16 * scaleFactor, 8, 4 * width * scaleFactor, colorSpace, (CGBitmapInfo)kCGImageAlphaNoneSkipFirst);\n        CGContextScaleCTM(context, scaleFactor, scaleFactor);\n        CGContextSetFillColorWithColor(context, [self membersGroupColor].CGColor);\n        CGContextFillRect(context, CGRectMake(0,0,width,16));\n        CGContextSetLineCap(context, kCGLineCapSquare);\n        CGContextSetStrokeColorWithColor(context, [self membersBorderColor].CGColor);\n        CGContextSetLineWidth(context, 3.0);\n        CGContextMoveToPoint(context, 1.0, 0.0);\n        CGContextAddLineToPoint(context, 1.0, 16.0);\n        CGContextStrokePath(context);\n        CGImageRef cgImage = CGBitmapContextCreateImage(context);\n        __usersDrawerBackgroundImage = [[UIImage imageWithCGImage:cgImage scale:scaleFactor orientation:UIImageOrientationUp] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 6, 0, 0) resizingMode:UIImageResizingModeStretch];\n        CFRelease(cgImage);\n        CGContextRelease(context);\n        CGColorSpaceRelease(colorSpace);\n    }\n    return [UIColor colorWithPatternImage:__usersDrawerBackgroundImage];\n}\n+(UIColor *)iPadBordersColor {\n    return __iPadBordersColor;\n}\n+(UIColor *)unreadBlueColor {\n    return __unreadBlueColor;\n}\n+(UIColor *)serverBorderColor {\n    return __serverBorderColor;\n}\n+(UIColor *)failedServerBorderColor {\n    return __failedServerBorderColor;\n}\n+(UIColor *)archivesHeadingTextColor {\n    return __archivesHeadingTextColor;\n}\n+(UIColor *)archivedChannelTextColor {\n    return __archivedChannelTextColor;\n}\n+(UIColor *)archivedBufferTextColor {\n    return __archivedBufferTextColor;\n}\n+(UIColor *)selectedArchivesHeadingColor {\n    return __selectedArchivesHeadingColor;\n}\n+(UIColor *)timestampTopBorderColor {\n    return __timestampTopBorderColor;\n}\n+(UIColor *)timestampBottomBorderColor {\n    return __timestampBottomBorderColor;\n}\n+(UIActivityIndicatorViewStyle)activityIndicatorViewStyle {\n    return __color_theme_is_dark?UIActivityIndicatorViewStyleWhite:UIActivityIndicatorViewStyleGray;\n}\n+(UIColor *)expandCollapseIndicatorColor {\n    return __expandCollapseIndicatorColor;\n}\n+(UIColor *)bufferHighlightColor {\n    return __bufferHighlightColor;\n}\n+(UIColor *)selectedBufferHighlightColor {\n    return __selectedBufferHighlightColor;\n}\n+(UIColor *)archivedBufferHighlightColor {\n    return __archivedBufferHighlightColor;\n}\n+(UIColor *)selectedArchivedBufferHighlightColor {\n    return __selectedArchivedBufferHighlightColor;\n}\n+(UIColor *)selectedArchivedBufferBackgroundColor {\n    return __selectedArchivedBufferBackgroundColor;\n}\n+(UIColor *)codeSpanForegroundColor {\n    return __codeSpanForegroundColor;\n}\n+(UIColor *)codeSpanBackgroundColor {\n    return __codeSpanBackgroundColor;\n}\n+(UIColor *)quoteBorderColor {\n    return __quoteBorderColor;\n}\n+(NSDictionary *)linkAttributes {\n    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];\n    if(__compact)\n        paragraphStyle.lineSpacing = 0;\n    else\n        paragraphStyle.lineSpacing = MESSAGE_LINE_SPACING;\n    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;\n    \n    return @{NSForegroundColorAttributeName: [UIColor linkColor],\n             NSParagraphStyleAttributeName: paragraphStyle };\n\n}\n+(NSDictionary *)lightLinkAttributes {\n    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];\n    if(__compact)\n        paragraphStyle.lineSpacing = 0;\n    else\n        paragraphStyle.lineSpacing = MESSAGE_LINE_SPACING;\n    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;\n    \n    return @{NSForegroundColorAttributeName: [UIColor lightLinkColor],\n             NSParagraphStyleAttributeName: paragraphStyle };\n}\n+(UIColor *)selfNickColor {\n    return __selfNickColor;\n}\n+(UIColor *)unreadCollapsedColor {\n    return __unreadCollapsedColor;\n}\n-(NSString *)toHexString {\n    CGFloat r,g,b;\n    \n    [self getRed:&r green:&g blue:&b alpha:nil];\n    \n    \n    return [NSString stringWithFormat:@\"%02x%02x%02x\", (int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b)];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UIDevice+UIDevice_iPhone6Hax.h",
    "content": "//\n//  UIDevice+UIDevice_iPhone6Hax.h\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n\n@interface UIDevice (UIDevice_iPhone6Hax)\n-(BOOL)isBigPhone;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UIDevice+UIDevice_iPhone6Hax.m",
    "content": "//\n//  UIDevice+UIDevice_iPhone6Hax.m\n//\n//  Copyright (C) 2014 IRCCloud, Ltd.\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#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n\nBOOL __isBigPhone = NO;\nBOOL __isBigPhone_set = NO;\n\n@implementation UIDevice (UIDevice_iPhone6Hax)\n-(BOOL)isBigPhone {\n    if(__isBigPhone_set)\n        return __isBigPhone;\n    \n    if(![[UIScreen mainScreen] respondsToSelector:@selector(nativeScale)])\n        __isBigPhone = NO;\n    else\n        __isBigPhone = [self userInterfaceIdiom] == UIUserInterfaceIdiomPhone && [[UIScreen mainScreen] nativeScale] > 2.0f;\n    \n    __isBigPhone_set = YES;\n    return __isBigPhone;\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UINavigationController+iPadSux.h",
    "content": "//\n//  UINavigationController+iPadSux.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n\n@interface UINavigationController (iPadSux)\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UINavigationController+iPadSux.m",
    "content": "//\n//  UINavigationController+iPadSux.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"UINavigationController+iPadSux.h\"\n\n@implementation UINavigationController (iPadSux)\n//Work-around for an iOS bug that prevents the keyboard from dismissing in a modal dialog on iPad\n- (BOOL)disablesAutomaticKeyboardDismissal {\n    return NO;\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UITableViewController+HeaderColorFix.h",
    "content": "//\n//  UITableViewController+HeaderColorFix.h\n//\n//  Copyright (C) 2019 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n\n@interface UITableViewController (HeaderColorFix)\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UITableViewController+HeaderColorFix.m",
    "content": "//\n//  UITableViewController+HeaderColorFix.m\n//\n//  Copyright (C) 2019 IRCCloud, Ltd.\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#import \"UITableViewController+HeaderColorFix.h\"\n\n@implementation UITableViewController (HeaderColorFix)\n-(void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section {\n    if([view isKindOfClass:UITableViewHeaderFooterView.class]) {\n        UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view;\n        header.textLabel.textColor = [UILabel appearanceWhenContainedInInstancesOfClasses:@[UITableViewHeaderFooterView.class]].textColor;\n    }\n}\n\n-(void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section {\n    if([view isKindOfClass:UITableViewHeaderFooterView.class]) {\n        UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view;\n        header.textLabel.textColor = [UILabel appearanceWhenContainedInInstancesOfClasses:@[UITableViewHeaderFooterView.class]].textColor;\n    }\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/URLHandler.h",
    "content": "//\n//  URLHandler.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <Foundation/Foundation.h>\n\ntypedef void (^mediaURLResult)(BOOL, NSString *);\n\n@interface URLHandler : NSObject {\n    NSMutableDictionary *_tasks;\n    NSMutableDictionary *_mediaURLs;\n    NSMutableDictionary *_fileIDs;\n}\n\n@property (copy) NSURL *appCallbackURL;\n@property (strong) UIWindow *window;\n\n+ (BOOL)isImageURL:(NSURL *)url;\n+ (BOOL)isYouTubeURL:(NSURL *)url;\n- (void)launchURL:(NSURL *)url;\n+ (UIActivityViewController *)activityControllerForItems:(NSArray *)items type:(NSString *)type;\n+ (int)URLtoBID:(NSURL *)url;\n- (NSDictionary *)MediaURLs:(NSURL *)url;\n- (void)fetchMediaURLs:(NSURL *)url result:(mediaURLResult)callback;\n- (void)addFileID:(NSString *)fileID URL:(NSURL *)url;\n- (void)clearFileIDs;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/URLHandler.m",
    "content": "//\n//  URLHandler.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <objc/message.h>\n#import <AVFoundation/AVFoundation.h>\n#import <AVKit/AVKit.h>\n#import <MediaPlayer/MediaPlayer.h>\n#import <SafariServices/SafariServices.h>\n#import \"URLHandler.h\"\n#import \"AppDelegate.h\"\n#import \"MainViewController.h\"\n#import \"ImageViewController.h\"\n#ifndef EXTENSION\n#import \"OpenInChromeController.h\"\n#import \"OpenInFirefoxControllerObjC.h\"\n#endif\n#import \"PastebinViewController.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"config.h\"\n#import \"ARChromeActivity.h\"\n#import \"TUSafariActivity.h\"\n#import \"UIDevice+UIDevice_iPhone6Hax.h\"\n@import Firebase;\n\n#ifndef EXTENSION\n@interface OpenInFirefoxActivity : UIActivity\n\n@end\n\n@implementation OpenInFirefoxActivity {\n    NSURL *_URL;\n}\n\n- (NSString *)activityType {\n    return NSStringFromClass([self class]);\n}\n\n- (NSString *)activityTitle {\n    return @\"Open in Firefox\";\n}\n\n- (UIImage *)activityImage {\n    return [UIImage imageNamed:@\"Firefox\"];\n}\n\n- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems {\n    if([[OpenInFirefoxControllerObjC sharedInstance] isFirefoxInstalled]) {\n        for (id activityItem in activityItems) {\n            if ([activityItem isKindOfClass:[NSURL class]] && [[UIApplication sharedApplication] canOpenURL:activityItem]) {\n                return YES;\n            }\n        }\n    }\n    return NO;\n}\n\n- (void)prepareWithActivityItems:(NSArray *)activityItems {\n    for (id activityItem in activityItems) {\n        if ([activityItem isKindOfClass:[NSURL class]]) {\n            self->_URL = activityItem;\n        }\n    }\n}\n\n- (void)performActivity {\n    BOOL completed = [[OpenInFirefoxControllerObjC sharedInstance] openInFirefox:self->_URL];\n    \n    [self activityDidFinish:completed];\n}\n\n@end\n#endif\n\n@implementation URLHandler\n\n#define HAS_IMAGE_SUFFIX(l) ([l hasSuffix:@\"jpg\"] || [l hasSuffix:@\"jpeg\"] || [l hasSuffix:@\"png\"] || [l hasSuffix:@\"gif\"] || [l hasSuffix:@\"bmp\"] || [l hasSuffix:@\"webp\"])\n\n#define IS_IMGUR(url) (([[url.host lowercaseString] isEqualToString:@\"imgur.com\"] || [[url.host lowercaseString] isEqualToString:@\"m.imgur.com\"]) || ([[url.host lowercaseString] isEqualToString:@\"i.imgur.com\"] && url.path.length > 1 && ([url.path hasSuffix:@\".gifv\"] || [url.path hasSuffix:@\".webm\"] || [url.path hasSuffix:@\".mp4\"])))\n\n#define IS_FLICKR(url) ([[url.host lowercaseString] hasSuffix:@\"flickr.com\"] && [[url.path lowercaseString] hasPrefix:@\"/photos/\"])\n\n#define IS_INSTAGRAM(url) (([[url.host lowercaseString] hasSuffix:@\"instagram.com\"] || \\\n                            [[url.host lowercaseString] hasSuffix:@\"instagr.am\"]) \\\n                           && [[url.path lowercaseString] hasPrefix:@\"/p/\"])\n\n#define IS_DROPLR(url) (([[url.host lowercaseString] isEqualToString:@\"droplr.com\"] || \\\n                         [[url.host lowercaseString] isEqualToString:@\"d.pr\"]) \\\n                         && [[url.path lowercaseString] hasPrefix:@\"/i/\"])\n\n#define IS_CLOUDAPP(url) ([url.host.lowercaseString isEqualToString:@\"cl.ly\"] \\\n                          && url.path.length \\\n                          && ![url.path.lowercaseString isEqualToString:@\"/robots.txt\"] \\\n                          && ![url.path.lowercaseString isEqualToString:@\"/image\"])\n\n#define IS_STEAM(url) (([url.host.lowercaseString hasSuffix:@\".steampowered.com\"] || [url.host.lowercaseString hasSuffix:@\".steamusercontent.com\"]) && [url.path.lowercaseString hasPrefix:@\"/ugc/\"])\n\n#define IS_LEET(url) (([url.host.lowercaseString hasSuffix:@\"leetfiles.com\"] || [url.host.lowercaseString hasSuffix:@\"leetfil.es\"]) \\\n                        && [url.path.lowercaseString hasPrefix:@\"/image\"])\n\n#define IS_GIPHY(url) ((([url.host.lowercaseString isEqualToString:@\"giphy.com\"] || [url.host.lowercaseString isEqualToString:@\"www.giphy.com\"]) && [url.path.lowercaseString hasPrefix:@\"/gifs/\"]) || [url.host.lowercaseString isEqualToString:@\"gph.is\"])\n\n#define IS_YOUTUBE(url) ((([url.host.lowercaseString isEqualToString:@\"youtube.com\"] || [url.host.lowercaseString hasSuffix:@\".youtube.com\"]) && [url.path.lowercaseString hasPrefix:@\"/watch\"]) || ([url.host.lowercaseString isEqualToString:@\"youtu.be\"] && url.path.length > 1))\n\n#define IS_WIKI(url) ([url.path.lowercaseString hasPrefix:@\"/wiki/\"] && HAS_IMAGE_SUFFIX(url.absoluteString.lowercaseString))\n\n#define IS_TWIMG(url) ([url.host.lowercaseString hasSuffix:@\".twimg.com\"] && [url.path.lowercaseString hasPrefix:@\"/media/\"] && [url.path rangeOfString:@\":\"].location != NSNotFound && HAS_IMAGE_SUFFIX([url.path substringToIndex:[url.path rangeOfString:@\":\"].location].lowercaseString))\n\n#define IS_XKCD(url) (([[url.host lowercaseString] hasSuffix:@\".xkcd.com\"] || [[url.host lowercaseString] isEqualToString:@\"xkcd.com\"]) && [url.path rangeOfCharacterFromSet:[[NSCharacterSet characterSetWithCharactersInString:@\"0123456789/\"] invertedSet]].location == NSNotFound)\n\n#define IS_IRCCLOUD_AVATAR(url) ([[url.host lowercaseString] isEqualToString:@\"static.irccloud-cdn.com\"] && [url.path hasPrefix:@\"/avatar-redirect/s\"])\n\n#define IS_SLACK_AVATAR(url) ([[url.host lowercaseString] hasSuffix:@\".slack-edge.com\"] && ([url.path hasSuffix:@\"-72\"] || [url.path hasSuffix:@\"-192\"] || [url.path hasSuffix:@\"-512\"]))\n\n#define IS_GRAVATAR(url) ([[url.host lowercaseString] hasSuffix:@\".gravatar.com\"] && [url.path hasPrefix:@\"/avatar/\"])\n\n-(instancetype)init {\n    self = [super init];\n    \n    if(self) {\n        self->_tasks = [[NSMutableDictionary alloc] init];\n        self->_mediaURLs = [[NSMutableDictionary alloc] init];\n        self->_fileIDs = [[NSMutableDictionary alloc] init];\n    }\n    \n    return self;\n}\n\n-(NSDictionary *)MediaURLs:(NSURL *)original_url {\n    NSURL *url = original_url;\n    if([self->_mediaURLs objectForKey:url])\n        return [self->_mediaURLs objectForKey:url];\n    \n    if([[url.host lowercaseString] isEqualToString:@\"www.dropbox.com\"]) {\n        if([url.path hasPrefix:@\"/s/\"])\n            url = [NSURL URLWithString:[NSString stringWithFormat:@\"https://dl.dropboxusercontent.com%@\", [url.path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]]];\n        else\n            url = [NSURL URLWithString:[NSString stringWithFormat:@\"%@?dl=1\", url.absoluteString]];\n    } else if(([[url.host lowercaseString] isEqualToString:@\"d.pr\"] || [[url.host lowercaseString] isEqualToString:@\"droplr.com\"]) && [url.path hasPrefix:@\"/i/\"] && ![url.path hasSuffix:@\"+\"]) {\n        url = [NSURL URLWithString:[NSString stringWithFormat:@\"https://droplr.com%@+\", [url.path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]]];\n    } else if([[url.host lowercaseString] isEqualToString:@\"imgur.com\"] || [[url.host lowercaseString] isEqualToString:@\"m.imgur.com\"]) {\n        return nil;\n    } else if([[url.host lowercaseString] isEqualToString:@\"i.imgur.com\"]) {\n        return nil;\n    } else if(([[url.host lowercaseString] hasSuffix:@\"giphy.com\"] || [[url.host lowercaseString] isEqualToString:@\"gph.is\"]) && url.pathExtension.length == 0) {\n        return nil;\n    } else if([[url.host lowercaseString] hasSuffix:@\"flickr.com\"] && [url.host rangeOfString:@\"static\"].location == NSNotFound) {\n        return nil;\n    /*} else if(([[url.host lowercaseString] hasSuffix:@\"instagram.com\"] || [[url.host lowercaseString] hasSuffix:@\"instagr.am\"]) && [url.path hasPrefix:@\"/p/\"]) {\n        return nil;*/\n    } else if([url.host.lowercaseString isEqualToString:@\"cl.ly\"]) {\n        return nil;\n    } else if([url.path hasPrefix:@\"/wiki/\"] && [url.absoluteString containsString:@\"/File:\"]) {\n        return nil;\n    } else if([url.host.lowercaseString isEqualToString:@\"xkcd.com\"] || [url.host.lowercaseString hasSuffix:@\".xkcd.com\"]) {\n        return nil;\n    } else if([url.host hasSuffix:@\"leetfiles.com\"]) {\n        NSString *u = url.absoluteString;\n        u = [u stringByReplacingOccurrencesOfString:@\"www.\" withString:@\"\"];\n        u = [u stringByReplacingOccurrencesOfString:@\"leetfiles.com/image\" withString:@\"i.leetfiles.com/\"];\n        u = [u stringByReplacingOccurrencesOfString:@\"?id=\" withString:@\"\"];\n        url = [NSURL URLWithString:u];\n    } else if([url.host hasSuffix:@\"leetfil.es\"]) {\n        NSString *u = url.absoluteString;\n        u = [u stringByReplacingOccurrencesOfString:@\"www.\" withString:@\"\"];\n        u = [u stringByReplacingOccurrencesOfString:@\"leetfil.es/image\" withString:@\"i.leetfiles.com/\"];\n        u = [u stringByReplacingOccurrencesOfString:@\"?id=\" withString:@\"\"];\n        url = [NSURL URLWithString:u];\n    }\n    \n    [self->_mediaURLs setObject:@{@\"thumb\":url, @\"image\":url, @\"url\":url} forKey:original_url];\n    \n    return [self->_mediaURLs objectForKey:url];\n}\n\n-(void)fetchMediaURLs:(NSURL *)url result:(mediaURLResult)callback {\n    if([self->_mediaURLs objectForKey:url]) {\n        callback(YES, [self->_mediaURLs objectForKey:url]);\n    } else if(![self->_tasks objectForKey:url]) {\n        [self->_tasks setObject:@(YES) forKey:url];\n        \n        if(([[url.host lowercaseString] isEqualToString:@\"imgur.com\"] || [[url.host lowercaseString] isEqualToString:@\"m.imgur.com\"]) && url.path.length > 1) {\n            NSString *imageID = [url.path substringFromIndex:1];\n            if([imageID rangeOfString:@\"/\"].location == NSNotFound) {\n                [self _loadImgur:imageID type:@\"image\" result:callback original_url:url];\n            } else if([imageID hasPrefix:@\"gallery/\"]) {\n                [self _loadImgur:[imageID substringFromIndex:8] type:@\"gallery\" result:callback original_url:url];\n            } else if([imageID hasPrefix:@\"a/\"]) {\n                [self _loadImgur:[imageID substringFromIndex:2] type:@\"album\" result:callback original_url:url];\n            } else if([imageID hasPrefix:@\"t/\"] && [[imageID substringFromIndex:2] rangeOfString:@\"/\"].location != NSNotFound) {\n                [self _loadImgur:[[imageID substringFromIndex:2] substringFromIndex:[[imageID substringFromIndex:2] rangeOfString:@\"/\"].location] type:@\"image\" result:callback original_url:url];\n            } else {\n                callback(NO, @\"Invalid URL\");\n            }\n        } else if([[url.host lowercaseString] isEqualToString:@\"i.imgur.com\"]) {\n            [self _loadImgur:[url.path substringToIndex:[url.path rangeOfString:@\".\"].location] type:@\"image\" result:callback original_url:url];\n        } else if(([[url.host lowercaseString] hasSuffix:@\"giphy.com\"] || [[url.host lowercaseString] isEqualToString:@\"gph.is\"]) && url.pathExtension.length == 0) {\n            NSString *u = url.absoluteString;\n            if([u rangeOfString:@\"/gifs/\"].location != NSNotFound) {\n                u = [NSString stringWithFormat:@\"http://giphy.com/gifs/%@\", [url.pathComponents objectAtIndex:2]];\n            }\n            [self _loadOembed:[NSString stringWithFormat:@\"https://giphy.com/services/oembed/?url=%@\", u] result:callback original_url:url];\n        } else if([[url.host lowercaseString] hasSuffix:@\"flickr.com\"] && [url.host rangeOfString:@\"static\"].location == NSNotFound) {\n            [self _loadOembed:[NSString stringWithFormat:@\"https://www.flickr.com/services/oembed/?url=%@&format=json\", url.absoluteString] result:callback original_url:url];\n        /*} else if(([[url.host lowercaseString] hasSuffix:@\"instagram.com\"] || [[url.host lowercaseString] hasSuffix:@\"instagr.am\"]) && [url.path hasPrefix:@\"/p/\"]) {\n            [self _loadOembed:[NSString stringWithFormat:@\"http://api.instagram.com/oembed?url=%@\", url.absoluteString] result:callback original_url:url];*/\n        } else if([url.host.lowercaseString isEqualToString:@\"cl.ly\"]) {\n            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];\n            [request addValue:@\"application/json\" forHTTPHeaderField:@\"Accept\"];\n            [[[NetworkConnection sharedInstance].urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n                if (error) {\n                    CLS_LOG(@\"Error fetching cl.ly metadata. Error %li : %@\", (long)error.code, error.userInfo);\n                    callback(NO,error.localizedDescription);\n                } else {\n                    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];\n                    if([[dict objectForKey:@\"item_type\"] isEqualToString:@\"image\"]) {\n                        [self->_mediaURLs setObject:@{@\"thumb\":[NSURL URLWithString:[dict objectForKey:@\"content_url\"]],\n                                                @\"image\":[NSURL URLWithString:[dict objectForKey:@\"content_url\"]],\n                                                @\"url\":url\n                                                } forKey:url];\n                        callback(YES, nil);\n                    } else {\n                        CLS_LOG(@\"Invalid type from cl.ly\");\n                        callback(NO,@\"This image type is not supported\");\n                    }\n                }\n            }] resume];\n        } else if([url.path hasPrefix:@\"/wiki/\"] && [url.absoluteString containsString:@\"/File:\"]) {\n            NSString *title = [url.absoluteString substringFromIndex:[url.absoluteString rangeOfString:@\"/File:\"].location + 1];\n            NSString *port = @\"\";\n            if(url.port)\n                port = [NSString stringWithFormat:@\":%@\", url.port];\n            NSURL *wikiurl = [NSURL URLWithString:[NSString stringWithFormat:@\"%@://%@%@%@\", url.scheme, url.host, port,[NSString stringWithFormat:@\"/w/api.php?action=query&format=json&prop=imageinfo&iiprop=url&titles=%@\", [title stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]]]];\n            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:wikiurl];\n            [request addValue:@\"application/json\" forHTTPHeaderField:@\"Accept\"];\n            [[[NetworkConnection sharedInstance].urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n                if (error) {\n                    CLS_LOG(@\"Error fetching MediaWiki metadata. Error %li : %@\", (long)error.code, error.userInfo);\n                    callback(NO,error.localizedDescription);\n                } else {\n                    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];\n                    NSDictionary *page = [[[[dict objectForKey:@\"query\"] objectForKey:@\"pages\"] allValues] objectAtIndex:0];\n                    if(page && [page objectForKey:@\"imageinfo\"]) {\n                        [self->_mediaURLs setObject:@{@\"thumb\":[NSURL URLWithString:[[[page objectForKey:@\"imageinfo\"] objectAtIndex:0] objectForKey:@\"url\"]],\n                                                @\"image\":[NSURL URLWithString:[[[page objectForKey:@\"imageinfo\"] objectAtIndex:0] objectForKey:@\"url\"]],\n                                                @\"url\":url\n                                                } forKey:url];\n                        callback(YES, nil);\n                    } else {\n                        CLS_LOG(@\"Invalid data from MediaWiki: %@\", dict);\n                        callback(NO,@\"This image type is not supported\");\n                    }\n                }\n            }] resume];\n        } else if([url.host.lowercaseString isEqualToString:@\"xkcd.com\"] || [url.host.lowercaseString hasSuffix:@\".xkcd.com\"]) {\n            [self _loadXKCD:url result:callback];\n        }\n    }\n}\n\n-(void)_loadOembed:(NSString *)url result:(mediaURLResult)callback original_url:(NSURL *)original_url {\n    NSURL *URL = [NSURL URLWithString:url];\n    NSURLRequest *request = [NSMutableURLRequest requestWithURL:URL];\n    [[[NetworkConnection sharedInstance].urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n        if (error) {\n            CLS_LOG(@\"Error fetching oembed. Error %li : %@\", (long)error.code, error.userInfo);\n            callback(NO,error.localizedDescription);\n        } else {\n            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];\n            if([[dict objectForKey:@\"type\"] isEqualToString:@\"photo\"]) {\n                [self->_mediaURLs setObject:@{@\"thumb\":[NSURL URLWithString:[dict objectForKey:@\"url\"]],\n                                        @\"image\":[NSURL URLWithString:[dict objectForKey:@\"url\"]],\n                                        @\"url\":original_url\n                                        } forKey:original_url];\n                callback(YES, nil);\n            } else if([[dict objectForKey:@\"provider_name\"] isEqualToString:@\"Instagram\"]) {\n                [self->_mediaURLs setObject:@{@\"thumb\":[NSURL URLWithString:[dict objectForKey:@\"thumbnail_url\"]],\n                                        @\"image\":[NSURL URLWithString:[dict objectForKey:@\"thumbnail_url\"]],\n                                        @\"description\":[[dict objectForKey:@\"title\"] isKindOfClass:NSString.class]?[dict objectForKey:@\"title\"]:@\"\",\n                                        @\"url\":original_url\n                                        } forKey:original_url];\n                callback(YES, nil);\n            } else if([[dict objectForKey:@\"provider_name\"] isEqualToString:@\"Giphy\"] && [[dict objectForKey:@\"url\"] rangeOfString:@\"/gifs/\"].location != NSNotFound) {\n                if([dict objectForKey:@\"image\"] && [[dict objectForKey:@\"image\"] hasSuffix:@\".gif\"]) {\n                    [self->_mediaURLs setObject:@{@\"thumb\":[NSURL URLWithString:[dict objectForKey:@\"image\"]],\n                                            @\"image\":[NSURL URLWithString:[dict objectForKey:@\"image\"]],\n                                            @\"url\":original_url\n                                            } forKey:original_url];\n                    callback(YES, nil);\n                } else {\n                    [self _loadGiphy:[[dict objectForKey:@\"url\"] substringFromIndex:[[dict objectForKey:@\"url\"] rangeOfString:@\"/gifs/\"].location + 6] result:callback original_url:original_url];\n                }\n            } else {\n                CLS_LOG(@\"Invalid type from oembed\");\n                callback(NO,@\"This URL type is not supported\");\n            }\n        }\n    }] resume];\n}\n\n-(void)_loadGiphy:(NSString *)gifID result:(mediaURLResult)callback original_url:(NSURL *)original_url {\n    //Request metadata using the Giphy public beta API key from https://giphy.api-docs.io/1.0/welcome/access-and-api-keys\n    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@\"https://api.giphy.com/v1/gifs/%@?api_key=dc6zaTOxFJmzC\", gifID]] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];\n    [request setHTTPShouldHandleCookies:NO];\n    \n    [[[NetworkConnection sharedInstance].urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n        if (error) {\n            CLS_LOG(@\"Error fetching giphy. Error %li : %@\", (long)error.code, error.userInfo);\n            callback(NO,error.localizedDescription);\n        } else {\n            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];\n            if([[[dict objectForKey:@\"meta\"] objectForKey:@\"status\"] intValue] == 200 && [[dict objectForKey:@\"data\"] objectForKey:@\"images\"]) {\n                dict = [[[dict objectForKey:@\"data\"] objectForKey:@\"images\"] objectForKey:@\"original\"];\n                if([[dict objectForKey:@\"mp4\"] length]) {\n                    [self->_mediaURLs setObject:@{@\"thumb\":[NSURL URLWithString:[dict objectForKey:@\"url\"]],\n                                            @\"mp4\":[NSURL URLWithString:[dict objectForKey:@\"mp4\"]],\n                                            @\"url\":original_url\n                                            } forKey:original_url];\n                    callback(YES, nil);\n                } else if([[dict objectForKey:@\"url\"] hasSuffix:@\".gif\"]) {\n                    [self->_mediaURLs setObject:@{@\"thumb\":[NSURL URLWithString:[dict objectForKey:@\"url\"]],\n                                            @\"image\":[NSURL URLWithString:[dict objectForKey:@\"url\"]],\n                                            @\"url\":original_url\n                                            } forKey:original_url];\n                    callback(YES, nil);\n                } else {\n                    CLS_LOG(@\"Invalid type from giphy: %@\", dict);\n                    callback(NO,@\"This image type is not supported\");\n                }\n            } else {\n                CLS_LOG(@\"giphy failure: %@\", dict);\n                callback(NO,@\"Unexpected response from server\");\n            }\n        }\n    }] resume];\n}\n\n-(void)_loadImgur:(NSString *)ID type:(NSString *)type result:(mediaURLResult)callback original_url:(NSURL *)original_url {\n#ifdef MASHAPE_KEY\n    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@\"https://imgur-apiv3.p.mashape.com/3/%@/%@\", type, ID]] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];\n    [request setValue:@MASHAPE_KEY forHTTPHeaderField:@\"X-Mashape-Authorization\"];\n#else\n    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@\"https://api.imgur.com/3/%@/%@\", type, ID]] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];\n#endif\n    [request setHTTPShouldHandleCookies:NO];\n#ifdef IMGUR_KEY\n    [request setValue:[NSString stringWithFormat:@\"Client-ID %@\", @IMGUR_KEY] forHTTPHeaderField:@\"Authorization\"];\n#endif\n    \n    [[[NetworkConnection sharedInstance].urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n        if (error) {\n            CLS_LOG(@\"Error fetching imgur. Error %li : %@\", (long)error.code, error.userInfo);\n            callback(NO,error.localizedDescription);\n        } else {\n            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];\n            if([[dict objectForKey:@\"success\"] intValue]) {\n                dict = [dict objectForKey:@\"data\"];\n                NSString *title = @\"\";\n                if([[dict objectForKey:@\"title\"] isKindOfClass:NSString.class])\n                    title = [dict objectForKey:@\"title\"];\n                if([[dict objectForKey:@\"images_count\"] intValue] == 1 || [[dict objectForKey:@\"is_album\"] intValue] == 0) {\n                    if([dict objectForKey:@\"images\"] && [(NSDictionary *)[dict objectForKey:@\"images\"] count] == 1)\n                        dict = [[dict objectForKey:@\"images\"] objectAtIndex:0];\n                    if([[dict objectForKey:@\"title\"] isKindOfClass:NSString.class] && [[dict objectForKey:@\"title\"] length])\n                        title = [dict objectForKey:@\"title\"];\n                    if([[dict objectForKey:@\"type\"] hasPrefix:@\"image/\"] && [[dict objectForKey:@\"animated\"] intValue] == 0) {\n                        NSMutableDictionary *d = @{@\"thumb\":[NSURL URLWithString:[dict objectForKey:@\"link\"]],\n                                            @\"image\":[NSURL URLWithString:[dict objectForKey:@\"link\"]],\n                                            @\"name\":title,\n                                            @\"description\":[[dict objectForKey:@\"description\"] isKindOfClass:NSString.class]?[dict objectForKey:@\"description\"]:@\"\",\n                                            @\"url\":original_url,\n                                            }.mutableCopy;\n                        if([[dict objectForKey:@\"width\"] intValue] && [[dict objectForKey:@\"height\"] intValue]) {\n                            [d setObject:@{@\"width\":[dict objectForKey:@\"width\"],@\"height\":[dict objectForKey:@\"height\"]} forKey:@\"properties\"];\n                        }\n                        [self->_mediaURLs setObject:d forKey:original_url];\n                        callback(YES, nil);\n                    } else if([[dict objectForKey:@\"animated\"] intValue] == 1 && [[dict objectForKey:@\"mp4\"] length] > 0) {\n                        if([[dict objectForKey:@\"looping\"] intValue] == 1) {\n                            NSMutableDictionary *d = @{@\"thumb\":[NSURL URLWithString:[[dict objectForKey:@\"mp4\"] stringByReplacingOccurrencesOfString:@\".mp4\" withString:@\".gif\"]],\n                                                       @\"mp4_loop\":[NSURL URLWithString:[dict objectForKey:@\"mp4\"]],\n                                                       @\"name\":title,\n                                                       @\"description\":[[dict objectForKey:@\"description\"] isKindOfClass:NSString.class]?[dict objectForKey:@\"description\"]:@\"\",\n                                                       @\"url\":original_url,\n                                                       }.mutableCopy;\n                            if([[dict objectForKey:@\"width\"] intValue] && [[dict objectForKey:@\"height\"] intValue]) {\n                                [d setObject:@{@\"width\":[dict objectForKey:@\"width\"],@\"height\":[dict objectForKey:@\"height\"]} forKey:@\"properties\"];\n                            }\n                            [self->_mediaURLs setObject:d forKey:original_url];\n                            callback(YES, nil);\n                        } else {\n                            NSMutableDictionary *d = @{@\"thumb\":[NSURL URLWithString:[[dict objectForKey:@\"mp4\"] stringByReplacingOccurrencesOfString:@\".mp4\" withString:@\".gif\"]],\n                                                       @\"mp4\":[NSURL URLWithString:[dict objectForKey:@\"mp4\"]],\n                                                       @\"name\":title,\n                                                       @\"description\":[[dict objectForKey:@\"description\"] isKindOfClass:NSString.class]?[dict objectForKey:@\"description\"]:@\"\",\n                                                       @\"url\":original_url,\n                                                       }.mutableCopy;\n                            if([[dict objectForKey:@\"width\"] intValue] && [[dict objectForKey:@\"height\"] intValue]) {\n                                [d setObject:@{@\"width\":[dict objectForKey:@\"width\"],@\"height\":[dict objectForKey:@\"height\"]} forKey:@\"properties\"];\n                            }\n                            [self->_mediaURLs setObject:d forKey:original_url];\n                            callback(YES, nil);\n                        }\n                    } else {\n                        CLS_LOG(@\"Invalid type from imgur: %@\", dict);\n                        callback(NO,@\"This image type is not supported\");\n                    }\n                } else {\n                    CLS_LOG(@\"Too many images from imgur: %@\", dict);\n                    callback(NO,@\"Albums with multiple images are not supported\");\n                }\n            } else {\n                CLS_LOG(@\"Imgur failure: %@\", dict);\n                callback(NO,@\"Unexpected response from server\");\n            }\n        }\n    }] resume];\n}\n\n-(void)_loadXKCD:(NSURL *)original_url result:(mediaURLResult)callback {\n    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@\"%@/info.0.json\", original_url.absoluteString]] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];\n    [request setHTTPShouldHandleCookies:NO];\n    \n    [[[NetworkConnection sharedInstance].urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n        if (error) {\n            CLS_LOG(@\"Error fetching xkcd. Error %li : %@\", (long)error.code, error.userInfo);\n            callback(NO,error.localizedDescription);\n        } else {\n            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];\n            if([dict objectForKey:@\"img\"]) {\n                [self->_mediaURLs setObject:@{@\"thumb\":[NSURL URLWithString:[dict objectForKey:@\"img\"]],\n                                        @\"image\":[NSURL URLWithString:[dict objectForKey:@\"img\"]],\n                                        @\"name\":[dict objectForKey:@\"safe_title\"],\n                                        @\"description\":[dict objectForKey:@\"alt\"],\n                                        @\"url\":original_url\n                                        } forKey:original_url];\n                callback(YES, nil);\n            } else {\n                CLS_LOG(@\"xkcd failure: %@\", dict);\n                callback(NO,@\"Unexpected response from server\");\n            }\n        }\n    }] resume];\n}\n\n+ (BOOL)isImageURL:(NSURL *)url\n{\n    NSString *l = [url.path lowercaseString];\n    // Use pre-processor macros instead of variables so conditions are still evaluated lazily\n    return ([url.scheme.lowercaseString isEqualToString:@\"http\"] || [url.scheme.lowercaseString isEqualToString:@\"https\"]) && (HAS_IMAGE_SUFFIX(l) || IS_IMGUR(url) || IS_FLICKR(url) || /*IS_INSTAGRAM(url) ||*/ IS_DROPLR(url) || IS_CLOUDAPP(url) || IS_STEAM(url) || IS_LEET(url) || IS_GIPHY(url) || IS_WIKI(url) || IS_TWIMG(url) || IS_XKCD(url) || IS_IRCCLOUD_AVATAR(url) || IS_SLACK_AVATAR(url) || IS_GRAVATAR(url));\n}\n\n+ (BOOL)isYouTubeURL:(NSURL *)url\n{\n    return IS_YOUTUBE(url);\n}\n\n- (void)addFileID:(NSString *)fileID URL:(NSURL *)url {\n    [_fileIDs setObject:fileID forKey:url];\n}\n\n- (void)clearFileIDs {\n    [_fileIDs removeAllObjects];\n}\n\n- (void)launchURL:(NSURL *)url\n{\n#ifndef EXTENSION\n    BOOL isCatalyst = NO;\n    if (@available(iOS 13.0, *)) {\n        isCatalyst = [NSProcessInfo processInfo].macCatalystApp;\n    }\n    UIApplication *app = [UIApplication sharedApplication];\n    AppDelegate *appDelegate = (AppDelegate *)app.delegate;\n    if(_window)\n        [appDelegate setActiveScene:_window];\n    MainViewController *mainViewController = [appDelegate mainViewController];\n\n    if([_fileIDs objectForKey:url]) {\n        NSURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@\"https://%@/file/json/%@\", IRCCLOUD_HOST, [_fileIDs objectForKey:url]]]];\n        [[[NetworkConnection sharedInstance].urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n            NSURL *result = url;\n            if (error) {\n                CLS_LOG(@\"Error fetching file metadata. Error %li : %@\", (long)error.code, error.userInfo);\n            } else {\n                NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];\n                \n                NSString *mime_type = [dict objectForKey:@\"mime_type\"];\n                NSString *extension = [dict objectForKey:@\"extension\"];\n                NSString *name = [dict objectForKey:@\"name\"];\n\n                if(extension.length == 0)\n                    extension = [NSString stringWithFormat:@\".%@\", [mime_type substringFromIndex:[mime_type rangeOfString:@\"/\"].location + 1]];\n\n                if(![name.lowercaseString hasSuffix:extension.lowercaseString])\n                    name = [[dict objectForKey:@\"id\"] stringByAppendingString:extension];\n                \n                if([NetworkConnection sharedInstance].fileURITemplate && [dict objectForKey:@\"id\"] && name)\n                    result = [NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":[dict objectForKey:@\"id\"], @\"name\":[name stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLPathAllowedCharacterSet]} error:nil]];\n            }\n            \n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [self->_fileIDs removeObjectForKey:result];\n                [self launchURL:result];\n            }];\n        }] resume];\n\n        return;\n    }\n    \n    if([[UIApplication sharedApplication] respondsToSelector:NSSelectorFromString(@\"_deactivateReachability\")])\n        ((id (*)(id, SEL)) objc_msgSend)([UIApplication sharedApplication], NSSelectorFromString(@\"_deactivateReachability\"));\n    \n    if(mainViewController.slidingViewController.presentedViewController) {\n        [mainViewController.slidingViewController dismissViewControllerAnimated:NO completion:^{\n            [self launchURL:url];\n        }];\n        return;\n    }\n    \n    if(mainViewController.presentedViewController) {\n        [mainViewController dismissViewControllerAnimated:NO completion:^{\n            [self launchURL:url];\n        }];\n        return;\n    }\n    \n    if([url.host isEqualToString:@\"www.irccloud.com\"]) {\n        if([url.path isEqualToString:@\"/chat/access-link\"]) {\n            CLS_LOG(@\"Opening access-link from handoff\");\n            NSString *u = [[url.absoluteString stringByReplacingOccurrencesOfString:@\"https://www.irccloud.com/\" withString:@\"irccloud://\"] stringByReplacingOccurrencesOfString:@\"&mobile=1\" withString:@\"\"];\n            [[NetworkConnection sharedInstance] logout];\n            appDelegate.loginSplashViewController.accessLink = [NSURL URLWithString:u];\n            appDelegate.window.backgroundColor = [UIColor colorWithRed:11.0/255.0 green:46.0/255.0 blue:96.0/255.0 alpha:1];\n            appDelegate.loginSplashViewController.view.alpha = 1;\n            if(appDelegate.window.rootViewController == appDelegate.loginSplashViewController)\n                [appDelegate.loginSplashViewController viewWillAppear:YES];\n            else\n                appDelegate.window.rootViewController = appDelegate.loginSplashViewController;\n            return;\n        } else if([url.path hasPrefix:@\"/verify-email/\"]) {\n            CLS_LOG(@\"Opening verify-email from handoff\");\n            [[[NetworkConnection sharedInstance].urlSession dataTaskWithURL:url completionHandler:\n              ^(NSData *data, NSURLResponse *response, NSError *error) {\n                  [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                      if([(NSHTTPURLResponse *)response statusCode] == 200) {\n                          UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Email Confirmed\" message:@\"Your email address was successfully confirmed\" preferredStyle:UIAlertControllerStyleAlert];\n                          [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleDefault handler:nil]];\n                          [appDelegate.window.rootViewController presentViewController:alert animated:YES completion:nil];\n                      } else {\n                          UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Email Confirmation Failed\" message:@\"Unable to confirm your email address.  Please try again shortly.\" preferredStyle:UIAlertControllerStyleAlert];\n                          [alert addAction:[UIAlertAction actionWithTitle:@\"Send Again\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                              [[NetworkConnection sharedInstance] resendVerifyEmailWithHandler:^(IRCCloudJSONObject *result) {\n                                  if([result objectForKey:@\"success\"]) {\n                                      UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Confirmation Sent\" message:@\"You should shortly receive an email with a link to confirm your address.\" preferredStyle:UIAlertControllerStyleAlert];\n                                      [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleDefault handler:nil]];\n                                      [appDelegate.window.rootViewController presentViewController:alert animated:YES completion:nil];\n                                  } else {\n                                      UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"Confirmation Failed\" message:[NSString stringWithFormat:@\"Unable to send confirmation message: %@.  Please try again shortly.\", [result objectForKey:@\"message\"]] preferredStyle:UIAlertControllerStyleAlert];\n                                      [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleDefault handler:nil]];\n                                      [appDelegate.window.rootViewController presentViewController:alert animated:YES completion:nil];\n                                  }\n                              }];\n                          }]];\n                          [alert addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleDefault handler:nil]];\n                          [appDelegate.window.rootViewController presentViewController:alert animated:YES completion:nil];\n                      }\n                  }];\n            }] resume];\n            return;\n        } else if([url.path isEqualToString:@\"/\"] && [url.fragment hasPrefix:@\"!/\"]) {\n            NSString *u = [url.absoluteString stringByReplacingOccurrencesOfString:@\"https://www.irccloud.com/#!/\" withString:@\"irc://\"];\n            if([u hasPrefix:@\"irc://ircs://\"])\n                u = [u substringFromIndex:6];\n            CLS_LOG(@\"Opening URL from handoff: %@\", u);\n            [mainViewController launchURL:[NSURL URLWithString:u]];\n            return;\n        } else if([url.path isEqualToString:@\"/invite\"]) {\n            url = [NSURL URLWithString:[url.absoluteString stringByReplacingOccurrencesOfString:@\"#\" withString:@\"%23\"]];\n        } else if([url.path hasPrefix:@\"/pastebin/\"]) {\n            url = [NSURL URLWithString:[NSString stringWithFormat:@\"irccloud-paste-https://%@%@\",url.host,url.path]];\n        } else if([url.path hasPrefix:@\"/irc/\"]) {\n            [appDelegate showMainView:YES];\n            [mainViewController launchURL:url];\n            return;\n        } else if([url.path hasPrefix:@\"/log-export/\"]) {\n            [appDelegate showMainView:YES];\n            [mainViewController launchURL:url];\n            return;\n        } else {\n            [[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n            return;\n        }\n    }\n    \n    if([url.host hasSuffix:@\"irccloud.com\"] && [url.path isEqualToString:@\"/invite\"]) {\n        int port = 6667;\n        int ssl = 0;\n        NSString *host;\n        NSString *channel;\n        for(NSString *p in [url.query componentsSeparatedByString:@\"&\"]) {\n            NSArray *args = [p componentsSeparatedByString:@\"=\"];\n            if(args.count == 2) {\n                if([args[0] isEqualToString:@\"channel\"])\n                    channel = args[1];\n                else if([args[0] isEqualToString:@\"hostname\"])\n                    host = args[1];\n                else if([args[0] isEqualToString:@\"port\"])\n                    port = [args[1] intValue];\n                else if([args[0] isEqualToString:@\"ssl\"])\n                    ssl = [args[1] intValue];\n            }\n        }\n        url = [NSURL URLWithString:[NSString stringWithFormat:@\"irc%@://%@:%i/%@\",(ssl > 0)?@\"s\":@\"\",host,port,channel]];\n    }\n    \n#ifdef ENTERPRISE\n    if([url.scheme hasPrefix:@\"http\"] && [url.host isEqualToString:IRCCLOUD_HOST] && [url.path hasPrefix:@\"/pastebin/\"]) {\n#else\n    if([url.scheme hasPrefix:@\"http\"] && [url.host hasSuffix:@\"irccloud.com\"] && [url.path hasPrefix:@\"/pastebin/\"]) {\n#endif\n        url = [NSURL URLWithString:[NSString stringWithFormat:@\"irccloud-paste-%@://%@%@\",url.scheme,url.host,url.path]];\n    }\n\n    if(![url.scheme hasPrefix:@\"irc\"]) {\n        [mainViewController dismissKeyboard];\n    }\n    \n    if([url.scheme hasPrefix:@\"irccloud-paste-\"]) {\n        PastebinViewController *pvc = [[UIStoryboard storyboardWithName:@\"MainStoryboard\" bundle:nil] instantiateViewControllerWithIdentifier:@\"PastebinViewController\"];\n        [pvc setUrl:[NSURL URLWithString:[url.absoluteString substringFromIndex:15]]];\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:pvc];\n            [nc.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n            if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && ![[UIDevice currentDevice] isBigPhone])\n                nc.modalPresentationStyle = UIModalPresentationPageSheet;\n            else\n                nc.modalPresentationStyle = UIModalPresentationCurrentContext;\n            [mainViewController.slidingViewController presentViewController:nc animated:YES completion:nil];\n        }];\n    } else if([url.scheme hasPrefix:@\"irc\"]) {\n        [mainViewController launchURL:[NSURL URLWithString:[url.absoluteString stringByReplacingOccurrencesOfString:@\"#\" withString:@\"%23\"]]];\n    } else if([url.scheme isEqualToString:@\"spotify\"]) {\n        if([[UIApplication sharedApplication] canOpenURL:url])\n            [[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n        else\n            [self launchURL:[NSURL URLWithString:[NSString stringWithFormat:@\"https://open.spotify.com/%@\",[[url.absoluteString substringFromIndex:8] stringByReplacingOccurrencesOfString:@\":\" withString:@\"/\"]]]];\n    } else if([url.scheme isEqualToString:@\"facetime\"]) {\n        [self launchURL:[NSURL URLWithString:[NSString stringWithFormat:@\"facetime-prompt%@\",[url.absoluteString substringFromIndex:8]]]];\n    } else if([url.scheme isEqualToString:@\"tel\"]) {\n        [self launchURL:[NSURL URLWithString:[NSString stringWithFormat:@\"telprompt%@\",[url.absoluteString substringFromIndex:3]]]];\n    } else if(!isCatalyst && [[NSUserDefaults standardUserDefaults] boolForKey:@\"imageViewer\"] && [[self class] isImageURL:url]) {\n        [self showImage:url];\n    } else if(!isCatalyst && [[NSUserDefaults standardUserDefaults] boolForKey:@\"videoViewer\"] && ([url.pathExtension.lowercaseString isEqualToString:@\"mov\"] || [url.pathExtension.lowercaseString isEqualToString:@\"mp4\"] || [url.pathExtension.lowercaseString isEqualToString:@\"m4v\"] || [url.pathExtension.lowercaseString isEqualToString:@\"3gp\"] || [url.pathExtension.lowercaseString isEqualToString:@\"quicktime\"])) {\n        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];\n        AVPlayerViewController *player = [[AVPlayerViewController alloc] init];\n        player.modalPresentationStyle = UIModalPresentationFullScreen;\n        player.player = [[AVPlayer alloc] initWithURL:url];\n        [mainViewController presentViewController:player animated:YES completion:nil];\n    } else if(!isCatalyst && [[NSUserDefaults standardUserDefaults] boolForKey:@\"videoViewer\"] && IS_YOUTUBE(url)) {\n        [mainViewController launchURL:url];\n    } else if([url.host.lowercaseString isEqualToString:@\"maps.apple.com\"]) {\n        [[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n    } else {\n        [self openWebpage:url];\n    }\n#endif\n}\n\n- (void)showImage:(NSURL *)url\n{\n#ifndef EXTENSION\n    AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;\n    ImageViewController *ivc = [[ImageViewController alloc] initWithURL:url];\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        appDelegate.mainViewController.ignoreVisibilityChanges = YES;\n        appDelegate.window.backgroundColor = [UIColor blackColor];\n        appDelegate.window.rootViewController = ivc;\n        [appDelegate.window addSubview:ivc.view];\n        appDelegate.slideViewController.view.frame = appDelegate.window.bounds;\n        [appDelegate.window insertSubview:appDelegate.slideViewController.view belowSubview:ivc.view];\n        appDelegate.mainViewController.ignoreVisibilityChanges = NO;\n        ivc.view.alpha = 0;\n        [UIView animateWithDuration:0.5f animations:^{\n            ivc.view.alpha = 1;\n        } completion:nil];\n    }];\n#endif\n}\n\n- (void)openWebpage:(NSURL *)url\n{\n#ifndef EXTENSION\n    if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Chrome\"] && [[OpenInChromeController sharedInstance] isChromeInstalled]) {\n        if([[OpenInChromeController sharedInstance] openInChrome:url withCallbackURL:self.appCallbackURL createNewTab:NO])\n            return;\n    }\n    if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Firefox\"] && [[OpenInFirefoxControllerObjC sharedInstance] isFirefoxInstalled]) {\n        if([[OpenInFirefoxControllerObjC sharedInstance] openInFirefox:url])\n            return;\n    }\n    if(![[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Safari\"] && ([SFSafariViewController class] && !((AppDelegate *)([UIApplication sharedApplication].delegate)).isOnVisionOS) && ([url.scheme isEqualToString:@\"http\"] || [url.scheme isEqualToString:@\"https\"])) {\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            UIApplication *app = [UIApplication sharedApplication];\n            AppDelegate *appDelegate = (AppDelegate *)app.delegate;\n            MainViewController *mainViewController = [appDelegate mainViewController];\n            [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;\n            [UIApplication sharedApplication].statusBarHidden = NO;\n            \n            [mainViewController.slidingViewController presentViewController:[[SFSafariViewController alloc] initWithURL:url] animated:YES completion:nil];\n        }];\n    } else {\n        [[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n    }\n#endif\n}\n\n+ (UIActivityViewController *)activityControllerForItems:(NSArray *)items type:(NSString *)type {\n#ifndef EXTENSION\n    NSArray *activities;\n    \n    if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Chrome\"] && [[OpenInChromeController sharedInstance] isChromeInstalled]) {\n        activities = @[[[ARChromeActivity alloc] initWithCallbackURL:[NSURL URLWithString:\n#ifdef ENTERPRISE\n                                                                      @\"irccloud-enterprise://\"\n#else\n                                                                      @\"irccloud://\"\n#endif\n                                                                      ]]];\n    } else if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Firefox\"] && [[OpenInFirefoxControllerObjC sharedInstance] isFirefoxInstalled]) {\n        activities = @[[[OpenInFirefoxActivity alloc] init]];\n    } else {\n        activities = @[[[TUSafariActivity alloc] init]];\n    }\n    \n    UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:activities];\n    activityController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {\n        [UIColor setTheme:[UIColor currentTheme]];\n        if(completed) {\n            if([activityType hasPrefix:@\"com.apple.UIKit.activity.\"])\n                activityType = [activityType substringFromIndex:25];\n            if([activityType hasPrefix:@\"com.apple.\"])\n                activityType = [activityType substringFromIndex:10];\n        }\n    };\n    return activityController;\n#else\n    return nil;\n#endif\n}\n\n+ (int)URLtoBID:(NSURL *)url {\n    if([url.path hasPrefix:@\"/irc/\"] && url.pathComponents.count >= 4) {\n        NSString *network = [[url.pathComponents objectAtIndex:2] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];\n        NSString *type = [url.pathComponents objectAtIndex:3];\n        if([type isEqualToString:@\"channel\"] || [type isEqualToString:@\"messages\"]) {\n            NSString *name = [[url.pathComponents objectAtIndex:4] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];\n            \n            for(Server *s in [[ServersDataSource sharedInstance] getServers]) {\n                NSString *serverHost = [s.hostname lowercaseString];\n                if([serverHost hasPrefix:@\"irc.\"])\n                    serverHost = [serverHost substringFromIndex:4];\n                serverHost = [serverHost stringByReplacingOccurrencesOfString:@\"_\" withString:@\"-\"];\n                \n                NSString *serverName = [s.name lowercaseString];\n                serverName = [serverName stringByReplacingOccurrencesOfString:@\"_\" withString:@\"-\"];\n\n                if([network isEqualToString:serverHost] || [network isEqualToString:serverName]) {\n                    for(Buffer *b in [[BuffersDataSource sharedInstance] getBuffersForServer:s.cid]) {\n                        if(([type isEqualToString:@\"channel\"] && [b.type isEqualToString:@\"channel\"]) || ([type isEqualToString:@\"messages\"] && [b.type isEqualToString:@\"conversation\"])) {\n                            NSString *bufferName = b.name;\n                            \n                            if([b.type isEqualToString:@\"channel\"]) {\n                                if([bufferName hasPrefix:@\"#\"])\n                                    bufferName = [bufferName substringFromIndex:1];\n                                if(![bufferName isEqualToString:[b accessibilityValue]])\n                                    bufferName = b.name;\n                            }\n                            \n                            if([bufferName isEqualToString:name])\n                                return b.bid;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return -1;\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UsersDataSource.h",
    "content": "//\n//  UsersDataSource.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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@interface User : NSObject<NSSecureCoding> {\n    int _cid;\n    int _bid;\n    NSString *_nick;\n    NSString *_display_name;\n    NSString *_old_nick;\n    NSString *_lowercase_nick;\n    NSString *_hostmask;\n    NSString *_mode;\n    int _away;\n    NSString *_away_msg;\n    NSTimeInterval _lastMention;\n    NSTimeInterval _lastMessage;\n    NSString *_ircserver;\n    BOOL _parted;\n}\n@property int cid, bid, away;\n@property NSString *nick, *old_nick, *hostmask, *mode, *away_msg, *ircserver, *display_name;\n@property (readonly) NSString *lowercase_nick;\n@property NSTimeInterval lastMention, lastMessage;\n@property BOOL parted;\n-(NSComparisonResult)compare:(User *)aUser;\n-(NSComparisonResult)compareByMentionTime:(User *)aUser;\n@end\n\n@interface UsersDataSource : NSObject {\n    NSMutableDictionary *_users;\n}\n+(UsersDataSource *)sharedInstance;\n-(void)serialize;\n-(void)clear;\n-(void)addUser:(User *)user;\n-(NSArray *)usersForBuffer:(int)bid;\n-(User *)getUser:(NSString *)nick cid:(int)cid bid:(int)bid;\n-(User *)getUser:(NSString *)nick cid:(int)cid;\n-(void)removeUser:(NSString *)nick cid:(int)cid bid:(int)bid;\n-(void)removeUsersForBuffer:(int)bid;\n-(void)updateNick:(NSString *)nick oldNick:(NSString *)oldNick cid:(int)cid bid:(int)bid;\n-(void)updateAway:(int)away msg:(NSString *)msg nick:(NSString *)nick cid:(int)cid;\n-(void)updateAway:(int)away nick:(NSString *)nick cid:(int)cid;\n-(void)updateHostmask:(NSString *)hostmask nick:(NSString *)nick cid:(int)cid bid:(int)bid;\n-(void)updateMode:(NSString *)mode nick:(NSString *)nick cid:(int)cid bid:(int)bid;\n-(void)updateDisplayName:(NSString *)displayName nick:(NSString *)nick cid:(int)cid;\n-(NSString *)getDisplayName:(NSString *)nick cid:(int)cid;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UsersDataSource.m",
    "content": "//\n//  UsersDataSource.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"UsersDataSource.h\"\n#import \"ChannelsDataSource.h\"\n#import \"BuffersDataSource.h\"\n#import \"ServersDataSource.h\"\n#import \"EventsDataSource.h\"\n\n@implementation User\n\n+ (BOOL)supportsSecureCoding {\n    return YES;\n}\n\n-(NSString *)nick {\n    return _nick;\n}\n\n-(void)setNick:(NSString *)nick {\n    self->_nick = nick;\n    self->_lowercase_nick = self.display_name.lowercaseString;\n}\n\n-(NSString *)lowercase_nick {\n    if(!_lowercase_nick)\n        self->_lowercase_nick = self->_nick.lowercaseString;\n    return _lowercase_nick;\n}\n\n-(NSString *)display_name {\n    if([self->_display_name isKindOfClass:NSString.class] &&_display_name.length)\n        return _display_name;\n    else\n        return _nick;\n}\n\n-(void)setDisplay_name:(NSString *)display_name {\n    self->_display_name = display_name;\n    self->_lowercase_nick = self.display_name.lowercaseString;\n}\n\n-(NSComparisonResult)compare:(User *)aUser {\n    return [self->_lowercase_nick localizedStandardCompare:aUser.lowercase_nick];\n}\n\n-(NSComparisonResult)compareByMentionTime:(User *)aUser {\n    if(self->_lastMention < aUser.lastMention) {\n        return NSOrderedDescending;\n    } else if(self->_lastMention > aUser.lastMention) {\n        return NSOrderedAscending;\n    } else if(self->_lastMessage < aUser.lastMessage) {\n        return NSOrderedDescending;\n    } else if(self->_lastMessage > aUser.lastMessage) {\n        return NSOrderedAscending;\n    } else {\n        return [self->_lowercase_nick localizedStandardCompare:aUser.lowercase_nick];\n    }\n}\n\n-(id)initWithCoder:(NSCoder *)aDecoder {\n    self = [super init];\n    if(self) {\n        decodeInt(self->_cid);\n        decodeInt(self->_bid);\n        decodeObjectOfClass(NSString.class, self->_nick);\n        decodeObjectOfClass(NSString.class, self->_old_nick);\n        decodeObjectOfClass(NSString.class, self->_hostmask);\n        decodeObjectOfClass(NSString.class, self->_mode);\n        decodeInt(self->_away);\n        decodeObjectOfClass(NSString.class, self->_away_msg);\n        decodeDouble(self->_lastMention);\n        decodeDouble(self->_lastMessage);\n        decodeObjectOfClass(NSString.class, self->_ircserver);\n        decodeObjectOfClass(NSString.class, self->_display_name);\n    }\n    return self;\n}\n\n-(void)encodeWithCoder:(NSCoder *)aCoder {\n    encodeInt(self->_cid);\n    encodeInt(self->_bid);\n    encodeObject(self->_nick);\n    encodeObject(self->_old_nick);\n    encodeObject(self->_hostmask);\n    encodeObject(self->_mode);\n    encodeInt(self->_away);\n    encodeObject(self->_away_msg);\n    encodeDouble(self->_lastMention);\n    encodeDouble(self->_lastMessage);\n    encodeObject(self->_ircserver);\n    encodeObject(self->_display_name);\n}\n\n-(NSString *)description {\n    return [NSString stringWithFormat:@\"{cid: %i, bid: %i, nick: %@, hostmask: %@}\", _cid, _bid, _nick, _hostmask];\n}\n@end\n\n@implementation UsersDataSource\n+(UsersDataSource *)sharedInstance {\n    static UsersDataSource *sharedInstance;\n\t\n    @synchronized(self) {\n        if(!sharedInstance)\n            sharedInstance = [[UsersDataSource alloc] init];\n\t\t\n        return sharedInstance;\n    }\n\treturn nil;\n}\n\n-(id)init {\n    self = [super init];\n    if(self) {\n        [NSKeyedArchiver setClassName:@\"IRCCloud.User\" forClass:User.class];\n        [NSKeyedUnarchiver setClass:User.class forClassName:@\"IRCCloud.User\"];\n\n#ifndef EXTENSION\n        if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"cacheVersion\"] isEqualToString:[[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleVersion\"]]) {\n            NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"users\"];\n            \n            @try {\n                NSError* error = nil;\n                self->_users = [[NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:NSDictionary.class, NSArray.class, User.class, NSString.class, NSNumber.class, nil] fromData:[NSData dataWithContentsOfFile:cacheFile] error:&error] mutableCopy];\n                if(error)\n                    @throw [NSException exceptionWithName:@\"NSError\" reason:error.debugDescription userInfo:@{ @\"NSError\" : error }];\n            } @catch(NSException *e) {\n                CLS_LOG(@\"Exception: %@\", e);\n                [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n                [[NSUserDefaults standardUserDefaults] removeObjectForKey:@\"cacheVersion\"];\n                [[ServersDataSource sharedInstance] clear];\n                [[BuffersDataSource sharedInstance] clear];\n                [[ChannelsDataSource sharedInstance] clear];\n                [[EventsDataSource sharedInstance] clear];\n            }\n        }\n#endif\n        if(!_users)\n            self->_users = [[NSMutableDictionary alloc] init];\n    }\n    return self;\n}\n\n-(void)serialize {\n    NSString *cacheFile = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"users\"];\n    \n    NSMutableDictionary *users = [[NSMutableDictionary alloc] init];\n    @synchronized(self->_users) {\n        for(NSNumber *bid in _users) {\n            [users setObject:[[self->_users objectForKey:bid] mutableCopy] forKey:bid];\n        }\n    }\n    \n    @synchronized(self) {\n        @try {\n            NSError* error = nil;\n            [[NSKeyedArchiver archivedDataWithRootObject:users requiringSecureCoding:YES error:&error] writeToFile:cacheFile atomically:YES];\n            if(error)\n                CLS_LOG(@\"Error archiving: %@\", error);\n            [[NSURL fileURLWithPath:cacheFile] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL];\n        }\n        @catch (NSException *exception) {\n            [[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];\n        }\n    }\n}\n\n-(void)clear {\n    @synchronized(self->_users) {\n        [self->_users removeAllObjects];\n    }\n}\n\n-(void)addUser:(User *)user {\n#ifndef EXTENSION\n    @synchronized(self->_users) {\n        NSMutableDictionary *users = [self->_users objectForKey:@(user.bid)];\n        if(!users) {\n            users = [[NSMutableDictionary alloc] init];\n            [self->_users setObject:users forKey:@(user.bid)];\n        }\n        [users setObject:user forKey:user.lowercase_nick];\n    }\n#endif\n}\n\n-(NSArray *)usersForBuffer:(int)bid {\n    @synchronized(self->_users) {\n        return [[[self->_users objectForKey:@(bid)] allValues] sortedArrayUsingSelector:@selector(compare:)];\n    }\n}\n\n-(User *)getUser:(NSString *)nick cid:(int)cid bid:(int)bid {\n    @synchronized(self->_users) {\n        return [[self->_users objectForKey:@(bid)] objectForKey:[nick lowercaseString]];\n    }\n}\n\n-(User *)getUser:(NSString *)nick cid:(int)cid {\n    @synchronized(self->_users) {\n        for(NSDictionary *buffer in _users.allValues) {\n            User *u = [buffer objectForKey:[nick lowercaseString]];\n            if(u && u.cid == cid)\n                return u;\n        }\n        return nil;\n    }\n}\n\n-(NSString *)getDisplayName:(NSString *)nick cid:(int)cid {\n    @synchronized(self->_users) {\n        for(NSDictionary *buffer in _users.allValues) {\n            for(User *u in buffer.allValues) {\n                if(u && u.cid != cid)\n                    break;\n                if(u && u.cid == cid && [u.nick isEqualToString:nick] && u.display_name.length)\n                    return u.display_name;\n            }\n        }\n        return nick;\n    }\n}\n\n-(void)removeUser:(NSString *)nick cid:(int)cid bid:(int)bid {\n    @synchronized(self->_users) {\n        [[self->_users objectForKey:@(bid)] removeObjectForKey:[nick lowercaseString]];\n    }\n}\n\n-(void)removeUsersForBuffer:(int)bid {\n    @synchronized(self->_users) {\n        [self->_users removeObjectForKey:@(bid)];\n    }\n}\n\n-(void)updateNick:(NSString *)nick oldNick:(NSString *)oldNick cid:(int)cid bid:(int)bid {\n    @synchronized(self->_users) {\n        User *user = [self getUser:oldNick cid:cid bid:bid];\n        if(user) {\n            user.nick = nick;\n            user.old_nick = oldNick;\n            [[self->_users objectForKey:@(bid)] removeObjectForKey:[oldNick lowercaseString]];\n            [[self->_users objectForKey:@(bid)] setObject:user forKey:[nick lowercaseString]];\n        }\n    }\n}\n\n-(void)updateDisplayName:(NSString *)displayName nick:(NSString *)nick cid:(int)cid {\n    @synchronized(self->_users) {\n        for(NSDictionary *d in _users.allValues) {\n            for(User *u in d.allValues) {\n                if(u.cid == cid && [u.nick isEqualToString:nick]) {\n                    [[self->_users objectForKey:@(u.bid)] removeObjectForKey:u.lowercase_nick];\n                    if([displayName isKindOfClass:NSString.class]) {\n                        u.display_name = displayName;\n                        [[self->_users objectForKey:@(u.bid)] setObject:u forKey:u.lowercase_nick];\n                    }\n                    break;\n                }\n            }\n        }\n    }\n}\n\n-(void)updateAway:(int)away msg:(NSString *)msg nick:(NSString *)nick cid:(int)cid {\n    @synchronized(self->_users) {\n        for(NSDictionary *buffer in _users.allValues) {\n            User *user = [buffer objectForKey:[nick lowercaseString]];\n            if(user && user.cid == cid) {\n                user.away = away;\n                user.away_msg = msg;\n            }\n        }\n    }\n}\n\n-(void)updateAway:(int)away nick:(NSString *)nick cid:(int)cid {\n    @synchronized(self->_users) {\n        for(NSDictionary *buffer in _users.allValues) {\n            User *user = [buffer objectForKey:[nick lowercaseString]];\n            if(user && user.cid == cid) {\n                user.away = away;\n            }\n        }\n    }\n}\n\n-(void)updateHostmask:(NSString *)hostmask nick:(NSString *)nick cid:(int)cid bid:(int)bid {\n    @synchronized(self->_users) {\n        User *user = [self getUser:nick cid:cid bid:bid];\n        if(user)\n            user.hostmask = hostmask;\n    }\n}\n\n-(void)updateMode:(NSString *)mode nick:(NSString *)nick cid:(int)cid bid:(int)bid {\n    @synchronized(self->_users) {\n        User *user = [self getUser:nick cid:cid bid:bid];\n        if(user)\n            user.mode = mode;\n    }\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UsersTableView.h",
    "content": "//\n//  UsersTableView.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"BuffersDataSource.h\"\n\n@protocol UsersTableViewDelegate<NSObject>\n-(void)userSelected:(NSString *)nick rect:(CGRect)rect;\n-(void)dismissKeyboard;\n@end\n\n@interface UsersTableView : UITableViewController<UIGestureRecognizerDelegate,UIContextMenuInteractionDelegate> {\n    NSArray *_data;\n    NSMutableArray *_sectionTitles;\n    NSMutableArray *_sectionIndexes;\n    NSMutableArray *_sectionSizes;\n    Buffer *_buffer;\n    UIViewController<UsersTableViewDelegate> *_delegate;\n    NSTimer *_refreshTimer;\n    UIFont *_headingFont;\n    UIFont *_countFont;\n    UIFont *_userFont;\n}\n@property UIViewController<UsersTableViewDelegate> *delegate;\n-(void)setBuffer:(Buffer *)buffer;\n-(void)refresh;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/UsersTableView.m",
    "content": "//\n//  UsersTableView.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 \"UsersTableView.h\"\n#import \"NetworkConnection.h\"\n#import \"UsersDataSource.h\"\n#import \"UIColor+IRCCloud.h\"\n#import \"ECSlidingViewController.h\"\n#import \"ColorFormatter.h\"\n@import Firebase;\n\n#define TYPE_HEADING 0\n#define TYPE_USER 1\n\n@interface UsersTableCell : UITableViewCell {\n    UILabel *_label;\n    UILabel *_count;\n    UIView *_border1;\n    UIView *_border2;\n    int _type;\n    UIColor *_bgColor;\n    UIColor *_fgColor;\n}\n@property int type;\n@property (readonly) UILabel *label,*count;\n@property (readonly) UIView *border1, *border2;\n@property UIColor *bgColor, *fgColor;\n@end\n\n@implementation UsersTableCell\n\n- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self->_type = 0;\n        \n        self.backgroundColor = [UIColor membersGroupColor];\n        \n        self->_label = self.textLabel;\n        self->_label.backgroundColor = [UIColor clearColor];\n        self->_label.textColor = [UIColor blackColor];\n        self->_label.font = [UIFont systemFontOfSize:16];\n\n        self->_count = [[UILabel alloc] init];\n        self->_count.backgroundColor = [UIColor clearColor];\n        self->_count.textColor = [UIColor grayColor];\n        self->_count.font = [UIFont systemFontOfSize:14];\n        [self.contentView addSubview:self->_count];\n        \n        self->_border1 = [[UIView alloc] init];\n        [self.contentView addSubview:self->_border1];\n        \n        self->_border2 = [[UIView alloc] init];\n        [self.contentView addSubview:self->_border2];\n    }\n    return self;\n}\n\n- (void)layoutSubviews {\n\t[super layoutSubviews];\n\t\n\tCGRect frame = [self.contentView bounds];\n    self->_border1.frame = CGRectMake(0,frame.size.height - 1,frame.size.width,1);\n    self->_border2.frame = CGRectMake(0,0,3,frame.size.height);\n\n    frame.origin.x = 12;\n    frame.size.width -= 24;\n    \n    if(self->_type == TYPE_HEADING) {\n        float countWidth = [self->_count.text sizeWithAttributes:@{NSFontAttributeName:self->_count.font}].width;\n        self->_count.frame = CGRectMake(frame.origin.x + frame.size.width - countWidth, frame.origin.y, countWidth, frame.size.height);\n        self->_count.hidden = NO;\n        self->_label.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width - countWidth - 6, frame.size.height);\n    } else {\n        self->_count.hidden = YES;\n        self->_label.frame = frame;\n    }\n}\n\n-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {\n    [super setHighlighted:highlighted animated:animated];\n    if(self.selected || _type == TYPE_HEADING)\n        highlighted = NO;\n    self.contentView.backgroundColor = highlighted?_border1.backgroundColor:self->_bgColor;\n    self->_label.textColor = highlighted?[UIColor whiteColor]:self->_fgColor;\n}\n@end\n\n@implementation UsersTableView\n\n-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {\n    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];\n    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n        [self.tableView reloadData];\n    }\n     ];\n}\n\n- (void)handleEvent:(NSNotification *)notification {\n    IRCCloudJSONObject *o = notification.object;\n    kIRCEvent event = [[notification.userInfo objectForKey:kIRCCloudEventKey] intValue];\n    switch(event) {\n        case kIRCEventAway:\n            if(o.cid == self->_buffer.cid)\n            [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                [self.tableView reloadData];\n            }];\n            break;\n        case kIRCEventUserInfo:\n        case kIRCEventChannelInit:\n        case kIRCEventJoin:\n        case kIRCEventPart:\n        case kIRCEventQuit:\n        case kIRCEventNickChange:\n        case kIRCEventMemberUpdates:\n        case kIRCEventUserChannelMode:\n        case kIRCEventKick:\n        case kIRCEventWhoList:\n            if(!_refreshTimer) {\n                self->_refreshTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(_refreshTimer) userInfo:nil repeats:NO];\n            }\n            break;\n        default:\n            break;\n    }\n}\n\n- (void)_refreshTimer {\n    self->_refreshTimer = nil;\n    [self refresh];\n}\n\n- (void)_addUsersFromList:(NSArray *)users heading:(NSString *)heading symbol:(NSString*)symbol groupColor:(UIColor *)groupColor borderColor:(UIColor *)borderColor headingColor:(UIColor *)headingColor data:(NSMutableArray *)data sectionTitles:(NSMutableArray *)sectionTitles sectionIndexes:(NSMutableArray *)sectionIndexes sectionSizes:(NSMutableArray *)sectionSizes {\n    if(users.count && symbol) {\n        //unichar lastChar = 0;\n        [data addObject:@{\n         @\"type\":@TYPE_HEADING,\n         @\"text\":heading,\n         @\"color\":headingColor,\n         @\"bgColor\":groupColor,\n         @\"count\":@(users.count),\n         @\"countColor\":headingColor,\n         @\"symbol\":symbol,\n         @\"borderColor\":borderColor\n         }];\n        //NSUInteger size = data.count;\n        for(User *user in users) {\n            /*if(sectionTitles != nil) {\n                if(user.nick.length && [user.lowercase_nick characterAtIndex:0] != lastChar) {\n                    lastChar = [user.lowercase_nick characterAtIndex:0];\n                    [sectionIndexes addObject:@(data.count)];\n                    [sectionTitles addObject:[[user.nick uppercaseString] substringToIndex:1]];\n                    [sectionSizes addObject:@(size)];\n                    size = 1;\n                } else {\n                    size++;\n                }\n            }*/\n            [data addObject:@{\n             @\"type\":@TYPE_USER,\n             @\"text\":user.display_name,\n             @\"user\":user,\n             @\"bgColor\":groupColor,\n             @\"last\":@(user == users.lastObject && ![heading isEqualToString:@\"Members\"]),\n             @\"borderColor\":borderColor\n             }];\n        }\n        /*if(sectionSizes != nil)\n            [sectionSizes addObject:@(size)];*/\n    }\n}\n\n- (void)setBuffer:(Buffer *)buffer {\n    self->_buffer = buffer;\n    self->_refreshTimer = nil;\n    [self refresh];\n    if(self->_data.count)\n        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];\n}\n\n- (void)refresh {\n    NSDictionary *PREFIX;\n    Server *s = [[ServersDataSource sharedInstance] getServer:self->_buffer.cid];\n    if(s) {\n        PREFIX = s.PREFIX;\n    }\n    if(!PREFIX || PREFIX.count == 0) {\n        PREFIX = @{(s && s.MODE_OWNER)?s.MODE_OWNER:@\"q\":@\"~\",\n                   (s && s.MODE_ADMIN)?s.MODE_ADMIN:@\"a\":@\"&\",\n                   (s && s.MODE_OP)?s.MODE_OP:@\"o\":@\"@\",\n                   (s && s.MODE_HALFOP)?s.MODE_HALFOP:@\"h\":@\"%\",\n                   (s && s.MODE_VOICED)?s.MODE_VOICED:@\"v\":@\"+\"};\n    }\n    \n    NSMutableArray *data = [[NSMutableArray alloc] init];\n    NSMutableArray *opers = [[NSMutableArray alloc] init];\n    NSMutableArray *owners = [[NSMutableArray alloc] init];\n    NSMutableArray *admins = [[NSMutableArray alloc] init];\n    NSMutableArray *ops = [[NSMutableArray alloc] init];\n    NSMutableArray *halfops = [[NSMutableArray alloc] init];\n    NSMutableArray *voiced = [[NSMutableArray alloc] init];\n    NSMutableArray *members = [[NSMutableArray alloc] init];\n    NSMutableArray *sectionTitles = [[NSMutableArray alloc] init];\n    NSMutableArray *sectionIndexes = [[NSMutableArray alloc] init];\n    NSMutableArray *sectionSizes = [[NSMutableArray alloc] init];\n    \n    NSString *opersGroupMode = @\"Y\";\n    \n    NSArray *users = [[UsersDataSource sharedInstance] usersForBuffer:self->_buffer.bid];\n    if(users.count > 1000) {\n        NSMutableDictionary *disableNickSuggestions = [[NSUserDefaults standardUserDefaults] objectForKey:@\"disable-nick-suggestions\"];\n        if(![[disableNickSuggestions objectForKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]] intValue]) {\n            disableNickSuggestions = disableNickSuggestions.mutableCopy;\n            CLS_LOG(@\"Channel has %lu members, disabling auto nick suggestions\", (unsigned long)users.count);\n            [disableNickSuggestions setObject:@1 forKey:[NSString stringWithFormat:@\"%i\",_buffer.bid]];\n            [[NSUserDefaults standardUserDefaults] setObject:disableNickSuggestions forKey:@\"disable-nick-suggestions\"];\n            [[NSUserDefaults standardUserDefaults] synchronize];\n        }\n    }\n    \n    for(User *user in users) {\n        if(user.nick.length) {\n            if([user.nick isEqualToString:s.nick]) {\n                if(user.display_name.length)\n                    s.from = user.display_name;\n                else\n                    s.from = user.nick;\n            }\n            NSString *mode = user.mode.lowercaseString;\n            if(mode) {\n                if([mode rangeOfString:s?s.MODE_OPER.lowercaseString:@\"y\"].location != NSNotFound && ([PREFIX objectForKey:s?s.MODE_OPER:@\"Y\"] || [PREFIX objectForKey:s?s.MODE_OPER.lowercaseString:@\"y\"])) {\n                    [opers addObject:user];\n                    if([user.mode rangeOfString:s?s.MODE_OPER:@\"Y\"].location != NSNotFound)\n                        opersGroupMode = s.MODE_OPER;\n                    else\n                        opersGroupMode = s.MODE_OPER.lowercaseString;\n                } else if([mode rangeOfString:s?s.MODE_OWNER.lowercaseString:@\"q\"].location != NSNotFound && [PREFIX objectForKey:s?s.MODE_OWNER:@\"q\"])\n                    [owners addObject:user];\n                else if([mode rangeOfString:s?s.MODE_ADMIN.lowercaseString:@\"a\"].location != NSNotFound && [PREFIX objectForKey:s?s.MODE_ADMIN:@\"a\"])\n                    [admins addObject:user];\n                else if([mode rangeOfString:s?s.MODE_OP.lowercaseString:@\"o\"].location != NSNotFound && [PREFIX objectForKey:s?s.MODE_OP:@\"o\"])\n                    [ops addObject:user];\n                else if([mode rangeOfString:s?s.MODE_HALFOP.lowercaseString:@\"h\"].location != NSNotFound && [PREFIX objectForKey:s?s.MODE_HALFOP:@\"h\"])\n                    [halfops addObject:user];\n                else if([mode rangeOfString:s?s.MODE_VOICED.lowercaseString:@\"v\"].location != NSNotFound && [PREFIX objectForKey:s?s.MODE_VOICED:@\"v\"])\n                    [voiced addObject:user];\n                else\n                    [members addObject:user];\n            } else {\n                [members addObject:user];\n            }\n        }\n    }\n    \n    NSString *operPrefix = [PREFIX objectForKey:opersGroupMode];\n    if(!operPrefix)\n        operPrefix = [PREFIX objectForKey:s?s.MODE_OPER.lowercaseString:@\"y\"];\n    \n    [self _addUsersFromList:opers heading:@\"Opers\" symbol:operPrefix groupColor:[UIColor opersGroupColor] borderColor:[UIColor opersBorderColor] headingColor:[UIColor opersHeadingColor] data:data sectionTitles:nil sectionIndexes:nil sectionSizes:nil];\n    [self _addUsersFromList:owners heading:@\"Owners\" symbol:[PREFIX objectForKey:s?s.MODE_OWNER:@\"q\"] groupColor:[UIColor ownersGroupColor] borderColor:[UIColor ownersBorderColor] headingColor:[UIColor ownersHeadingColor] data:data sectionTitles:nil sectionIndexes:nil sectionSizes:nil];\n    [self _addUsersFromList:admins heading:@\"Admins\" symbol:[PREFIX objectForKey:s?s.MODE_ADMIN:@\"a\"] groupColor:[UIColor adminsGroupColor] borderColor:[UIColor adminsBorderColor] headingColor:[UIColor adminsHeadingColor] data:data sectionTitles:nil sectionIndexes:nil sectionSizes:nil];\n    [self _addUsersFromList:ops heading:@\"Ops\" symbol:[PREFIX objectForKey:s?s.MODE_OP:@\"o\"] groupColor:[UIColor opsGroupColor] borderColor:[UIColor opsBorderColor] headingColor:[UIColor opsHeadingColor] data:data sectionTitles:nil sectionIndexes:nil sectionSizes:nil];\n    [self _addUsersFromList:halfops heading:@\"Half Ops\" symbol:[PREFIX objectForKey:s?s.MODE_HALFOP:@\"h\"] groupColor:[UIColor halfopsGroupColor] borderColor:[UIColor halfopsBorderColor] headingColor:[UIColor halfopsHeadingColor] data:data sectionTitles:nil sectionIndexes:nil sectionSizes:nil];\n    [self _addUsersFromList:voiced heading:@\"Voiced\" symbol:[PREFIX objectForKey:s?s.MODE_VOICED:@\"v\"] groupColor:[UIColor voicedGroupColor] borderColor:[UIColor voicedBorderColor] headingColor:[UIColor voicedHeadingColor] data:data sectionTitles:nil sectionIndexes:nil sectionSizes:nil];\n    [sectionIndexes addObject:@(0)];\n    [self _addUsersFromList:members heading:@\"Members\" symbol:@\"\" groupColor:[UIColor membersGroupColor] borderColor:[UIColor membersBorderColor] headingColor:[UIColor membersHeadingColor] data:data sectionTitles:sectionTitles sectionIndexes:sectionIndexes sectionSizes:sectionSizes];\n    if(sectionSizes.count == 0)\n        [sectionSizes addObject:@(data.count)];\n    \n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        if([[[NetworkConnection sharedInstance].prefs objectForKey:@\"font\"] isEqualToString:@\"mono\"]) {\n            self->_headingFont = [UIFont fontWithName:@\"Courier\" size:FONT_SIZE];\n            self->_countFont = [UIFont fontWithName:@\"Courier\" size:FONT_SIZE];\n            self->_userFont = [UIFont fontWithName:@\"Courier\" size:FONT_SIZE];\n        } else {\n            UIFontDescriptor *d = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody];\n            self->_headingFont = self->_countFont = self->_userFont = [UIFont fontWithDescriptor:d size:FONT_SIZE];\n        }\n        \n        self->_refreshTimer = nil;\n        self->_data = data;\n        self->_sectionTitles = sectionTitles;\n        self->_sectionIndexes = sectionIndexes;\n        self->_sectionSizes = sectionSizes;\n        [self.tableView reloadData];\n        self.tableView.backgroundColor = [UIColor usersDrawerBackgroundColor];\n    }];\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.tableView.scrollsToTop = NO;\n    self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;\n    self.tableView.insetsLayoutMarginsFromSafeArea = NO;\n    self.tableView.insetsContentViewsToSafeArea = NO;\n\n    UILongPressGestureRecognizer *lp = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(_longPress:)];\n    lp.minimumPressDuration = 1.0;\n    lp.delegate = self;\n    [self.tableView addGestureRecognizer:lp];\n    \n    if (@available(iOS 13.0, *)) {\n        if([NSProcessInfo processInfo].macCatalystApp)\n            [self.tableView addInteraction:[[UIContextMenuInteraction alloc] initWithDelegate:self]];\n    }\n    \n    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n    self.view.backgroundColor = [UIColor usersDrawerBackgroundColor];\n\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:kIRCCloudEventNotification object:nil];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refresh) name:kIRCCloudBacklogCompletedNotification object:nil];\n    \n    self->_refreshTimer = nil;\n\n    if([[[NetworkConnection sharedInstance].prefs objectForKey:@\"font\"] isEqualToString:@\"mono\"]) {\n        self->_headingFont = [UIFont fontWithName:@\"Courier\" size:FONT_SIZE];\n        self->_countFont = [UIFont fontWithName:@\"Courier\" size:FONT_SIZE];\n        self->_userFont = [UIFont fontWithName:@\"Courier\" size:FONT_SIZE];\n    } else {\n        UIFontDescriptor *d = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody];\n        self->_headingFont = self->_countFont = self->_userFont = [UIFont fontWithDescriptor:d size:FONT_SIZE];\n    }\n}\n\n-(void)dealloc {\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n- (void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    if([[[NetworkConnection sharedInstance].prefs objectForKey:@\"font\"] isEqualToString:@\"mono\"]) {\n        self->_headingFont = [UIFont fontWithName:@\"Courier\" size:FONT_SIZE];\n        self->_countFont = [UIFont fontWithName:@\"Courier\" size:FONT_SIZE];\n        self->_userFont = [UIFont fontWithName:@\"Courier\" size:FONT_SIZE];\n    } else {\n        UIFontDescriptor *d = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody];\n        self->_headingFont = self->_countFont = self->_userFont = [UIFont fontWithDescriptor:d size:FONT_SIZE];\n    }\n    [self.tableView reloadData];\n}\n\n- (void)didMoveToParentViewController:(UIViewController *)parent {\n    [self refresh];\n    self->_refreshTimer = nil;\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n#pragma mark - Table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n/*    if(self->_data.count > 20)\n        return _sectionIndexes.count;\n    else*/\n        return 1;\n}\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n/*    if(self->_data.count > 20)\n        return [[self->_sectionSizes objectAtIndex:section] intValue];\n    else*/\n        return _data.count;\n}\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    return 32;\n}\n\n/*-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {\n    if(self->_data.count > 20)\n        return _sectionTitles;\n    else\n        return nil;\n}\n\n-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {\n    if(section == 0)\n        return nil;\n    else\n        return [self->_sectionTitles objectAtIndex:section - 1];\n}*/\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    UsersTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"userscell\"];\n    if(!cell)\n        cell = [[UsersTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"userscell\"];\n    NSUInteger idx = [[self->_sectionIndexes objectAtIndex:indexPath.section] intValue] + indexPath.row;\n    NSDictionary *row = [self->_data objectAtIndex:idx];\n    cell.selectionStyle = UITableViewCellSelectionStyleNone;\n    cell.type = [[row objectForKey:@\"type\"] intValue];\n    cell.bgColor = [row objectForKey:@\"bgColor\"];\n    cell.label.text = [row objectForKey:@\"text\"];\n    if(cell.type == TYPE_USER)\n        cell.fgColor = [(User *)[row objectForKey:@\"user\"] away]?[UIColor memberListAwayTextColor]:[UIColor memberListTextColor];\n    else\n        cell.fgColor = [row objectForKey:@\"color\"];\n    if([[NetworkConnection sharedInstance] prefs] && [[[[NetworkConnection sharedInstance] prefs] objectForKey:@\"mode-showsymbol\"] boolValue])\n        cell.count.text = [NSString stringWithFormat:@\"%@ %@\", [row objectForKey:@\"symbol\"], [row objectForKey:@\"count\"]];\n    else\n        cell.count.text = [NSString stringWithFormat:@\"%@\", [row objectForKey:@\"count\"]];\n    cell.count.textColor = [row objectForKey:@\"countColor\"];\n    if(cell.type == TYPE_HEADING) {\n        if(self->_headingFont)\n            cell.label.font = self->_headingFont;\n        \n        if(self->_countFont)\n            cell.count.font = self->_countFont;\n    } else {\n        if(self->_userFont)\n            cell.label.font = self->_userFont;\n    }\n    if(cell.type == TYPE_HEADING || ![[row objectForKey:@\"last\"] intValue]) {\n        cell.border1.hidden = YES;\n    } else {\n        cell.border1.hidden = ![UIColor isDarkTheme];\n    }\n    cell.border1.backgroundColor = [row objectForKey:@\"borderColor\"];\n    cell.border2.hidden = ![UIColor isDarkTheme];\n    cell.border2.backgroundColor = [row objectForKey:@\"borderColor\"];\n    return cell;\n}\n\n/*\n// Override to support conditional editing of the table view.\n- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    // Return NO if you do not want the specified item to be editable.\n    return YES;\n}\n*/\n\n/*\n// Override to support editing the table view.\n- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    if (editingStyle == UITableViewCellEditingStyleDelete) {\n        // Delete the row from the data source\n        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];\n    }   \n    else if (editingStyle == UITableViewCellEditingStyleInsert) {\n        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view\n    }   \n}\n*/\n\n/*\n// Override to support rearranging the table view.\n- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath\n{\n}\n*/\n\n/*\n// Override to support conditional rearranging of the table view.\n- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    // Return NO if you do not want the item to be re-orderable.\n    return YES;\n}\n*/\n\n#pragma mark - Table view delegate\n\n-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {\n    if([UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPad)\n        [self->_delegate dismissKeyboard];\n}\n\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [tableView deselectRowAtIndexPath:indexPath animated:NO];\n    NSUInteger idx = [[self->_sectionIndexes objectAtIndex:indexPath.section] intValue] + indexPath.row;\n    if([[[self->_data objectAtIndex:idx] objectForKey:@\"type\"] intValue] == TYPE_USER)\n        [self->_delegate userSelected:[[self->_data objectAtIndex:idx] objectForKey:@\"text\"] rect:[self.tableView rectForRowAtIndexPath:indexPath]];\n}\n\n-(void)_showLongPressMenu:(CGPoint)location {\n    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];\n    if(indexPath) {\n        if(indexPath.row < _data.count) {\n            NSUInteger idx = [[self->_sectionIndexes objectAtIndex:indexPath.section] intValue] + indexPath.row;\n            if([[[self->_data objectAtIndex:idx] objectForKey:@\"type\"] intValue] == TYPE_USER)\n                [self->_delegate userSelected:[[self->_data objectAtIndex:idx] objectForKey:@\"text\"] rect:[self.tableView rectForRowAtIndexPath:indexPath]];\n        }\n    }\n}\n\n-(void)_longPress:(UILongPressGestureRecognizer *)gestureRecognizer {\n    @synchronized(self->_data) {\n        if(gestureRecognizer.state == UIGestureRecognizerStateBegan) {\n            [self _showLongPressMenu:[gestureRecognizer locationInView:self.tableView]];\n        }\n    }\n}\n\n- (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction\n                        configurationForMenuAtLocation:(CGPoint)location API_AVAILABLE(ios(13.0)) {\n    [self _showLongPressMenu:location];\n    return nil;\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/WhoListTableViewController.h",
    "content": "//\n//  WhoListTableViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"IRCCloudJSONObject.h\"\n\n@interface WhoListTableViewController : UITableViewController {\n    IRCCloudJSONObject *_event;\n    NSArray *_data;\n    NSDictionary *_selectedRow;\n}\n@property (strong) IRCCloudJSONObject *event;\n-(void)refresh;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/WhoListTableViewController.m",
    "content": "//\n//  WhoListTableViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import <MobileCoreServices/UTCoreTypes.h>\n#import \"WhoListTableViewController.h\"\n#import \"LinkTextView.h\"\n#import \"ColorFormatter.h\"\n#import \"NetworkConnection.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@interface WhoTableCell : UITableViewCell {\n    LinkTextView *_info;\n}\n@property (readonly) LinkTextView *info;\n@end\n\n@implementation WhoTableCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        \n        self->_info = [[LinkTextView alloc] init];\n        self->_info.font = [UIFont systemFontOfSize:FONT_SIZE];\n        self->_info.editable = NO;\n        self->_info.scrollEnabled = NO;\n        self->_info.textContainerInset = UIEdgeInsetsZero;\n        self->_info.backgroundColor = [UIColor clearColor];\n        self->_info.textColor = [UIColor messageTextColor];\n        [self.contentView addSubview:self->_info];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n\t[super layoutSubviews];\n\t\n\tCGRect frame = [self.contentView bounds];\n    frame.origin.x = 6;\n    frame.size.width -= 12;\n    \n    self->_info.frame = frame;\n}\n\n-(void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n@end\n\n@implementation WhoListTableViewController\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed)];\n    self.tableView.backgroundColor = [[UITableViewCell appearance] backgroundColor];\n    [self refresh];\n}\n\n-(void)refresh {\n    NSMutableArray *data = [[NSMutableArray alloc] init];\n    \n    for(NSDictionary *user in [self->_event objectForKey:@\"users\"]) {\n        NSMutableDictionary *u = [[NSMutableDictionary alloc] initWithDictionary:user];\n        NSString *name;\n        if([[user objectForKey:@\"realname\"] length])\n            name = [NSString stringWithFormat:@\"%c%@%c (%@)\", BOLD, [user objectForKey:@\"nick\"], BOLD, [user objectForKey:@\"realname\"]];\n        else\n            name = [NSString stringWithFormat:@\"%c%@\", BOLD, [user objectForKey:@\"nick\"]];\n        NSAttributedString *formatted = [ColorFormatter format:[NSString stringWithFormat:@\"%@%c%@%cConnected via %@\\n%@\",name,CLEAR,[[user objectForKey:@\"away\"] intValue]?@\" [away]\\n\":@\"\\n\", ITALICS,[user objectForKey:@\"ircserver\"], [user objectForKey:@\"usermask\"]] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil];\n        [u setObject:formatted forKey:@\"formatted\"];\n        [u setObject:@([LinkTextView heightOfString:formatted constrainedToWidth:self.tableView.bounds.size.width - 6 - 12] + 16) forKey:@\"height\"];\n        [data addObject:u];\n    }\n    \n    self->_data = data;\n    [self.tableView reloadData];\n}\n\n-(void)doneButtonPressed {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)addButtonPressed {\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n#pragma mark - Table view data source\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    return [[row objectForKey:@\"height\"] floatValue];\n}\n\n-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return 1;\n}\n\n-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return [self->_data count];\n}\n\n-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    WhoTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"whocell\"];\n    if(!cell)\n        cell = [[WhoTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"whocell\"];\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    cell.info.attributedText = [row objectForKey:@\"formatted\"];\n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [tableView deselectRowAtIndexPath:indexPath animated:NO];\n    self->_selectedRow = [self->_data objectAtIndex:[indexPath row]];\n    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];\n    \n    [alert addAction:[UIAlertAction actionWithTitle:@\"Send a message\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        [self dismissViewControllerAnimated:YES completion:nil];\n        [[NetworkConnection sharedInstance] say:[NSString stringWithFormat:@\"/query %@\", [self->_selectedRow objectForKey:@\"nick\"]] to:nil cid:self->_event.cid handler:nil];\n    }]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Whois\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        [self dismissViewControllerAnimated:YES completion:nil];\n        [[NetworkConnection sharedInstance] say:[NSString stringWithFormat:@\"/whois %@\", [self->_selectedRow objectForKey:@\"nick\"]] to:nil cid:self->_event.cid handler:nil];\n    }]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Copy hostmask\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alert) {\n        UIPasteboard *pb = [UIPasteboard generalPasteboard];\n        [pb setValue:[NSString stringWithFormat:@\"%@!%@\", [self->_selectedRow objectForKey:@\"nick\"], [self->_selectedRow objectForKey:@\"usermask\"]] forPasteboardType:(NSString *)kUTTypeUTF8PlainText];\n    }]];\n    [alert addAction:[UIAlertAction actionWithTitle:@\"Cancel\" style:UIAlertActionStyleCancel handler:nil]];\n    alert.popoverPresentationController.sourceRect = [self.tableView rectForRowAtIndexPath:indexPath];\n    alert.popoverPresentationController.sourceView = self.view;\n    [self.navigationController presentViewController:alert animated:YES completion:nil];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/WhoWasTableViewController.h",
    "content": "//\n//  WhoWasTableViewController.h\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"IRCCloudJSONObject.h\"\n\n@interface WhoWasTableViewController : UITableViewController {\n    NSArray *_data;\n    IRCCloudJSONObject *_event;\n    UILabel *_placeholder;\n}\n@property (strong) IRCCloudJSONObject *event;\n-(void)refresh;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/WhoWasTableViewController.m",
    "content": "//\n//  WhoWasTableViewController.h\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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#import \"WhoWasTableViewController.h\"\n#import \"LinkTextView.h\"\n#import \"ColorFormatter.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@interface ThenWhoWasTableCell : UITableViewCell {\n    LinkTextView *_label;\n}\n@property (readonly) LinkTextView *label;\n@end\n\n@implementation ThenWhoWasTableCell\n\n-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {\n    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];\n    if (self) {\n        self.selectionStyle = UITableViewCellSelectionStyleNone;\n        \n        self->_label = [[LinkTextView alloc] init];\n        self->_label.font = [UIFont systemFontOfSize:FONT_SIZE];\n        self->_label.backgroundColor = [UIColor clearColor];\n        self->_label.textColor = [UIColor messageTextColor];\n        self->_label.selectable = YES;\n        self->_label.editable = NO;\n        self->_label.scrollEnabled = NO;\n        self->_label.textContainerInset = UIEdgeInsetsZero;\n        self->_label.dataDetectorTypes = UIDataDetectorTypeNone;\n        self->_label.textContainer.lineFragmentPadding = 0;\n        [self.contentView addSubview:self->_label];\n    }\n    return self;\n}\n\n-(void)layoutSubviews {\n\t[super layoutSubviews];\n\t\n\tCGRect frame = [self.contentView bounds];\n    frame.origin.x = 6;\n    frame.origin.y = 6;\n    frame.size.width -= 12;\n    frame.size.height -= 8;\n    \n    self->_label.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);\n}\n\n-(void)setSelected:(BOOL)selected animated:(BOOL)animated {\n    [super setSelected:selected animated:animated];\n}\n\n@end\n\n@implementation WhoWasTableViewController\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)viewDidLoad {\n    [super viewDidLoad];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed)];\n\n    self->_placeholder = [[UILabel alloc] initWithFrame:CGRectZero];\n    self->_placeholder.backgroundColor = [UIColor clearColor];\n    self->_placeholder.font = [UIFont systemFontOfSize:FONT_SIZE];\n    self->_placeholder.numberOfLines = 0;\n    self->_placeholder.textAlignment = NSTextAlignmentCenter;\n    self->_placeholder.textColor = [UIColor messageTextColor];\n}\n\n-(void)viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    CGRect frame = self.tableView.frame;\n    frame.size.height = self->_placeholder.font.pointSize * 2;\n    self->_placeholder.frame = frame;\n    [self.tableView.superview addSubview:self->_placeholder];\n    [self refresh];\n}\n\n-(void)viewWillDisappear:(BOOL)animated {\n    [super viewWillDisappear:animated];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n-(void)refresh {\n    NSMutableArray *data = [[NSMutableArray alloc] init];\n    \n    if([[self->_event objectForKey:@\"lines\"] count] == 1 && [[[self->_event objectForKey:@\"lines\"] objectAtIndex:0] objectForKey:@\"no_such_nick\"]) {\n        self->_data = nil;\n        self->_placeholder.text = @\"There was no such nickname\";\n    } else {\n        self->_placeholder.text = nil;\n        \n        for(NSDictionary *line in [self->_event objectForKey:@\"lines\"]) {\n            NSMutableDictionary *c = [[NSMutableDictionary alloc] init];\n            NSMutableString *text = [[NSMutableString alloc] init];\n            [text appendFormat:@\"%c%c%@Nick%c\\n%@\\n\", BOLD, COLOR_RGB, [[UIColor navBarHeadingColor] toHexString], CLEAR, [line objectForKey:@\"nick\"]];\n            if([line objectForKey:@\"user\"] && [line objectForKey:@\"host\"])\n                [text appendFormat:@\"%c%c%@Usermask%c\\n%@@%@\\n\", BOLD, COLOR_RGB, [[UIColor navBarHeadingColor] toHexString], CLEAR, [line objectForKey:@\"user\"], [line objectForKey:@\"host\"]];\n            [text appendFormat:@\"%c%c%@Real Name%c\\n%@\\n\", BOLD, COLOR_RGB, [[UIColor navBarHeadingColor] toHexString], CLEAR, [line objectForKey:@\"realname\"]];\n            [text appendFormat:@\"%c%c%@Last Seen%c\\n%@\\n\", BOLD, COLOR_RGB, [[UIColor navBarHeadingColor] toHexString], CLEAR, [line objectForKey:@\"last_seen\"]];\n            [text appendFormat:@\"%c%c%@Connecting Via%c\\n%@\\n\", BOLD, COLOR_RGB, [[UIColor navBarHeadingColor] toHexString], CLEAR, [line objectForKey:@\"ircserver\"]];\n            if([line objectForKey:@\"connecting_from\"])\n                [text appendFormat:@\"%c%c%@Info%c\\n%@\\n\", BOLD, COLOR_RGB, [[UIColor navBarHeadingColor] toHexString], CLEAR, [line objectForKey:@\"connecting_from\"]];\n            if([line objectForKey:@\"actual_host\"])\n                [text appendFormat:@\"%c%c%@Actual Host%c\\n%@\\n\", BOLD, COLOR_RGB, [[UIColor navBarHeadingColor] toHexString], CLEAR, [line objectForKey:@\"actual_host\"]];\n            [c setObject:[ColorFormatter format:text defaultColor:[UITableViewCell appearance].detailTextLabelColor mono:NO linkify:NO server:nil links:nil] forKey:@\"text\"];\n            [c setObject:@([LinkTextView heightOfString:[c objectForKey:@\"text\"] constrainedToWidth:self.tableView.bounds.size.width - 6 - 12]) forKey:@\"height\"];\n            [data addObject:c];\n        }\n        \n        self->_data = data;\n    }\n    [self.tableView reloadData];\n    \n    self.navigationItem.title = [NSString stringWithFormat:@\"WHOWAS response for %@\", [self->_event objectForKey:@\"nick\"]];\n}\n\n-(void)doneButtonPressed {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n-(void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n}\n\n#pragma mark - Table view data source\n\n-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath row]];\n    return [[row objectForKey:@\"height\"] floatValue];\n}\n\n-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\n    return [self->_data count];\n}\n\n-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n    return 1;\n}\n\n-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n    ThenWhoWasTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"whowascell\"];\n    if(!cell)\n        cell = [[ThenWhoWasTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@\"whowascell\"];\n    NSDictionary *row = [self->_data objectAtIndex:[indexPath section]];\n    cell.label.attributedText = [row objectForKey:@\"text\"];\n    return cell;\n}\n\n#pragma mark - Table view delegate\n\n-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n    [tableView deselectRowAtIndexPath:indexPath animated:NO];\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/WhoisViewController.h",
    "content": "//\n//  WhoisViewController.h\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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 <UIKit/UIKit.h>\n#import \"LinkTextView.h\"\n#import \"IRCCloudJSONObject.h\"\n\n@interface WhoisViewController : UIViewController<LinkTextViewDelegate> {\n    UIScrollView *_scrollView;\n    LinkTextView *_label;\n}\n-(void)setData:(IRCCloudJSONObject*)object;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/WhoisViewController.m",
    "content": "//\n//  WhoisViewController.m\n//\n//  Copyright (C) 2013 IRCCloud, Ltd.\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#import \"WhoisViewController.h\"\n#import \"ColorFormatter.h\"\n#import \"AppDelegate.h\"\n#import \"UIColor+IRCCloud.h\"\n\n@implementation WhoisViewController\n\n-(id)init {\n    self = [super init];\n    if (self) {\n        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)];\n        \n        self->_scrollView = [[UIScrollView alloc] init];\n        self->_scrollView.backgroundColor = [UIColor contentBackgroundColor];\n        self->_label = [[LinkTextView alloc] init];\n        self->_label.linkDelegate = self;\n        self->_label.editable = NO;\n        self->_label.scrollEnabled = NO;\n        self->_label.backgroundColor = [UIColor clearColor];\n        self->_label.textColor = [UIColor messageTextColor];\n        self->_label.textContainerInset = UIEdgeInsetsZero;\n        \n        [self->_scrollView addSubview:self->_label];\n    }\n    return self;\n}\n\n-(void)appendWhoisLine:(NSMutableAttributedString *)data key:(NSString *)key data:(IRCCloudJSONObject *)object nick:(NSString *)nick server:(Server *)s {\n    [self appendWhoisLine:data key:key data:object nick:nick server:s format:@\"%@ %@\\n\"];\n}\n\n-(void)appendWhoisLine:(NSMutableAttributedString *)data key:(NSString *)key data:(IRCCloudJSONObject *)object nick:(NSString *)nick server:(Server *)s format:(NSString *)fmt {\n    if([[object objectForKey:key] length]) {\n        [data appendAttributedString:[ColorFormatter format:[NSString stringWithFormat:fmt, nick, [object objectForKey:key]] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:s links:nil]];\n    }\n}\n\n-(void)setData:(IRCCloudJSONObject *)object {\n    NSString *nick = [object objectForKey:@\"user_nick\"] ? [object objectForKey:@\"user_nick\"] : [object objectForKey:@\"nick\"];\n    self.navigationItem.title = nick;\n\n    Server *s = [[ServersDataSource sharedInstance] getServer:[[object objectForKey:@\"cid\"] intValue]];\n    \n    NSArray *matches;\n    NSMutableArray *links = [[NSMutableArray alloc] init];\n    NSMutableAttributedString *data = [[NSMutableAttributedString alloc] init];\n    \n    NSString *actualHost = @\"\";\n    if([object objectForKey:@\"actual_host\"])\n        actualHost = [NSString stringWithFormat:@\"/%@\", [object objectForKey:@\"actual_host\"]];\n    [data appendAttributedString:[ColorFormatter format:[NSString stringWithFormat:@\"%@%c (%@%c%@%c)\", [object objectForKey:@\"user_realname\"], CLEAR, [object objectForKey:@\"user_mask\"], CLEAR, actualHost, CLEAR] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:s links:nil]];\n    \n    if([[object objectForKey:@\"user_logged_in_as\"] length]) {\n        [data appendAttributedString:[ColorFormatter format:[NSString stringWithFormat:@\" is authed as %@\", [object objectForKey:@\"user_logged_in_as\"]] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:s links:nil]];\n    }\n    \n    [data appendAttributedString:[ColorFormatter format:@\"\\n\" defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil]];\n    \n    if([object objectForKey:@\"away\"]) {\n        NSString *away = @\"Away\";\n        if(![[object objectForKey:@\"away\"] isEqualToString:@\"away\"])\n            away = [away stringByAppendingFormat:@\": %@\", [object objectForKey:@\"away\"]];\n        \n        [data appendAttributedString:[ColorFormatter format:[NSString stringWithFormat:@\"%@\\n\", away] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:s links:nil]];\n    }\n    \n    if([[object objectForKey:@\"signon_time\"] intValue]) {\n        [data appendAttributedString:[ColorFormatter format:[NSString stringWithFormat:@\"Online for about %@\", [self duration:([[NSDate date] timeIntervalSince1970] - [[object objectForKey:@\"signon_time\"] doubleValue])]] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:s links:nil]];\n        \n        if([[object objectForKey:@\"idle_secs\"] intValue]) {\n            [data appendAttributedString:[ColorFormatter format:[NSString stringWithFormat:@\" (idle for %@)\", [self duration:[[object objectForKey:@\"idle_secs\"] intValue]]] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:s links:nil]];\n        }\n        \n        [data appendAttributedString:[[NSAttributedString alloc] initWithString:@\"\\n\"]];\n    }\n    \n    [self appendWhoisLine:data key:@\"bot_msg\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"op_msg\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"opername_msg\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"userip\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"server_addr\" data:object nick:nick server:s format:@\"%@ is connected via: %@\"];\n   \n    if([[object objectForKey:@\"server_extra\"] length]) {\n        [data appendAttributedString:[ColorFormatter format:@\" (\" defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil]];\n        NSUInteger offset = data.length;\n        [data appendAttributedString:[ColorFormatter format:[object objectForKey:@\"server_extra\"] defaultColor:[UIColor messageTextColor] mono:NO linkify:YES server:s links:&matches]];\n        [data appendAttributedString:[ColorFormatter format:@\")\" defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil]];\n        for(NSTextCheckingResult *result in matches) {\n            NSURL *u;\n            if(result.resultType == NSTextCheckingTypeLink) {\n                u = result.URL;\n            } else {\n                NSString *url = [[data attributedSubstringFromRange:NSMakeRange(result.range.location+offset, result.range.length)] string];\n                if(![url hasPrefix:@\"irc\"])\n                    url = [[NSString stringWithFormat:@\"irc%@://%@:%i/%@\", (s.ssl==1)?@\"s\":@\"\", s.hostname, s.port, url] stringByReplacingOccurrencesOfString:@\"#\" withString:@\"%23\"];\n                u = [NSURL URLWithString:url];\n                \n            }\n            [links addObject:[NSTextCheckingResult linkCheckingResultWithRange:NSMakeRange(result.range.location+offset, result.range.length) URL:u]];\n        }\n    }\n    \n    [data appendAttributedString:[ColorFormatter format:@\"\\n\" defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil]];\n    \n    [self appendWhoisLine:data key:@\"host\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"country\" data:object nick:nick server:s];\n\n    [self addChannels:[object objectForKey:@\"channels_oper\"] forGroup:@\"Oper\" attributedString:data links:links server:s];\n    [self addChannels:[object objectForKey:@\"channels_owner\"] forGroup:@\"Owner\" attributedString:data links:links server:s];\n    [self addChannels:[object objectForKey:@\"channels_admin\"] forGroup:@\"Admin\" attributedString:data links:links server:s];\n    [self addChannels:[object objectForKey:@\"channels_op\"] forGroup:@\"Operator\" attributedString:data links:links server:s];\n    [self addChannels:[object objectForKey:@\"channels_halfop\"] forGroup:@\"Half-Operator\" attributedString:data links:links server:s];\n    [self addChannels:[object objectForKey:@\"channels_voiced\"] forGroup:@\"Voiced\" attributedString:data links:links server:s];\n    [self addChannels:[object objectForKey:@\"channels_member\"] forGroup:@\"Member\" attributedString:data links:links server:s];\n\n    [self appendWhoisLine:data key:@\"secure\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"client_cert\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"cgi\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"help\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"staff\" data:object nick:nick server:s format:@\"%@ is staff: %@\\n\"];\n    \n    if([[object objectForKey:@\"special\"] isKindOfClass:NSArray.class] && [(NSArray *)[object objectForKey:@\"special\"] count]) {\n        for(NSString *sp in [object objectForKey:@\"special\"]) {\n            [data appendAttributedString:[ColorFormatter format:[NSString stringWithFormat:@\"%@ %@\\n\", nick, sp] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:s links:nil]];\n        }\n    }\n    \n    [self appendWhoisLine:data key:@\"modes\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"callerid\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"stats_dline\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"btn_metadata\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"text\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"msg_only_reg\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"suspend\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"chanop\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"kill\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"helper\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"admin\" data:object nick:nick server:s];\n    [self appendWhoisLine:data key:@\"codepage\" data:object nick:nick server:s];\n    \n    self->_label.attributedText = data;\n    self->_label.linkAttributes = [UIColor linkAttributes];\n    for(NSTextCheckingResult *result in links)\n        [self->_label addLinkWithTextCheckingResult:result];\n}\n\n-(SupportedOrientationsReturnType)supportedInterfaceOrientations {\n    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskAllButUpsideDown:UIInterfaceOrientationMaskAll;\n}\n\n-(void)addChannels:(NSArray *)channels forGroup:(NSString *)group attributedString:(NSMutableAttributedString *)data links:(NSMutableArray *)links server:(Server *)s {\n    if(channels.count) {\n        [data appendAttributedString:[ColorFormatter format:[NSString stringWithFormat:[group isEqualToString:@\"Member\"]?@\"%@ of:\\n\":@\"%@ in:\\n\", group] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:nil links:nil]];\n        for(NSString *channel in channels) {\n            NSUInteger offset = data.length;\n            [data appendAttributedString:[ColorFormatter format:[NSString stringWithFormat:@\" • %@\\n\", channel] defaultColor:[UIColor messageTextColor] mono:NO linkify:NO server:s links:nil]];\n            [links addObject:[NSTextCheckingResult linkCheckingResultWithRange:NSMakeRange(offset + 3, data.length - offset - 3) URL:[NSURL URLWithString:[NSString stringWithFormat:@\"irc://%i/%@\", s.cid, [channel stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]]]]];\n        }\n    }\n}\n\n-(NSString *)duration:(int)seconds {\n    int minutes = seconds / 60;\n    int hours = minutes / 60;\n    int days = hours / 24;\n    if(days) {\n        if(days == 1)\n            return [NSString stringWithFormat:@\"%i day\", days];\n        else\n            return [NSString stringWithFormat:@\"%i days\", days];\n    } else if(hours) {\n        if(hours == 1)\n            return [NSString stringWithFormat:@\"%i hour\", hours];\n        else\n            return [NSString stringWithFormat:@\"%i hours\", hours];\n    } else if(minutes) {\n        if(minutes == 1)\n            return [NSString stringWithFormat:@\"%i minute\", minutes];\n        else\n            return [NSString stringWithFormat:@\"%i minutes\", minutes];\n    } else {\n        if(seconds == 1)\n            return [NSString stringWithFormat:@\"%i second\", seconds];\n        else\n            return [NSString stringWithFormat:@\"%i seconds\", seconds];\n    }\n}\n\n-(void)loadView {\n    [super loadView];\n    self.navigationController.navigationBar.clipsToBounds = YES;\n    self.navigationController.navigationBar.barStyle = [UIColor isDarkTheme]?UIBarStyleBlack:UIBarStyleDefault;\n    self->_label.frame = CGRectMake(12,2,self.view.bounds.size.width-24, [LinkTextView heightOfString:self->_label.attributedText constrainedToWidth:self.view.bounds.size.width-24]+12);\n    self->_scrollView.frame = self.view.frame;\n    self->_scrollView.contentSize = self->_label.frame.size;\n    self.view = self->_scrollView;\n}\n\n-(void)doneButtonPressed:(id)sender {\n    [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n- (void)LinkTextView:(LinkTextView *)label didSelectLinkWithTextCheckingResult:(NSTextCheckingResult *)result {\n    [(AppDelegate *)([UIApplication sharedApplication].delegate) launchURL:result.URL];\n    if([result.URL.scheme hasPrefix:@\"irc\"])\n        [self dismissViewControllerAnimated:YES completion:nil];\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/YouTubeViewController.h",
    "content": "//\n//  YouTubeViewController.h\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import <UIKit/UIKit.h>\n#import \"YTPlayerView.h\"\n\n@interface YouTubeViewController : UIViewController<YTPlayerViewDelegate,UIPopoverPresentationControllerDelegate> {\n    NSURL *_url;\n    UIActivityIndicatorView *_activity;\n    YTPlayerView *_player;\n    UIToolbar *_toolbar;\n}\n@property YTPlayerView *player;\n@property (readonly) NSURL *url;\n@property (readonly) UIToolbar *toolbar;\n-(id)initWithURL:(NSURL *)url;\n@end\n"
  },
  {
    "path": "IRCCloud/Classes/YouTubeViewController.m",
    "content": "//\n//  YouTubeViewController.m\n//\n//  Copyright (C) 2016 IRCCloud, Ltd.\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#import <AVFoundation/AVFoundation.h>\n#import <MobileCoreServices/UTCoreTypes.h>\n#import <SafariServices/SafariServices.h>\n#import \"OpenInChromeController.h\"\n#import \"OpenInFirefoxControllerObjC.h\"\n#import \"YouTubeViewController.h\"\n#import \"AppDelegate.h\"\n#import \"MainViewController.h\"\n#import \"UIColor+IRCCloud.h\"\n@import Firebase;\n\n#define YTMARGIN 130\n\n@implementation YouTubeViewController\n\n- (id)initWithURL:(NSURL *)url {\n    self = [super init];\n    if(self) {\n        self->_url = url;\n    }\n    return self;\n}\n\n- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {\n    return @[\n             [UIPreviewAction actionWithTitle:@\"Copy URL\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                 UIPasteboard *pb = [UIPasteboard generalPasteboard];\n                 [pb setValue:self->_url.absoluteString forPasteboardType:(NSString *)kUTTypeUTF8PlainText];\n             }],\n             [UIPreviewAction actionWithTitle:@\"Share\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                 UIApplication *app = [UIApplication sharedApplication];\n                 AppDelegate *appDelegate = (AppDelegate *)app.delegate;\n                 MainViewController *mainViewController = [appDelegate mainViewController];\n                 \n                 [UIColor clearTheme];\n                 UIActivityViewController *activityController = [URLHandler activityControllerForItems:@[self->_url] type:@\"Youtube\"];\n                 activityController.popoverPresentationController.sourceView = mainViewController.slidingViewController.view;\n                 [mainViewController.slidingViewController presentViewController:activityController animated:YES completion:nil];\n             }],\n             [UIPreviewAction actionWithTitle:@\"Open in Browser\" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {\n                 if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Chrome\"] && [[OpenInChromeController sharedInstance] openInChrome:self->_url\n                                                                                                                                                         withCallbackURL:[NSURL URLWithString:\n#ifdef ENTERPRISE\n                                                                                                                                                                          @\"irccloud-enterprise://\"\n#else\n                                                                                                                                                                          @\"irccloud://\"\n#endif\n                                                                                                                                                                          ]\n                                                                                                                                                            createNewTab:NO])\n                     return;\n                 else if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Firefox\"] && [[OpenInFirefoxControllerObjC sharedInstance] openInFirefox:self->_url])\n                     return;\n                 else\n                     [[UIApplication sharedApplication] openURL:self->_url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n             }]\n             ];\n}\n\n-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {\n    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];\n    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n        int margin = (size.width > size.height)?YTMARGIN:0;\n        CGFloat width = self.view.bounds.size.width - margin;\n        CGFloat height = (width / 16.0f) * 9.0f;\n        self->_player.frame = CGRectMake(margin/2, (self.view.bounds.size.height - height) / 2.0f, width, height);\n    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {\n        \n    }\n    ];\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.9];\n    self.view.autoresizesSubviews = YES;\n    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(_YTpanned:)];\n    [self.view addGestureRecognizer:panGesture];\n    \n    self->_toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0,self.view.bounds.size.height - 44,self.view.bounds.size.width, 44)];\n    [self->_toolbar setBackgroundImage:[[UIImage alloc] init] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];\n    [self->_toolbar setShadowImage:[[UIImage alloc] init] forToolbarPosition:UIToolbarPositionAny];\n    [self->_toolbar setBarStyle:UIBarStyleBlack];\n    self->_toolbar.translucent = YES;\n    self->_toolbar.items = @[\n                      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(_YTShare:)],\n                      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],\n                      [[UIBarButtonItem alloc] initWithTitle:@\"Done\" style:UIBarButtonItemStylePlain target:self action:@selector(_YTWrapperTapped)]\n                      ];\n    self->_toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;\n    [self.view addSubview:self->_toolbar];\n    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_YTWrapperTapped)];\n    [self.view addGestureRecognizer:tap];\n    \n    NSString *videoID;\n    NSMutableDictionary *params = [[NSMutableDictionary alloc] init];\n    [params setObject:self->_url.absoluteString forKey:@\"origin\"];\n    \n    if([self->_url.host isEqualToString:@\"youtu.be\"]) {\n        videoID = [self->_url.path substringFromIndex:1];\n    }\n    \n    for(NSString *param in [self->_url.query componentsSeparatedByString:@\"&\"]) {\n        NSArray *kv = [param componentsSeparatedByString:@\"=\"];\n        if(kv.count == 2) {\n            if([[kv objectAtIndex:0] isEqualToString:@\"v\"]) {\n                videoID = [kv objectAtIndex:1];\n            } else if([[kv objectAtIndex:0] isEqualToString:@\"t\"]) {\n                int start = 0;\n                NSString *t = [kv objectAtIndex:1];\n                int number = 0;\n                for(int i = 0; i < t.length; i++) {\n                    switch([t characterAtIndex:i]) {\n                        case '0':\n                        case '1':\n                        case '2':\n                        case '3':\n                        case '4':\n                        case '5':\n                        case '6':\n                        case '7':\n                        case '8':\n                        case '9':\n                            number *= 10;\n                            number += [t characterAtIndex:i] - '0';\n                            break;\n                        case 'h':\n                            start += number * 60;\n                            number = 0;\n                            break;\n                        case 'm':\n                            start += number * 60;\n                            number = 0;\n                            break;\n                        case 's':\n                            start += number;\n                            number = 0;\n                            break;\n                        default:\n                            CLS_LOG(@\"Unrecognized time separator: %c\", [t characterAtIndex:i]);\n                            number = 0;\n                            break;\n                    }\n                }\n                start += number;\n                [params setObject:@(start) forKey:@\"start\"];\n            } else {\n                [params setObject:[kv objectAtIndex:1] forKey:[kv objectAtIndex:0]];\n            }\n        }\n    }\n    \n    int margin = UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)?YTMARGIN:0;\n    CGFloat width = self.view.bounds.size.width - margin;\n    CGFloat height = (width / 16.0f) * 9.0f;\n    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];\n    self->_player = [[YTPlayerView alloc] initWithFrame:CGRectMake(margin/2, (self.view.bounds.size.height - height) / 2.0f, width, height)];\n    self->_player.backgroundColor = [UIColor blackColor];\n    self->_player.webView.backgroundColor = [UIColor blackColor];\n    self->_player.hidden = YES;\n    self->_player.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;\n    self->_player.autoresizesSubviews = YES;\n    self->_player.delegate = self;\n    if(videoID)\n        [self->_player loadWithVideoId:videoID playerVars:params];\n    else\n        CLS_LOG(@\"Unable to extract video ID from URL: %@\", _url);\n    [self.view addSubview:self->_player];\n    \n    self->_activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];\n    self->_activity.center = self.view.center;\n    self->_activity.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;\n    self->_activity.hidesWhenStopped = YES;\n    [self->_activity startAnimating];\n    [self.view addSubview:self->_activity];\n}\n\n-(void)_YTWrapperTapped {\n    [UIView animateWithDuration:0.25 animations:^{\n        self.view.alpha = 0;\n    } completion:^(BOOL finished) {\n        [self.presentingViewController dismissViewControllerAnimated:NO completion:nil];\n    }];\n    [self->_activity stopAnimating];\n    self->_player.delegate = nil;\n    self->_player.webView.navigationDelegate = nil;\n    [self->_player stopVideo];\n    [self->_player.webView stopLoading];\n}\n\n-(void)_YTShare:(id)sender {\n    UIActivityViewController *activityController = [URLHandler activityControllerForItems:@[self->_url] type:@\"Youtube\"];\n    activityController.popoverPresentationController.delegate = self;\n    activityController.popoverPresentationController.barButtonItem = sender;\n    [self presentViewController:activityController animated:YES completion:nil];\n}\n\n-(void)playerViewDidBecomeReady:(YTPlayerView *)playerView {\n    [self->_activity stopAnimating];\n    playerView.hidden = NO;\n}\n\n-(void)playerView:(YTPlayerView *)playerView receivedError:(YTPlayerError)error {\n    if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Chrome\"] && [[OpenInChromeController sharedInstance] openInChrome:self->_url\n                                                                                                                                            withCallbackURL:[NSURL URLWithString:\n#ifdef ENTERPRISE\n                                                                                                                                                             @\"irccloud-enterprise://\"\n#else\n                                                                                                                                                             @\"irccloud://\"\n#endif\n                                                                                                                                                             ]\n                                                                                                                                               createNewTab:NO])\n        return;\n    else if([[[NSUserDefaults standardUserDefaults] objectForKey:@\"browser\"] isEqualToString:@\"Firefox\"] && [[OpenInFirefoxControllerObjC sharedInstance] openInFirefox:self->_url])\n        return;\n    else\n        [[UIApplication sharedApplication] openURL:self->_url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n}\n\n- (void)_YTpanned:(UIPanGestureRecognizer *)recognizer {\n    CGRect frame = self->_player.frame;\n    \n    switch(recognizer.state) {\n        case UIGestureRecognizerStateBegan:\n            if(fabs([recognizer velocityInView:self.view].y) > fabs([recognizer velocityInView:self.view].x)) {\n            }\n            break;\n        case UIGestureRecognizerStateCancelled: {\n            frame.origin.y = 0;\n            [UIView animateWithDuration:0.25 animations:^{\n                self->_player.frame = frame;\n            }];\n            self.view.alpha = 1;\n            break;\n        }\n        case UIGestureRecognizerStateChanged:\n            frame.origin.y = (self.view.bounds.size.height - frame.size.height) / 2 + [recognizer translationInView:self.view].y;\n            self->_player.frame = frame;\n            self.view.alpha = 1 - (fabs([recognizer translationInView:self.view].y) / self.view.frame.size.height / 2);\n            break;\n        case UIGestureRecognizerStateEnded:\n        {\n            if(fabs([recognizer translationInView:self.view].y) > 100 || fabs([recognizer velocityInView:self.view].y) > 1000) {\n                frame.origin.y = ([recognizer translationInView:self.view].y > 0)?self.view.bounds.size.height:-self.view.bounds.size.height;\n                [UIView animateWithDuration:0.25 animations:^{\n                    self->_player.frame = frame;\n                    self.view.alpha = 0;\n                } completion:^(BOOL finished) {\n                    [self _YTWrapperTapped];\n                }];\n            } else {\n                frame.origin.y = (self.view.bounds.size.height - frame.size.height) / 2;\n                [UIView animateWithDuration:0.25 animations:^{\n                    self->_player.frame = frame;\n                    self.view.alpha = 1;\n                }];\n            }\n            break;\n        }\n        default:\n            break;\n    }\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n/*\n#pragma mark - Navigation\n\n// In a storyboard-based application, you will often want to do a little preparation before navigation\n- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {\n    // Get the new view controller using [segue destinationViewController].\n    // Pass the selected object to the new view controller.\n}\n*/\n\n@end\n"
  },
  {
    "path": "IRCCloud/EventsTableCell.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"22505\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" colorMatched=\"YES\">\n    <device id=\"retina4_7\" orientation=\"portrait\" appearance=\"light\"/>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"22504\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <tableViewCell contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"none\" indentationWidth=\"10\" rowHeight=\"45\" id=\"KGk-i7-Jjw\" customClass=\"EventsTableCell\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"428\" height=\"45\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMaxY=\"YES\"/>\n            <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"KGk-i7-Jjw\" id=\"H2p-sc-9uM\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"428\" height=\"45\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mCi-xX-5DS\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"428\" height=\"1\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"height\" constant=\"1\" id=\"CDG-1R-Fry\"/>\n                        </constraints>\n                    </view>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Air-U6-OOz\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"42\" width=\"428\" height=\"3\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"height\" constant=\"3\" id=\"iBt-k6-x0q\"/>\n                        </constraints>\n                    </view>\n                    <view hidden=\"YES\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"KgT-oH-O7i\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"22\" width=\"428\" height=\"1\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"height\" constant=\"1\" id=\"2y0-hA-t78\"/>\n                        </constraints>\n                    </view>\n                    <view hidden=\"YES\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"FYg-pz-vsM\">\n                        <rect key=\"frame\" x=\"150\" y=\"0.0\" width=\"128\" height=\"45\"/>\n                        <subviews>\n                            <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"New Messages\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2Cd-th-WEc\">\n                                <rect key=\"frame\" x=\"6\" y=\"0.0\" width=\"116\" height=\"45\"/>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                                <nil key=\"textColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                        </subviews>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"height\" secondItem=\"2Cd-th-WEc\" secondAttribute=\"height\" id=\"IC5-Ip-KKx\"/>\n                            <constraint firstItem=\"2Cd-th-WEc\" firstAttribute=\"centerY\" secondItem=\"FYg-pz-vsM\" secondAttribute=\"centerY\" id=\"mdH-YS-clS\"/>\n                            <constraint firstAttribute=\"width\" secondItem=\"2Cd-th-WEc\" secondAttribute=\"width\" constant=\"12\" id=\"tQM-VL-vUg\"/>\n                            <constraint firstItem=\"2Cd-th-WEc\" firstAttribute=\"centerX\" secondItem=\"FYg-pz-vsM\" secondAttribute=\"centerX\" id=\"y7G-PU-Yq4\"/>\n                        </constraints>\n                    </view>\n                    <label opaque=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" horizontalCompressionResistancePriority=\"250\" verticalCompressionResistancePriority=\"1000\" text=\"\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"none\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nEj-fz-vAL\" customClass=\"LinkLabel\">\n                        <rect key=\"frame\" x=\"110\" y=\"2\" width=\"252\" height=\"0.0\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"\" textAlignment=\"right\" lineBreakMode=\"clip\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fOD-UD-tHL\">\n                        <rect key=\"frame\" x=\"68\" y=\"2\" width=\"66\" height=\"0.0\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"width\" constant=\"66\" id=\"JaC-Af-7TS\"/>\n                        </constraints>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <view hidden=\"YES\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"qsr-vg-LVN\">\n                        <rect key=\"frame\" x=\"104\" y=\"-4\" width=\"264\" height=\"55\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                    </view>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"c4u-g2-2uu\">\n                        <rect key=\"frame\" x=\"102\" y=\"2\" width=\"4\" height=\"43\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"width\" constant=\"4\" id=\"AJh-cH-BSg\"/>\n                        </constraints>\n                    </view>\n                    <label verifyAmbiguity=\"off\" opaque=\"NO\" clipsSubviews=\"YES\" contentMode=\"left\" horizontalCompressionResistancePriority=\"1000\" verticalCompressionResistancePriority=\"1000\" placeholderIntrinsicWidth=\"infinite\" placeholderIntrinsicHeight=\"infinite\" text=\"\" textAlignment=\"natural\" lineBreakMode=\"wordWrap\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsLetterSpacingToFitWidth=\"YES\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"V3s-xQ-nVF\" customClass=\"LinkLabel\">\n                        <rect key=\"frame\" x=\"110\" y=\"2\" width=\"252\" height=\"43\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <label hidden=\"YES\" opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"32\" placeholderIntrinsicHeight=\"32\" text=\"\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oeb-cI-59G\">\n                        <rect key=\"frame\" x=\"110\" y=\"4\" width=\"32\" height=\"32\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"\" textAlignment=\"right\" lineBreakMode=\"clip\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"9ZM-5c-yUP\">\n                        <rect key=\"frame\" x=\"354\" y=\"2\" width=\"66\" height=\"0.0\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"g7o-m6-B7g\">\n                        <rect key=\"frame\" x=\"62\" y=\"4\" width=\"0.0\" height=\"0.0\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"LfV-F3-NEI\" customClass=\"UIControl\">\n                        <rect key=\"frame\" x=\"46\" y=\"-8\" width=\"32\" height=\"24\"/>\n                        <color key=\"backgroundColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"width\" constant=\"32\" id=\"Dt7-Fu-LjK\"/>\n                            <constraint firstAttribute=\"height\" constant=\"24\" id=\"mpP-7e-Sxk\"/>\n                        </constraints>\n                    </view>\n                    <imageView userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"9aa-Ko-5ri\">\n                        <rect key=\"frame\" x=\"66\" y=\"4\" width=\"44\" height=\"44\"/>\n                        <gestureRecognizers/>\n                        <constraints>\n                            <constraint firstAttribute=\"width\" constant=\"44\" id=\"AhO-xV-4Mx\"/>\n                            <constraint firstAttribute=\"height\" constant=\"44\" id=\"N6m-U7-nrr\"/>\n                        </constraints>\n                        <connections>\n                            <outletCollection property=\"gestureRecognizers\" destination=\"uTr-V1-KHO\" appends=\"YES\" id=\"FqS-8g-sYq\"/>\n                        </connections>\n                    </imageView>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"WPz-RI-MPI\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"45\" width=\"428\" height=\"0.0\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                    </view>\n                    <label hidden=\"YES\" opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"252\" verticalHuggingPriority=\"251\" text=\"\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"none\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"XqQ-by-tQa\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"1\" width=\"428\" height=\"41\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                </subviews>\n                <constraints>\n                    <constraint firstItem=\"Air-U6-OOz\" firstAttribute=\"leading\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"leading\" id=\"151-Ll-lkm\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"top\" secondItem=\"nEj-fz-vAL\" secondAttribute=\"bottom\" id=\"29E-wE-L1s\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"fOD-UD-tHL\" secondAttribute=\"bottom\" priority=\"100\" id=\"2UV-md-BHV\"/>\n                    <constraint firstItem=\"9aa-Ko-5ri\" firstAttribute=\"trailing\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"leading\" id=\"3qd-ta-bgg\"/>\n                    <constraint firstItem=\"g7o-m6-B7g\" firstAttribute=\"top\" secondItem=\"nEj-fz-vAL\" secondAttribute=\"bottom\" priority=\"750\" constant=\"2\" id=\"4gQ-Xa-Sui\"/>\n                    <constraint firstItem=\"mCi-xX-5DS\" firstAttribute=\"top\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"top\" id=\"52b-SU-woC\"/>\n                    <constraint firstItem=\"oeb-cI-59G\" firstAttribute=\"leading\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"leading\" id=\"5mm-tp-TXv\"/>\n                    <constraint firstItem=\"9aa-Ko-5ri\" firstAttribute=\"top\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"top\" constant=\"4\" id=\"7aK-3S-iur\"/>\n                    <constraint firstItem=\"FYg-pz-vsM\" firstAttribute=\"centerX\" secondItem=\"KgT-oH-O7i\" secondAttribute=\"centerX\" id=\"7hL-Sy-lYb\"/>\n                    <constraint firstItem=\"fOD-UD-tHL\" firstAttribute=\"leading\" secondItem=\"g7o-m6-B7g\" secondAttribute=\"trailing\" constant=\"6\" id=\"8ZI-LM-dI5\"/>\n                    <constraint firstItem=\"9ZM-5c-yUP\" firstAttribute=\"height\" secondItem=\"fOD-UD-tHL\" secondAttribute=\"height\" id=\"BON-ig-6HA\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"FYg-pz-vsM\" secondAttribute=\"bottom\" id=\"Cj4-7B-Dcp\"/>\n                    <constraint firstItem=\"XqQ-by-tQa\" firstAttribute=\"top\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"top\" constant=\"1\" id=\"Frs-E3-vgn\"/>\n                    <constraint firstItem=\"LfV-F3-NEI\" firstAttribute=\"centerX\" secondItem=\"g7o-m6-B7g\" secondAttribute=\"centerX\" id=\"Hqs-Dl-E76\"/>\n                    <constraint firstItem=\"qsr-vg-LVN\" firstAttribute=\"top\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"top\" constant=\"-6\" id=\"Ifv-QD-BjA\"/>\n                    <constraint firstItem=\"nEj-fz-vAL\" firstAttribute=\"top\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"top\" constant=\"2\" id=\"O0z-rZ-iSx\"/>\n                    <constraint firstItem=\"KgT-oH-O7i\" firstAttribute=\"trailing\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"trailing\" id=\"Q35-43-XyX\"/>\n                    <constraint firstItem=\"XqQ-by-tQa\" firstAttribute=\"leading\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"leading\" id=\"Qqn-rz-qWY\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"Air-U6-OOz\" secondAttribute=\"bottom\" id=\"RZ7-Q4-bsF\"/>\n                    <constraint firstItem=\"qsr-vg-LVN\" firstAttribute=\"leading\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"leading\" constant=\"-6\" id=\"RzF-Ou-dcT\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"Air-U6-OOz\" secondAttribute=\"trailing\" id=\"S4u-o6-ga1\"/>\n                    <constraint firstItem=\"c4u-g2-2uu\" firstAttribute=\"leading\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"leading\" constant=\"-8\" id=\"SUj-bj-KgZ\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"bottom\" id=\"Seh-7j-Oie\"/>\n                    <constraint firstItem=\"qsr-vg-LVN\" firstAttribute=\"height\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"height\" constant=\"12\" id=\"UbJ-gZ-HMg\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"WPz-RI-MPI\" secondAttribute=\"bottom\" id=\"Xxd-3S-pNQ\"/>\n                    <constraint firstItem=\"KgT-oH-O7i\" firstAttribute=\"leading\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"leading\" id=\"YGl-z7-rle\"/>\n                    <constraint firstItem=\"9ZM-5c-yUP\" firstAttribute=\"firstBaseline\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"firstBaseline\" id=\"Yw2-Z2-HwK\"/>\n                    <constraint firstItem=\"KgT-oH-O7i\" firstAttribute=\"centerY\" secondItem=\"FYg-pz-vsM\" secondAttribute=\"centerY\" id=\"b8V-19-WU1\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"trailing\" constant=\"66\" id=\"c36-GD-zjI\"/>\n                    <constraint firstItem=\"g7o-m6-B7g\" firstAttribute=\"centerY\" secondItem=\"9aa-Ko-5ri\" secondAttribute=\"centerY\" priority=\"1\" id=\"c8G-Dm-16A\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"WPz-RI-MPI\" secondAttribute=\"trailing\" id=\"duw-DR-0En\"/>\n                    <constraint firstItem=\"XqQ-by-tQa\" firstAttribute=\"trailing\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"trailing\" id=\"eCT-hF-ckV\"/>\n                    <constraint firstItem=\"g7o-m6-B7g\" firstAttribute=\"trailing\" secondItem=\"9aa-Ko-5ri\" secondAttribute=\"leading\" constant=\"-4\" id=\"gEz-B6-BGn\"/>\n                    <constraint firstItem=\"fOD-UD-tHL\" firstAttribute=\"firstBaseline\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"firstBaseline\" id=\"hup-Wf-qD2\"/>\n                    <constraint firstItem=\"c4u-g2-2uu\" firstAttribute=\"top\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"top\" id=\"jtU-1T-0IB\"/>\n                    <constraint firstItem=\"9ZM-5c-yUP\" firstAttribute=\"width\" secondItem=\"fOD-UD-tHL\" secondAttribute=\"width\" id=\"lA1-AB-LS1\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"9ZM-5c-yUP\" secondAttribute=\"trailing\" constant=\"8\" id=\"mfo-0I-29z\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"leading\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"leading\" constant=\"110\" id=\"nTv-tZ-edl\"/>\n                    <constraint firstItem=\"WPz-RI-MPI\" firstAttribute=\"top\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"bottom\" id=\"nsU-HK-2Wm\"/>\n                    <constraint firstItem=\"oeb-cI-59G\" firstAttribute=\"top\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"top\" constant=\"2\" id=\"qPn-0k-p7r\"/>\n                    <constraint firstItem=\"LfV-F3-NEI\" firstAttribute=\"centerY\" secondItem=\"g7o-m6-B7g\" secondAttribute=\"centerY\" id=\"rZj-7T-xvk\"/>\n                    <constraint firstItem=\"nEj-fz-vAL\" firstAttribute=\"leading\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"leading\" id=\"sDo-jb-7ON\"/>\n                    <constraint firstItem=\"c4u-g2-2uu\" firstAttribute=\"height\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"height\" id=\"tCR-a6-5SY\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"height\" relation=\"greaterThanOrEqual\" secondItem=\"fOD-UD-tHL\" secondAttribute=\"height\" id=\"u4u-Xj-mxr\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"mCi-xX-5DS\" secondAttribute=\"trailing\" id=\"uZX-KQ-OrH\"/>\n                    <constraint firstItem=\"WPz-RI-MPI\" firstAttribute=\"leading\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"leading\" id=\"vII-dc-gBd\"/>\n                    <constraint firstItem=\"XqQ-by-tQa\" firstAttribute=\"bottom\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"bottom\" constant=\"-3\" id=\"wcC-D2-EJ0\"/>\n                    <constraint firstItem=\"nEj-fz-vAL\" firstAttribute=\"trailing\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"trailing\" id=\"wix-a3-K77\"/>\n                    <constraint firstItem=\"FYg-pz-vsM\" firstAttribute=\"top\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"top\" id=\"x3H-wD-1u6\"/>\n                    <constraint firstItem=\"qsr-vg-LVN\" firstAttribute=\"width\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"width\" constant=\"12\" id=\"xFe-dn-DNz\"/>\n                    <constraint firstItem=\"mCi-xX-5DS\" firstAttribute=\"leading\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"leading\" id=\"yvD-dx-jsg\"/>\n                </constraints>\n            </tableViewCellContentView>\n            <gestureRecognizers/>\n            <connections>\n                <outlet property=\"_accessory\" destination=\"oeb-cI-59G\" id=\"uC5-yF-SeU\"/>\n                <outlet property=\"_avatar\" destination=\"9aa-Ko-5ri\" id=\"Pj6-Ze-4N6\"/>\n                <outlet property=\"_avatarHeight\" destination=\"N6m-U7-nrr\" id=\"kVI-in-0LW\"/>\n                <outlet property=\"_avatarOffset\" destination=\"3qd-ta-bgg\" id=\"Hd6-Db-uaE\"/>\n                <outlet property=\"_avatarTop\" destination=\"7aK-3S-iur\" id=\"MaW-Rz-gTQ\"/>\n                <outlet property=\"_avatarWidth\" destination=\"AhO-xV-4Mx\" id=\"JeY-ph-t5R\"/>\n                <outlet property=\"_bottomBorder\" destination=\"Air-U6-OOz\" id=\"mKT-1S-Zyf\"/>\n                <outlet property=\"_codeBlockBackground\" destination=\"qsr-vg-LVN\" id=\"1PD-z8-bhs\"/>\n                <outlet property=\"_datestamp\" destination=\"XqQ-by-tQa\" id=\"iMV-oi-Xyr\"/>\n                <outlet property=\"_lastSeenEID\" destination=\"2Cd-th-WEc\" id=\"fvk-De-jpw\"/>\n                <outlet property=\"_lastSeenEIDBackground\" destination=\"KgT-oH-O7i\" id=\"VVX-Ha-KdL\"/>\n                <outlet property=\"_lastSeenEIDOffset\" destination=\"YGl-z7-rle\" id=\"0vb-wL-dDW\"/>\n                <outlet property=\"_message\" destination=\"V3s-xQ-nVF\" id=\"gNL-XQ-5Mw\"/>\n                <outlet property=\"_messageOffsetBottom\" destination=\"Seh-7j-Oie\" id=\"TDq-L0-M6d\"/>\n                <outlet property=\"_messageOffsetLeft\" destination=\"nTv-tZ-edl\" id=\"9s6-Mb-ggg\"/>\n                <outlet property=\"_messageOffsetRight\" destination=\"c36-GD-zjI\" id=\"TkA-Pl-9p3\"/>\n                <outlet property=\"_messageOffsetTop\" destination=\"29E-wE-L1s\" id=\"WyI-2w-E8j\"/>\n                <outlet property=\"_nickname\" destination=\"nEj-fz-vAL\" id=\"PXa-eL-OMV\"/>\n                <outlet property=\"_nicknameOffset\" destination=\"sDo-jb-7ON\" id=\"wIq-hF-pR1\"/>\n                <outlet property=\"_quoteBorder\" destination=\"c4u-g2-2uu\" id=\"x1Z-yO-aPO\"/>\n                <outlet property=\"_reply\" destination=\"g7o-m6-B7g\" id=\"0sJ-rV-fY8\"/>\n                <outlet property=\"_replyButton\" destination=\"LfV-F3-NEI\" id=\"sev-gg-kJs\"/>\n                <outlet property=\"_replyCenter\" destination=\"c8G-Dm-16A\" id=\"Rw4-qp-IN7\"/>\n                <outlet property=\"_replyXOffset\" destination=\"gEz-B6-BGn\" id=\"ThU-3N-seU\"/>\n                <outlet property=\"_rightTimestampOffset\" destination=\"mfo-0I-29z\" id=\"FdX-bb-Gz3\"/>\n                <outlet property=\"_socketClosedBar\" destination=\"WPz-RI-MPI\" id=\"ntm-fR-kM1\"/>\n                <outlet property=\"_timestampLeft\" destination=\"fOD-UD-tHL\" id=\"zah-YF-oz2\"/>\n                <outlet property=\"_timestampRight\" destination=\"9ZM-5c-yUP\" id=\"74i-dE-FoC\"/>\n                <outlet property=\"_timestampWidth\" destination=\"JaC-Af-7TS\" id=\"p4s-yM-2aO\"/>\n                <outlet property=\"_topBorder\" destination=\"mCi-xX-5DS\" id=\"ljq-0k-Bvd\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"114.49275362318842\" y=\"35.15625\"/>\n        </tableViewCell>\n        <tapGestureRecognizer id=\"uTr-V1-KHO\">\n            <connections>\n                <action selector=\"avatarTapped:\" destination=\"KGk-i7-Jjw\" id=\"fZi-BT-bBu\"/>\n                <outlet property=\"delegate\" destination=\"-1\" id=\"jie-EB-V5D\"/>\n            </connections>\n        </tapGestureRecognizer>\n    </objects>\n</document>\n"
  },
  {
    "path": "IRCCloud/EventsTableCell_File.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"14113\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" colorMatched=\"YES\">\n    <device id=\"retina4_7\" orientation=\"portrait\">\n        <adaptation id=\"fullscreen\"/>\n    </device>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"14088\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <tableViewCell contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"none\" indentationWidth=\"10\" rowHeight=\"64\" id=\"KGk-i7-Jjw\" customClass=\"EventsTableCell_File\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"428\" height=\"64\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMaxY=\"YES\"/>\n            <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"KGk-i7-Jjw\" id=\"H2p-sc-9uM\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"428\" height=\"63.5\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"yrb-QY-YHD\">\n                        <rect key=\"frame\" x=\"46\" y=\"0.0\" width=\"320\" height=\"59.5\"/>\n                        <color key=\"backgroundColor\" white=\"0.66666666666666663\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                    </view>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"JfP-9Z-IJ9\" userLabel=\"Extension Container\">\n                        <rect key=\"frame\" x=\"50\" y=\"4\" width=\"56\" height=\"51.5\"/>\n                        <subviews>\n                            <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"9\" adjustsLetterSpacingToFitWidth=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"TjJ-PR-Rlo\">\n                                <rect key=\"frame\" x=\"4\" y=\"4\" width=\"48\" height=\"43.5\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"QHY-cs-wqT\"/>\n                                </constraints>\n                                <fontDescription key=\"fontDescription\" type=\"boldSystem\" pointSize=\"17\"/>\n                                <color key=\"textColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                        </subviews>\n                        <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"1\" alpha=\"1\" colorSpace=\"calibratedRGB\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"TjJ-PR-Rlo\" secondAttribute=\"bottom\" constant=\"4\" id=\"9GS-YJ-Hko\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"TjJ-PR-Rlo\" secondAttribute=\"trailing\" constant=\"4\" id=\"Zd0-l0-VlW\"/>\n                            <constraint firstItem=\"TjJ-PR-Rlo\" firstAttribute=\"top\" secondItem=\"JfP-9Z-IJ9\" secondAttribute=\"top\" constant=\"4\" id=\"bAH-P2-0GC\"/>\n                            <constraint firstItem=\"TjJ-PR-Rlo\" firstAttribute=\"leading\" secondItem=\"JfP-9Z-IJ9\" secondAttribute=\"leading\" constant=\"4\" id=\"zbB-y6-bUu\"/>\n                        </constraints>\n                    </view>\n                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"0xX-wE-bEd\">\n                        <rect key=\"frame\" x=\"110\" y=\"24\" width=\"252\" height=\"0.0\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" horizontalCompressionResistancePriority=\"250\" verticalCompressionResistancePriority=\"1000\" placeholderIntrinsicWidth=\"infinite\" placeholderIntrinsicHeight=\"infinite\" text=\"\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"V3s-xQ-nVF\" customClass=\"LinkLabel\">\n                        <rect key=\"frame\" x=\"110\" y=\"24\" width=\"252\" height=\"11.5\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Nga-WO-Pee\">\n                        <rect key=\"frame\" x=\"110\" y=\"35.5\" width=\"252\" height=\"0.0\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                </subviews>\n                <constraints>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"trailing\" secondItem=\"0xX-wE-bEd\" secondAttribute=\"trailing\" id=\"1Uf-cf-EBr\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"yrb-QY-YHD\" secondAttribute=\"bottom\" constant=\"4\" id=\"2fj-9f-GZ5\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"JfP-9Z-IJ9\" secondAttribute=\"bottom\" constant=\"8\" id=\"5sx-hm-B1Q\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"top\" secondItem=\"0xX-wE-bEd\" secondAttribute=\"bottom\" id=\"7Pf-AI-sph\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"leading\" secondItem=\"0xX-wE-bEd\" secondAttribute=\"leading\" id=\"EcY-ej-Gb7\"/>\n                    <constraint firstItem=\"JfP-9Z-IJ9\" firstAttribute=\"leading\" secondItem=\"yrb-QY-YHD\" secondAttribute=\"leading\" constant=\"4\" id=\"HrJ-Re-pl3\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"bottom\" constant=\"28\" id=\"Seh-7j-Oie\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"trailing\" secondItem=\"yrb-QY-YHD\" secondAttribute=\"trailing\" constant=\"-4\" id=\"c08-Et-C1x\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"trailing\" constant=\"66\" id=\"c36-GD-zjI\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"leading\" secondItem=\"JfP-9Z-IJ9\" secondAttribute=\"trailing\" constant=\"4\" id=\"c9P-Gs-OPs\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"bottom\" secondItem=\"Nga-WO-Pee\" secondAttribute=\"top\" id=\"kNI-Yt-0Fo\"/>\n                    <constraint firstItem=\"yrb-QY-YHD\" firstAttribute=\"top\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"top\" id=\"mwg-PK-i8S\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"leading\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"leading\" constant=\"110\" id=\"nTv-tZ-edl\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"trailing\" secondItem=\"Nga-WO-Pee\" secondAttribute=\"trailing\" id=\"o7L-EB-bke\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"top\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"top\" constant=\"24\" id=\"ot5-Jw-0Dm\"/>\n                    <constraint firstItem=\"JfP-9Z-IJ9\" firstAttribute=\"top\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"top\" constant=\"4\" id=\"rwz-UP-lmn\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"leading\" secondItem=\"Nga-WO-Pee\" secondAttribute=\"leading\" id=\"tuV-Di-CBY\"/>\n                </constraints>\n            </tableViewCellContentView>\n            <connections>\n                <outlet property=\"_background\" destination=\"yrb-QY-YHD\" id=\"2kN-Nc-hmd\"/>\n                <outlet property=\"_extension\" destination=\"TjJ-PR-Rlo\" id=\"gud-d4-duA\"/>\n                <outlet property=\"_filename\" destination=\"0xX-wE-bEd\" id=\"GLg-V4-bfU\"/>\n                <outlet property=\"_message\" destination=\"V3s-xQ-nVF\" id=\"gNL-XQ-5Mw\"/>\n                <outlet property=\"_messageOffsetBottom\" destination=\"Seh-7j-Oie\" id=\"TDq-L0-M6d\"/>\n                <outlet property=\"_messageOffsetLeft\" destination=\"nTv-tZ-edl\" id=\"9s6-Mb-ggg\"/>\n                <outlet property=\"_messageOffsetRight\" destination=\"c36-GD-zjI\" id=\"TkA-Pl-9p3\"/>\n                <outlet property=\"_messageOffsetTop\" destination=\"ot5-Jw-0Dm\" id=\"Z3e-TP-ncF\"/>\n                <outlet property=\"_mimeType\" destination=\"Nga-WO-Pee\" id=\"c9r-Fj-3tH\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"79\" y=\"62\"/>\n        </tableViewCell>\n    </objects>\n</document>\n"
  },
  {
    "path": "IRCCloud/EventsTableCell_ReplyCount.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"14105\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" colorMatched=\"YES\">\n    <device id=\"retina4_7\" orientation=\"portrait\">\n        <adaptation id=\"fullscreen\"/>\n    </device>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"14088\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <tableViewCell contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"none\" indentationWidth=\"10\" rowHeight=\"64\" id=\"KGk-i7-Jjw\" customClass=\"EventsTableCell_ReplyCount\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"428\" height=\"64\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMaxY=\"YES\"/>\n            <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"KGk-i7-Jjw\" id=\"H2p-sc-9uM\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"428\" height=\"63.5\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Q30-F7-35n\">\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" verticalHuggingPriority=\"251\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"\" lineBreakMode=\"wordWrap\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"200\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oAr-0W-Ehq\">\n                        <rect key=\"frame\" x=\"4\" y=\"0.0\" width=\"0.0\" height=\"63.5\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                </subviews>\n                <constraints>\n                    <constraint firstItem=\"Q30-F7-35n\" firstAttribute=\"top\" secondItem=\"oAr-0W-Ehq\" secondAttribute=\"top\" id=\"7O0-9i-Tv5\"/>\n                    <constraint firstItem=\"oAr-0W-Ehq\" firstAttribute=\"bottom\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"bottom\" id=\"CXs-JS-IId\"/>\n                    <constraint firstItem=\"oAr-0W-Ehq\" firstAttribute=\"top\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"top\" id=\"EEY-Ec-P0s\"/>\n                    <constraint firstItem=\"oAr-0W-Ehq\" firstAttribute=\"leading\" secondItem=\"Q30-F7-35n\" secondAttribute=\"trailing\" constant=\"4\" id=\"HOy-Nc-il3\"/>\n                    <constraint firstItem=\"Q30-F7-35n\" firstAttribute=\"leading\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"leading\" id=\"S1j-17-xi4\"/>\n                </constraints>\n            </tableViewCellContentView>\n            <connections>\n                <outlet property=\"_messageOffsetLeft\" destination=\"S1j-17-xi4\" id=\"6xR-Av-GNd\"/>\n                <outlet property=\"_reply\" destination=\"Q30-F7-35n\" id=\"6FP-QF-AiO\"/>\n                <outlet property=\"_replyCount\" destination=\"oAr-0W-Ehq\" id=\"wy2-sT-DPU\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"79\" y=\"62\"/>\n        </tableViewCell>\n    </objects>\n</document>\n"
  },
  {
    "path": "IRCCloud/EventsTableCell_Thumbnail.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"13528\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" colorMatched=\"YES\">\n    <device id=\"retina4_7\" orientation=\"portrait\">\n        <adaptation id=\"fullscreen\"/>\n    </device>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"13526\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <tableViewCell contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"none\" indentationWidth=\"10\" rowHeight=\"166\" id=\"KGk-i7-Jjw\" customClass=\"EventsTableCell_Thumbnail\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"425\" height=\"166\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMaxY=\"YES\"/>\n            <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"KGk-i7-Jjw\" id=\"H2p-sc-9uM\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"425\" height=\"165.5\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"yrb-QY-YHD\">\n                        <rect key=\"frame\" x=\"106\" y=\"0.0\" width=\"257\" height=\"161.5\"/>\n                        <color key=\"backgroundColor\" white=\"0.66666666666666663\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                    </view>\n                    <imageView verifyAmbiguity=\"off\" userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" verticalCompressionResistancePriority=\"999\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"k9p-Ie-CdE\" customClass=\"YYAnimatedImageView\">\n                        <rect key=\"frame\" x=\"110\" y=\"4\" width=\"200\" height=\"120\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"height\" priority=\"999\" constant=\"120\" id=\"Mt5-kg-VBc\"/>\n                            <constraint firstAttribute=\"width\" constant=\"200\" id=\"bcH-Lr-aiR\"/>\n                        </constraints>\n                    </imageView>\n                    <activityIndicatorView opaque=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"750\" verticalHuggingPriority=\"750\" animating=\"YES\" style=\"white\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ugL-C9-hxa\">\n                        <rect key=\"frame\" x=\"200.5\" y=\"54.5\" width=\"20\" height=\"20\"/>\n                    </activityIndicatorView>\n                    <label verifyAmbiguity=\"off\" opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" verticalCompressionResistancePriority=\"1000\" placeholderIntrinsicWidth=\"249\" placeholderIntrinsicHeight=\"21\" text=\"\" textAlignment=\"natural\" lineBreakMode=\"wordWrap\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"0xX-wE-bEd\">\n                        <rect key=\"frame\" x=\"110\" y=\"124\" width=\"249\" height=\"21\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <label verifyAmbiguity=\"off\" opaque=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" horizontalCompressionResistancePriority=\"250\" verticalCompressionResistancePriority=\"1000\" placeholderIntrinsicWidth=\"249\" placeholderIntrinsicHeight=\"infinite\" text=\"\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"V3s-xQ-nVF\" customClass=\"LinkLabel\">\n                        <rect key=\"frame\" x=\"110\" y=\"145\" width=\"249\" height=\"12.5\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                </subviews>\n                <constraints>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"trailing\" secondItem=\"0xX-wE-bEd\" secondAttribute=\"trailing\" id=\"1Uf-cf-EBr\"/>\n                    <constraint firstItem=\"0xX-wE-bEd\" firstAttribute=\"top\" secondItem=\"k9p-Ie-CdE\" secondAttribute=\"bottom\" id=\"1YQ-D7-GeY\"/>\n                    <constraint firstItem=\"k9p-Ie-CdE\" firstAttribute=\"top\" secondItem=\"yrb-QY-YHD\" secondAttribute=\"top\" constant=\"4\" id=\"2fj-9f-GZ5\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"top\" secondItem=\"0xX-wE-bEd\" secondAttribute=\"bottom\" id=\"7Pf-AI-sph\"/>\n                    <constraint firstItem=\"ugL-C9-hxa\" firstAttribute=\"centerY\" secondItem=\"k9p-Ie-CdE\" secondAttribute=\"centerY\" id=\"98T-ez-ZkB\"/>\n                    <constraint firstItem=\"yrb-QY-YHD\" firstAttribute=\"leading\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"leading\" constant=\"-4\" id=\"BMA-CX-gSF\"/>\n                    <constraint firstItem=\"k9p-Ie-CdE\" firstAttribute=\"leading\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"leading\" id=\"C2v-5d-39z\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"leading\" secondItem=\"0xX-wE-bEd\" secondAttribute=\"leading\" id=\"EcY-ej-Gb7\"/>\n                    <constraint firstItem=\"yrb-QY-YHD\" firstAttribute=\"top\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"top\" id=\"IY5-nG-4w6\"/>\n                    <constraint firstItem=\"ugL-C9-hxa\" firstAttribute=\"centerX\" secondItem=\"k9p-Ie-CdE\" secondAttribute=\"centerX\" id=\"OTC-jI-Rez\"/>\n                    <constraint firstItem=\"yrb-QY-YHD\" firstAttribute=\"bottom\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"bottom\" constant=\"4\" id=\"Q0h-sL-6o8\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"trailing\" secondItem=\"yrb-QY-YHD\" secondAttribute=\"trailing\" constant=\"-4\" id=\"c08-Et-C1x\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"V3s-xQ-nVF\" secondAttribute=\"trailing\" constant=\"66\" id=\"c36-GD-zjI\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"yrb-QY-YHD\" secondAttribute=\"bottom\" constant=\"4\" id=\"fBd-wU-PMb\"/>\n                    <constraint firstItem=\"V3s-xQ-nVF\" firstAttribute=\"leading\" secondItem=\"H2p-sc-9uM\" secondAttribute=\"leading\" constant=\"110\" id=\"nTv-tZ-edl\"/>\n                </constraints>\n            </tableViewCellContentView>\n            <connections>\n                <outlet property=\"_background\" destination=\"yrb-QY-YHD\" id=\"2kN-Nc-hmd\"/>\n                <outlet property=\"_filename\" destination=\"0xX-wE-bEd\" id=\"GLg-V4-bfU\"/>\n                <outlet property=\"_message\" destination=\"V3s-xQ-nVF\" id=\"gNL-XQ-5Mw\"/>\n                <outlet property=\"_messageOffsetLeft\" destination=\"nTv-tZ-edl\" id=\"9s6-Mb-ggg\"/>\n                <outlet property=\"_messageOffsetRight\" destination=\"c36-GD-zjI\" id=\"TkA-Pl-9p3\"/>\n                <outlet property=\"_spinner\" destination=\"ugL-C9-hxa\" id=\"rvF-Yc-8Sl\"/>\n                <outlet property=\"_thumbnail\" destination=\"k9p-Ie-CdE\" id=\"f4s-bv-R6D\"/>\n                <outlet property=\"_thumbnailHeight\" destination=\"Mt5-kg-VBc\" id=\"ZC5-4n-d5X\"/>\n                <outlet property=\"_thumbnailWidth\" destination=\"bcH-Lr-aiR\" id=\"clX-mD-Nzb\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"74.5\" y=\"106\"/>\n        </tableViewCell>\n    </objects>\n</document>\n"
  },
  {
    "path": "IRCCloud/IRCCloud-Enterprise-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>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</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>VERSION_STRING</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleSpokenName</key>\n\t<string>I R C Cloud</string>\n\t<key>CFBundleURLTypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>Viewer</string>\n\t\t\t<key>CFBundleURLIconFile</key>\n\t\t\t<string>Icon</string>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>com.irccloud.launch</string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>irccloud-enterprise</string>\n\t\t\t</array>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>Viewer</string>\n\t\t\t<key>CFBundleURLIconFile</key>\n\t\t\t<string>Icon</string>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>com.irccloud.irc</string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>irc</string>\n\t\t\t</array>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>Viewer</string>\n\t\t\t<key>CFBundleURLIconFile</key>\n\t\t\t<string>Icon</string>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>com.irccloud.irc.secure</string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>ircs</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>GIT_VERSION</string>\n\t<key>ITSAppUsesNonExemptEncryption</key>\n\t<false/>\n\t<key>LSApplicationQueriesSchemes</key>\n\t<array>\n\t\t<string>firefox</string>\n\t\t<string>googlechrome</string>\n\t\t<string>googlechrome-x-callback</string>\n\t\t<string>org-appextension-feature-password-management</string>\n\t</array>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t\t<key>NSExceptionDomains</key>\n\t\t<dict>\n\t\t\t<key>irccloud.com</key>\n\t\t\t<dict>\n\t\t\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t\t\t<false/>\n\t\t\t\t<key>NSIncludesSubdomains</key>\n\t\t\t\t<true/>\n\t\t\t</dict>\n\t\t</dict>\n\t</dict>\n\t<key>NSCameraUsageDescription</key>\n\t<string>${PRODUCT_NAME} requires access to your camera to share photos and videos on IRC</string>\n\t<key>NSMicrophoneUsageDescription</key>\n\t<string>${PRODUCT_NAME} requires access to your microphone to record a video</string>\n\t<key>NSPhotoLibraryAddUsageDescription</key>\n\t<string>${PRODUCT_NAME} requires access to your photo library to download photos and videos</string>\n\t<key>NSPhotoLibraryUsageDescription</key>\n\t<string>${PRODUCT_NAME} requires access to your photo library to share photos and videos on IRC</string>\n\t<key>NSLocalNetworkUsageDescription</key>\n\t<string>${PRODUCT_NAME} would like to load an image or video resource from the local network</string>\n\t<key>NSUbiquitousContainers</key>\n\t<dict>\n\t\t<key>iCloud.com.irccloud.enterprise.public</key>\n\t\t<dict>\n\t\t\t<key>NSUbiquitousContainerIsDocumentScopePublic</key>\n\t\t\t<true/>\n\t\t\t<key>NSUbiquitousContainerName</key>\n\t\t\t<string>${PRODUCT_NAME}</string>\n\t\t\t<key>NSUbiquitousContainerSupportedFolderLevels</key>\n\t\t\t<string>Any</string>\n\t\t</dict>\n\t</dict>\n\t<key>NSUserActivityTypes</key>\n\t<array>\n\t\t<string>com.irccloud.enterprise.buffer</string>\n\t</array>\n\t<key>UIAppFonts</key>\n\t<array>\n\t\t<string>Hack-BoldItalic.ttf</string>\n\t\t<string>Hack-Italic.ttf</string>\n\t\t<string>Hack-Bold.ttf</string>\n\t\t<string>Hack-Regular.ttf</string>\n\t\t<string>SourceSansPro-LightIt.otf</string>\n\t\t<string>SourceSansPro-Regular.otf</string>\n\t\t<string>SourceSansPro-Semibold.otf</string>\n\t\t<string>FontAwesome.otf</string>\n\t</array>\n\t<key>UIApplicationSceneManifest</key>\n\t<dict>\n\t\t<key>UIApplicationSupportsMultipleScenes</key>\n\t\t<true/>\n\t\t<key>UISceneConfigurations</key>\n\t\t<dict>\n\t\t\t<key>UIWindowSceneSessionRoleApplication</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>UILaunchStoryboardName</key>\n\t\t\t\t\t<string>Launch</string>\n\t\t\t\t\t<key>UISceneClassName</key>\n\t\t\t\t\t<string>UIWindowScene</string>\n\t\t\t\t\t<key>UISceneConfigurationName</key>\n\t\t\t\t\t<string>main</string>\n\t\t\t\t\t<key>UISceneDelegateClassName</key>\n\t\t\t\t\t<string>SceneDelegate</string>\n\t\t\t\t\t<key>UISceneStoryboardFile</key>\n\t\t\t\t\t<string>MainStoryboard</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t</dict>\n\t</dict>\n\t<key>UIBackgroundModes</key>\n\t<array>\n\t\t<string>audio</string>\n\t\t<string>remote-notification</string>\n\t</array>\n\t<key>UILaunchStoryboardName</key>\n\t<string>Launch</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>MainStoryboard</string>\n\t<key>UIPrerenderedIcon</key>\n\t<true/>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UIRequiresFullScreen</key>\n\t<false/>\n\t<key>UIRequiresPersistentWiFi</key>\n\t<true/>\n\t<key>UIStatusBarStyle</key>\n\t<string>UIStatusBarStyleBlackOpaque</string>\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\t<key>UIViewControllerBasedStatusBarAppearance</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "IRCCloud/IRCCloud-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>UIDesignRequiresCompatibility</key>\n\t<true/>\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>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</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>VERSION_STRING</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleSpokenName</key>\n\t<string>I R C Cloud</string>\n\t<key>CFBundleURLTypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>Viewer</string>\n\t\t\t<key>CFBundleURLIconFile</key>\n\t\t\t<string>Icon</string>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>com.irccloud.launch</string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>irccloud</string>\n\t\t\t</array>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>Viewer</string>\n\t\t\t<key>CFBundleURLIconFile</key>\n\t\t\t<string>Icon</string>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>com.irccloud.irc</string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>irc</string>\n\t\t\t</array>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>Viewer</string>\n\t\t\t<key>CFBundleURLIconFile</key>\n\t\t\t<string>Icon</string>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>com.irccloud.irc.secure</string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>ircs</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>GIT_VERSION</string>\n\t<key>INIntentsSupported</key>\n\t<array>\n\t\t<string>INSendMessageIntent</string>\n\t</array>\n\t<key>ITSAppUsesNonExemptEncryption</key>\n\t<false/>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.social-networking</string>\n\t<key>LSApplicationQueriesSchemes</key>\n\t<array>\n\t\t<string>firefox</string>\n\t\t<string>googlechrome</string>\n\t\t<string>googlechrome-x-callback</string>\n\t\t<string>org-appextension-feature-password-management</string>\n\t</array>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t\t<key>NSExceptionDomains</key>\n\t\t<dict>\n\t\t\t<key>irccloud.com</key>\n\t\t\t<dict>\n\t\t\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t\t\t<false/>\n\t\t\t\t<key>NSIncludesSubdomains</key>\n\t\t\t\t<true/>\n\t\t\t</dict>\n\t\t</dict>\n\t</dict>\n\t<key>NSCameraUsageDescription</key>\n\t<string>${PRODUCT_NAME} requires access to your camera to share photos and videos on IRC</string>\n\t<key>NSMicrophoneUsageDescription</key>\n\t<string>${PRODUCT_NAME} requires access to your microphone to record a video</string>\n\t<key>NSPhotoLibraryAddUsageDescription</key>\n\t<string>${PRODUCT_NAME} requires access to your photo library to download photos and videos</string>\n\t<key>NSPhotoLibraryUsageDescription</key>\n\t<string>${PRODUCT_NAME} requires access to your photo library to share photos and videos on IRC</string>\n\t<key>NSLocalNetworkUsageDescription</key>\n\t<string>${PRODUCT_NAME} would like to load an image or video resource from the local network</string>\n\t<key>NSUbiquitousContainers</key>\n\t<dict>\n\t\t<key>iCloud.com.irccloud.IRCCloud.public</key>\n\t\t<dict>\n\t\t\t<key>NSUbiquitousContainerIsDocumentScopePublic</key>\n\t\t\t<true/>\n\t\t\t<key>NSUbiquitousContainerName</key>\n\t\t\t<string>${PRODUCT_NAME}</string>\n\t\t\t<key>NSUbiquitousContainerSupportedFolderLevels</key>\n\t\t\t<string>Any</string>\n\t\t</dict>\n\t</dict>\n\t<key>NSUserActivityTypes</key>\n\t<array>\n\t\t<string>com.irccloud.buffer</string>\n\t\t<string>INSendMessageIntent</string>\n\t</array>\n\t<key>UIAppFonts</key>\n\t<array>\n\t\t<string>Hack-BoldItalic.ttf</string>\n\t\t<string>Hack-Italic.ttf</string>\n\t\t<string>Hack-Bold.ttf</string>\n\t\t<string>Hack-Regular.ttf</string>\n\t\t<string>SourceSansPro-LightIt.otf</string>\n\t\t<string>SourceSansPro-Regular.otf</string>\n\t\t<string>SourceSansPro-Semibold.otf</string>\n\t\t<string>FontAwesome.otf</string>\n\t</array>\n\t<key>UIApplicationSceneManifest</key>\n\t<dict>\n\t\t<key>UIApplicationSupportsMultipleScenes</key>\n\t\t<true/>\n\t\t<key>UIApplicationSupportsTabbedSceneCollection</key>\n\t\t<false/>\n\t\t<key>UISceneConfigurations</key>\n\t\t<dict>\n\t\t\t<key>UIWindowSceneSessionRoleApplication</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>UILaunchStoryboardName</key>\n\t\t\t\t\t<string>Launch</string>\n\t\t\t\t\t<key>UISceneClassName</key>\n\t\t\t\t\t<string>UIWindowScene</string>\n\t\t\t\t\t<key>UISceneConfigurationName</key>\n\t\t\t\t\t<string>main</string>\n\t\t\t\t\t<key>UISceneDelegateClassName</key>\n\t\t\t\t\t<string>SceneDelegate</string>\n\t\t\t\t\t<key>UISceneStoryboardFile</key>\n\t\t\t\t\t<string>MainStoryboard</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t</dict>\n\t</dict>\n\t<key>UIBackgroundModes</key>\n\t<array>\n\t\t<string>audio</string>\n\t\t<string>remote-notification</string>\n\t</array>\n\t<key>UILaunchStoryboardName</key>\n\t<string>Launch</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>MainStoryboard</string>\n\t<key>UIPrerenderedIcon</key>\n\t<true/>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UIRequiresFullScreen</key>\n\t<false/>\n\t<key>UIRequiresPersistentWiFi</key>\n\t<true/>\n\t<key>UIStatusBarStyle</key>\n\t<string>UIStatusBarStyleDefault</string>\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\t<key>UIViewControllerBasedStatusBarAppearance</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "IRCCloud/IRCCloud-Prefix.pch",
    "content": "//\n// Prefix header for all source files of the 'IRCCloud' target in the 'IRCCloud' project\n//\n\n#import <Availability.h>\n\n#ifndef __IPHONE_11_0\n#warning \"This project uses features only available in iOS SDK 11.0 and later.\"\n#endif\n\n#ifdef __OBJC__\n    #import <UIKit/UIKit.h>\n    #import <Foundation/Foundation.h>\n    @import FirebaseCrashlytics;\nvoid FirebaseLog(NSString *format, ...);\n#endif\n\n#define OBJC_STRINGIFY(x) @#x\n#define encodeObject(x) [aCoder encodeObject:([x isKindOfClass:NSNull.class])?nil:x forKey:OBJC_STRINGIFY(x)]\n#define encodeInt(x) [aCoder encodeInt:x forKey:OBJC_STRINGIFY(x)]\n#define encodeDouble(x) [aCoder encodeDouble:x forKey:OBJC_STRINGIFY(x)]\n#define encodeFloat(x) [aCoder encodeFloat:x forKey:OBJC_STRINGIFY(x)]\n#define encodeBool(x) [aCoder encodeBool:x forKey:OBJC_STRINGIFY(x)]\n\n#define decodeObjectOfClasses(c,x) x = [aDecoder decodeObjectOfClasses:c forKey:OBJC_STRINGIFY(x)]\n#define decodeObjectOfClass(c,x) x = [aDecoder decodeObjectOfClass:c forKey:OBJC_STRINGIFY(x)]\n#define decodeInt(x) x = [aDecoder decodeIntForKey:OBJC_STRINGIFY(x)]\n#define decodeDouble(x) x = [aDecoder decodeDoubleForKey:OBJC_STRINGIFY(x)]\n#define decodeFloat(x) x = [aDecoder decodeFloatForKey:OBJC_STRINGIFY(x)]\n#define decodeBool(x) x = [aDecoder decodeBoolForKey:OBJC_STRINGIFY(x)]\n\n#define SupportedOrientationsReturnType UIInterfaceOrientationMask\n\n#undef CLS_LOG\n#define CLS_LOG(__FORMAT__, ...) FirebaseLog(@\"%s line %d $ \" __FORMAT__, __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)\n"
  },
  {
    "path": "IRCCloud/IRCCloud.entitlements",
    "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>aps-environment</key>\n\t<string>production</string>\n\t<key>com.apple.developer.associated-domains</key>\n\t<array>\n\t\t<string>activitycontinuation:www.irccloud.com</string>\n\t\t<string>activitycontinuation:irccloud.com</string>\n\t\t<string>webcredentials:www.irccloud.com</string>\n\t\t<string>webcredentials:irccloud.com</string>\n\t\t<string>applinks:www.irccloud.com</string>\n\t\t<string>applinks:irccloud.com</string>\n\t</array>\n\t<key>com.apple.developer.icloud-container-identifiers</key>\n\t<array>\n\t\t<string>iCloud.$(CFBundleIdentifier).public</string>\n\t</array>\n\t<key>com.apple.developer.icloud-services</key>\n\t<array>\n\t\t<string>CloudDocuments</string>\n\t\t<string>CloudKit</string>\n\t</array>\n\t<key>com.apple.developer.ubiquity-container-identifiers</key>\n\t<array>\n\t\t<string>iCloud.$(CFBundleIdentifier).public</string>\n\t</array>\n\t<key>com.apple.developer.ubiquity-kvstore-identifier</key>\n\t<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>\n\t<key>com.apple.security.app-sandbox</key>\n\t<true/>\n\t<key>com.apple.security.application-groups</key>\n\t<array>\n\t\t<string>group.com.irccloud.share</string>\n\t</array>\n\t<key>com.apple.security.device.audio-input</key>\n\t<true/>\n\t<key>com.apple.security.device.camera</key>\n\t<true/>\n\t<key>com.apple.security.files.user-selected.read-write</key>\n\t<true/>\n\t<key>com.apple.security.network.client</key>\n\t<true/>\n\t<key>com.apple.security.personal-information.photos-library</key>\n\t<true/>\n\t<key>keychain-access-groups</key>\n\t<array>\n\t\t<string>$(AppIdentifierPrefix)com.irccloud.IRCCloud</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "IRCCloud/Launch.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"10117\" systemVersion=\"15E65\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"10085\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Llm-lL-Icb\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xb3-aO-Qok\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Zkb-HN-NOG\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <imageView userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" image=\"login_logo\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"RNe-Pb-x7L\">\n                                <rect key=\"frame\" x=\"276\" y=\"48\" width=\"48\" height=\"48\"/>\n                            </imageView>\n                        </subviews>\n                        <color key=\"backgroundColor\" red=\"0.15686274510000001\" green=\"0.3411764706\" blue=\"0.67843137249999996\" alpha=\"1\" colorSpace=\"calibratedRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"RNe-Pb-x7L\" firstAttribute=\"top\" secondItem=\"Zkb-HN-NOG\" secondAttribute=\"top\" constant=\"48\" id=\"aUH-Rm-vCa\"/>\n                            <constraint firstItem=\"RNe-Pb-x7L\" firstAttribute=\"centerX\" secondItem=\"Zkb-HN-NOG\" secondAttribute=\"centerX\" id=\"v3z-Ed-dnJ\"/>\n                        </constraints>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <image name=\"login_logo\" width=\"48\" height=\"48\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "IRCCloud/MainStoryboard.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"23504\" targetRuntime=\"iOS.CocoaTouch.iPad\" propertyAccessControl=\"none\" useAutolayout=\"YES\" colorMatched=\"YES\" initialViewController=\"QPs-Li-UDL\">\n    <device id=\"ipad9_7\" orientation=\"portrait\" layout=\"fullscreen\" appearance=\"light\"/>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"23506\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <scenes>\n        <!--Splash View Controller-->\n        <scene sceneID=\"lDn-GI-ZhL\">\n            <objects>\n                <viewController storyboardIdentifier=\"SplashViewController\" useStoryboardIdentifierAsRestorationIdentifier=\"YES\" id=\"QPs-Li-UDL\" customClass=\"SplashViewController\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"FQR-3t-1qH\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"Awh-XZ-gHt\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Gte-0B-Dsy\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"768\" height=\"1024\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <imageView userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" image=\"login_logo\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"iqP-3p-GfM\">\n                                <rect key=\"frame\" x=\"360\" y=\"48\" width=\"48\" height=\"48\"/>\n                            </imageView>\n                        </subviews>\n                        <color key=\"backgroundColor\" red=\"0.15686274510000001\" green=\"0.3411764706\" blue=\"0.67843137249999996\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"iqP-3p-GfM\" firstAttribute=\"top\" secondItem=\"Gte-0B-Dsy\" secondAttribute=\"top\" constant=\"48\" id=\"TkB-wB-RPw\"/>\n                            <constraint firstItem=\"iqP-3p-GfM\" firstAttribute=\"centerX\" secondItem=\"Gte-0B-Dsy\" secondAttribute=\"centerX\" id=\"lEU-td-xT0\"/>\n                        </constraints>\n                    </view>\n                    <extendedEdge key=\"edgesForExtendedLayout\" bottom=\"YES\"/>\n                    <connections>\n                        <outlet property=\"_logo\" destination=\"iqP-3p-GfM\" id=\"VfL-mL-hM3\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"tM0-gJ-ADH\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"1203.90625\" y=\"465.82031249999994\"/>\n        </scene>\n        <!--Pastebin View Controller-->\n        <scene sceneID=\"pFD-Fu-fz5\">\n            <objects>\n                <viewController storyboardIdentifier=\"PastebinViewController\" useStoryboardIdentifierAsRestorationIdentifier=\"YES\" id=\"a1L-kP-L2V\" customClass=\"PastebinViewController\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Xhq-45-vjC\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"s9y-L3-iv0\"/>\n                    </layoutGuides>\n                    <view key=\"view\" clearsContextBeforeDrawing=\"NO\" contentMode=\"scaleToFill\" id=\"Tel-12-tSs\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"768\" height=\"1024\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <wkWebView contentMode=\"scaleToFill\" allowsLinkPreview=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ApB-8M-7Ob\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"768\" height=\"980\"/>\n                                <color key=\"backgroundColor\" red=\"0.36078431370000003\" green=\"0.38823529410000002\" blue=\"0.4039215686\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <wkWebViewConfiguration key=\"configuration\" allowsAirPlayForMediaPlayback=\"NO\" allowsPictureInPictureMediaPlayback=\"NO\">\n                                    <dataDetectorTypes key=\"dataDetectorTypes\" none=\"YES\"/>\n                                    <audiovisualMediaTypes key=\"mediaTypesRequiringUserActionForPlayback\" none=\"YES\"/>\n                                    <wkPreferences key=\"preferences\"/>\n                                </wkWebViewConfiguration>\n                            </wkWebView>\n                            <toolbar opaque=\"NO\" clearsContextBeforeDrawing=\"NO\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4XG-18-Q15\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"980\" width=\"768\" height=\"44\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"44\" id=\"yW5-gE-0mu\"/>\n                                </constraints>\n                                <items/>\n                            </toolbar>\n                            <activityIndicatorView opaque=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"750\" verticalHuggingPriority=\"750\" hidesWhenStopped=\"YES\" animating=\"YES\" style=\"gray\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"QlI-1C-F2E\">\n                                <rect key=\"frame\" x=\"374\" y=\"502\" width=\"20\" height=\"20\"/>\n                            </activityIndicatorView>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"4XG-18-Q15\" firstAttribute=\"leading\" secondItem=\"Tel-12-tSs\" secondAttribute=\"leading\" id=\"FVA-Fu-6oO\"/>\n                            <constraint firstItem=\"ApB-8M-7Ob\" firstAttribute=\"leading\" secondItem=\"Tel-12-tSs\" secondAttribute=\"leading\" id=\"GNG-gO-JLa\"/>\n                            <constraint firstItem=\"QlI-1C-F2E\" firstAttribute=\"centerX\" secondItem=\"Tel-12-tSs\" secondAttribute=\"centerX\" id=\"Gw2-bM-4rc\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"4XG-18-Q15\" secondAttribute=\"trailing\" id=\"MzT-Mc-wWq\"/>\n                            <constraint firstItem=\"QlI-1C-F2E\" firstAttribute=\"centerY\" secondItem=\"Tel-12-tSs\" secondAttribute=\"centerY\" id=\"RfY-V0-mDp\"/>\n                            <constraint firstItem=\"ApB-8M-7Ob\" firstAttribute=\"top\" secondItem=\"Tel-12-tSs\" secondAttribute=\"top\" id=\"ZXC-h8-4dF\"/>\n                            <constraint firstItem=\"s9y-L3-iv0\" firstAttribute=\"top\" secondItem=\"4XG-18-Q15\" secondAttribute=\"bottom\" id=\"eEq-vA-arF\"/>\n                            <constraint firstItem=\"4XG-18-Q15\" firstAttribute=\"top\" secondItem=\"ApB-8M-7Ob\" secondAttribute=\"bottom\" id=\"ei4-ar-30c\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"ApB-8M-7Ob\" secondAttribute=\"trailing\" id=\"x2J-By-nTX\"/>\n                        </constraints>\n                    </view>\n                    <connections>\n                        <outlet property=\"_activity\" destination=\"QlI-1C-F2E\" id=\"dI1-Bk-gOp\"/>\n                        <outlet property=\"_toolbar\" destination=\"4XG-18-Q15\" id=\"Zhz-m8-uz1\"/>\n                        <outlet property=\"_webView\" destination=\"ApB-8M-7Ob\" id=\"bYx-yF-srC\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"YL3-Md-RJa\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"495.3125\" y=\"-4.1015625\"/>\n        </scene>\n        <!--Login Splash View Controller-->\n        <scene sceneID=\"bzc-Rq-eb2\">\n            <objects>\n                <viewController storyboardIdentifier=\"LoginSplashViewController\" useStoryboardIdentifierAsRestorationIdentifier=\"YES\" id=\"thh-5b-esU\" customClass=\"LoginSplashViewController\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"pLE-aC-qBZ\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"u2o-Ld-Vqf\"/>\n                    </layoutGuides>\n                    <view key=\"view\" autoresizesSubviews=\"NO\" contentMode=\"scaleToFill\" id=\"uLz-Jv-72R\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"768\" height=\"1024\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <imageView userInteractionEnabled=\"NO\" contentMode=\"scaleAspectFill\" image=\"login_logo\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sfr-SS-1jI\">\n                                <rect key=\"frame\" x=\"272\" y=\"68\" width=\"48\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"EgP-kr-Ryh\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"Fu8-gd-2du\"/>\n                                </constraints>\n                            </imageView>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"70\" placeholderIntrinsicHeight=\"infinite\" text=\"IRC\" textAlignment=\"right\" lineBreakMode=\"tailTruncation\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"70\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hgu-D2-Mph\">\n                                <rect key=\"frame\" x=\"334\" y=\"68\" width=\"70\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"PHw-Q2-KdF\"/>\n                                </constraints>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"41\"/>\n                                <color key=\"textColor\" red=\"0.61176470589999998\" green=\"0.78039215689999997\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"120\" placeholderIntrinsicHeight=\"infinite\" text=\"Cloud\" lineBreakMode=\"tailTruncation\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"120\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"KFZ-UT-EG5\">\n                                <rect key=\"frame\" x=\"404\" y=\"68\" width=\"120\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"kqu-oJ-dEp\"/>\n                                </constraints>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"41\"/>\n                                <color key=\"textColor\" red=\"0.2666666667\" green=\"0.50196078430000002\" blue=\"0.98039215690000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" alpha=\"0.0\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"320\" placeholderIntrinsicHeight=\"32\" text=\"Enterprise Edition\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"320\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"iSf-t4-0KQ\">\n                                <rect key=\"frame\" x=\"224\" y=\"132\" width=\"320\" height=\"32\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"320\" id=\"Itp-RM-P45\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"32\" id=\"UNl-kc-ZYN\"/>\n                                </constraints>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"18\"/>\n                                <color key=\"textColor\" red=\"0.61176470589999998\" green=\"0.78039215689999997\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <view autoresizesSubviews=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lUW-Yp-Apz\" customClass=\"UIControl\">\n                                <rect key=\"frame\" x=\"301.5\" y=\"132\" width=\"65\" height=\"32\"/>\n                                <subviews>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Login\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"65\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"g3i-pB-ttr\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"5\" width=\"65\" height=\"22\"/>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"18\"/>\n                                        <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"32\" id=\"6pR-pa-8Bm\"/>\n                                    <constraint firstItem=\"g3i-pB-ttr\" firstAttribute=\"leading\" secondItem=\"lUW-Yp-Apz\" secondAttribute=\"leading\" id=\"7KF-G8-2mK\"/>\n                                    <constraint firstItem=\"g3i-pB-ttr\" firstAttribute=\"centerY\" secondItem=\"lUW-Yp-Apz\" secondAttribute=\"centerY\" id=\"FFS-xL-9dx\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"65\" id=\"hEg-UQ-NyZ\"/>\n                                    <constraint firstItem=\"g3i-pB-ttr\" firstAttribute=\"centerX\" secondItem=\"lUW-Yp-Apz\" secondAttribute=\"centerX\" id=\"nDO-eT-xbZ\"/>\n                                </constraints>\n                                <connections>\n                                    <action selector=\"loginHintPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"BBq-Px-w73\"/>\n                                </connections>\n                            </view>\n                            <view autoresizesSubviews=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"RjR-3c-mm2\" customClass=\"UIControl\">\n                                <rect key=\"frame\" x=\"401.5\" y=\"132\" width=\"65\" height=\"32\"/>\n                                <subviews>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Sign Up\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"65\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2IH-5B-3G7\">\n                                        <rect key=\"frame\" x=\"0.5\" y=\"5\" width=\"64\" height=\"22\"/>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"18\"/>\n                                        <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"65\" id=\"8LQ-Ht-DZy\"/>\n                                    <constraint firstItem=\"2IH-5B-3G7\" firstAttribute=\"centerY\" secondItem=\"RjR-3c-mm2\" secondAttribute=\"centerY\" id=\"9JP-F6-Fmw\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"32\" id=\"CTa-JI-B6w\"/>\n                                    <constraint firstItem=\"2IH-5B-3G7\" firstAttribute=\"centerX\" secondItem=\"RjR-3c-mm2\" secondAttribute=\"centerX\" id=\"q8S-Hq-pxu\"/>\n                                </constraints>\n                                <connections>\n                                    <action selector=\"signupHintPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"aPD-ui-sWS\"/>\n                                </connections>\n                            </view>\n                            <view autoresizesSubviews=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"vjV-1j-Hve\" customClass=\"UIControl\">\n                                <rect key=\"frame\" x=\"292\" y=\"132\" width=\"184\" height=\"32\"/>\n                                <subviews>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"150\" placeholderIntrinsicHeight=\"infinite\" text=\"Need an account?\" lineBreakMode=\"tailTruncation\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"150\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Qgw-oW-fa6\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"150\" height=\"32\"/>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"18\"/>\n                                        <color key=\"textColor\" red=\"0.61176470589999998\" green=\"0.78039215689999997\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"65\" placeholderIntrinsicHeight=\"infinite\" text=\"Sign Up\" lineBreakMode=\"tailTruncation\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"65\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Q9f-JP-OuI\">\n                                        <rect key=\"frame\" x=\"119\" y=\"0.0\" width=\"65\" height=\"32\"/>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"18\"/>\n                                        <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstItem=\"Q9f-JP-OuI\" firstAttribute=\"height\" secondItem=\"vjV-1j-Hve\" secondAttribute=\"height\" id=\"7vc-fN-NQG\"/>\n                                    <constraint firstAttribute=\"trailing\" secondItem=\"Q9f-JP-OuI\" secondAttribute=\"trailing\" id=\"G8U-tV-KP5\"/>\n                                    <constraint firstItem=\"Qgw-oW-fa6\" firstAttribute=\"centerY\" secondItem=\"vjV-1j-Hve\" secondAttribute=\"centerY\" id=\"Rw3-eD-z8H\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"32\" id=\"T8j-A8-Ugr\"/>\n                                    <constraint firstItem=\"Q9f-JP-OuI\" firstAttribute=\"centerY\" secondItem=\"vjV-1j-Hve\" secondAttribute=\"centerY\" id=\"ddD-MQ-nEN\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"184\" id=\"gtw-AY-yjl\"/>\n                                    <constraint firstItem=\"Qgw-oW-fa6\" firstAttribute=\"leading\" secondItem=\"vjV-1j-Hve\" secondAttribute=\"leading\" id=\"iEd-Ai-Xai\"/>\n                                    <constraint firstItem=\"Qgw-oW-fa6\" firstAttribute=\"height\" secondItem=\"vjV-1j-Hve\" secondAttribute=\"height\" id=\"qOq-Dz-XNR\"/>\n                                </constraints>\n                                <connections>\n                                    <action selector=\"signupHintPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"u4H-vg-N9Z\"/>\n                                </connections>\n                            </view>\n                            <view autoresizesSubviews=\"NO\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lmN-wO-9gf\" customClass=\"UIControl\">\n                                <rect key=\"frame\" x=\"276\" y=\"132\" width=\"216\" height=\"32\"/>\n                                <subviews>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"210\" placeholderIntrinsicHeight=\"infinite\" text=\"Already have an account?\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"210\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"RQO-72-9Fj\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"210\" height=\"32\"/>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"18\"/>\n                                        <color key=\"textColor\" red=\"0.61176470589999998\" green=\"0.78039215689999997\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"65\" placeholderIntrinsicHeight=\"infinite\" text=\"Login\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"65\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"aSL-wY-tFH\">\n                                        <rect key=\"frame\" x=\"151\" y=\"0.0\" width=\"65\" height=\"32\"/>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"18\"/>\n                                        <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"32\" id=\"10d-s0-6tA\"/>\n                                    <constraint firstItem=\"RQO-72-9Fj\" firstAttribute=\"height\" secondItem=\"lmN-wO-9gf\" secondAttribute=\"height\" id=\"6d3-Wd-ggb\"/>\n                                    <constraint firstItem=\"RQO-72-9Fj\" firstAttribute=\"centerY\" secondItem=\"lmN-wO-9gf\" secondAttribute=\"centerY\" id=\"9cE-iI-l65\"/>\n                                    <constraint firstItem=\"RQO-72-9Fj\" firstAttribute=\"leading\" secondItem=\"lmN-wO-9gf\" secondAttribute=\"leading\" id=\"NCP-da-lrg\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"216\" id=\"Nxp-DB-TOV\"/>\n                                    <constraint firstAttribute=\"trailing\" secondItem=\"aSL-wY-tFH\" secondAttribute=\"trailing\" id=\"gcH-po-8o5\"/>\n                                    <constraint firstItem=\"aSL-wY-tFH\" firstAttribute=\"height\" secondItem=\"lmN-wO-9gf\" secondAttribute=\"height\" id=\"mkc-iF-DJq\"/>\n                                    <constraint firstItem=\"aSL-wY-tFH\" firstAttribute=\"centerY\" secondItem=\"lmN-wO-9gf\" secondAttribute=\"centerY\" id=\"vHT-HH-5Ri\"/>\n                                </constraints>\n                                <connections>\n                                    <action selector=\"loginHintPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"har-Md-KNf\"/>\n                                </connections>\n                            </view>\n                            <view autoresizesSubviews=\"NO\" opaque=\"NO\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zTV-Zl-uPd\" userLabel=\"Loading View\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"180\" width=\"768\" height=\"844\"/>\n                                <subviews>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" text=\"Loading\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"320\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2LD-X7-x0T\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"30\" width=\"768\" height=\"21\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" constant=\"21\" id=\"Wgb-H2-k95\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                                        <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                    <activityIndicatorView hidden=\"YES\" opaque=\"NO\" contentMode=\"scaleToFill\" hidesWhenStopped=\"YES\" style=\"gray\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4IH-UP-pdU\">\n                                        <rect key=\"frame\" x=\"374\" y=\"54\" width=\"20\" height=\"20\"/>\n                                        <color key=\"color\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                    </activityIndicatorView>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"0.2666666667\" green=\"0.50196078430000002\" blue=\"0.98039215690000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstItem=\"2LD-X7-x0T\" firstAttribute=\"width\" secondItem=\"zTV-Zl-uPd\" secondAttribute=\"width\" id=\"UW7-MZ-1tR\"/>\n                                    <constraint firstItem=\"4IH-UP-pdU\" firstAttribute=\"top\" secondItem=\"2LD-X7-x0T\" secondAttribute=\"bottom\" constant=\"3\" id=\"WZc-qR-tQv\"/>\n                                    <constraint firstItem=\"4IH-UP-pdU\" firstAttribute=\"centerX\" secondItem=\"zTV-Zl-uPd\" secondAttribute=\"centerX\" id=\"afW-MW-hUy\"/>\n                                    <constraint firstItem=\"2LD-X7-x0T\" firstAttribute=\"top\" secondItem=\"zTV-Zl-uPd\" secondAttribute=\"top\" constant=\"30\" id=\"oeN-Ux-Odq\"/>\n                                    <constraint firstItem=\"2LD-X7-x0T\" firstAttribute=\"centerX\" secondItem=\"zTV-Zl-uPd\" secondAttribute=\"centerX\" id=\"xfs-Dp-C0g\"/>\n                                </constraints>\n                            </view>\n                            <view autoresizesSubviews=\"NO\" opaque=\"NO\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mJM-f8-v0Q\" userLabel=\"Login View\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"160\" width=\"768\" height=\"864\"/>\n                                <subviews>\n                                    <textField opaque=\"NO\" clipsSubviews=\"YES\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"left\" contentVerticalAlignment=\"center\" placeholder=\"Name\" minimumFontSize=\"17\" background=\"login_top_input\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zZw-jo-Si9\">\n                                        <rect key=\"frame\" x=\"241.5\" y=\"16\" width=\"285\" height=\"39\"/>\n                                        <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" constant=\"39\" id=\"RKf-tZ-EU7\"/>\n                                            <constraint firstAttribute=\"width\" constant=\"285\" id=\"YBZ-m3-wHq\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                        <textInputTraits key=\"textInputTraits\" autocapitalizationType=\"words\" autocorrectionType=\"no\" returnKeyType=\"next\" textContentType=\"name\"/>\n                                        <userDefinedRuntimeAttributes>\n                                            <userDefinedRuntimeAttribute type=\"color\" keyPath=\"_placeholderLabel.textColor\">\n                                                <color key=\"value\" red=\"0.15686274510000001\" green=\"0.3411764706\" blue=\"0.67843137249999996\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            </userDefinedRuntimeAttribute>\n                                        </userDefinedRuntimeAttributes>\n                                        <connections>\n                                            <action selector=\"textFieldChanged:\" destination=\"thh-5b-esU\" eventType=\"editingChanged\" id=\"nW1-qf-Sh0\"/>\n                                            <outlet property=\"delegate\" destination=\"thh-5b-esU\" id=\"wTb-04-ngq\"/>\n                                        </connections>\n                                    </textField>\n                                    <textField opaque=\"NO\" clipsSubviews=\"YES\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"left\" contentVerticalAlignment=\"center\" placeholder=\"Email address\" minimumFontSize=\"17\" background=\"login_top_input\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YDn-hm-4nv\">\n                                        <rect key=\"frame\" x=\"241.5\" y=\"16\" width=\"285\" height=\"39\"/>\n                                        <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"285\" id=\"vG6-eo-Vsb\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"39\" id=\"y7f-Q1-2vv\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                        <textInputTraits key=\"textInputTraits\" autocorrectionType=\"no\" keyboardType=\"emailAddress\" returnKeyType=\"next\" textContentType=\"username\"/>\n                                        <userDefinedRuntimeAttributes>\n                                            <userDefinedRuntimeAttribute type=\"color\" keyPath=\"_placeholderLabel.textColor\">\n                                                <color key=\"value\" red=\"0.15686274510000001\" green=\"0.3411764706\" blue=\"0.67843137249999996\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            </userDefinedRuntimeAttribute>\n                                        </userDefinedRuntimeAttributes>\n                                        <connections>\n                                            <action selector=\"textFieldChanged:\" destination=\"thh-5b-esU\" eventType=\"editingChanged\" id=\"whT-rY-wTA\"/>\n                                            <outlet property=\"delegate\" destination=\"thh-5b-esU\" id=\"sZP-Zq-aqX\"/>\n                                        </connections>\n                                    </textField>\n                                    <textField opaque=\"NO\" clipsSubviews=\"YES\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"left\" contentVerticalAlignment=\"center\" placeholder=\"Password\" minimumFontSize=\"17\" background=\"login_bottom_input\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"J5j-oJ-a2d\">\n                                        <rect key=\"frame\" x=\"241.5\" y=\"54\" width=\"285\" height=\"39\"/>\n                                        <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"285\" id=\"0Qt-ab-doD\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"39\" id=\"2Eo-qu-Cb8\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                        <textInputTraits key=\"textInputTraits\" returnKeyType=\"go\" enablesReturnKeyAutomatically=\"YES\" secureTextEntry=\"YES\" textContentType=\"password\"/>\n                                        <userDefinedRuntimeAttributes>\n                                            <userDefinedRuntimeAttribute type=\"color\" keyPath=\"_placeholderLabel.textColor\">\n                                                <color key=\"value\" red=\"0.15686274510000001\" green=\"0.3411764706\" blue=\"0.67843137249999996\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            </userDefinedRuntimeAttribute>\n                                        </userDefinedRuntimeAttributes>\n                                        <connections>\n                                            <action selector=\"textFieldChanged:\" destination=\"thh-5b-esU\" eventType=\"editingChanged\" id=\"OX3-tt-PJe\"/>\n                                            <outlet property=\"delegate\" destination=\"thh-5b-esU\" id=\"nfh-ga-0h2\"/>\n                                        </connections>\n                                    </textField>\n                                    <textField opaque=\"NO\" clipsSubviews=\"YES\" alpha=\"0.0\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"left\" contentVerticalAlignment=\"center\" placeholder=\"Host\" minimumFontSize=\"17\" background=\"login_only_input\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Pgp-x3-8jk\">\n                                        <rect key=\"frame\" x=\"241.5\" y=\"16\" width=\"285\" height=\"39\"/>\n                                        <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"285\" id=\"EFP-9z-kTr\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"39\" id=\"KdW-Og-G6a\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                        <textInputTraits key=\"textInputTraits\" autocorrectionType=\"no\" keyboardType=\"URL\"/>\n                                        <userDefinedRuntimeAttributes>\n                                            <userDefinedRuntimeAttribute type=\"color\" keyPath=\"_placeholderLabel.textColor\">\n                                                <color key=\"value\" red=\"0.15686274510000001\" green=\"0.3411764706\" blue=\"0.67843137249999996\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            </userDefinedRuntimeAttribute>\n                                        </userDefinedRuntimeAttributes>\n                                        <connections>\n                                            <action selector=\"textFieldChanged:\" destination=\"thh-5b-esU\" eventType=\"editingChanged\" id=\"NaS-IK-ESx\"/>\n                                            <outlet property=\"delegate\" destination=\"thh-5b-esU\" id=\"Tz4-Z7-4TU\"/>\n                                        </connections>\n                                    </textField>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" alpha=\"0.0\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"320\" placeholderIntrinsicHeight=\"32\" text=\"e.g. irccloud.yourcompany.com\" lineBreakMode=\"tailTruncation\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"320\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"TTY-xf-Jla\">\n                                        <rect key=\"frame\" x=\"241.5\" y=\"55\" width=\"320\" height=\"32\"/>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"18\"/>\n                                        <color key=\"textColor\" red=\"0.043137254899999998\" green=\"0.18039215689999999\" blue=\"0.37647058820000001\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" alpha=\"0.0\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"infinite\" placeholderIntrinsicHeight=\"40\" text=\"Just enter the email address you signed up with and we'll send you a link to log straight in.\" textAlignment=\"center\" lineBreakMode=\"wordWrap\" numberOfLines=\"0\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"288\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"82t-Dd-vQq\">\n                                        <rect key=\"frame\" x=\"240\" y=\"147\" width=\"288\" height=\"40\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"288\" id=\"XbU-pe-q3u\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"13\"/>\n                                        <color key=\"textColor\" red=\"0.043137254899999998\" green=\"0.18039215689999999\" blue=\"0.37647058820000001\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                    <button opaque=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"FEy-g6-oN2\">\n                                        <rect key=\"frame\" x=\"240\" y=\"133\" width=\"288\" height=\"40\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" constant=\"40\" id=\"6Fa-Tm-kJz\"/>\n                                            <constraint firstAttribute=\"width\" constant=\"288\" id=\"gSS-5x-u3j\"/>\n                                        </constraints>\n                                        <color key=\"tintColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <state key=\"normal\" title=\"Login\" backgroundImage=\"login_button\">\n                                            <color key=\"titleColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            <color key=\"titleShadowColor\" red=\"0.5\" green=\"0.5\" blue=\"0.5\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        </state>\n                                        <connections>\n                                            <action selector=\"loginButtonPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"xg2-g4-3iq\"/>\n                                        </connections>\n                                    </button>\n                                    <button opaque=\"NO\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"U1F-cw-qxd\">\n                                        <rect key=\"frame\" x=\"240\" y=\"133\" width=\"288\" height=\"40\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"288\" id=\"8tS-KY-xeS\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"40\" id=\"j6X-mX-ypO\"/>\n                                        </constraints>\n                                        <color key=\"tintColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <state key=\"normal\" title=\"Sign up for an account\" backgroundImage=\"signup_button\">\n                                            <color key=\"titleColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            <color key=\"titleShadowColor\" red=\"0.5\" green=\"0.5\" blue=\"0.5\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        </state>\n                                        <connections>\n                                            <action selector=\"signupButtonPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"Lzb-mg-RAB\"/>\n                                        </connections>\n                                    </button>\n                                    <button opaque=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"LyO-2o-3Ej\">\n                                        <rect key=\"frame\" x=\"240\" y=\"133\" width=\"288\" height=\"40\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"288\" id=\"JOG-jD-i3k\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"40\" id=\"dZx-m5-8Rz\"/>\n                                        </constraints>\n                                        <color key=\"tintColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <state key=\"normal\" title=\"Next\" backgroundImage=\"login_button\">\n                                            <color key=\"titleColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            <color key=\"titleShadowColor\" red=\"0.5\" green=\"0.5\" blue=\"0.5\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        </state>\n                                        <connections>\n                                            <action selector=\"nextButtonPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"x09-Ns-n2m\"/>\n                                        </connections>\n                                    </button>\n                                    <button opaque=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"EZC-Qj-aeF\">\n                                        <rect key=\"frame\" x=\"240\" y=\"101\" width=\"288\" height=\"40\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" constant=\"40\" id=\"W9L-vc-ag4\"/>\n                                            <constraint firstAttribute=\"width\" constant=\"288\" id=\"dDh-Mf-KwY\"/>\n                                        </constraints>\n                                        <color key=\"tintColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <state key=\"normal\" title=\"Send an access link\" backgroundImage=\"login_button\">\n                                            <color key=\"titleColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            <color key=\"titleShadowColor\" red=\"0.5\" green=\"0.5\" blue=\"0.5\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        </state>\n                                        <connections>\n                                            <action selector=\"sendAccessLinkButtonPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"Q9V-th-RNU\"/>\n                                        </connections>\n                                    </button>\n                                    <button hidden=\"YES\" opaque=\"NO\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"5kc-v2-8O4\">\n                                        <rect key=\"frame\" x=\"493.5\" y=\"60\" width=\"27\" height=\"27\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" constant=\"27\" id=\"RM6-I3-gqg\"/>\n                                            <constraint firstAttribute=\"width\" constant=\"27\" id=\"ppl-VP-Ghb\"/>\n                                        </constraints>\n                                        <state key=\"normal\" image=\"onepassword-button\">\n                                            <color key=\"titleShadowColor\" red=\"0.5\" green=\"0.5\" blue=\"0.5\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        </state>\n                                        <connections>\n                                            <action selector=\"onePasswordButtonPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"lqz-Yg-kDD\"/>\n                                        </connections>\n                                    </button>\n                                    <view autoresizesSubviews=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Eug-wi-F8f\" customClass=\"UIControl\">\n                                        <rect key=\"frame\" x=\"254\" y=\"173\" width=\"260\" height=\"24\"/>\n                                        <subviews>\n                                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"150\" placeholderIntrinsicHeight=\"infinite\" text=\"Forgotten your password?\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"150\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"OFl-cz-MMm\">\n                                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"150\" height=\"24\"/>\n                                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                                <color key=\"textColor\" red=\"0.61176470589999998\" green=\"0.78039215689999997\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <nil key=\"highlightedColor\"/>\n                                            </label>\n                                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"85\" placeholderIntrinsicHeight=\"infinite\" text=\"Get an access link\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"85\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cfc-xP-d4G\">\n                                                <rect key=\"frame\" x=\"173\" y=\"0.0\" width=\"85\" height=\"24\"/>\n                                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <nil key=\"highlightedColor\"/>\n                                            </label>\n                                        </subviews>\n                                        <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <constraints>\n                                            <constraint firstItem=\"OFl-cz-MMm\" firstAttribute=\"centerY\" secondItem=\"Eug-wi-F8f\" secondAttribute=\"centerY\" id=\"Bnv-bV-scQ\"/>\n                                            <constraint firstAttribute=\"width\" constant=\"260\" id=\"Dgc-Ia-Ght\"/>\n                                            <constraint firstItem=\"cfc-xP-d4G\" firstAttribute=\"centerY\" secondItem=\"Eug-wi-F8f\" secondAttribute=\"centerY\" id=\"FSx-N9-7KJ\"/>\n                                            <constraint firstItem=\"OFl-cz-MMm\" firstAttribute=\"height\" secondItem=\"Eug-wi-F8f\" secondAttribute=\"height\" id=\"Fjd-u1-DUv\"/>\n                                            <constraint firstItem=\"cfc-xP-d4G\" firstAttribute=\"height\" secondItem=\"Eug-wi-F8f\" secondAttribute=\"height\" id=\"UCU-G4-WAl\"/>\n                                            <constraint firstItem=\"OFl-cz-MMm\" firstAttribute=\"leading\" secondItem=\"Eug-wi-F8f\" secondAttribute=\"leading\" id=\"bmM-2h-mDQ\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"24\" id=\"gvO-hw-bta\"/>\n                                            <constraint firstAttribute=\"trailing\" secondItem=\"cfc-xP-d4G\" secondAttribute=\"trailing\" constant=\"2\" id=\"hDi-ap-Bza\"/>\n                                        </constraints>\n                                        <connections>\n                                            <action selector=\"forgotPasswordHintPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"wTF-LU-FjN\"/>\n                                        </connections>\n                                    </view>\n                                    <view autoresizesSubviews=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"wHq-8E-O6Q\" userLabel=\"Reset Password Hint\" customClass=\"UIControl\">\n                                        <rect key=\"frame\" x=\"302\" y=\"197\" width=\"164\" height=\"24\"/>\n                                        <subviews>\n                                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"24\" placeholderIntrinsicHeight=\"infinite\" text=\"or\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"24\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1qy-Ki-Hbf\">\n                                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"24\" height=\"24\"/>\n                                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                                <color key=\"textColor\" red=\"0.61176470589999998\" green=\"0.78039215689999997\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <nil key=\"highlightedColor\"/>\n                                            </label>\n                                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"180\" placeholderIntrinsicHeight=\"infinite\" text=\"request a password reset\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"85\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6U8-qM-cR3\">\n                                                <rect key=\"frame\" x=\"-18\" y=\"0.0\" width=\"180\" height=\"24\"/>\n                                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <nil key=\"highlightedColor\"/>\n                                            </label>\n                                        </subviews>\n                                        <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"164\" id=\"2ws-V3-gBY\"/>\n                                            <constraint firstAttribute=\"trailing\" secondItem=\"6U8-qM-cR3\" secondAttribute=\"trailing\" constant=\"2\" id=\"7nB-71-2vi\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"24\" id=\"Rh9-i2-F2y\"/>\n                                            <constraint firstItem=\"6U8-qM-cR3\" firstAttribute=\"centerY\" secondItem=\"wHq-8E-O6Q\" secondAttribute=\"centerY\" id=\"VTf-d5-n8V\"/>\n                                            <constraint firstItem=\"1qy-Ki-Hbf\" firstAttribute=\"height\" secondItem=\"wHq-8E-O6Q\" secondAttribute=\"height\" id=\"WpQ-RN-7PV\"/>\n                                            <constraint firstItem=\"1qy-Ki-Hbf\" firstAttribute=\"leading\" secondItem=\"wHq-8E-O6Q\" secondAttribute=\"leading\" id=\"Z7r-LG-SWA\"/>\n                                            <constraint firstItem=\"1qy-Ki-Hbf\" firstAttribute=\"centerY\" secondItem=\"wHq-8E-O6Q\" secondAttribute=\"centerY\" id=\"qwk-Me-06i\"/>\n                                            <constraint firstItem=\"6U8-qM-cR3\" firstAttribute=\"height\" secondItem=\"wHq-8E-O6Q\" secondAttribute=\"height\" id=\"vjL-ne-lWS\"/>\n                                        </constraints>\n                                        <connections>\n                                            <action selector=\"resetPasswordHintPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"ZqH-JY-eBM\"/>\n                                        </connections>\n                                    </view>\n                                    <view autoresizesSubviews=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Q3h-ZU-20z\">\n                                        <rect key=\"frame\" x=\"241.5\" y=\"11\" width=\"256\" height=\"20\"/>\n                                        <subviews>\n                                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"150\" placeholderIntrinsicHeight=\"infinite\" text=\"Forgotten your password?\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"150\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"WIW-NY-U2C\">\n                                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"150\" height=\"20\"/>\n                                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"12\"/>\n                                                <color key=\"textColor\" red=\"0.043137254899999998\" green=\"0.18039215689999999\" blue=\"0.37647058820000001\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <nil key=\"highlightedColor\"/>\n                                            </label>\n                                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"center\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"85\" placeholderIntrinsicHeight=\"infinite\" text=\"Not a problem.\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"85\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"SvH-ed-wZv\">\n                                                <rect key=\"frame\" x=\"169\" y=\"0.0\" width=\"85\" height=\"20\"/>\n                                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"12\"/>\n                                                <color key=\"textColor\" red=\"0.043137254899999998\" green=\"0.18039215689999999\" blue=\"0.37647058820000001\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <nil key=\"highlightedColor\"/>\n                                            </label>\n                                        </subviews>\n                                        <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"256\" id=\"3hj-S4-j9S\"/>\n                                            <constraint firstItem=\"SvH-ed-wZv\" firstAttribute=\"centerY\" secondItem=\"Q3h-ZU-20z\" secondAttribute=\"centerY\" id=\"7rb-qo-gAj\"/>\n                                            <constraint firstItem=\"WIW-NY-U2C\" firstAttribute=\"height\" secondItem=\"Q3h-ZU-20z\" secondAttribute=\"height\" id=\"T16-2y-3b9\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"20\" id=\"lRt-wZ-lTW\"/>\n                                            <constraint firstItem=\"SvH-ed-wZv\" firstAttribute=\"height\" secondItem=\"Q3h-ZU-20z\" secondAttribute=\"height\" id=\"v5y-Q1-qNG\"/>\n                                            <constraint firstItem=\"WIW-NY-U2C\" firstAttribute=\"centerY\" secondItem=\"Q3h-ZU-20z\" secondAttribute=\"centerY\" id=\"wV1-mp-jvc\"/>\n                                            <constraint firstAttribute=\"trailing\" secondItem=\"SvH-ed-wZv\" secondAttribute=\"trailing\" constant=\"2\" id=\"xjb-VZ-8t2\"/>\n                                            <constraint firstItem=\"WIW-NY-U2C\" firstAttribute=\"leading\" secondItem=\"Q3h-ZU-20z\" secondAttribute=\"leading\" id=\"ysr-yL-ttT\"/>\n                                        </constraints>\n                                    </view>\n                                    <view autoresizesSubviews=\"NO\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jub-VI-17w\" customClass=\"UIControl\">\n                                        <rect key=\"frame\" x=\"245\" y=\"173\" width=\"278\" height=\"32\"/>\n                                        <subviews>\n                                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"197\" placeholderIntrinsicHeight=\"infinite\" text=\"By signing up you agree to our\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"150\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Khs-H2-Er6\">\n                                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"197\" height=\"32\"/>\n                                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                                <color key=\"textColor\" red=\"0.61176470589999998\" green=\"0.78039215689999997\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <nil key=\"highlightedColor\"/>\n                                            </label>\n                                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"109\" placeholderIntrinsicHeight=\"infinite\" text=\"Terms of Service\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"85\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"D0M-i8-rXB\">\n                                                <rect key=\"frame\" x=\"167\" y=\"0.0\" width=\"109\" height=\"32\"/>\n                                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <nil key=\"highlightedColor\"/>\n                                            </label>\n                                        </subviews>\n                                        <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <constraints>\n                                            <constraint firstItem=\"Khs-H2-Er6\" firstAttribute=\"height\" secondItem=\"jub-VI-17w\" secondAttribute=\"height\" id=\"0cO-q0-rWR\"/>\n                                            <constraint firstItem=\"D0M-i8-rXB\" firstAttribute=\"centerY\" secondItem=\"jub-VI-17w\" secondAttribute=\"centerY\" id=\"4RM-Sc-FhR\"/>\n                                            <constraint firstItem=\"D0M-i8-rXB\" firstAttribute=\"height\" secondItem=\"jub-VI-17w\" secondAttribute=\"height\" id=\"G5D-SV-5LK\"/>\n                                            <constraint firstItem=\"Khs-H2-Er6\" firstAttribute=\"centerY\" secondItem=\"jub-VI-17w\" secondAttribute=\"centerY\" id=\"JVO-Ay-Nf6\"/>\n                                            <constraint firstAttribute=\"width\" constant=\"278\" id=\"iOB-pl-TPz\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"32\" id=\"jtU-ph-EjS\"/>\n                                            <constraint firstAttribute=\"trailing\" secondItem=\"D0M-i8-rXB\" secondAttribute=\"trailing\" constant=\"2\" id=\"l4z-qK-H1q\"/>\n                                            <constraint firstItem=\"Khs-H2-Er6\" firstAttribute=\"leading\" secondItem=\"jub-VI-17w\" secondAttribute=\"leading\" id=\"sie-mc-tgq\"/>\n                                        </constraints>\n                                        <connections>\n                                            <action selector=\"TOSHintPressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"y3C-9l-MTS\"/>\n                                        </connections>\n                                    </view>\n                                    <view autoresizesSubviews=\"NO\" alpha=\"0.0\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nSz-Ik-Vba\" customClass=\"UIControl\">\n                                        <rect key=\"frame\" x=\"254\" y=\"173\" width=\"260\" height=\"32\"/>\n                                        <subviews>\n                                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"150\" placeholderIntrinsicHeight=\"infinite\" text=\"Looking for the Standard Edition?\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"150\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"uSb-Bo-wuu\">\n                                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"150\" height=\"32\"/>\n                                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                                <color key=\"textColor\" red=\"0.61176470589999998\" green=\"0.78039215689999997\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <nil key=\"highlightedColor\"/>\n                                            </label>\n                                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"85\" placeholderIntrinsicHeight=\"infinite\" text=\"Get it here\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"85\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"P0F-IN-TxF\">\n                                                <rect key=\"frame\" x=\"173\" y=\"0.0\" width=\"85\" height=\"32\"/>\n                                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <nil key=\"highlightedColor\"/>\n                                            </label>\n                                        </subviews>\n                                        <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <constraints>\n                                            <constraint firstItem=\"uSb-Bo-wuu\" firstAttribute=\"height\" secondItem=\"nSz-Ik-Vba\" secondAttribute=\"height\" id=\"HLo-Ls-rKX\"/>\n                                            <constraint firstItem=\"uSb-Bo-wuu\" firstAttribute=\"leading\" secondItem=\"nSz-Ik-Vba\" secondAttribute=\"leading\" id=\"IMC-Vz-G2q\"/>\n                                            <constraint firstItem=\"P0F-IN-TxF\" firstAttribute=\"height\" secondItem=\"nSz-Ik-Vba\" secondAttribute=\"height\" id=\"Jeq-bi-mwl\"/>\n                                            <constraint firstItem=\"uSb-Bo-wuu\" firstAttribute=\"centerY\" secondItem=\"nSz-Ik-Vba\" secondAttribute=\"centerY\" id=\"YFr-SZ-f1p\"/>\n                                            <constraint firstAttribute=\"width\" constant=\"260\" id=\"dZq-kW-YIw\"/>\n                                            <constraint firstAttribute=\"trailing\" secondItem=\"P0F-IN-TxF\" secondAttribute=\"trailing\" constant=\"2\" id=\"hft-j8-OhY\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"32\" id=\"mtq-Ya-lO1\"/>\n                                            <constraint firstItem=\"P0F-IN-TxF\" firstAttribute=\"centerY\" secondItem=\"nSz-Ik-Vba\" secondAttribute=\"centerY\" id=\"uSR-0o-cY4\"/>\n                                        </constraints>\n                                        <connections>\n                                            <action selector=\"enterpriseLearnMorePressed:\" destination=\"thh-5b-esU\" eventType=\"touchUpInside\" id=\"mxT-di-RfG\"/>\n                                        </connections>\n                                    </view>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"0.2666666667\" green=\"0.50196078430000002\" blue=\"0.98039215690000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstItem=\"YDn-hm-4nv\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"4ns-Uy-wp9\"/>\n                                    <constraint firstItem=\"Q3h-ZU-20z\" firstAttribute=\"top\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"top\" constant=\"11\" id=\"5hI-DE-UYi\"/>\n                                    <constraint firstItem=\"5kc-v2-8O4\" firstAttribute=\"centerY\" secondItem=\"J5j-oJ-a2d\" secondAttribute=\"centerY\" id=\"6Z0-Ok-c1Q\"/>\n                                    <constraint firstItem=\"wHq-8E-O6Q\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"AoW-zr-ajF\"/>\n                                    <constraint firstItem=\"wHq-8E-O6Q\" firstAttribute=\"top\" secondItem=\"Eug-wi-F8f\" secondAttribute=\"bottom\" id=\"B3o-Y3-MwX\"/>\n                                    <constraint firstItem=\"U1F-cw-qxd\" firstAttribute=\"top\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"top\" constant=\"133\" id=\"CgG-Qp-sEM\"/>\n                                    <constraint firstItem=\"Eug-wi-F8f\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"GyJ-pd-xqL\"/>\n                                    <constraint firstItem=\"82t-Dd-vQq\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"L1L-aE-nOh\"/>\n                                    <constraint firstItem=\"TTY-xf-Jla\" firstAttribute=\"leading\" secondItem=\"Pgp-x3-8jk\" secondAttribute=\"leading\" id=\"L4V-ke-bfz\"/>\n                                    <constraint firstItem=\"Pgp-x3-8jk\" firstAttribute=\"top\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"top\" constant=\"16\" id=\"L8G-3W-Olx\"/>\n                                    <constraint firstItem=\"EZC-Qj-aeF\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"Lbf-bH-CHn\"/>\n                                    <constraint firstItem=\"TTY-xf-Jla\" firstAttribute=\"top\" secondItem=\"Pgp-x3-8jk\" secondAttribute=\"bottom\" id=\"NHw-kJ-NPQ\"/>\n                                    <constraint firstItem=\"FEy-g6-oN2\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"QvE-75-Dvs\"/>\n                                    <constraint firstItem=\"J5j-oJ-a2d\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"T8p-Ki-W1m\"/>\n                                    <constraint firstItem=\"nSz-Ik-Vba\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"TMT-IP-NOg\"/>\n                                    <constraint firstItem=\"FEy-g6-oN2\" firstAttribute=\"top\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"top\" constant=\"133\" id=\"Vbe-0V-ITS\"/>\n                                    <constraint firstItem=\"LyO-2o-3Ej\" firstAttribute=\"top\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"top\" constant=\"133\" id=\"XSy-i6-UuO\"/>\n                                    <constraint firstItem=\"jub-VI-17w\" firstAttribute=\"top\" secondItem=\"U1F-cw-qxd\" secondAttribute=\"bottom\" id=\"Yw4-cs-5XE\"/>\n                                    <constraint firstItem=\"zZw-jo-Si9\" firstAttribute=\"top\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"top\" constant=\"16\" id=\"ZxP-q2-nk9\"/>\n                                    <constraint firstItem=\"Eug-wi-F8f\" firstAttribute=\"top\" secondItem=\"FEy-g6-oN2\" secondAttribute=\"bottom\" id=\"bYT-eH-frN\"/>\n                                    <constraint firstItem=\"J5j-oJ-a2d\" firstAttribute=\"top\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"top\" constant=\"54\" id=\"boR-1r-hxJ\"/>\n                                    <constraint firstItem=\"Pgp-x3-8jk\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"fQH-BX-gWw\"/>\n                                    <constraint firstItem=\"jub-VI-17w\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"gOZ-Jt-6Mf\"/>\n                                    <constraint firstItem=\"Q3h-ZU-20z\" firstAttribute=\"leading\" secondItem=\"zZw-jo-Si9\" secondAttribute=\"leading\" id=\"gq0-rE-wMu\"/>\n                                    <constraint firstItem=\"LyO-2o-3Ej\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"gsh-ge-V4v\"/>\n                                    <constraint firstItem=\"U1F-cw-qxd\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"jwg-qB-87Z\"/>\n                                    <constraint firstItem=\"EZC-Qj-aeF\" firstAttribute=\"top\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"top\" constant=\"101\" id=\"lU0-8i-LIL\"/>\n                                    <constraint firstItem=\"nSz-Ik-Vba\" firstAttribute=\"top\" secondItem=\"LyO-2o-3Ej\" secondAttribute=\"bottom\" id=\"lbQ-wP-X9K\"/>\n                                    <constraint firstItem=\"YDn-hm-4nv\" firstAttribute=\"top\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"top\" constant=\"16\" id=\"ntI-JY-ChK\"/>\n                                    <constraint firstItem=\"82t-Dd-vQq\" firstAttribute=\"top\" secondItem=\"EZC-Qj-aeF\" secondAttribute=\"bottom\" constant=\"6\" id=\"ozg-Vq-8r5\"/>\n                                    <constraint firstItem=\"zZw-jo-Si9\" firstAttribute=\"centerX\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"centerX\" id=\"qUd-mJ-Ix1\"/>\n                                    <constraint firstItem=\"5kc-v2-8O4\" firstAttribute=\"trailing\" secondItem=\"J5j-oJ-a2d\" secondAttribute=\"trailing\" constant=\"-6\" id=\"y1g-Vp-Q6I\"/>\n                                </constraints>\n                            </view>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" text=\"Version\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"280\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lSc-2u-RsF\">\n                                <rect key=\"frame\" x=\"244\" y=\"987\" width=\"280\" height=\"21\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"280\" id=\"9Jk-nt-cog\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"21\" id=\"zj1-sP-x9q\"/>\n                                </constraints>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"12\"/>\n                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                        </subviews>\n                        <color key=\"backgroundColor\" red=\"0.043137254899999998\" green=\"0.18039215689999999\" blue=\"0.37647058820000001\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"Hgu-D2-Mph\" firstAttribute=\"leading\" secondItem=\"sfr-SS-1jI\" secondAttribute=\"trailing\" constant=\"14\" id=\"6zi-kR-k0M\"/>\n                            <constraint firstItem=\"zTV-Zl-uPd\" firstAttribute=\"bottom\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"bottom\" id=\"7bO-V0-F24\"/>\n                            <constraint firstItem=\"mJM-f8-v0Q\" firstAttribute=\"leading\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"leading\" id=\"9dt-Nl-5iT\"/>\n                            <constraint firstItem=\"sfr-SS-1jI\" firstAttribute=\"leading\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"centerX\" constant=\"-112\" id=\"Bbd-DV-aee\"/>\n                            <constraint firstItem=\"zTV-Zl-uPd\" firstAttribute=\"top\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"topMargin\" constant=\"160\" id=\"CFl-aC-swv\"/>\n                            <constraint firstItem=\"zTV-Zl-uPd\" firstAttribute=\"leading\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"leading\" id=\"DMO-28-jKq\"/>\n                            <constraint firstItem=\"lSc-2u-RsF\" firstAttribute=\"centerX\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"centerX\" id=\"DPI-D4-Hu9\"/>\n                            <constraint firstItem=\"mJM-f8-v0Q\" firstAttribute=\"top\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"top\" constant=\"160\" id=\"Fwf-sH-qhq\"/>\n                            <constraint firstItem=\"iSf-t4-0KQ\" firstAttribute=\"centerX\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"centerX\" id=\"GYI-n1-Fjj\"/>\n                            <constraint firstItem=\"KFZ-UT-EG5\" firstAttribute=\"leading\" secondItem=\"Hgu-D2-Mph\" secondAttribute=\"trailing\" id=\"IDQ-Hy-lUM\"/>\n                            <constraint firstItem=\"mJM-f8-v0Q\" firstAttribute=\"bottom\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"bottom\" id=\"IfR-z4-Crh\"/>\n                            <constraint firstItem=\"RjR-3c-mm2\" firstAttribute=\"centerX\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"centerX\" constant=\"50\" id=\"Ldx-lT-XCq\"/>\n                            <constraint firstItem=\"iSf-t4-0KQ\" firstAttribute=\"top\" secondItem=\"sfr-SS-1jI\" secondAttribute=\"bottom\" constant=\"16\" id=\"MqC-ah-T8D\"/>\n                            <constraint firstItem=\"lmN-wO-9gf\" firstAttribute=\"centerX\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"centerX\" id=\"QVN-Lj-9tW\"/>\n                            <constraint firstItem=\"lUW-Yp-Apz\" firstAttribute=\"top\" secondItem=\"sfr-SS-1jI\" secondAttribute=\"bottom\" constant=\"16\" id=\"SFg-8Y-u4v\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"zTV-Zl-uPd\" secondAttribute=\"trailing\" id=\"SNJ-Xf-riH\"/>\n                            <constraint firstItem=\"sfr-SS-1jI\" firstAttribute=\"top\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"topMargin\" constant=\"48\" id=\"TaT-bV-ldV\"/>\n                            <constraint firstItem=\"mJM-f8-v0Q\" firstAttribute=\"trailing\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"trailing\" id=\"YnH-T3-zCB\"/>\n                            <constraint firstItem=\"lSc-2u-RsF\" firstAttribute=\"bottom\" secondItem=\"mJM-f8-v0Q\" secondAttribute=\"bottom\" constant=\"-16\" id=\"Z8b-xm-FVb\"/>\n                            <constraint firstItem=\"Hgu-D2-Mph\" firstAttribute=\"top\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"topMargin\" constant=\"48\" id=\"c3C-hj-GfH\"/>\n                            <constraint firstItem=\"vjV-1j-Hve\" firstAttribute=\"centerX\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"centerX\" id=\"eJH-0f-Zoo\"/>\n                            <constraint firstItem=\"lmN-wO-9gf\" firstAttribute=\"top\" secondItem=\"sfr-SS-1jI\" secondAttribute=\"bottom\" constant=\"16\" id=\"g1E-qO-b56\"/>\n                            <constraint firstItem=\"RjR-3c-mm2\" firstAttribute=\"top\" secondItem=\"sfr-SS-1jI\" secondAttribute=\"bottom\" constant=\"16\" id=\"m74-2T-28g\"/>\n                            <constraint firstItem=\"lUW-Yp-Apz\" firstAttribute=\"centerX\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"centerX\" constant=\"-50\" id=\"sQe-lu-zaH\"/>\n                            <constraint firstItem=\"KFZ-UT-EG5\" firstAttribute=\"top\" secondItem=\"uLz-Jv-72R\" secondAttribute=\"topMargin\" constant=\"48\" id=\"twl-9Z-wcj\"/>\n                            <constraint firstItem=\"vjV-1j-Hve\" firstAttribute=\"top\" secondItem=\"sfr-SS-1jI\" secondAttribute=\"bottom\" constant=\"16\" id=\"uvR-r6-2ZG\"/>\n                        </constraints>\n                    </view>\n                    <connections>\n                        <outlet property=\"Cloud\" destination=\"KFZ-UT-EG5\" id=\"LZA-ai-RJn\"/>\n                        <outlet property=\"IRC\" destination=\"Hgu-D2-Mph\" id=\"LcZ-3w-dic\"/>\n                        <outlet property=\"OnePassword\" destination=\"5kc-v2-8O4\" id=\"XXw-dF-zJv\"/>\n                        <outlet property=\"TOSHint\" destination=\"jub-VI-17w\" id=\"nzX-hN-aYD\"/>\n                        <outlet property=\"activity\" destination=\"4IH-UP-pdU\" id=\"mjR-L6-tQv\"/>\n                        <outlet property=\"enterEmailAddressHint\" destination=\"82t-Dd-vQq\" id=\"a7b-m9-Lnl\"/>\n                        <outlet property=\"enterpriseHint\" destination=\"iSf-t4-0KQ\" id=\"m1Q-jl-BaX\"/>\n                        <outlet property=\"enterpriseLearnMore\" destination=\"nSz-Ik-Vba\" id=\"rzd-st-PP1\"/>\n                        <outlet property=\"forgotPasswordHint\" destination=\"Eug-wi-F8f\" id=\"71r-kh-PdL\"/>\n                        <outlet property=\"forgotPasswordLogin\" destination=\"lUW-Yp-Apz\" id=\"aDC-Qf-oP9\"/>\n                        <outlet property=\"forgotPasswordSignup\" destination=\"RjR-3c-mm2\" id=\"ceS-bN-gQz\"/>\n                        <outlet property=\"host\" destination=\"Pgp-x3-8jk\" id=\"grj-Re-Gar\"/>\n                        <outlet property=\"hostHint\" destination=\"TTY-xf-Jla\" id=\"dfo-am-XxP\"/>\n                        <outlet property=\"hostYOffset\" destination=\"L8G-3W-Olx\" id=\"Ipd-0b-JXc\"/>\n                        <outlet property=\"loadingView\" destination=\"zTV-Zl-uPd\" id=\"s71-Sz-u80\"/>\n                        <outlet property=\"loadingViewYOffset\" destination=\"CFl-aC-swv\" id=\"hNd-VC-5If\"/>\n                        <outlet property=\"login\" destination=\"FEy-g6-oN2\" id=\"02S-WU-wo3\"/>\n                        <outlet property=\"loginHint\" destination=\"lmN-wO-9gf\" id=\"RXF-5Q-Uoj\"/>\n                        <outlet property=\"loginView\" destination=\"mJM-f8-v0Q\" id=\"eqt-WT-C68\"/>\n                        <outlet property=\"loginViewYOffset\" destination=\"Fwf-sH-qhq\" id=\"tWn-E9-CAJ\"/>\n                        <outlet property=\"loginYOffset\" destination=\"Vbe-0V-ITS\" id=\"boB-oG-Lrk\"/>\n                        <outlet property=\"logo\" destination=\"sfr-SS-1jI\" id=\"7bq-VV-Hq9\"/>\n                        <outlet property=\"name\" destination=\"zZw-jo-Si9\" id=\"941-yh-jVw\"/>\n                        <outlet property=\"next\" destination=\"LyO-2o-3Ej\" id=\"e92-0u-RJY\"/>\n                        <outlet property=\"nextYOffset\" destination=\"XSy-i6-UuO\" id=\"0ga-Ii-cqf\"/>\n                        <outlet property=\"notAProblem\" destination=\"Q3h-ZU-20z\" id=\"42p-Fp-PY9\"/>\n                        <outlet property=\"password\" destination=\"J5j-oJ-a2d\" id=\"Ie0-Ot-ZcS\"/>\n                        <outlet property=\"passwordYOffset\" destination=\"boR-1r-hxJ\" id=\"w1h-St-8s4\"/>\n                        <outlet property=\"resetPasswordHint\" destination=\"wHq-8E-O6Q\" id=\"rTR-al-VVr\"/>\n                        <outlet property=\"sendAccessLink\" destination=\"EZC-Qj-aeF\" id=\"4Ri-tb-boK\"/>\n                        <outlet property=\"sendAccessLinkYOffset\" destination=\"lU0-8i-LIL\" id=\"QIv-Su-Fim\"/>\n                        <outlet property=\"signup\" destination=\"U1F-cw-qxd\" id=\"9hf-ud-oph\"/>\n                        <outlet property=\"signupHint\" destination=\"vjV-1j-Hve\" id=\"QlE-wY-Q53\"/>\n                        <outlet property=\"signupYOffset\" destination=\"CgG-Qp-sEM\" id=\"lIb-v9-0UH\"/>\n                        <outlet property=\"status\" destination=\"2LD-X7-x0T\" id=\"5Eb-uw-j5k\"/>\n                        <outlet property=\"username\" destination=\"YDn-hm-4nv\" id=\"oof-4P-2Ko\"/>\n                        <outlet property=\"usernameYOffset\" destination=\"ntI-JY-ChK\" id=\"UDH-BZ-BaK\"/>\n                        <outlet property=\"version\" destination=\"lSc-2u-RsF\" id=\"9W7-ws-0Eb\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"cJN-o5-ji0\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"-581.25\" y=\"1104.4921875\"/>\n        </scene>\n        <!--MainViewController-->\n        <scene sceneID=\"q00-RY-ajR\">\n            <objects>\n                <viewController storyboardIdentifier=\"MainViewController\" automaticallyAdjustsScrollViewInsets=\"NO\" useStoryboardIdentifierAsRestorationIdentifier=\"YES\" id=\"eA9-ra-BSf\" userLabel=\"MainViewController\" customClass=\"MainViewController\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"tjD-Mf-au6\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"9R7-ni-VzZ\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"cMl-aC-QBW\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"768\" height=\"954\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <view userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cZW-xP-lCa\" userLabel=\"Borders\">\n                                <rect key=\"frame\" x=\"-1\" y=\"0.0\" width=\"770\" height=\"1018\"/>\n                                <subviews>\n                                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8dM-P4-uec\">\n                                        <rect key=\"frame\" x=\"1\" y=\"0.0\" width=\"768\" height=\"1018\"/>\n                                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                    </view>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"0.7022702693939209\" green=\"0.77676546573638916\" blue=\"0.99924099445343018\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"bottom\" secondItem=\"8dM-P4-uec\" secondAttribute=\"bottom\" id=\"FkN-yJ-LDf\"/>\n                                    <constraint firstItem=\"8dM-P4-uec\" firstAttribute=\"leading\" secondItem=\"cZW-xP-lCa\" secondAttribute=\"leading\" constant=\"1\" id=\"Nn7-7b-wiW\"/>\n                                    <constraint firstAttribute=\"trailing\" secondItem=\"8dM-P4-uec\" secondAttribute=\"trailing\" constant=\"1\" id=\"ipl-No-ZdU\"/>\n                                    <constraint firstItem=\"8dM-P4-uec\" firstAttribute=\"top\" secondItem=\"cZW-xP-lCa\" secondAttribute=\"top\" id=\"y63-KL-mpF\"/>\n                                </constraints>\n                            </view>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" showsHorizontalScrollIndicator=\"NO\" dataMode=\"prototypes\" style=\"plain\" separatorStyle=\"none\" rowHeight=\"44\" sectionHeaderHeight=\"22\" sectionFooterHeight=\"22\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"t8Z-Pu-wcU\" userLabel=\"Events Table View\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"768\" height=\"954\"/>\n                                <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"768\" id=\"Quf-Ug-9cF\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"954\" id=\"rCT-DO-2FK\"/>\n                                </constraints>\n                                <connections>\n                                    <outlet property=\"dataSource\" destination=\"pci-6M-5ag\" id=\"dL3-I2-yXI\"/>\n                                    <outlet property=\"delegate\" destination=\"pci-6M-5ag\" id=\"FBM-Jj-fgs\"/>\n                                </connections>\n                            </tableView>\n                            <imageView hidden=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" placeholderIntrinsicWidth=\"48\" placeholderIntrinsicHeight=\"48\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"WXm-cx-Mj2\">\n                                <rect key=\"frame\" x=\"10\" y=\"0.0\" width=\"48\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"Xg8-nI-bU5\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"zKP-km-Cs5\"/>\n                                </constraints>\n                            </imageView>\n                            <view alpha=\"0.0\" contentMode=\"scaleToFill\" placeholderIntrinsicWidth=\"768\" placeholderIntrinsicHeight=\"32\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fvC-nM-NHm\" userLabel=\"Top Unread View\" customClass=\"UIControl\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"768\" height=\"32\"/>\n                                <subviews>\n                                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"↑\" lineBreakMode=\"clip\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"14\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nV2-yC-Cav\">\n                                        <rect key=\"frame\" x=\"6\" y=\"7\" width=\"11\" height=\"17\"/>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                        <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                    <view opaque=\"NO\" contentMode=\"scaleToFill\" placeholderIntrinsicWidth=\"24\" placeholderIntrinsicHeight=\"24\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NXY-Lp-a7w\" customClass=\"HighlightsCountView\">\n                                        <rect key=\"frame\" x=\"17\" y=\"4\" width=\"24\" height=\"24\"/>\n                                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                    </view>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" text=\"Label\" lineBreakMode=\"wordWrap\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"722\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2eF-8l-jgk\">\n                                        <rect key=\"frame\" x=\"17\" y=\"6\" width=\"719\" height=\"20\"/>\n                                        <accessibility key=\"accessibilityConfiguration\" hint=\"Scrolls to first unread message\">\n                                            <accessibilityTraits key=\"traits\" button=\"YES\"/>\n                                        </accessibility>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"20\" id=\"KPG-4E-IUi\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                        <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                    <button opaque=\"NO\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NXj-Yr-xxw\" userLabel=\"Dismiss\">\n                                        <rect key=\"frame\" x=\"736\" y=\"0.0\" width=\"32\" height=\"32\"/>\n                                        <accessibility key=\"accessibilityConfiguration\" hint=\"Clears unread messages\" label=\"Dismiss\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"32\" id=\"JE7-12-8YL\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"32\" id=\"KPi-pD-rkc\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"boldSystem\" pointSize=\"15\"/>\n                                        <state key=\"normal\" image=\"accept\">\n                                            <color key=\"titleColor\" red=\"0.19607843459999999\" green=\"0.30980393290000002\" blue=\"0.52156865600000002\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            <color key=\"titleShadowColor\" red=\"0.5\" green=\"0.5\" blue=\"0.5\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        </state>\n                                        <state key=\"highlighted\">\n                                            <color key=\"titleColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        </state>\n                                        <connections>\n                                            <action selector=\"dismissButtonPressed:\" destination=\"pci-6M-5ag\" eventType=\"touchUpInside\" id=\"QI1-u4-bJ5\"/>\n                                        </connections>\n                                    </button>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"0.25540044903755188\" green=\"0.38604474067687988\" blue=\"0.99844574928283691\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstItem=\"NXY-Lp-a7w\" firstAttribute=\"leading\" secondItem=\"nV2-yC-Cav\" secondAttribute=\"trailing\" id=\"BL7-Lb-IZd\"/>\n                                    <constraint firstItem=\"nV2-yC-Cav\" firstAttribute=\"top\" secondItem=\"fvC-nM-NHm\" secondAttribute=\"top\" constant=\"7\" id=\"D1t-Jz-vKQ\"/>\n                                    <constraint firstItem=\"NXj-Yr-xxw\" firstAttribute=\"trailing\" secondItem=\"fvC-nM-NHm\" secondAttribute=\"trailing\" id=\"FwE-VC-fP9\"/>\n                                    <constraint firstItem=\"NXj-Yr-xxw\" firstAttribute=\"top\" secondItem=\"fvC-nM-NHm\" secondAttribute=\"top\" id=\"GpZ-co-OXD\"/>\n                                    <constraint firstItem=\"2eF-8l-jgk\" firstAttribute=\"leading\" secondItem=\"nV2-yC-Cav\" secondAttribute=\"trailing\" id=\"L3L-aJ-TBg\"/>\n                                    <constraint firstAttribute=\"height\" secondItem=\"2eF-8l-jgk\" secondAttribute=\"height\" constant=\"12\" id=\"Suy-TO-Abq\"/>\n                                    <constraint firstItem=\"2eF-8l-jgk\" firstAttribute=\"top\" secondItem=\"fvC-nM-NHm\" secondAttribute=\"top\" constant=\"6\" id=\"UHv-x9-7KF\"/>\n                                    <constraint firstItem=\"NXj-Yr-xxw\" firstAttribute=\"leading\" secondItem=\"2eF-8l-jgk\" secondAttribute=\"trailing\" id=\"aDj-HC-Pf3\"/>\n                                    <constraint firstItem=\"nV2-yC-Cav\" firstAttribute=\"leading\" secondItem=\"fvC-nM-NHm\" secondAttribute=\"leading\" constant=\"6\" id=\"kFb-Al-XWg\"/>\n                                    <constraint firstItem=\"NXY-Lp-a7w\" firstAttribute=\"top\" secondItem=\"fvC-nM-NHm\" secondAttribute=\"top\" constant=\"4\" id=\"kyb-JT-xdK\"/>\n                                </constraints>\n                                <connections>\n                                    <action selector=\"topUnreadBarClicked:\" destination=\"pci-6M-5ag\" eventType=\"touchUpInside\" id=\"mBD-y7-KIn\"/>\n                                </connections>\n                            </view>\n                            <view alpha=\"0.0\" contentMode=\"scaleToFill\" placeholderIntrinsicWidth=\"768\" placeholderIntrinsicHeight=\"32\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"scS-39-nDE\" userLabel=\"Bottom Unread View\" customClass=\"UIControl\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"854\" width=\"768\" height=\"32\"/>\n                                <subviews>\n                                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"↓\" lineBreakMode=\"clip\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"14\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"MQi-6s-Aew\">\n                                        <rect key=\"frame\" x=\"6\" y=\"7\" width=\"11\" height=\"17\"/>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                        <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                    <view opaque=\"NO\" contentMode=\"scaleToFill\" placeholderIntrinsicWidth=\"24\" placeholderIntrinsicHeight=\"24\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2A3-WY-mos\" customClass=\"HighlightsCountView\">\n                                        <rect key=\"frame\" x=\"17\" y=\"4\" width=\"24\" height=\"24\"/>\n                                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                    </view>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" text=\"Label\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"742\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jfo-ng-UHu\">\n                                        <rect key=\"frame\" x=\"17\" y=\"6\" width=\"745\" height=\"20\"/>\n                                        <accessibility key=\"accessibilityConfiguration\" hint=\"Scrolls to bottom\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"20\" id=\"pEJ-oh-CxO\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                        <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"0.25540044903755188\" green=\"0.38604474067687988\" blue=\"0.99844574928283691\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstItem=\"MQi-6s-Aew\" firstAttribute=\"top\" secondItem=\"scS-39-nDE\" secondAttribute=\"top\" constant=\"7\" id=\"1sk-ey-wfh\"/>\n                                    <constraint firstItem=\"2A3-WY-mos\" firstAttribute=\"top\" secondItem=\"scS-39-nDE\" secondAttribute=\"top\" constant=\"4\" id=\"Iix-k4-eoy\"/>\n                                    <constraint firstItem=\"2A3-WY-mos\" firstAttribute=\"leading\" secondItem=\"MQi-6s-Aew\" secondAttribute=\"trailing\" id=\"N7P-7N-iZa\"/>\n                                    <constraint firstItem=\"jfo-ng-UHu\" firstAttribute=\"top\" secondItem=\"scS-39-nDE\" secondAttribute=\"top\" constant=\"6\" id=\"WHh-al-W5j\"/>\n                                    <constraint firstAttribute=\"trailing\" secondItem=\"jfo-ng-UHu\" secondAttribute=\"trailing\" constant=\"6\" id=\"mf7-83-49y\"/>\n                                    <constraint firstItem=\"jfo-ng-UHu\" firstAttribute=\"leading\" secondItem=\"MQi-6s-Aew\" secondAttribute=\"trailing\" id=\"pD2-km-Kpp\"/>\n                                    <constraint firstItem=\"MQi-6s-Aew\" firstAttribute=\"leading\" secondItem=\"scS-39-nDE\" secondAttribute=\"leading\" constant=\"6\" id=\"tMZ-Fy-RWv\"/>\n                                    <constraint firstAttribute=\"height\" secondItem=\"jfo-ng-UHu\" secondAttribute=\"height\" constant=\"12\" id=\"twV-Cb-ePd\"/>\n                                </constraints>\n                                <connections>\n                                    <action selector=\"bottomUnreadBarClicked:\" destination=\"pci-6M-5ag\" eventType=\"touchUpInside\" id=\"KPy-hi-heu\"/>\n                                </connections>\n                            </view>\n                            <view hidden=\"YES\" autoresizesSubviews=\"NO\" contentMode=\"scaleToFill\" placeholderIntrinsicWidth=\"768\" placeholderIntrinsicHeight=\"32\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"QgU-LW-Wne\" userLabel=\"Server Status Bar\" customClass=\"UIControl\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"854\" width=\"768\" height=\"32\"/>\n                                <subviews>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" text=\"\" lineBreakMode=\"wordWrap\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sIl-WH-w2W\">\n                                        <rect key=\"frame\" x=\"6\" y=\"6\" width=\"756\" height=\"20\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"20\" id=\"lCz-IX-GWn\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                                        <color key=\"textColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstItem=\"sIl-WH-w2W\" firstAttribute=\"top\" secondItem=\"QgU-LW-Wne\" secondAttribute=\"top\" constant=\"6\" id=\"AFS-Jt-ihf\"/>\n                                    <constraint firstItem=\"sIl-WH-w2W\" firstAttribute=\"leading\" secondItem=\"QgU-LW-Wne\" secondAttribute=\"leading\" constant=\"6\" id=\"DSE-ha-pJb\"/>\n                                    <constraint firstAttribute=\"trailing\" secondItem=\"sIl-WH-w2W\" secondAttribute=\"trailing\" constant=\"6\" id=\"Ssp-cN-LDC\"/>\n                                    <constraint firstAttribute=\"height\" secondItem=\"sIl-WH-w2W\" secondAttribute=\"height\" constant=\"12\" id=\"syk-Ns-BsH\"/>\n                                </constraints>\n                                <connections>\n                                    <action selector=\"serverStatusBarPressed:\" destination=\"eA9-ra-BSf\" eventType=\"touchUpInside\" id=\"d2g-cF-pTa\"/>\n                                </connections>\n                            </view>\n                            <activityIndicatorView opaque=\"NO\" contentMode=\"scaleToFill\" style=\"white\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"37K-X6-4EC\">\n                                <rect key=\"frame\" x=\"374\" y=\"467\" width=\"20\" height=\"20\"/>\n                            </activityIndicatorView>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" alpha=\"0.0\" contentMode=\"left\" text=\"Double-tap to quickly reply to the sender\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"290\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"biy-MM-eKX\">\n                                <rect key=\"frame\" x=\"239\" y=\"799\" width=\"290\" height=\"55\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"55\" id=\"8Ck-Wn-AOK\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"290\" id=\"EmZ-vM-uzU\"/>\n                                </constraints>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" alpha=\"0.0\" contentMode=\"left\" text=\"Swipe with 2 fingers to return to the previous channel or conversation\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"290\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Me3-jh-nJf\">\n                                <rect key=\"frame\" x=\"239\" y=\"799\" width=\"290\" height=\"55\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"290\" id=\"TRm-q9-E0j\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"55\" id=\"bXb-fr-AbV\"/>\n                                </constraints>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" alpha=\"0.0\" contentMode=\"left\" text=\"Swipe left and right to quickly open and close the sidebars\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"290\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"IOs-dt-XUa\">\n                                <rect key=\"frame\" x=\"239\" y=\"799\" width=\"290\" height=\"55\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"55\" id=\"DY5-aL-REE\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"290\" id=\"e9j-Ou-nSL\"/>\n                                </constraints>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <view hidden=\"YES\" contentMode=\"scaleToFill\" placeholderIntrinsicWidth=\"768\" placeholderIntrinsicHeight=\"32\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cdg-2x-04N\" userLabel=\"Global Msg\" customClass=\"UIControl\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"768\" height=\"32\"/>\n                                <subviews>\n                                    <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"\" textAlignment=\"center\" lineBreakMode=\"wordWrap\" numberOfLines=\"0\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Lax-2l-YNN\" userLabel=\"Global Msg Label\" customClass=\"LinkLabel\">\n                                        <rect key=\"frame\" x=\"6\" y=\"6\" width=\"756\" height=\"20\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"20\" id=\"FAV-Vz-Y1s\"/>\n                                        </constraints>\n                                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                                        <color key=\"textColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        <nil key=\"highlightedColor\"/>\n                                    </label>\n                                </subviews>\n                                <color key=\"backgroundColor\" red=\"1\" green=\"0.99541655610000002\" blue=\"0.33555298379999998\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" secondItem=\"Lax-2l-YNN\" secondAttribute=\"height\" constant=\"12\" id=\"jbC-Fk-Vqs\"/>\n                                    <constraint firstItem=\"Lax-2l-YNN\" firstAttribute=\"top\" secondItem=\"cdg-2x-04N\" secondAttribute=\"top\" constant=\"6\" id=\"lvw-sS-6VK\"/>\n                                    <constraint firstItem=\"Lax-2l-YNN\" firstAttribute=\"trailing\" secondItem=\"cdg-2x-04N\" secondAttribute=\"trailing\" constant=\"-6\" id=\"oMF-C9-z8J\"/>\n                                    <constraint firstItem=\"Lax-2l-YNN\" firstAttribute=\"leading\" secondItem=\"cdg-2x-04N\" secondAttribute=\"leading\" constant=\"6\" id=\"spR-Ww-NPG\"/>\n                                </constraints>\n                            </view>\n                            <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fW5-GL-Rkw\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"886\" width=\"768\" height=\"68\"/>\n                                <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"68\" id=\"SuG-V2-yni\"/>\n                                </constraints>\n                            </view>\n                        </subviews>\n                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"t8Z-Pu-wcU\" firstAttribute=\"leading\" secondItem=\"cMl-aC-QBW\" secondAttribute=\"leading\" id=\"05q-ul-QYb\"/>\n                            <constraint firstItem=\"fvC-nM-NHm\" firstAttribute=\"trailing\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"trailing\" id=\"0Xd-4G-Etu\"/>\n                            <constraint firstItem=\"cZW-xP-lCa\" firstAttribute=\"bottom\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"bottom\" constant=\"64\" id=\"91J-TJ-yAS\"/>\n                            <constraint firstItem=\"biy-MM-eKX\" firstAttribute=\"centerX\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"centerX\" id=\"A4m-LD-gkQ\"/>\n                            <constraint firstItem=\"cZW-xP-lCa\" firstAttribute=\"top\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"top\" id=\"Ch4-tp-4A2\"/>\n                            <constraint firstItem=\"fW5-GL-Rkw\" firstAttribute=\"top\" secondItem=\"Me3-jh-nJf\" secondAttribute=\"bottom\" constant=\"32\" id=\"FAp-B3-jyQ\"/>\n                            <constraint firstItem=\"QgU-LW-Wne\" firstAttribute=\"leading\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"leading\" id=\"FKB-gP-fFL\"/>\n                            <constraint firstItem=\"fW5-GL-Rkw\" firstAttribute=\"centerX\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"centerX\" id=\"IbI-A6-63q\"/>\n                            <constraint firstItem=\"fW5-GL-Rkw\" firstAttribute=\"top\" secondItem=\"scS-39-nDE\" secondAttribute=\"bottom\" id=\"J0Y-Xk-O0Z\"/>\n                            <constraint firstItem=\"cdg-2x-04N\" firstAttribute=\"top\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"top\" id=\"JUW-xp-JDU\"/>\n                            <constraint firstItem=\"cZW-xP-lCa\" firstAttribute=\"trailing\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"trailing\" constant=\"1\" id=\"OvL-OY-vuO\"/>\n                            <constraint firstItem=\"Me3-jh-nJf\" firstAttribute=\"centerX\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"centerX\" id=\"PWx-KW-Z4o\"/>\n                            <constraint firstItem=\"t8Z-Pu-wcU\" firstAttribute=\"bottom\" secondItem=\"fW5-GL-Rkw\" secondAttribute=\"bottom\" id=\"QeJ-M1-Agt\"/>\n                            <constraint firstItem=\"cdg-2x-04N\" firstAttribute=\"leading\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"leading\" id=\"ReQ-JQ-9ec\"/>\n                            <constraint firstItem=\"fvC-nM-NHm\" firstAttribute=\"top\" secondItem=\"cMl-aC-QBW\" secondAttribute=\"topMargin\" id=\"Rzg-lw-y1f\"/>\n                            <constraint firstItem=\"QgU-LW-Wne\" firstAttribute=\"trailing\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"trailing\" id=\"Scs-D8-1kC\"/>\n                            <constraint firstItem=\"WXm-cx-Mj2\" firstAttribute=\"top\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"top\" id=\"Uac-VW-eBx\"/>\n                            <constraint firstItem=\"fvC-nM-NHm\" firstAttribute=\"leading\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"leading\" id=\"V6x-4l-7UT\"/>\n                            <constraint firstItem=\"scS-39-nDE\" firstAttribute=\"trailing\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"trailing\" id=\"VZc-Pt-UES\"/>\n                            <constraint firstItem=\"scS-39-nDE\" firstAttribute=\"leading\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"leading\" id=\"a6b-3K-IcD\"/>\n                            <constraint firstItem=\"IOs-dt-XUa\" firstAttribute=\"centerX\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"centerX\" id=\"b2a-kk-F0b\"/>\n                            <constraint firstItem=\"t8Z-Pu-wcU\" firstAttribute=\"top\" secondItem=\"cMl-aC-QBW\" secondAttribute=\"top\" id=\"fDn-WZ-8Cc\"/>\n                            <constraint firstItem=\"fW5-GL-Rkw\" firstAttribute=\"top\" secondItem=\"IOs-dt-XUa\" secondAttribute=\"bottom\" constant=\"32\" id=\"j0S-ub-unD\"/>\n                            <constraint firstItem=\"fW5-GL-Rkw\" firstAttribute=\"width\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"width\" id=\"kIm-8i-MUJ\"/>\n                            <constraint firstItem=\"WXm-cx-Mj2\" firstAttribute=\"leading\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"leading\" constant=\"10\" id=\"lLW-ey-6EA\"/>\n                            <constraint firstItem=\"cZW-xP-lCa\" firstAttribute=\"leading\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"leading\" constant=\"-1\" id=\"qV8-bf-c8R\"/>\n                            <constraint firstItem=\"cdg-2x-04N\" firstAttribute=\"trailing\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"trailing\" id=\"sbk-sT-1h4\"/>\n                            <constraint firstItem=\"QgU-LW-Wne\" firstAttribute=\"bottom\" secondItem=\"fW5-GL-Rkw\" secondAttribute=\"top\" id=\"v7h-O3-ikW\"/>\n                            <constraint firstItem=\"biy-MM-eKX\" firstAttribute=\"bottom\" secondItem=\"fW5-GL-Rkw\" secondAttribute=\"top\" constant=\"-32\" id=\"vjd-lg-eLH\"/>\n                            <constraint firstItem=\"37K-X6-4EC\" firstAttribute=\"centerX\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"centerX\" id=\"zCV-aa-mio\"/>\n                            <constraint firstItem=\"37K-X6-4EC\" firstAttribute=\"centerY\" secondItem=\"t8Z-Pu-wcU\" secondAttribute=\"centerY\" id=\"zTe-7S-eJo\"/>\n                        </constraints>\n                    </view>\n                    <extendedEdge key=\"edgesForExtendedLayout\"/>\n                    <simulatedNavigationBarMetrics key=\"simulatedTopBarMetrics\" translucent=\"NO\" prompted=\"NO\"/>\n                    <connections>\n                        <outlet property=\"_2swipeTip\" destination=\"Me3-jh-nJf\" id=\"rVD-Gd-QtM\"/>\n                        <outlet property=\"_borders\" destination=\"cZW-xP-lCa\" id=\"P1s-GI-My9\"/>\n                        <outlet property=\"_bottomBar\" destination=\"fW5-GL-Rkw\" id=\"hu4-zZ-MjF\"/>\n                        <outlet property=\"_bottomBarHeightConstraint\" destination=\"SuG-V2-yni\" id=\"cDA-7s-7nQ\"/>\n                        <outlet property=\"_bottomBarOffsetConstraint\" destination=\"QeJ-M1-Agt\" id=\"7eq-X7-HZw\"/>\n                        <outlet property=\"_bottomUnreadBarYOffsetConstraint\" destination=\"J0Y-Xk-O0Z\" id=\"mmJ-qK-vvJ\"/>\n                        <outlet property=\"_connectingStatus\" destination=\"Lgm-9B-bG7\" id=\"JDh-bT-fUg\"/>\n                        <outlet property=\"_connectingView\" destination=\"HHq-2d-yEd\" id=\"NH2-ao-sp5\"/>\n                        <outlet property=\"_connectingXOffsetConstraint\" destination=\"A49-Jb-UIn\" id=\"6zB-zh-Kfx\"/>\n                        <outlet property=\"_eventActivity\" destination=\"37K-X6-4EC\" id=\"w6Q-8m-TGd\"/>\n                        <outlet property=\"_eventsView\" destination=\"pci-6M-5ag\" id=\"nMo-GO-grI\"/>\n                        <outlet property=\"_eventsViewHeightConstraint\" destination=\"rCT-DO-2FK\" id=\"esC-0s-Uex\"/>\n                        <outlet property=\"_eventsViewOffsetLeftConstraint\" destination=\"05q-ul-QYb\" id=\"edf-DV-pcU\"/>\n                        <outlet property=\"_eventsViewWidthConstraint\" destination=\"Quf-Ug-9cF\" id=\"W99-Oq-ZdB\"/>\n                        <outlet property=\"_globalMsg\" destination=\"Lax-2l-YNN\" id=\"VEd-hO-20y\"/>\n                        <outlet property=\"_globalMsgContainer\" destination=\"cdg-2x-04N\" id=\"1uC-VZ-PK7\"/>\n                        <outlet property=\"_headerActivity\" destination=\"yae-WF-wTK\" id=\"Fyz-aG-4Cg\"/>\n                        <outlet property=\"_loadMoreBacklog\" destination=\"Sya-Jj-2rP\" id=\"960-iI-L2b\"/>\n                        <outlet property=\"_lock\" destination=\"gvD-vL-cXM\" id=\"RI0-KN-ZRd\"/>\n                        <outlet property=\"_mentionTip\" destination=\"biy-MM-eKX\" id=\"B6u-7a-y5b\"/>\n                        <outlet property=\"_serverStatus\" destination=\"sIl-WH-w2W\" id=\"SCA-Bb-sKp\"/>\n                        <outlet property=\"_serverStatusBar\" destination=\"QgU-LW-Wne\" id=\"32D-5d-bWX\"/>\n                        <outlet property=\"_swipeTip\" destination=\"IOs-dt-XUa\" id=\"4xP-HT-6Jh\"/>\n                        <outlet property=\"_titleLabel\" destination=\"YHw-ba-1Ak\" id=\"Ozi-zn-tVP\"/>\n                        <outlet property=\"_titleOffsetXConstraint\" destination=\"0nM-QH-BmQ\" id=\"5DH-Yc-61Y\"/>\n                        <outlet property=\"_titleOffsetYConstraint\" destination=\"NdU-NZ-ojV\" id=\"w7V-qF-FCH\"/>\n                        <outlet property=\"_titleView\" destination=\"nlM-WR-4UV\" id=\"Qxd-kS-1zf\"/>\n                        <outlet property=\"_topUnreadBarYOffsetConstraint\" destination=\"Rzg-lw-y1f\" id=\"af9-uk-T0A\"/>\n                        <outlet property=\"_topicLabel\" destination=\"Pau-R1-cSx\" id=\"hA1-42-nVB\"/>\n                        <outlet property=\"_topicWidthConstraint\" destination=\"XlM-mS-AXU\" id=\"rFn-FH-R0V\"/>\n                        <outlet property=\"_topicXOffsetConstraint\" destination=\"83z-LY-g93\" id=\"k6U-Tq-zj2\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"y4g-wn-AmU\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n                <view contentMode=\"scaleToFill\" id=\"ReW-yj-JrG\" userLabel=\"Backlog Failed View\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"584\" height=\"60\"/>\n                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMaxY=\"YES\"/>\n                    <subviews>\n                        <button opaque=\"NO\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Sya-Jj-2rP\">\n                            <rect key=\"frame\" x=\"12\" y=\"14\" width=\"560\" height=\"32\"/>\n                            <constraints>\n                                <constraint firstAttribute=\"height\" constant=\"32\" id=\"qVw-oi-YgT\"/>\n                            </constraints>\n                            <fontDescription key=\"fontDescription\" type=\"boldSystem\" pointSize=\"15\"/>\n                            <state key=\"normal\" title=\"Load More Backlog\">\n                                <color key=\"titleColor\" red=\"0.19607843459999999\" green=\"0.30980393290000002\" blue=\"0.52156865600000002\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                <color key=\"titleShadowColor\" red=\"0.5\" green=\"0.5\" blue=\"0.5\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                            </state>\n                            <state key=\"highlighted\">\n                                <color key=\"titleColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                            </state>\n                            <connections>\n                                <action selector=\"loadMoreBacklogButtonPressed:\" destination=\"pci-6M-5ag\" eventType=\"touchUpInside\" id=\"iIn-3V-7bC\"/>\n                            </connections>\n                        </button>\n                    </subviews>\n                    <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                    <constraints>\n                        <constraint firstItem=\"Sya-Jj-2rP\" firstAttribute=\"leading\" secondItem=\"ReW-yj-JrG\" secondAttribute=\"leading\" constant=\"12\" id=\"7xx-kt-JiU\"/>\n                        <constraint firstItem=\"Sya-Jj-2rP\" firstAttribute=\"centerX\" secondItem=\"ReW-yj-JrG\" secondAttribute=\"centerX\" id=\"Beh-8s-SIp\"/>\n                        <constraint firstItem=\"Sya-Jj-2rP\" firstAttribute=\"centerY\" secondItem=\"ReW-yj-JrG\" secondAttribute=\"centerY\" id=\"dyI-hO-rHZ\"/>\n                        <constraint firstAttribute=\"trailing\" secondItem=\"Sya-Jj-2rP\" secondAttribute=\"trailing\" constant=\"12\" id=\"o2h-sX-n9c\"/>\n                    </constraints>\n                </view>\n                <tableViewController storyboardIdentifier=\"EventsTableViewController\" id=\"pci-6M-5ag\" customClass=\"EventsTableView\">\n                    <extendedEdge key=\"edgesForExtendedLayout\"/>\n                    <simulatedStatusBarMetrics key=\"simulatedStatusBarMetrics\" statusBarStyle=\"blackOpaque\"/>\n                    <connections>\n                        <outlet property=\"_backlogFailedButton\" destination=\"Sya-Jj-2rP\" id=\"saQ-ds-Wx4\"/>\n                        <outlet property=\"_backlogFailedView\" destination=\"ReW-yj-JrG\" id=\"fCx-Rz-NFh\"/>\n                        <outlet property=\"_bottomHighlightsCountView\" destination=\"2A3-WY-mos\" id=\"gQ4-ph-Yd4\"/>\n                        <outlet property=\"_bottomUnreadArrow\" destination=\"MQi-6s-Aew\" id=\"8Jx-T7-qFY\"/>\n                        <outlet property=\"_bottomUnreadLabel\" destination=\"jfo-ng-UHu\" id=\"XX2-mp-IXe\"/>\n                        <outlet property=\"_bottomUnreadLabelXOffsetConstraint\" destination=\"pD2-km-Kpp\" id=\"FJT-P3-hUk\"/>\n                        <outlet property=\"_bottomUnreadView\" destination=\"scS-39-nDE\" id=\"Ytz-Ch-daX\"/>\n                        <outlet property=\"_delegate\" destination=\"eA9-ra-BSf\" id=\"uGg-vX-v2h\"/>\n                        <outlet property=\"_headerView\" destination=\"tmc-fI-0Xs\" id=\"BFZ-vI-cNO\"/>\n                        <outlet property=\"_loadMoreBacklog\" destination=\"Sya-Jj-2rP\" id=\"YVU-7f-mst\"/>\n                        <outlet property=\"_stickyAvatar\" destination=\"WXm-cx-Mj2\" id=\"RZb-zC-iTA\"/>\n                        <outlet property=\"_stickyAvatarHeightConstraint\" destination=\"zKP-km-Cs5\" id=\"lgb-f8-WPN\"/>\n                        <outlet property=\"_stickyAvatarWidthConstraint\" destination=\"Xg8-nI-bU5\" id=\"0VB-Yo-ymh\"/>\n                        <outlet property=\"_stickyAvatarXOffsetConstraint\" destination=\"lLW-ey-6EA\" id=\"CNi-70-m2S\"/>\n                        <outlet property=\"_stickyAvatarYOffsetConstraint\" destination=\"Uac-VW-eBx\" id=\"MSL-Dc-ffe\"/>\n                        <outlet property=\"_tableView\" destination=\"t8Z-Pu-wcU\" id=\"eMn-Er-9RS\"/>\n                        <outlet property=\"_topHighlightsCountView\" destination=\"NXY-Lp-a7w\" id=\"6Ba-t0-uOx\"/>\n                        <outlet property=\"_topUnreadArrow\" destination=\"nV2-yC-Cav\" id=\"6q1-Dk-Y3g\"/>\n                        <outlet property=\"_topUnreadDismissXOffsetConstraint\" destination=\"FwE-VC-fP9\" id=\"VDN-HX-dZ9\"/>\n                        <outlet property=\"_topUnreadLabel\" destination=\"2eF-8l-jgk\" id=\"2gY-fj-9rU\"/>\n                        <outlet property=\"_topUnreadLabelXOffsetConstraint\" destination=\"L3L-aJ-TBg\" id=\"3jc-vB-Mfk\"/>\n                        <outlet property=\"_topUnreadView\" destination=\"fvC-nM-NHm\" id=\"5aR-Ab-DI7\"/>\n                    </connections>\n                </tableViewController>\n                <view opaque=\"NO\" contentMode=\"scaleToFill\" id=\"HHq-2d-yEd\" userLabel=\"Loading View\" customClass=\"UIControl\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"584\" height=\"40\"/>\n                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                    <subviews>\n                        <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" text=\"Loading\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"14\" preferredMaxLayoutWidth=\"584\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Lgm-9B-bG7\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"10\" width=\"584\" height=\"20\"/>\n                            <fontDescription key=\"fontDescription\" type=\"boldSystem\" pointSize=\"16\"/>\n                            <color key=\"textColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                            <nil key=\"highlightedColor\"/>\n                            <size key=\"shadowOffset\" width=\"0.0\" height=\"0.0\"/>\n                        </label>\n                    </subviews>\n                    <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                    <constraints>\n                        <constraint firstItem=\"Lgm-9B-bG7\" firstAttribute=\"leading\" secondItem=\"HHq-2d-yEd\" secondAttribute=\"leading\" id=\"A49-Jb-UIn\"/>\n                        <constraint firstItem=\"Lgm-9B-bG7\" firstAttribute=\"centerY\" secondItem=\"HHq-2d-yEd\" secondAttribute=\"centerY\" id=\"Dbe-gW-oI5\"/>\n                        <constraint firstAttribute=\"trailing\" secondItem=\"Lgm-9B-bG7\" secondAttribute=\"trailing\" id=\"w1L-4c-oHW\"/>\n                    </constraints>\n                </view>\n                <view opaque=\"NO\" contentMode=\"scaleToFill\" placeholderIntrinsicWidth=\"500\" placeholderIntrinsicHeight=\"40\" id=\"nlM-WR-4UV\" userLabel=\"Title View\" customClass=\"UIControl\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"500\" height=\"40\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMaxY=\"YES\"/>\n                    <subviews>\n                        <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Label\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" preferredMaxLayoutWidth=\"16\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gvD-vL-cXM\" userLabel=\"Lock\">\n                            <rect key=\"frame\" x=\"234\" y=\"11\" width=\"16\" height=\"18\"/>\n                            <constraints>\n                                <constraint firstAttribute=\"height\" constant=\"18\" id=\"Upo-wn-aPb\"/>\n                                <constraint firstAttribute=\"width\" constant=\"16\" id=\"z20-i6-nSP\"/>\n                            </constraints>\n                            <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                            <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                            <nil key=\"highlightedColor\"/>\n                        </label>\n                        <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" text=\"\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"18\" preferredMaxLayoutWidth=\"0.0\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YHw-ba-1Ak\" userLabel=\"Title\">\n                            <rect key=\"frame\" x=\"250\" y=\"9\" width=\"0.0\" height=\"22\"/>\n                            <constraints>\n                                <constraint firstAttribute=\"height\" constant=\"22\" id=\"uQU-3q-ONr\"/>\n                            </constraints>\n                            <fontDescription key=\"fontDescription\" type=\"boldSystem\" pointSize=\"20\"/>\n                            <color key=\"textColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                            <nil key=\"highlightedColor\"/>\n                            <size key=\"shadowOffset\" width=\"0.0\" height=\"0.0\"/>\n                        </label>\n                        <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" text=\"\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"12\" preferredMaxLayoutWidth=\"500\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Pau-R1-cSx\" userLabel=\"Topic\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"31\" width=\"500\" height=\"9\"/>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"500\" id=\"XlM-mS-AXU\"/>\n                            </constraints>\n                            <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                            <color key=\"textColor\" red=\"0.33333333333333331\" green=\"0.33333333333333331\" blue=\"0.33333333333333331\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                            <nil key=\"highlightedColor\"/>\n                            <size key=\"shadowOffset\" width=\"0.0\" height=\"0.0\"/>\n                        </label>\n                    </subviews>\n                    <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                    <constraints>\n                        <constraint firstItem=\"YHw-ba-1Ak\" firstAttribute=\"centerX\" secondItem=\"Pau-R1-cSx\" secondAttribute=\"centerX\" id=\"0nM-QH-BmQ\"/>\n                        <constraint firstItem=\"Pau-R1-cSx\" firstAttribute=\"leading\" secondItem=\"nlM-WR-4UV\" secondAttribute=\"leading\" id=\"83z-LY-g93\"/>\n                        <constraint firstItem=\"gvD-vL-cXM\" firstAttribute=\"trailing\" secondItem=\"YHw-ba-1Ak\" secondAttribute=\"leading\" id=\"AlA-D2-HcQ\"/>\n                        <constraint firstAttribute=\"bottom\" secondItem=\"Pau-R1-cSx\" secondAttribute=\"bottom\" id=\"FOq-lM-rw2\"/>\n                        <constraint firstItem=\"YHw-ba-1Ak\" firstAttribute=\"centerY\" secondItem=\"nlM-WR-4UV\" secondAttribute=\"centerY\" id=\"NdU-NZ-ojV\"/>\n                        <constraint firstItem=\"YHw-ba-1Ak\" firstAttribute=\"width\" relation=\"lessThanOrEqual\" secondItem=\"Pau-R1-cSx\" secondAttribute=\"width\" id=\"cLw-MU-oaT\"/>\n                        <constraint firstItem=\"Pau-R1-cSx\" firstAttribute=\"top\" secondItem=\"YHw-ba-1Ak\" secondAttribute=\"bottom\" id=\"h0d-nR-pvy\"/>\n                        <constraint firstItem=\"gvD-vL-cXM\" firstAttribute=\"centerY\" secondItem=\"YHw-ba-1Ak\" secondAttribute=\"centerY\" id=\"led-gr-zbD\"/>\n                        <constraint firstAttribute=\"trailing\" secondItem=\"Pau-R1-cSx\" secondAttribute=\"trailing\" id=\"q8B-Gf-hPM\"/>\n                    </constraints>\n                    <connections>\n                        <action selector=\"titleAreaPressed:\" destination=\"eA9-ra-BSf\" eventType=\"touchUpInside\" id=\"9bF-vh-2Hg\"/>\n                    </connections>\n                </view>\n                <view contentMode=\"scaleToFill\" id=\"tmc-fI-0Xs\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"64\" height=\"64\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMaxY=\"YES\"/>\n                    <subviews>\n                        <activityIndicatorView opaque=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"750\" verticalHuggingPriority=\"750\" animating=\"YES\" style=\"gray\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"yae-WF-wTK\">\n                            <rect key=\"frame\" x=\"22\" y=\"22\" width=\"20\" height=\"20\"/>\n                        </activityIndicatorView>\n                    </subviews>\n                    <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                    <constraints>\n                        <constraint firstItem=\"yae-WF-wTK\" firstAttribute=\"centerY\" secondItem=\"tmc-fI-0Xs\" secondAttribute=\"centerY\" id=\"RaG-Y5-CUR\"/>\n                        <constraint firstItem=\"yae-WF-wTK\" firstAttribute=\"centerX\" secondItem=\"tmc-fI-0Xs\" secondAttribute=\"centerX\" id=\"vU0-qJ-d6N\"/>\n                    </constraints>\n                </view>\n            </objects>\n            <point key=\"canvasLocation\" x=\"323.4375\" y=\"1086.328125\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <image name=\"accept\" width=\"20\" height=\"20\"/>\n        <image name=\"login_bottom_input\" width=\"288\" height=\"38\"/>\n        <image name=\"login_button\" width=\"288\" height=\"40\"/>\n        <image name=\"login_logo\" width=\"48\" height=\"48\"/>\n        <image name=\"login_only_input\" width=\"288\" height=\"38\"/>\n        <image name=\"login_top_input\" width=\"288\" height=\"39\"/>\n        <image name=\"onepassword-button\" width=\"27\" height=\"27\"/>\n        <image name=\"signup_button\" width=\"288\" height=\"40\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "IRCCloud/OnePasswordExtension.h",
    "content": "//Copyright (c) 2014-2020 AgileBits Inc.\n//\n//Permission is hereby granted, free of charge, to any person obtaining a copy\n//of this software and associated documentation files (the \"Software\"), to deal\n//in the Software without restriction, including without limitation the rights\n//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n//copies of the Software, and to permit persons to whom the Software is\n//furnished to do so, subject to the following conditions:\n//\n//The above copyright notice and this permission notice shall be included in all\n//copies or substantial portions of the Software.\n//\n//THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n//SOFTWARE.\n\n#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n#import <MobileCoreServices/MobileCoreServices.h>\n\n#ifdef __IPHONE_8_0\n#import <WebKit/WebKit.h>\n#endif\n\n#if __has_feature(nullability)\nNS_ASSUME_NONNULL_BEGIN\n#else\n#define nullable\n#define __nullable\n#define nonnull\n#define __nonnull\n#endif\n\n// Login Dictionary keys - Used to get or set the properties of a 1Password Login\n\nFOUNDATION_EXPORT NSString *const AppExtensionURLStringKey;\nFOUNDATION_EXPORT NSString *const AppExtensionUsernameKey;\nFOUNDATION_EXPORT NSString *const AppExtensionPasswordKey;\nFOUNDATION_EXPORT NSString *const AppExtensionTOTPKey;\nFOUNDATION_EXPORT NSString *const AppExtensionTitleKey;\nFOUNDATION_EXPORT NSString *const AppExtensionNotesKey;\nFOUNDATION_EXPORT NSString *const AppExtensionSectionTitleKey;\nFOUNDATION_EXPORT NSString *const AppExtensionFieldsKey;\nFOUNDATION_EXPORT NSString *const AppExtensionReturnedFieldsKey;\nFOUNDATION_EXPORT NSString *const AppExtensionOldPasswordKey;\nFOUNDATION_EXPORT NSString *const AppExtensionPasswordGeneratorOptionsKey;\n\n// Password Generator options - Used to set the 1Password Password Generator options when saving a new Login or when changing the password for for an existing Login\nFOUNDATION_EXPORT NSString *const AppExtensionGeneratedPasswordMinLengthKey;\nFOUNDATION_EXPORT NSString *const AppExtensionGeneratedPasswordMaxLengthKey;\nFOUNDATION_EXPORT NSString *const AppExtensionGeneratedPasswordRequireDigitsKey;\nFOUNDATION_EXPORT NSString *const AppExtensionGeneratedPasswordRequireSymbolsKey;\nFOUNDATION_EXPORT NSString *const AppExtensionGeneratedPasswordForbiddenCharactersKey;\n\n// Errors codes\nFOUNDATION_EXPORT NSString *const AppExtensionErrorDomain;\n\nFOUNDATION_EXPORT NS_ENUM(NSUInteger, AppExtensionErrorCode) {\n    AppExtensionErrorCodeCancelledByUser                    = 0,\n    AppExtensionErrorCodeAPINotAvailable                    = 1,\n    AppExtensionErrorCodeFailedToContactExtension           = 2,\n    AppExtensionErrorCodeFailedToLoadItemProviderData       = 3,\n    AppExtensionErrorCodeCollectFieldsScriptFailed          = 4,\n    AppExtensionErrorCodeFillFieldsScriptFailed             = 5,\n    AppExtensionErrorCodeUnexpectedData                     = 6,\n    AppExtensionErrorCodeFailedToObtainURLStringFromWebView = 7\n};\n\n// Note to creators of libraries or frameworks:\n// If you include this code within your library, then to prevent potential duplicate symbol\n// conflicts for adopters of your library, you should rename the OnePasswordExtension class\n// and associated typedefs. You might to so by adding your own project prefix, e.g.,\n// MyLibraryOnePasswordExtension.\n\ntypedef void (^OnePasswordLoginDictionaryCompletionBlock)(NSDictionary * __nullable loginDictionary, NSError * __nullable error);\ntypedef void (^OnePasswordSuccessCompletionBlock)(BOOL success, NSError * __nullable error);\ntypedef void (^OnePasswordExtensionItemCompletionBlock)(NSExtensionItem * __nullable extensionItem, NSError * __nullable error);\n\n@interface OnePasswordExtension : NSObject\n\n+ (OnePasswordExtension *)sharedExtension;\n\n/*!\n @discussion Determines if the 1Password Extension is available. Allows you to only show the 1Password login button to those\n that can use it. Of course, you could leave the button enabled and educate users about the virtues of strong, unique\n passwords instead :)\n \n @return isAppExtensionAvailable Returns YES if any app that supports the generic `org-appextension-feature-password-management` feature is installed on the device.\n */\n#ifdef __IPHONE_8_0\n- (BOOL)isAppExtensionAvailable NS_EXTENSION_UNAVAILABLE_IOS(\"Not available in an extension. Check if org-appextension-feature-password-management:// URL can be opened by the app.\");\n#else\n- (BOOL)isAppExtensionAvailable;\n#endif\n\n/*!\n Called from your login page, this method will find all available logins for the given URLString.\n \n @discussion 1Password will show all matching Login for the naked domain of the given URLString. For example if the user has an item in your 1Password vault with \"subdomain1.domain.com” as the website and another one with \"subdomain2.domain.com”, and the URLString is \"https://domain.com\", 1Password will show both items.\n \n However, if no matching login is found for \"https://domain.com\", the 1Password Extension will display the \"Show all Logins\" button so that the user can search among all the Logins in the vault. This is especially useful when the user has a login for \"https://olddomain.com\".\n \n After the user selects a login, it is stored into an NSDictionary and given to your completion handler. Use the `Login Dictionary keys` above to\n extract the needed information and update your UI. The completion block is guaranteed to be called on the main thread.\n \n @param URLString For the matching Logins in the 1Password vault.\n \n @param viewController The view controller from which the 1Password Extension is invoked. Usually `self`\n \n @param sender The sender which triggers the share sheet to show. UIButton, UIBarButtonItem or UIView. Can also be nil on iPhone, but not on iPad.\n \n @param completion A completion block called with two parameters loginDictionary and error once completed. The loginDictionary reply parameter that contains the username, password and the One-Time Password if available. The error Reply parameter that is nil if the 1Password Extension has been successfully completed, or it contains error information about the completion failure.\n */\n- (void)findLoginForURLString:(nonnull NSString *)URLString forViewController:(nonnull UIViewController *)viewController sender:(nullable id)sender completion:(nonnull OnePasswordLoginDictionaryCompletionBlock)completion;\n\n/*!\n Create a new login within 1Password and allow the user to generate a new password before saving.\n \n @discussion The provided URLString should be unique to your app or service and be identical to what you pass into the find login method.\n The completion block is guaranteed to be called on the main\n thread.\n \n @param URLString For the new Login to be saved in 1Password.\n \n @param loginDetailsDictionary about the Login to be saved, including custom fields, are stored in an dictionary and given to the 1Password Extension.\n \n @param passwordGenerationOptions The Password generator options represented in a dictionary form.\n \n @param viewController The view controller from which the 1Password Extension is invoked. Usually `self`\n \n @param sender The sender which triggers the share sheet to show. UIButton, UIBarButtonItem or UIView. Can also be nil on iPhone, but not on iPad.\n \n @param completion A completion block which is called with type parameters loginDictionary and error. The loginDictionary reply parameter which contain all the information about the newly saved Login. Use the `Login Dictionary keys` above to extract the needed information and update your UI. For example, updating the UI with the newly generated password lets the user know their action was successful. The error reply parameter that is nil if the 1Password Extension has been successfully completed, or it contains error information about the completion failure.\n */\n- (void)storeLoginForURLString:(nonnull NSString *)URLString loginDetails:(nullable NSDictionary *)loginDetailsDictionary passwordGenerationOptions:(nullable NSDictionary *)passwordGenerationOptions forViewController:(nonnull UIViewController *)viewController sender:(nullable id)sender completion:(nonnull OnePasswordLoginDictionaryCompletionBlock)completion;\n\n/*!\n Change the password for an existing login within 1Password.\n \n @discussion The provided URLString should be unique to your app or service and be identical to what you pass into the find login method. The completion block is guaranteed to be called on the main thread.\n \n 1Password 6 and later:\n The 1Password Extension will display all available the matching Logins for the given URL string. The user can choose which Login item to update. The \"New Login\" button will also be available at all times, in case the user wishes to to create a new Login instead,\n \n 1Password 5:\n These are the three scenarios that are supported:\n 1. A single matching Login is found: 1Password will enter edit mode for that Login and will update its password using the value for AppExtensionPasswordKey.\n 2. More than a one matching Logins are found: 1Password will display a list of all matching Logins. The user must choose which one to update. Once in edit mode, the Login will be updated with the new password.\n 3. No matching login is found: 1Password will create a new Login using the optional fields if available to populate its properties.\n \n @param URLString for the Login to be updated with a new password in 1Password.\n \n @param loginDetailsDictionary about the Login to be saved, including old password and the username, are stored in an dictionary and given to the 1Password Extension.\n \n @param passwordGenerationOptions The Password generator options epresented in a dictionary form.\n \n @param viewController The view controller from which the 1Password Extension is invoked. Usually `self`\n \n @param sender The sender which triggers the share sheet to show. UIButton, UIBarButtonItem or UIView. Can also be nil on iPhone, but not on iPad.\n \n @param completion A completion block which is called with type parameters loginDictionary and error. The loginDictionary reply parameter which contain all the information about the newly updated Login, including the newly generated and the old password. Use the `Login Dictionary keys` above to extract the needed information and update your UI. For example, updating the UI with the newly generated password lets the user know their action was successful. The error reply parameter that is nil if the 1Password Extension has been successfully completed, or it contains error information about the completion failure.\n */\n- (void)changePasswordForLoginForURLString:(nonnull NSString *)URLString loginDetails:(nullable NSDictionary *)loginDetailsDictionary passwordGenerationOptions:(nullable NSDictionary *)passwordGenerationOptions forViewController:(UIViewController *)viewController sender:(nullable id)sender completion:(nonnull OnePasswordLoginDictionaryCompletionBlock)completion;\n\n/*!\n Called from your web view controller, this method will show all the saved logins for the active page in the provided web\n view, and automatically fill the HTML form fields. Supports WKWebView.\n \n @discussion 1Password will show all matching Login for the naked domain of the current website. For example if the user has an item in your 1Password vault with \"subdomain1.domain.com” as the website and another one with \"subdomain2.domain.com”, and the current website is \"https://domain.com\", 1Password will show both items.\n \n However, if no matching login is found for \"https://domain.com\", the 1Password Extension will display the \"New Login\" button so that the user can create a new Login for the current website.\n \n @param webView The web view which displays the form to be filled. The active WKWebView. Must not be nil.\n \n @param viewController The view controller from which the 1Password Extension is invoked. Usually `self`\n \n @param sender The sender which triggers the share sheet to show. UIButton, UIBarButtonItem or UIView. Can also be nil on iPhone, but not on iPad.\n \n @param yesOrNo Boolean flag. If YES is passed only matching Login items will be shown, otherwise the 1Password Extension will also display Credit Cards and Identities.\n \n @param completion Completion block called on completion with parameters success, and error. The success reply parameter that is YES if the 1Password Extension has been successfully completed or NO otherwise. The error reply parameter that is nil if the 1Password Extension has been successfully completed, or it contains error information about the completion failure.\n */\n- (void)fillItemIntoWebView:(nonnull WKWebView *)webView forViewController:(nonnull UIViewController *)viewController sender:(nullable id)sender showOnlyLogins:(BOOL)yesOrNo completion:(nonnull OnePasswordSuccessCompletionBlock)completion;\n\n/*!\n Called in the UIActivityViewController completion block to find out whether or not the user selected the 1Password Extension activity.\n \n @param activityType or the bundle identidier of the selected activity in the share sheet.\n \n @return isOnePasswordExtensionActivityType Returns YES if the selected activity is the 1Password extension, NO otherwise.\n */\n- (BOOL)isOnePasswordExtensionActivityType:(nullable NSString *)activityType;\n\n/*!\n The returned NSExtensionItem can be used to create your own UIActivityViewController. Use `isOnePasswordExtensionActivityType:` and `fillReturnedItems:intoWebView:completion:` in the activity view controller completion block to process the result. The completion block is guaranteed to be called on the main thread.\n \n @param webView The web view which displays the form to be filled. The active WKWebView. Must not be nil.\n \n @param completion Completion block called on completion with extensionItem and error. The extensionItem reply parameter that is contains all the info required by the 1Password extension if has been successfully completed or nil otherwise. The error reply parameter that is nil if the 1Password extension item has been successfully created, or it contains error information about the completion failure.\n */\n- (void)createExtensionItemForWebView:(nonnull WKWebView *)webView completion:(nonnull OnePasswordExtensionItemCompletionBlock)completion;\n\n/*!\n Method used in the UIActivityViewController completion block to fill information into a web view.\n \n @param returnedItems Array which contains the selected activity in the share sheet. Empty array if the share sheet is cancelled by the user.\n @param webView The web view which displays the form to be filled. The active WKWebView. Must not be nil.\n \n @param completion Completion block called on completion with parameters success, and error. The success reply parameter that is YES if the 1Password Extension has been successfully completed or NO otherwise. The error reply parameter that is nil if the 1Password Extension has been successfully completed, or it contains error information about the completion failure.\n */\n- (void)fillReturnedItems:(nullable NSArray *)returnedItems intoWebView:(nonnull WKWebView *)webView completion:(nonnull OnePasswordSuccessCompletionBlock)completion;\n@end\n\n#if __has_feature(nullability)\nNS_ASSUME_NONNULL_END\n#endif\n"
  },
  {
    "path": "IRCCloud/OnePasswordExtension.m",
    "content": "//Copyright (c) 2014-2020 AgileBits Inc.\n//\n//Permission is hereby granted, free of charge, to any person obtaining a copy\n//of this software and associated documentation files (the \"Software\"), to deal\n//in the Software without restriction, including without limitation the rights\n//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n//copies of the Software, and to permit persons to whom the Software is\n//furnished to do so, subject to the following conditions:\n//\n//The above copyright notice and this permission notice shall be included in all\n//copies or substantial portions of the Software.\n//\n//THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n//SOFTWARE.\n\n#import \"OnePasswordExtension.h\"\n\nNSString *const AppExtensionURLStringKey                            = @\"url_string\";\nNSString *const AppExtensionUsernameKey                             = @\"username\";\nNSString *const AppExtensionPasswordKey                             = @\"password\";\nNSString *const AppExtensionTOTPKey                                 = @\"totp\";\nNSString *const AppExtensionTitleKey                                = @\"login_title\";\nNSString *const AppExtensionNotesKey                                = @\"notes\";\nNSString *const AppExtensionSectionTitleKey                         = @\"section_title\";\nNSString *const AppExtensionFieldsKey                               = @\"fields\";\nNSString *const AppExtensionReturnedFieldsKey                       = @\"returned_fields\";\nNSString *const AppExtensionOldPasswordKey                          = @\"old_password\";\nNSString *const AppExtensionPasswordGeneratorOptionsKey             = @\"password_generator_options\";\n\nNSString *const AppExtensionGeneratedPasswordMinLengthKey           = @\"password_min_length\";\nNSString *const AppExtensionGeneratedPasswordMaxLengthKey           = @\"password_max_length\";\nNSString *const AppExtensionGeneratedPasswordRequireDigitsKey       = @\"password_require_digits\";\nNSString *const AppExtensionGeneratedPasswordRequireSymbolsKey      = @\"password_require_symbols\";\nNSString *const AppExtensionGeneratedPasswordForbiddenCharactersKey = @\"password_forbidden_characters\";\n\nNSString *const AppExtensionErrorDomain                             = @\"OnePasswordExtension\";\n\n// Version\n#define VERSION_NUMBER @(185)\nstatic NSString *const AppExtensionVersionNumberKey = @\"version_number\";\n\n// Available App Extension Actions\nstatic NSString *const kUTTypeAppExtensionFindLoginAction = @\"org.appextension.find-login-action\";\nstatic NSString *const kUTTypeAppExtensionSaveLoginAction = @\"org.appextension.save-login-action\";\nstatic NSString *const kUTTypeAppExtensionChangePasswordAction = @\"org.appextension.change-password-action\";\nstatic NSString *const kUTTypeAppExtensionFillWebViewAction = @\"org.appextension.fill-webview-action\";\nstatic NSString *const kUTTypeAppExtensionFillBrowserAction = @\"org.appextension.fill-browser-action\";\n\n// WebView Dictionary keys\nstatic NSString *const AppExtensionWebViewPageFillScript = @\"fillScript\";\nstatic NSString *const AppExtensionWebViewPageDetails = @\"pageDetails\";\n\n@implementation OnePasswordExtension\n\n#pragma mark - Public Methods\n\n+ (OnePasswordExtension *)sharedExtension {\n    static dispatch_once_t onceToken;\n    static OnePasswordExtension *__sharedExtension;\n\n    dispatch_once(&onceToken, ^{\n        __sharedExtension = [OnePasswordExtension new];\n    });\n\n    return __sharedExtension;\n}\n\n- (BOOL)isAppExtensionAvailable {\n    if ([self isSystemAppExtensionAPIAvailable]) {\n        return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@\"org-appextension-feature-password-management://\"]];\n    }\n\n    return NO;\n}\n\n#pragma mark - Native app Login\n\n- (void)findLoginForURLString:(nonnull NSString *)URLString forViewController:(nonnull UIViewController *)viewController sender:(nullable id)sender completion:(nonnull OnePasswordLoginDictionaryCompletionBlock)completion {\n    NSAssert(URLString != nil, @\"URLString must not be nil\");\n    NSAssert(viewController != nil, @\"viewController must not be nil\");\n\n    if (NO == [self isSystemAppExtensionAPIAvailable]) {\n        NSLog(@\"Failed to findLoginForURLString, system API is not available\");\n        if (completion) {\n            completion(nil, [OnePasswordExtension systemAppExtensionAPINotAvailableError]);\n        }\n\n        return;\n    }\n\n    NSDictionary *item = @{ AppExtensionVersionNumberKey: VERSION_NUMBER, AppExtensionURLStringKey: URLString };\n\n    UIActivityViewController *activityViewController = [self activityViewControllerForItem:item viewController:viewController sender:sender typeIdentifier:kUTTypeAppExtensionFindLoginAction];\n    activityViewController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {\n        if (returnedItems.count == 0) {\n            NSError *error = nil;\n            if (activityError) {\n                NSLog(@\"Failed to findLoginForURLString: %@\", activityError);\n                error = [OnePasswordExtension failedToContactExtensionErrorWithActivityError:activityError];\n            }\n            else {\n                error = [OnePasswordExtension extensionCancelledByUserError];\n            }\n\n            if (completion) {\n                completion(nil, error);\n            }\n\n            return;\n        }\n\n        [self processExtensionItem:returnedItems.firstObject completion:^(NSDictionary *itemDictionary, NSError *error) {\n            if (completion) {\n                completion(itemDictionary, error);\n            }\n        }];\n    };\n\n    [viewController presentViewController:activityViewController animated:YES completion:nil];\n}\n\n#pragma mark - New User Registration\n\n- (void)storeLoginForURLString:(nonnull NSString *)URLString loginDetails:(nullable NSDictionary *)loginDetailsDictionary passwordGenerationOptions:(nullable NSDictionary *)passwordGenerationOptions forViewController:(nonnull UIViewController *)viewController sender:(nullable id)sender completion:(nonnull OnePasswordLoginDictionaryCompletionBlock)completion {\n    NSAssert(URLString != nil, @\"URLString must not be nil\");\n    NSAssert(viewController != nil, @\"viewController must not be nil\");\n\n    if (NO == [self isSystemAppExtensionAPIAvailable]) {\n        NSLog(@\"Failed to storeLoginForURLString, system API is not available\");\n        if (completion) {\n            completion(nil, [OnePasswordExtension systemAppExtensionAPINotAvailableError]);\n        }\n\n        return;\n    }\n\n    NSMutableDictionary *newLoginAttributesDict = [NSMutableDictionary new];\n    newLoginAttributesDict[AppExtensionVersionNumberKey] = VERSION_NUMBER;\n    newLoginAttributesDict[AppExtensionURLStringKey] = URLString;\n    [newLoginAttributesDict addEntriesFromDictionary:loginDetailsDictionary];\n    if (passwordGenerationOptions.count > 0) {\n        newLoginAttributesDict[AppExtensionPasswordGeneratorOptionsKey] = passwordGenerationOptions;\n    }\n\n    UIActivityViewController *activityViewController = [self activityViewControllerForItem:newLoginAttributesDict viewController:viewController sender:sender typeIdentifier:kUTTypeAppExtensionSaveLoginAction];\n    activityViewController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {\n        if (returnedItems.count == 0) {\n            NSError *error = nil;\n            if (activityError) {\n                NSLog(@\"Failed to storeLoginForURLString: %@\", activityError);\n                error = [OnePasswordExtension failedToContactExtensionErrorWithActivityError:activityError];\n            }\n            else {\n                error = [OnePasswordExtension extensionCancelledByUserError];\n            }\n\n            if (completion) {\n                completion(nil, error);\n            }\n\n            return;\n        }\n\n        [self processExtensionItem:returnedItems.firstObject completion:^(NSDictionary *itemDictionary, NSError *error) {\n            if (completion) {\n                completion(itemDictionary, error);\n            }\n        }];\n    };\n\n    [viewController presentViewController:activityViewController animated:YES completion:nil];\n}\n\n#pragma mark - Change Password\n\n- (void)changePasswordForLoginForURLString:(nonnull NSString *)URLString loginDetails:(nullable NSDictionary *)loginDetailsDictionary passwordGenerationOptions:(nullable NSDictionary *)passwordGenerationOptions forViewController:(UIViewController *)viewController sender:(nullable id)sender completion:(nonnull OnePasswordLoginDictionaryCompletionBlock)completion {\n    NSAssert(URLString != nil, @\"URLString must not be nil\");\n    NSAssert(viewController != nil, @\"viewController must not be nil\");\n\n    if (NO == [self isSystemAppExtensionAPIAvailable]) {\n        NSLog(@\"Failed to changePasswordForLoginWithUsername, system API is not available\");\n        if (completion) {\n            completion(nil, [OnePasswordExtension systemAppExtensionAPINotAvailableError]);\n        }\n\n        return;\n    }\n\n    NSMutableDictionary *item = [NSMutableDictionary new];\n    item[AppExtensionVersionNumberKey] = VERSION_NUMBER;\n    item[AppExtensionURLStringKey] = URLString;\n    [item addEntriesFromDictionary:loginDetailsDictionary];\n    if (passwordGenerationOptions.count > 0) {\n        item[AppExtensionPasswordGeneratorOptionsKey] = passwordGenerationOptions;\n    }\n\n    UIActivityViewController *activityViewController = [self activityViewControllerForItem:item viewController:viewController sender:sender typeIdentifier:kUTTypeAppExtensionChangePasswordAction];\n\n    activityViewController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {\n        if (returnedItems.count == 0) {\n            NSError *error = nil;\n            if (activityError) {\n                NSLog(@\"Failed to changePasswordForLoginWithUsername: %@\", activityError);\n                error = [OnePasswordExtension failedToContactExtensionErrorWithActivityError:activityError];\n            }\n            else {\n                error = [OnePasswordExtension extensionCancelledByUserError];\n            }\n\n            if (completion) {\n                completion(nil, error);\n            }\n\n            return;\n        }\n\n        [self processExtensionItem:returnedItems.firstObject completion:^(NSDictionary *itemDictionary, NSError *error) {\n            if (completion) {\n                completion(itemDictionary, error);\n            }\n        }];\n    };\n\n    [viewController presentViewController:activityViewController animated:YES completion:nil];\n}\n\n#pragma mark - Web View filling Support\n\n- (void)fillItemIntoWebView:(nonnull WKWebView *)webView forViewController:(nonnull UIViewController *)viewController sender:(nullable id)sender showOnlyLogins:(BOOL)yesOrNo completion:(nonnull OnePasswordSuccessCompletionBlock)completion {\n    NSAssert(webView != nil, @\"webView must not be nil\");\n    NSAssert(viewController != nil, @\"viewController must not be nil\");\n    NSAssert([webView isKindOfClass:[WKWebView class]], @\"webView must be an instance of WKWebView.\");\n\n    [self fillItemIntoWKWebView:webView forViewController:viewController sender:(id)sender showOnlyLogins:yesOrNo completion:^(BOOL success, NSError *error) {\n        if (completion) {\n            completion(success, error);\n        }\n    }];\n}\n\n#pragma mark - Support for custom UIActivityViewControllers\n\n- (BOOL)isOnePasswordExtensionActivityType:(nullable NSString *)activityType {\n    return [@\"com.agilebits.onepassword-ios.extension\" isEqualToString:activityType] || [@\"com.agilebits.beta.onepassword-ios.extension\" isEqualToString:activityType];\n}\n\n- (void)createExtensionItemForWebView:(nonnull WKWebView *)webView completion:(nonnull OnePasswordExtensionItemCompletionBlock)completion {\n    NSAssert(webView != nil, @\"webView must not be nil\");\n    NSAssert([webView isKindOfClass:[WKWebView class]], @\"webView must be an instance of WKWebView.\");\n    \n    [webView evaluateJavaScript:OPWebViewCollectFieldsScript completionHandler:^(NSString *result, NSError *evaluateError) {\n        if (result == nil) {\n            NSLog(@\"1Password Extension failed to collect web page fields: %@\", evaluateError);\n            NSError *failedToCollectFieldsError = [OnePasswordExtension failedToCollectFieldsErrorWithUnderlyingError:evaluateError];\n            if (completion) {\n                if ([NSThread isMainThread]) {\n                    completion(nil, failedToCollectFieldsError);\n                }\n                else {\n                    dispatch_async(dispatch_get_main_queue(), ^{\n                        completion(nil, failedToCollectFieldsError);\n                    });\n                }\n            }\n\n            return;\n        }\n\n        [self createExtensionItemForURLString:webView.URL.absoluteString webPageDetails:result completion:completion];\n    }];\n}\n\n- (void)fillReturnedItems:(nullable NSArray *)returnedItems intoWebView:(nonnull WKWebView *)webView completion:(nonnull OnePasswordSuccessCompletionBlock)completion {\n    NSAssert(webView != nil, @\"webView must not be nil\");\n\n    if (returnedItems.count == 0) {\n        NSError *error = [OnePasswordExtension extensionCancelledByUserError];\n        if (completion) {\n            completion(NO, error);\n        }\n\n        return;\n    }\n\n    [self processExtensionItem:returnedItems.firstObject completion:^(NSDictionary *itemDictionary, NSError *error) {\n        if (itemDictionary.count == 0) {\n            if (completion) {\n                completion(NO, error);\n            }\n\n            return;\n        }\n\n        NSString *fillScript = itemDictionary[AppExtensionWebViewPageFillScript];\n        [self executeFillScript:fillScript inWebView:webView completion:^(BOOL success, NSError *executeFillScriptError) {\n            if (completion) {\n                completion(success, executeFillScriptError);\n            }\n        }];\n    }];\n}\n\n#pragma mark - Private methods\n\n- (BOOL)isSystemAppExtensionAPIAvailable {\n    return [NSExtensionItem class] != nil;\n}\n\n- (void)findLoginIn1PasswordWithURLString:(nonnull NSString *)URLString collectedPageDetails:(nullable NSString *)collectedPageDetails forWebViewController:(nonnull UIViewController *)forViewController sender:(nullable id)sender withWebView:(nonnull WKWebView *)webView showOnlyLogins:(BOOL)yesOrNo completion:(nonnull OnePasswordSuccessCompletionBlock)completion {\n    if ([URLString length] == 0) {\n        NSError *URLStringError = [OnePasswordExtension failedToObtainURLStringFromWebViewError];\n        NSLog(@\"Failed to findLoginIn1PasswordWithURLString: %@\", URLStringError);\n        if (completion) {\n            completion(NO, URLStringError);\n        }\n        return;\n    }\n\n    NSError *jsonError = nil;\n    NSData *data = [collectedPageDetails dataUsingEncoding:NSUTF8StringEncoding];\n    NSDictionary *collectedPageDetailsDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];\n\n    if (collectedPageDetailsDictionary.count == 0) {\n        NSLog(@\"Failed to parse JSON collected page details: %@\", jsonError);\n        if (completion) {\n            completion(NO, jsonError);\n        }\n        return;\n    }\n\n    NSDictionary *item = @{ AppExtensionVersionNumberKey : VERSION_NUMBER, AppExtensionURLStringKey : URLString, AppExtensionWebViewPageDetails : collectedPageDetailsDictionary };\n\n    NSString *typeIdentifier = yesOrNo ? kUTTypeAppExtensionFillWebViewAction  : kUTTypeAppExtensionFillBrowserAction;\n    UIActivityViewController *activityViewController = [self activityViewControllerForItem:item viewController:forViewController sender:sender typeIdentifier:typeIdentifier];\n    activityViewController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {\n        if (returnedItems.count == 0) {\n            NSError *error = nil;\n            if (activityError) {\n                NSLog(@\"Failed to findLoginIn1PasswordWithURLString: %@\", activityError);\n                error = [OnePasswordExtension failedToContactExtensionErrorWithActivityError:activityError];\n            }\n            else {\n                error = [OnePasswordExtension extensionCancelledByUserError];\n            }\n\n            if (completion) {\n                completion(NO, error);\n            }\n\n            return;\n        }\n\n        [self processExtensionItem:returnedItems.firstObject completion:^(NSDictionary *itemDictionary, NSError *processExtensionItemError) {\n            if (itemDictionary.count == 0) {\n                if (completion) {\n                    completion(NO, processExtensionItemError);\n                }\n\n                return;\n            }\n\n            NSString *fillScript = itemDictionary[AppExtensionWebViewPageFillScript];\n            [self executeFillScript:fillScript inWebView:webView completion:^(BOOL success, NSError *executeFillScriptError) {\n                if (completion) {\n                    completion(success, executeFillScriptError);\n                }\n            }];\n        }];\n    };\n\n    [forViewController presentViewController:activityViewController animated:YES completion:nil];\n}\n\n- (void)fillItemIntoWKWebView:(nonnull WKWebView *)webView forViewController:(nonnull UIViewController *)viewController sender:(nullable id)sender showOnlyLogins:(BOOL)yesOrNo completion:(nonnull OnePasswordSuccessCompletionBlock)completion {\n    [webView evaluateJavaScript:OPWebViewCollectFieldsScript completionHandler:^(NSString *result, NSError *error) {\n        if (result == nil) {\n            NSLog(@\"1Password Extension failed to collect web page fields: %@\", error);\n            if (completion) {\n                completion(NO,[OnePasswordExtension failedToCollectFieldsErrorWithUnderlyingError:error]);\n            }\n\n            return;\n        }\n\n        [self findLoginIn1PasswordWithURLString:webView.URL.absoluteString collectedPageDetails:result forWebViewController:viewController sender:sender withWebView:webView showOnlyLogins:yesOrNo completion:^(BOOL success, NSError *findLoginError) {\n            if (completion) {\n                completion(success, findLoginError);\n            }\n        }];\n    }];\n}\n\n- (void)executeFillScript:(NSString * __nullable)fillScript inWebView:(nonnull WKWebView *)webView completion:(nonnull OnePasswordSuccessCompletionBlock)completion {\n\n    if (fillScript == nil) {\n        NSLog(@\"Failed to executeFillScript, fillScript is missing\");\n        if (completion) {\n            completion(NO, [OnePasswordExtension failedToFillFieldsErrorWithLocalizedErrorMessage:NSLocalizedStringFromTable(@\"Failed to fill web page because script is missing\", @\"OnePasswordExtension\", @\"1Password Extension Error Message\") underlyingError:nil]);\n        }\n\n        return;\n    }\n\n    NSMutableString *scriptSource = [OPWebViewFillScript mutableCopy];\n    [scriptSource appendFormat:@\"(document, %@, undefined);\", fillScript];\n\n    [webView evaluateJavaScript:scriptSource completionHandler:^(NSString *result, NSError *evaluationError) {\n        BOOL success = (result != nil);\n        NSError *error = nil;\n\n        if (!success) {\n            NSLog(@\"Cannot executeFillScript, evaluateJavaScript failed: %@\", evaluationError);\n            error = [OnePasswordExtension failedToFillFieldsErrorWithLocalizedErrorMessage:NSLocalizedStringFromTable(@\"Failed to fill web page because script could not be evaluated\", @\"OnePasswordExtension\", @\"1Password Extension Error Message\") underlyingError:error];\n        }\n\n        if (completion) {\n            completion(success, error);\n        }\n    }];\n}\n\n- (void)processExtensionItem:(nullable NSExtensionItem *)extensionItem completion:(nonnull OnePasswordLoginDictionaryCompletionBlock)completion {\n    if (extensionItem.attachments.count == 0) {\n        NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @\"Unexpected data returned by App Extension: extension item had no attachments.\" };\n        NSError *error = [[NSError alloc] initWithDomain:AppExtensionErrorDomain code:AppExtensionErrorCodeUnexpectedData userInfo:userInfo];\n        if (completion) {\n            completion(nil, error);\n        }\n        return;\n    }\n\n    NSItemProvider *itemProvider = extensionItem.attachments.firstObject;\n    if (NO == [itemProvider hasItemConformingToTypeIdentifier:(__bridge NSString *)kUTTypePropertyList]) {\n        NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @\"Unexpected data returned by App Extension: extension item attachment does not conform to kUTTypePropertyList type identifier\" };\n        NSError *error = [[NSError alloc] initWithDomain:AppExtensionErrorDomain code:AppExtensionErrorCodeUnexpectedData userInfo:userInfo];\n        if (completion) {\n            completion(nil, error);\n        }\n        return;\n    }\n\n\n    [itemProvider loadItemForTypeIdentifier:(__bridge NSString *)kUTTypePropertyList options:nil completionHandler:^(NSDictionary *itemDictionary, NSError *itemProviderError) {\n         NSError *error = nil;\n         if (itemDictionary.count == 0) {\n             NSLog(@\"Failed to loadItemForTypeIdentifier: %@\", itemProviderError);\n             error = [OnePasswordExtension failedToLoadItemProviderDataErrorWithUnderlyingError:itemProviderError];\n         }\n\n         if (completion) {\n             if ([NSThread isMainThread]) {\n                 completion(itemDictionary, error);\n             }\n             else {\n                 dispatch_async(dispatch_get_main_queue(), ^{\n                     completion(itemDictionary, error);\n                 });\n             }\n         }\n     }];\n}\n\n- (UIActivityViewController *)activityViewControllerForItem:(nonnull NSDictionary *)item viewController:(nonnull UIViewController*)viewController sender:(nullable id)sender typeIdentifier:(nonnull NSString *)typeIdentifier {\n    NSAssert(NO == (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && sender == nil), @\"sender must not be nil on iPad.\");\n\n    NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithItem:item typeIdentifier:typeIdentifier];\n\n    NSExtensionItem *extensionItem = [[NSExtensionItem alloc] init];\n    extensionItem.attachments = @[ itemProvider ];\n\n    UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:@[ extensionItem ]  applicationActivities:nil];\n\n    if ([sender isKindOfClass:[UIBarButtonItem class]]) {\n        controller.popoverPresentationController.barButtonItem = sender;\n    }\n    else if ([sender isKindOfClass:[UIView class]]) {\n        controller.popoverPresentationController.sourceView = [sender superview];\n        controller.popoverPresentationController.sourceRect = [sender frame];\n    }\n    else {\n        NSLog(@\"sender can be nil on iPhone\");\n    }\n\n    return controller;\n}\n\n- (void)createExtensionItemForURLString:(nonnull NSString *)URLString webPageDetails:(nullable NSString *)webPageDetails completion:(nonnull OnePasswordExtensionItemCompletionBlock)completion {\n    NSError *jsonError = nil;\n    NSData *data = [webPageDetails dataUsingEncoding:NSUTF8StringEncoding];\n    NSDictionary *webPageDetailsDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];\n\n    if (webPageDetailsDictionary.count == 0) {\n        NSLog(@\"Failed to parse JSON collected page details: %@\", jsonError);\n        if (completion) {\n            completion(nil, jsonError);\n        }\n        return;\n    }\n\n    NSDictionary *item = @{ AppExtensionVersionNumberKey : VERSION_NUMBER, AppExtensionURLStringKey : URLString, AppExtensionWebViewPageDetails : webPageDetailsDictionary };\n\n    NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithItem:item typeIdentifier:kUTTypeAppExtensionFillBrowserAction];\n\n    NSExtensionItem *extensionItem = [[NSExtensionItem alloc] init];\n    extensionItem.attachments = @[ itemProvider ];\n\n    if (completion) {\n        if ([NSThread isMainThread]) {\n            completion(extensionItem, nil);\n        }\n        else {\n            dispatch_async(dispatch_get_main_queue(), ^{\n                completion(extensionItem, nil);\n            });\n        }\n    }\n}\n\n#pragma mark - Errors\n\n+ (NSError *)systemAppExtensionAPINotAvailableError {\n    NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : NSLocalizedStringFromTable(@\"App Extension API is not available in this version of iOS\", @\"OnePasswordExtension\", @\"1Password Extension Error Message\") };\n    return [NSError errorWithDomain:AppExtensionErrorDomain code:AppExtensionErrorCodeAPINotAvailable userInfo:userInfo];\n}\n\n\n+ (NSError *)extensionCancelledByUserError {\n    NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : NSLocalizedStringFromTable(@\"1Password Extension was cancelled by the user\", @\"OnePasswordExtension\", @\"1Password Extension Error Message\") };\n    return [NSError errorWithDomain:AppExtensionErrorDomain code:AppExtensionErrorCodeCancelledByUser userInfo:userInfo];\n}\n\n+ (NSError *)failedToContactExtensionErrorWithActivityError:(nullable NSError *)activityError {\n    NSMutableDictionary *userInfo = [NSMutableDictionary new];\n    userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@\"Failed to contact the 1Password Extension\", @\"OnePasswordExtension\", @\"1Password Extension Error Message\");\n    if (activityError) {\n        userInfo[NSUnderlyingErrorKey] = activityError;\n    }\n\n    return [NSError errorWithDomain:AppExtensionErrorDomain code:AppExtensionErrorCodeFailedToContactExtension userInfo:userInfo];\n}\n\n+ (NSError *)failedToCollectFieldsErrorWithUnderlyingError:(nullable NSError *)underlyingError {\n    NSMutableDictionary *userInfo = [NSMutableDictionary new];\n    userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@\"Failed to execute script that collects web page information\", @\"OnePasswordExtension\", @\"1Password Extension Error Message\");\n    if (underlyingError) {\n        userInfo[NSUnderlyingErrorKey] = underlyingError;\n    }\n\n    return [NSError errorWithDomain:AppExtensionErrorDomain code:AppExtensionErrorCodeCollectFieldsScriptFailed userInfo:userInfo];\n}\n\n+ (NSError *)failedToFillFieldsErrorWithLocalizedErrorMessage:(nullable NSString *)errorMessage underlyingError:(nullable NSError *)underlyingError {\n    NSMutableDictionary *userInfo = [NSMutableDictionary new];\n    if (errorMessage) {\n        userInfo[NSLocalizedDescriptionKey] = errorMessage;\n    }\n    if (underlyingError) {\n        userInfo[NSUnderlyingErrorKey] = underlyingError;\n    }\n\n    return [NSError errorWithDomain:AppExtensionErrorDomain code:AppExtensionErrorCodeFillFieldsScriptFailed userInfo:userInfo];\n}\n\n+ (NSError *)failedToLoadItemProviderDataErrorWithUnderlyingError:(nullable NSError *)underlyingError {\n    NSMutableDictionary *userInfo = [NSMutableDictionary new];\n    userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@\"Failed to parse information returned by 1Password Extension\", @\"OnePasswordExtension\", @\"1Password Extension Error Message\");\n    if (underlyingError) {\n        userInfo[NSUnderlyingErrorKey] = underlyingError;\n    }\n\n    return [[NSError alloc] initWithDomain:AppExtensionErrorDomain code:AppExtensionErrorCodeFailedToLoadItemProviderData userInfo:userInfo];\n}\n\n+ (NSError *)failedToObtainURLStringFromWebViewError {\n    NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : NSLocalizedStringFromTable(@\"Failed to obtain URL String from web view. The web view must be loaded completely when calling the 1Password Extension\", @\"OnePasswordExtension\", @\"1Password Extension Error Message\") };\n    return [NSError errorWithDomain:AppExtensionErrorDomain code:AppExtensionErrorCodeFailedToObtainURLStringFromWebView userInfo:userInfo];\n}\n\n#pragma mark - WebView field collection and filling scripts\n\nstatic NSString *const OPWebViewCollectFieldsScript = @\";(function(document, undefined) {\\\n\\\n    document.addEventListener('input',function(b){!1!==b.isTrusted&&'input'===b.target.tagName.toLowerCase()&&(b.target.dataset['com.agilebits.onepassword.userEdited']='yes')},!0);\\\n(function(b,a,c){a.FieldCollector=new function(){function f(d){return d?d.toString().toLowerCase():''}function e(d,b,a,e){e!==c&&e===a||null===a||a===c||(d[b]=a)}function k(d,b){var a=[];try{a=d.querySelectorAll(b)}catch(J){console.error('[COLLECT FIELDS] @ag_querySelectorAll Exception in selector \\\"'+b+'\\\"')}return a}function m(d){var a,c=[];if(d.labels&&d.labels.length&&0<d.labels.length)c=Array.prototype.slice.call(d.labels);else{d.id&&(c=c.concat(Array.prototype.slice.call(k(b,'label[for='+JSON.stringify(d.id)+\\\n']'))));if(d.name){a=k(b,'label[for='+JSON.stringify(d.name)+']');for(var e=0;e<a.length;e++)-1===c.indexOf(a[e])&&c.push(a[e])}for(a=d;a&&a!=b;a=a.parentNode)'label'===f(a.tagName)&&-1===c.indexOf(a)&&c.push(a)}0===c.length&&(a=d.parentNode,'dd'===a.tagName.toLowerCase()&&null!==a.previousElementSibling&&'dt'===a.previousElementSibling.tagName.toLowerCase()&&c.push(a.previousElementSibling));return 0<c.length?c.map(function(d){return l(r(d))}).join(''):null}function n(d){var a;for(d=d.parentElement||\\\nd.parentNode;d&&'td'!=f(d.tagName);)d=d.parentElement||d.parentNode;if(!d||d===c)return null;a=d.parentElement||d.parentNode;if('tr'!=a.tagName.toLowerCase())return null;a=a.previousElementSibling;if(!a||'tr'!=(a.tagName+'').toLowerCase()||a.cells&&d.cellIndex>=a.cells.length)return null;d=r(a.cells[d.cellIndex]);return d=l(d)}function p(a){return a.options?(a=Array.prototype.slice.call(a.options).map(function(a){var d=a.text,d=d?f(d).replace(/\\\\s/mg,'').replace(/[~`!@$%^&*()\\\\-_+=:;'\\\"\\\\[\\\\]|\\\\\\\\,<.>\\\\/?]/mg,\\\n''):null;return[d?d:null,a.value]}),{options:a}):null}function F(a){switch(f(a.type)){case 'checkbox':return a.checked?'✓':'';case 'hidden':a=a.value;if(!a||'number'!=typeof a.length)return'';254<a.length&&(a=a.substr(0,254)+'...SNIPPED');return a;case 'submit':case 'button':case 'reset':if(''===a.value)return l(r(a))||'';default:return a.value}}function G(a,b){if(-1===['text','password'].indexOf(b.type.toLowerCase())||!(h.test(a.value)||h.test(a.htmlID)||h.test(a.htmlName)||h.test(a.placeholder)||\\\nh.test(a['label-tag'])||h.test(a['label-data'])||h.test(a['label-aria'])))return!1;if(!a.visible)return!0;if('password'==b.type.toLowerCase())return!1;a=b.type;t(b,!0);return a!==b.type}function H(a){var b={};a.forEach(function(a){b[a.opid]=a});return b}function g(a,b){var c=a[b];if('string'==typeof c)return c;a=a.getAttribute(b);return'string'==typeof a?a:null}function z(a){return'input'===a.nodeName.toLowerCase()&&-1===a.type.search(/button|submit|reset|hidden|checkbox/i)}var u={},h=/((\\\\b|_|-)pin(\\\\b|_|-)|password|passwort|kennwort|(\\\\b|_|-)passe(\\\\b|_|-)|contraseña|senha|密码|adgangskode|hasło|wachtwoord)/i;\\\nthis.collect=this.a=function(b,c){u={};var d=b.defaultView?b.defaultView:a,h=b.activeElement,E=Array.prototype.slice.call(k(b,'form')).map(function(a,b){var c={};b='__form__'+b;a.opid=b;c.opid=b;e(c,'htmlName',g(a,'name'));e(c,'htmlID',g(a,'id'));b=g(a,'action');b=new URL(b,window.location.href);e(c,'htmlAction',b?b.href:null);e(c,'htmlMethod',g(a,'method'));return c}),D=Array.prototype.slice.call(v(b)).map(function(a,b){z(a)&&a.hasAttribute('value')&&!a.dataset['com.agilebits.onepassword.initialValue']&&\\\n(a.dataset['com.agilebits.onepassword.initialValue']=a.value);var c={},d='__'+b,q=-1==a.maxLength?999:a.maxLength;if(!q||'number'===typeof q&&isNaN(q))q=999;u[d]=a;a.opid=d;c.opid=d;c.elementNumber=b;e(c,'maxLength',Math.min(q,999),999);c.visible=w(a);c.viewable=x(a);e(c,'htmlID',g(a,'id'));e(c,'htmlName',g(a,'name'));e(c,'htmlClass',g(a,'class'));e(c,'tabindex',g(a,'tabindex'));e(c,'title',g(a,'title'));e(c,'userEdited',!!a.dataset['com.agilebits.onepassword.userEdited']);if('hidden'!=f(a.type)){e(c,\\\n'label-tag',m(a));e(c,'label-data',g(a,'data-label'));e(c,'label-aria',g(a,'aria-label'));e(c,'label-top',n(a));b=[];for(d=a;d&&d.nextSibling;){d=d.nextSibling;if(y(d))break;A(b,d)}e(c,'label-right',b.join(''));b=[];B(a,b);b=b.reverse().join('');e(c,'label-left',b);e(c,'placeholder',g(a,'placeholder'))}e(c,'rel',g(a,'rel'));e(c,'type',f(g(a,'type')));e(c,'value',F(a));e(c,'checked',a.checked,!1);e(c,'autoCompleteType',a.getAttribute('x-autocompletetype')||a.getAttribute('autocompletetype')||a.getAttribute('autocomplete'),\\\n'off');e(c,'disabled',a.disabled);e(c,'readonly',a.c||a.readOnly);e(c,'selectInfo',p(a));e(c,'aria-hidden','true'==a.getAttribute('aria-hidden'),!1);e(c,'aria-disabled','true'==a.getAttribute('aria-disabled'),!1);e(c,'aria-haspopup','true'==a.getAttribute('aria-haspopup'),!1);e(c,'data-unmasked',a.dataset.unmasked);e(c,'data-stripe',g(a,'data-stripe'));e(c,'data-braintree-name',g(a,'data-braintree-name'));e(c,'onepasswordFieldType',a.dataset.onepasswordFieldType||a.type);e(c,'onepasswordDesignation',\\\na.dataset.onepasswordDesignation);e(c,'onepasswordSignInUrl',a.dataset.onepasswordSignInUrl);e(c,'onepasswordSectionTitle',a.dataset.onepasswordSectionTitle);e(c,'onepasswordSectionFieldKind',a.dataset.onepasswordSectionFieldKind);e(c,'onepasswordSectionFieldTitle',a.dataset.onepasswordSectionFieldTitle);e(c,'onepasswordSectionFieldValue',a.dataset.onepasswordSectionFieldValue);a.form&&(c.form=g(a.form,'opid'));e(c,'fakeTested',G(c,a),!1);return c});D.filter(function(a){return a.fakeTested}).forEach(function(a){var b=\\\nu[a.opid];b.getBoundingClientRect();var c=b.value;t(b,!1);b.dispatchEvent(C(b,'keydown'));b.dispatchEvent(C(b,'keypress'));b.dispatchEvent(C(b,'keyup'));if(''===b.value||b.dataset['com.agilebits.onepassword.initialValue']&&b.value===b.dataset['com.agilebits.onepassword.initialValue'])b.value=c;b.click&&b.click();a.postFakeTestVisible=w(b);a.postFakeTestViewable=x(b);a.postFakeTestType=b.type;a=b.value;var c=b.ownerDocument.createEvent('HTMLEvents'),d=b.ownerDocument.createEvent('HTMLEvents');b.dispatchEvent(C(b,\\\n'keydown'));b.dispatchEvent(C(b,'keypress'));b.dispatchEvent(C(b,'keyup'));d.initEvent('input',!0,!0);b.dispatchEvent(d);c.initEvent('change',!0,!0);b.dispatchEvent(c);b.blur();if(''===b.value||b.dataset['com.agilebits.onepassword.initialValue']&&b.value===b.dataset['com.agilebits.onepassword.initialValue'])b.value=a});c={documentUUID:c,title:b.title,url:d.location.href,documentURL:b.location.href,forms:H(E),fields:D,collectedTimestamp:(new Date).getTime()};(b=b.querySelector('[data-onepassword-title]'))&&\\\nb.dataset.onepasswordTitle&&(c.displayTitle=b.dataset.onepasswordTitle);h&&z(h)&&t(h,!0);return c};this.elementForOPID=this.b=function(a){return u[a]}}})(document,window,void 0);document.elementForOPID=I;function C(b,a){var c;c=b.ownerDocument.createEvent('Events');c.initEvent(a,!0,!1);c.charCode=0;c.keyCode=0;c.which=0;c.srcElement=b;c.target=b;return c}window.LOGIN_TITLES=[/^\\\\W*log\\\\W*[oi]n\\\\W*$/i,/log\\\\W*[oi]n (?:securely|now)/i,/^\\\\W*sign\\\\W*[oi]n\\\\W*$/i,'continue','submit','weiter','accès','вход','connexion','entrar','anmelden','accedi','valider','登录','लॉग इन करें'];window.CHANGE_PASSWORD_TITLES=[/^(change|update) password$/i,'save changes','update'];\\\nwindow.LOGIN_RED_HERRING_TITLES=['already have an account','sign in with'];window.REGISTER_TITLES=['register','sign up','signup','join',/^create (my )?(account|profile)$/i,'регистрация','inscription','regístrate','cadastre-se','registrieren','registrazione','注册','साइन अप करें'];window.SEARCH_TITLES='search find поиск найти искать recherche suchen buscar suche ricerca procurar 検索'.split(' ');window.FORGOT_PASSWORD_TITLES='forgot geändert vergessen hilfe changeemail español'.split(' ');\\\nwindow.REMEMBER_ME_TITLES=['remember me','rememberme','keep me signed in'];window.BACK_TITLES=['back','назад'];window.DIVITIS_BUTTON_CLASSES=['button','btn-primary'];function r(b){return b.textContent||b.innerText}function l(b){var a=null;b&&(a=b.replace(/^\\\\s+|\\\\s+$|\\\\r?\\\\n.*$/mg,'').replace(/\\\\s{2,}/,' '),a=0<a.length?a:null);return a}function A(b,a){var c='';3===a.nodeType?c=a.nodeValue:1===a.nodeType&&(c=r(a));(a=l(c))&&b.push(a)}\\\nfunction y(b){var a;b&&void 0!==b?(a='select option input form textarea button table iframe body head script'.split(' '),b?(b=b?(b.tagName||'').toLowerCase():'',a=a.constructor==Array?0<=a.indexOf(b):b===a):a=!1):a=!0;return a}\\\nfunction B(b,a,c){var f;for(c||(c=0);b&&b.previousSibling;){b=b.previousSibling;if(y(b))return;A(a,b)}if(b&&0===a.length){for(f=null;!f;){b=b.parentElement||b.parentNode;if(!b)return;for(f=b.previousSibling;f&&!y(f)&&f.lastChild;)f=f.lastChild}y(f)||(A(a,f),0===a.length&&B(f,a,c+1))}}\\\nfunction w(b){for(var a=b,c=(b=b.ownerDocument)?b.defaultView:{},f;a&&a!==b;){f=c.getComputedStyle&&a instanceof Element?c.getComputedStyle(a,null):a.style;if(!f)return!0;if('none'===f.display||'hidden'==f.visibility)return!1;a=a.parentNode}return a===b}\\\nfunction x(b){var a=b.ownerDocument.documentElement,c=b.getBoundingClientRect(),f=a.scrollWidth,e=a.scrollHeight,k=c.left-a.clientLeft,a=c.top-a.clientTop,m;if(!w(b)||!b.offsetParent||10>b.clientWidth||10>b.clientHeight)return!1;var n=b.getClientRects();if(0===n.length)return!1;for(var p=0;p<n.length;p++)if(m=n[p],m.left>f||0>m.right)return!1;if(0>k||k>f||0>a||a>e)return!1;for(c=b.ownerDocument.elementFromPoint(k+(c.right>window.innerWidth?(window.innerWidth-k)/2:c.width/2),a+(c.bottom>window.innerHeight?\\\n(window.innerHeight-a)/2:c.height/2));c&&c!==b&&c!==document;){if(c.tagName&&'string'===typeof c.tagName&&'label'===c.tagName.toLowerCase()&&b.labels&&0<b.labels.length)return 0<=Array.prototype.slice.call(b.labels).indexOf(c);c=c.parentNode}return c===b}\\\nfunction I(b){var a;if(void 0===b||null===b)return null;if(a=FieldCollector.b(b))return a;try{var c=Array.prototype.slice.call(v(document)),f=c.filter(function(a){return a.opid==b});if(0<f.length)a=f[0],1<f.length&&console.warn('More than one element found with opid '+b);else{var e=parseInt(b.split('__')[1],10);isNaN(e)||(a=c[e])}}catch(k){console.error('An unexpected error occurred: '+k)}finally{return a}};function v(b){var a=[];try{a=b.querySelectorAll('input, select, button')}catch(c){console.error('[COMMON] @ag_querySelectorAll Exception in selector \\\"input, select, button\\\"')}return a}function t(b,a){if(b){var c;a&&(c=b.value);'function'===typeof b.click&&b.click();'function'===typeof b.focus&&b.focus();a&&b.value!==c&&(b.value=c)}};\\\n    \\\n    return JSON.stringify(FieldCollector.a(document, 'oneshotUUID'));\\\n})(document);\\\n\\\n\";\n\nstatic NSString *const OPWebViewFillScript = @\";(function(document, fillScript, undefined) {\\\n\\\n    var g=!0,h=!0,k=!0;function m(a){return a?0===a.indexOf('https://')&&'http:'===document.location.protocol&&(a=document.querySelectorAll('input[type=password]'),0<a.length&&(confirmResult=confirm('1Password warning: This is an unsecured HTTP page, and any information you submit can potentially be seen and changed by others. This Login was originally saved on a secure (HTTPS) page.\\\\n\\\\nDo you still wish to fill this login?'),0==confirmResult))?!0:!1:!1}\\\nfunction l(a){var b,c=[],d=a.properties,e=1,f=[];d&&d.delay_between_operations&&(e=d.delay_between_operations);if(!m(a.savedURL)){var r=function(a,b){var c=a[0];if(void 0===c)b();else{if('delay'===c.operation||'delay'===c[0])e=c.parameters?c.parameters[0]:c[1];else if(c=n(c))for(var d=0;d<c.length;d++)-1===f.indexOf(c[d])&&f.push(c[d]);setTimeout(function(){r(a.slice(1),b)},e)}};g=k=!0;if(b=a.options)b.hasOwnProperty('animate')&&(h=b.animate),b.hasOwnProperty('markFilling')&&(g=b.markFilling);if((b=\\\na.metadata)&&b.hasOwnProperty('action'))switch(b.action){case 'fillPassword':g=!1;break;case 'fillLogin':k=!1}a.hasOwnProperty('script')&&r(a.script,function(){a.hasOwnProperty('autosubmit')&&'function'==typeof autosubmit&&(a.itemType&&'fillLogin'!==a.itemType||(0<f.length?setTimeout(function(){autosubmit(a.autosubmit,d.allow_clicky_autosubmit,f)},AUTOSUBMIT_DELAY):DEBUG_AUTOSUBMIT&&console.log('[AUTOSUBMIT] Not attempting to submit since no fields were filled: ',f)));c=f.map(function(a){return a&&\\\na.hasOwnProperty('opid')?a.opid:null});'object'==typeof protectedGlobalPage&&protectedGlobalPage.c('fillItemResults',{documentUUID:documentUUID,fillContextIdentifier:a.fillContextIdentifier,usedOpids:c},function(){fillingItemType=null})})}}var y={fill_by_opid:p,fill_by_query:q,click_on_opid:t,click_on_query:u,touch_all_fields:v,simple_set_value_by_query:w,focus_by_opid:x,delay:null};\\\nfunction n(a){var b;if(a.hasOwnProperty('operation')&&a.hasOwnProperty('parameters'))b=a.operation,a=a.parameters;else if('[object Array]'===Object.prototype.toString.call(a))b=a[0],a=a.splice(1);else return null;return y.hasOwnProperty(b)?y[b].apply(this,a):null}function p(a,b){return(a=z(a))?(A(a,b),[a]):null}function q(a,b){a=B(a);return Array.prototype.map.call(Array.prototype.slice.call(a),function(a){A(a,b);return a},this)}\\\nfunction w(a,b){var c=[];a=B(a);Array.prototype.forEach.call(Array.prototype.slice.call(a),function(a){a.disabled||a.a||a.readOnly||void 0===a.value||(a.value=b,c.push(a))});return c}function x(a){(a=z(a))&&C(a,!0);return null}function t(a){return(a=z(a))?C(a,!1)?[a]:null:null}function u(a){a=B(a);return Array.prototype.map.call(Array.prototype.slice.call(a),function(a){C(a,!0);return[a]},this)}function v(){D()};var E={'true':!0,y:!0,1:!0,yes:!0,'✓':!0},F=200;function A(a,b){var c;if(!(!a||null===b||void 0===b||k&&(a.disabled||a.a||a.readOnly)))switch(g&&!a.opfilled&&(a.opfilled=!0,a.form&&(a.form.opfilled=!0)),a.type?a.type.toLowerCase():null){case 'checkbox':c=b&&1<=b.length&&E.hasOwnProperty(b.toLowerCase())&&!0===E[b.toLowerCase()];a.checked===c||G(a,function(a){a.checked=c});break;case 'radio':!0===E[b.toLowerCase()]&&a.click();break;default:a.value==b||G(a,function(a){a.value=b})}}\\\nfunction G(a,b){H(a);b(a);I(a);J(a)&&(a.className+=' com-agilebits-onepassword-extension-animated-fill',setTimeout(function(){a&&a.className&&(a.className=a.className.replace(/(\\\\s)?com-agilebits-onepassword-extension-animated-fill/,''))},F))};document.elementForOPID=z;function K(a,b){var c;c=a.ownerDocument.createEvent('Events');c.initEvent(b,!0,!1);c.charCode=0;c.keyCode=0;c.which=0;c.srcElement=a;c.target=a;return c}function H(a){var b=a.value;C(a,!1);a.dispatchEvent(K(a,'keydown'));a.dispatchEvent(K(a,'keypress'));a.dispatchEvent(K(a,'keyup'));if(''===a.value||a.dataset['com.agilebits.onepassword.initialValue']&&a.value===a.dataset['com.agilebits.onepassword.initialValue'])a.value=b}\\\nfunction I(a){var b=a.value,c=a.ownerDocument.createEvent('HTMLEvents'),d=a.ownerDocument.createEvent('HTMLEvents');a.dispatchEvent(K(a,'keydown'));a.dispatchEvent(K(a,'keypress'));a.dispatchEvent(K(a,'keyup'));d.initEvent('input',!0,!0);a.dispatchEvent(d);c.initEvent('change',!0,!0);a.dispatchEvent(c);a.blur();if(''===a.value||a.dataset['com.agilebits.onepassword.initialValue']&&a.value===a.dataset['com.agilebits.onepassword.initialValue'])a.value=b}\\\nfunction L(){var a=/((\\\\b|_|-)pin(\\\\b|_|-)|password|passwort|kennwort|passe|contraseña|senha|密码|adgangskode|hasło|wachtwoord)/i;return Array.prototype.slice.call(B(\\\"input[type='text']\\\")).filter(function(b){return b.value&&a.test(b.value)},this)}function D(){L().forEach(function(a){H(a);a.click&&a.click();I(a)})}\\\nwindow.LOGIN_TITLES=[/^\\\\W*log\\\\W*[oi]n\\\\W*$/i,/log\\\\W*[oi]n (?:securely|now)/i,/^\\\\W*sign\\\\W*[oi]n\\\\W*$/i,'continue','submit','weiter','accès','вход','connexion','entrar','anmelden','accedi','valider','登录','लॉग इन करें'];window.CHANGE_PASSWORD_TITLES=[/^(change|update) password$/i,'save changes','update'];window.LOGIN_RED_HERRING_TITLES=['already have an account','sign in with'];\\\nwindow.REGISTER_TITLES=['register','sign up','signup','join',/^create (my )?(account|profile)$/i,'регистрация','inscription','regístrate','cadastre-se','registrieren','registrazione','注册','साइन अप करें'];window.SEARCH_TITLES='search find поиск найти искать recherche suchen buscar suche ricerca procurar 検索'.split(' ');window.FORGOT_PASSWORD_TITLES='forgot geändert vergessen hilfe changeemail español'.split(' ');window.REMEMBER_ME_TITLES=['remember me','rememberme','keep me signed in'];\\\nwindow.BACK_TITLES=['back','назад'];window.DIVITIS_BUTTON_CLASSES=['button','btn-primary'];function J(a){var b;if(b=h)a:{b=a;for(var c=a.ownerDocument,d=c?c.defaultView:{},e;b&&b!==c;){e=d.getComputedStyle&&b instanceof Element?d.getComputedStyle(b,null):b.style;if(!e){b=!0;break a}if('none'===e.display||'hidden'==e.visibility){b=!1;break a}b=b.parentNode}b=b===c}return b?-1!=='email text password number tel url'.split(' ').indexOf(a.type||''):!1}\\\nfunction z(a){var b;if(void 0===a||null===a)return null;if(b=FieldCollector.b(a))return b;try{var c=Array.prototype.slice.call(B('input, select, button')),d=c.filter(function(b){return b.opid==a});if(0<d.length)b=d[0],1<d.length&&console.warn('More than one element found with opid '+a);else{var e=parseInt(a.split('__')[1],10);isNaN(e)||(b=c[e])}}catch(f){console.error('An unexpected error occurred: '+f)}finally{return b}};function B(a){var b=document,c=[];try{c=b.querySelectorAll(a)}catch(d){console.error('[COMMON] @ag_querySelectorAll Exception in selector \\\"'+a+'\\\"')}return c}function C(a,b){if(!a)return!1;var c;b&&(c=a.value);'function'===typeof a.click&&a.click();'function'===typeof a.focus&&a.focus();b&&a.value!==c&&(a.value=c);return'function'===typeof a.click||'function'===typeof a.focus};\\\n\\\n    l(fillScript);\\\n    return JSON.stringify({'success': true});\\\n})\\\n\\\n\";\n\n@end\n"
  },
  {
    "path": "IRCCloud/Resources/EnterpriseImages.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"iOS7-Notifications@2x-1.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"iOS7-Notifications@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"iOS7-Settings.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"iOS7-Settings@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"iOS7-Settings@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"iOS7-Spotlight@2x-1.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"iOS7-Spotlight@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"57x57\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"57x57\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"iOS7-iPhone@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"iOS7-iPhone@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"iOS7-Notifications.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"iOS7-Notifications@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"iOS7-Settings-1.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"iOS7-Settings@2x-1.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"iOS7-Spotlight.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"iOS7-Spotlight@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"50x50\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-Small-50.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"50x50\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-Small-50@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"72x72\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-72.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"72x72\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-72@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"iOS7-iPad.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"iOS7-iPad@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"83.5x83.5\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"iOS9-iPadPro.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"1024x1024\",\n      \"idiom\" : \"ios-marketing\",\n      \"filename\" : \"AppStore.png\",\n      \"scale\" : \"1x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  },\n  \"properties\" : {\n    \"pre-rendered\" : true\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/EnterpriseImages.xcassets/LaunchImage.launchimage/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"736h\",\n      \"filename\" : \"Retina HD 5.5 iOS 8 @3x-1.png\",\n      \"minimum-system-version\" : \"8.0\",\n      \"orientation\" : \"portrait\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"736h\",\n      \"filename\" : \"Retina HD 5.5 iOS 8 @3x.png\",\n      \"minimum-system-version\" : \"8.0\",\n      \"orientation\" : \"landscape\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"667h\",\n      \"filename\" : \"Retina HD 4.7 iOS 8 @2x.png\",\n      \"minimum-system-version\" : \"8.0\",\n      \"orientation\" : \"portrait\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @2x@2x-1.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"retina4\",\n      \"filename\" : \"Retina 4 iOS 5,6 @2x + iOS 7,8 @2x.png\",\n      \"minimum-system-version\" : \"7.0\",\n      \"orientation\" : \"portrait\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x-2.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x-1.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x@2x-2.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"extent\" : \"full-screen\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @2x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"extent\" : \"full-screen\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @2x@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"extent\" : \"full-screen\",\n      \"filename\" : \"Retina 4 iOS 5,6 @2x + iOS 7,8 @2x-1.png\",\n      \"subtype\" : \"retina4\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"to-status-bar\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x (no sidebar).png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x-3.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"to-status-bar\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x no sidebar.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"to-status-bar\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x (no sidebar)@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x@2x-3.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"to-status-bar\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x no sidebar@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"filename\" : \"iOS 5,6 @1x @2x + iOS 7,8 @1x @2x@2x-1.png\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/EnterpriseLogo.xcassets/login_logo.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"login_logo_enterprise.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"login_logo_enterprise@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"login_logo_enterprise@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/accept.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"accept.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"accept@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"accept@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/login_bottom_input.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"login_bottom_input.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"login_bottom_input@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"login_bottom_input@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/login_button.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"login_button.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"login_button@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"login_button@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/login_mid_input.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"login_mid_input.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"login_mid_input@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"login_mid_input@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/login_only_input.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"login_only_input.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"login_only_input@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"login_only_input@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/login_top_input.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"login_top_input.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"login_top_input@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"login_top_input@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/menu.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"menu.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"menu@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"menu@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/send_fail.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"send_fail.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"send_fail@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"send_fail@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/settings.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"settings.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"settings@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"settings@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/signup_button.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"signup_button.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"signup_button@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"signup_button@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/tip_bg.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"tip_bg.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"tip_bg@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"tip_bg@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/upload_arrow.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"upload_arrow.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"upload_arrow@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"upload_arrow@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Icons.xcassets/users.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"users.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"users@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"users@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Images.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"filename\" : \"AppStore.png\",\n      \"idiom\" : \"universal\",\n      \"platform\" : \"ios\",\n      \"size\" : \"1024x1024\"\n    },\n    {\n      \"appearances\" : [\n        {\n          \"appearance\" : \"luminosity\",\n          \"value\" : \"dark\"\n        }\n      ],\n      \"filename\" : \"Dark Icon.png\",\n      \"idiom\" : \"universal\",\n      \"platform\" : \"ios\",\n      \"size\" : \"1024x1024\"\n    },\n    {\n      \"appearances\" : [\n        {\n          \"appearance\" : \"luminosity\",\n          \"value\" : \"tinted\"\n        }\n      ],\n      \"idiom\" : \"universal\",\n      \"platform\" : \"ios\",\n      \"size\" : \"1024x1024\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "IRCCloud/Resources/Images.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/Logo.xcassets/login_logo.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\",\n      \"filename\" : \"login_logo.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\",\n      \"filename\" : \"login_logo@2x.png\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\",\n      \"filename\" : \"login_logo@3x.png\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "IRCCloud/Resources/en.lproj/Localizable.strings",
    "content": "/* \n  Localizable.strings\n  IRCCloud\n\n  Created by Sam Steele on 5/15/13.\n  Copyright (c) 2013 IRCCloud, Ltd. All rights reserved.\n*/\n\n\"NA_MSG\"  = \"Reply\";\n\"N_MSGCH\" = \"‹%@› %@ (%@)\";\n\"N_SMSGCH\" = \"%@ (%@)\";\n\"N_MSG\"   = \"‹%@› %@ (%@)\";\n\"N_SMSG\"  = \"%@ (%@)\";\n\"N_MECH\"  = \"— %@ %@ (%@)\";\n\"N_ME\"    = \"— %@ %@ (%@)\";\n\"N_CHI\"   = \"%@ invited you to join %@\";\n\"N_CI\"    = \"%@ is trying to contact you on %@\";\n"
  },
  {
    "path": "IRCCloud/Resources/licenses.txt",
    "content": "IRCCloud\nCopyright (C) 2022 IRCCloud, Ltd.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nSBJson\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\nUnittWebSocketClient\nCopyright 2011 UnitT Software. All rights reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not\nuse this file except in compliance with the License. You may obtain a copy of\nthe License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\nWARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\nLicense for the specific language governing permissions and limitations under\nthe License.\n\nECSlidingViewController\nCopyright (C) 2013 EdgeCase\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\nUIExpandingTextView\nCopyright 2011 Brandon Hamilton.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\nOpenInFirefoxClient\nThis Source Code Form is subject to the terms of the Mozilla Public\nLicense, v. 2.0. If a copy of the MPL was not distributed with this\nfile, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nOpenInChrome\nCopyright 2013, Google Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n    * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,           \nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY           \nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nARChromeActivity\nCopyright (c) 2012 Alex Robinson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nTUSafariActivity:\nCopyright (c) 2012 ThinkUltimate (http://thinkultimate.com).\n\nhttp://github.com/davbeck/TUSafariActivity\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n- Redistributions of source code must retain the above copyright notice,\nthis list of conditions and the following disclaimer.\n- Redistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation\nand/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\nOF THE POSSIBILITY OF SUCH DAMAGE.\n\nURL Regex pattern\nCopyright (C) 2007 The Android Open Source Project\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nNSURL+IDN.m\n\nCreated by Jorge Bernal on 4/8/11.\nAdapted from OmniNetworking framework\n\nCopyright 1997-2005 Omni Development, Inc.  All rights reserved.\n\nThis software may only be used and reproduced according to the\nterms in the file OmniSourceLicense.html, which should be\ndistributed with this project and can also be found at\n<http://www.omnigroup.com/developer/sourcecode/sourcelicense/>\n\nSSZipArchive\n\nCopyright (c) 2010-2015, Sam Soffes, http://soff.es\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nCSURITemplate\n\nCreated by Will Harris on 26/02/2013.\nCopyright (c) 2013 Cogenta Systems Ltd. All rights reserved.\n\nYTPlayerView\nCopyright 2014 Google Inc. All rights reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nHack Copyright 2015, Christopher Simpkins with Reserved Font Name \"Hack\".\n\nBitstream Vera Sans Mono Copyright 2003 Bitstream Inc. and licensed under the Bitstream Vera License with Reserved Font Names \"Bitstream\" and \"Vera\"\n\nDejaVu modifications of the original Bitstream Vera Sans Mono typeface have been committed to the public domain.\n\nThis Font Software is licensed under the Hack Open Font License v2.0 and the Bitstream Vera License.\n\nHack Open Font License v2.0\n\n(Version 1.0 - 06 September 2015)\n\n(Version 2.0 - 27 September 2015)\n\nCopyright 2015 by Christopher Simpkins. All Rights Reserved.\n\nDEFINITIONS\n\n\"Author\" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.\n\nPERMISSION AND CONDITIONS\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license (\"Fonts\") and associated source code, documentation, and binary files (the \"Font Software\"), to reproduce and distribute the modifications to the Bitstream Vera Font Software, including without limitation the rights to use, study, copy, merge, embed, modify, redistribute, and/or sell modified or unmodified copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:\n\n(1) The above copyright notice and this permission notice shall be included in all modified and unmodified copies of the Font Software typefaces. These notices can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.\n\n(2) The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing the word \"Hack\".\n\n(3) Neither the Font Software nor any of its individual components, in original or modified versions, may be sold by itself.\n\nTERMINATION\n\nThis license becomes null and void if any of the above conditions are not met.\n\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.\n\nExcept as contained in this notice, the names of Christopher Simpkins and the Author(s) of the Font Software shall not be used to promote, endorse or advertise any modified version, except to acknowledge the contribution(s) of Christopher Simpkins and the Author(s) or with their explicit written permission. For further information, contact: chris at sourcefoundry dot org.\n\nBITSTREAM VERA LICENSE\n\nCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license (\"Fonts\") and associated documentation files (the \"Font Software\"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:\n\nThe above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces.\n\nThe Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words \"Bitstream\" or the word \"Vera\".\n\nThis License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the \"Bitstream Vera\" names.\n\nThe Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.\n\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.\n\nExcept as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.\n\nTrustKit\nCopyright (c) 2015 Data Theorem, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\nYYImage\nCopyright (c) 2015 ibireme <ibireme@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\nNSString+Score\nCopyright (c) 2011 Involved Pty Ltd. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "IRCCloud/UIExpandingTextView.h",
    "content": "/*\n *  UIExpandingTextView.h\n *  \n *  Created by Brandon Hamilton on 2011/05/03.\n *  Copyright 2011 Brandon Hamilton.\n *  \n *  Permission is hereby granted, free of charge, to any person obtaining a copy\n *  of this software and associated documentation files (the \"Software\"), to deal\n *  in the Software without restriction, including without limitation the rights\n *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n *  copies of the Software, and to permit persons to whom the Software is\n *  furnished to do so, subject to the following conditions:\n *  \n *  The above copyright notice and this permission notice shall be included in\n *  all copies or substantial portions of the Software.\n *  \n *  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n *  THE SOFTWARE.\n */\n\n#import <UIKit/UIKit.h>\n#import \"UIExpandingTextViewInternal.h\"\n\n@class UIExpandingTextView;\n\n@protocol UIExpandingTextViewDelegate\n\n@optional\n- (BOOL)expandingTextViewShouldBeginEditing:(UIExpandingTextView *)expandingTextView;\n- (BOOL)expandingTextViewShouldEndEditing:(UIExpandingTextView *)expandingTextView;\n\n- (void)expandingTextViewDidBeginEditing:(UIExpandingTextView *)expandingTextView;\n- (void)expandingTextViewDidEndEditing:(UIExpandingTextView *)expandingTextView;\n\n- (BOOL)expandingTextView:(UIExpandingTextView *)expandingTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;\n- (void)expandingTextViewDidChange:(UIExpandingTextView *)expandingTextView;\n\n- (void)expandingTextView:(UIExpandingTextView *)expandingTextView willChangeHeight:(float)height;\n- (void)expandingTextView:(UIExpandingTextView *)expandingTextView didChangeHeight:(float)height;\n\n- (void)expandingTextViewDidChangeSelection:(UIExpandingTextView *)expandingTextView;\n- (BOOL)expandingTextViewShouldReturn:(UIExpandingTextView *)expandingTextView;\n@end\n\n@interface UIExpandingTextView : UIView <UITextViewDelegate> \n{\n    UIExpandingTextViewInternal *internalTextView;\n    UIImageView *textViewBackgroundImage;\n    int minimumHeight;\n\tint maximumHeight;\n    int maximumNumberOfLines;\n\tint minimumNumberOfLines;\n\tBOOL animateHeightChange;\n\t__weak NSObject <UIExpandingTextViewDelegate> *delegate;\n\tNSString *text;\n\tUIFont *font;\n\tUIColor *textColor;\n\tNSTextAlignment textAlignment;\n\tNSRange selectedRange;\n\tBOOL editable;\n\tUIDataDetectorTypes dataDetectorTypes;\n\tUIReturnKeyType returnKeyType;\n    BOOL forceSizeUpdate;\n    NSString *placeholder;\n    UILabel *placeholderLabel;\n}\n\n@property (nonatomic, retain) UITextView *internalTextView;\n\n@property int maximumNumberOfLines;\n@property int minimumNumberOfLines;\n@property BOOL animateHeightChange;\n\n@property (weak) NSObject<UIExpandingTextViewDelegate> *delegate;\n@property (nonatomic) NSString *text;\n@property (nonatomic) NSAttributedString *attributedText;\n@property (nonatomic) UIFont *font;\n@property (nonatomic) UIColor *textColor;\n@property (nonatomic) NSTextAlignment textAlignment;\n@property (nonatomic) NSRange selectedRange;\n@property (nonatomic,getter=isEditable) BOOL editable;\n@property (nonatomic) UIDataDetectorTypes dataDetectorTypes __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_3_0);\n@property (nonatomic) UIReturnKeyType returnKeyType;\n@property (nonatomic) UIImageView *textViewBackgroundImage;\n@property (nonatomic,copy) NSString *placeholder;\n@property (nonatomic) int minimumHeight;\n@property (nonatomic) UIKeyboardAppearance keyboardAppearance;\n- (BOOL)hasText;\n- (void)scrollRangeToVisible:(NSRange)range;\n- (void)clearText;\n- (void)setBackgroundImage:(UIImage *)image;\n@end\n"
  },
  {
    "path": "IRCCloud/UIExpandingTextView.m",
    "content": "/*\n *  UIExpandingTextView.m\n *  \n *  Created by Brandon Hamilton on 2011/05/03.\n *  Copyright 2011 Brandon Hamilton.\n *  \n *  Permission is hereby granted, free of charge, to any person obtaining a copy\n *  of this software and associated documentation files (the \"Software\"), to deal\n *  in the Software without restriction, including without limitation the rights\n *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n *  copies of the Software, and to permit persons to whom the Software is\n *  furnished to do so, subject to the following conditions:\n *  \n *  The above copyright notice and this permission notice shall be included in\n *  all copies or substantial portions of the Software.\n *  \n *  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n *  THE SOFTWARE.\n */\n\n/* \n *  This class is based on growingTextView by Hans Pickaers \n *  http://www.hanspinckaers.com/multi-line-uitextview-similar-to-sms\n */\n\n#import \"UIExpandingTextView.h\"\n\n#define kTextInsetX 4\n#define kTextInsetBottom 0\n\n@implementation UIExpandingTextView\n\n@synthesize internalTextView;\n@synthesize delegate;\n\n@synthesize text;\n@synthesize font;\n@synthesize textColor;\n@synthesize textAlignment; \n@synthesize selectedRange;\n@synthesize editable;\n@synthesize dataDetectorTypes; \n@synthesize animateHeightChange;\n@synthesize returnKeyType;\n@synthesize textViewBackgroundImage;\n@synthesize placeholder;\n@synthesize minimumHeight;\n\n- (void)setPlaceholder:(NSString *)placeholders\n{\n    placeholder = placeholders;\n    placeholderLabel.text = placeholders;\n}\n\n- (int)minimumNumberOfLines\n{\n    return minimumNumberOfLines;\n}\n\n- (int)maximumNumberOfLines\n{\n    return maximumNumberOfLines;\n}\n\n- (id)initWithFrame:(CGRect)frame \n{\n    if ((self = [super initWithFrame:frame])) \n    {\n        forceSizeUpdate = NO;\n\t\tCGRect backgroundFrame = frame;\n        backgroundFrame.origin.y = 0;\n\t\tbackgroundFrame.origin.x = 0;\n        \n        CGRect textViewFrame = CGRectInset(backgroundFrame, kTextInsetX, 0);\n\n        /* Internal Text View component */\n\t\tinternalTextView = [[UIExpandingTextViewInternal alloc] initWithFrame:textViewFrame];\n\t\tinternalTextView.delegate        = self;\n\t\tinternalTextView.font            = [UIFont systemFontOfSize:15.0]; \n\t\tinternalTextView.contentInset    = UIEdgeInsetsMake(-1,0,-1,0);\n        internalTextView.text            = @\"-\";\n\t\tinternalTextView.scrollEnabled   = NO;\n        internalTextView.opaque          = NO;\n        internalTextView.backgroundColor = [UIColor clearColor];\n        internalTextView.showsHorizontalScrollIndicator = NO;\n        internalTextView.textContainer.lineBreakMode = NSLineBreakByWordWrapping;\n        [internalTextView sizeToFit];\n        \n        /* set placeholder */\n        placeholderLabel = [[UILabel alloc]initWithFrame:CGRectMake(8,3,self.bounds.size.width - 16,self.bounds.size.height)];\n        placeholderLabel.text = placeholder;\n        placeholderLabel.font = internalTextView.font;\n        placeholderLabel.backgroundColor = [UIColor clearColor];\n        placeholderLabel.textColor = [UIColor grayColor];\n        [internalTextView addSubview:placeholderLabel];\n        \n        /* Custom Background image */\n        textViewBackgroundImage = [[UIImageView alloc] initWithFrame:backgroundFrame];\n        textViewBackgroundImage.image          = [[UIImage imageNamed:@\"textbg\"] stretchableImageWithLeftCapWidth:0.5 topCapHeight:0.5];\n        textViewBackgroundImage.contentMode    = UIViewContentModeScaleToFill;\n        \n        [self addSubview:textViewBackgroundImage];\n        [self addSubview:internalTextView];\n\n\t\t[self setMinimumNumberOfLines:1];\n\t\tanimateHeightChange = YES;\n\t\tinternalTextView.text = @\"\";\n\t\t[self setMaximumNumberOfLines:13];\n        internalTextView.scrollEnabled = NO;\n        \n        [self sizeToFit];\n    }\n    return self;\n}\n\n-(void)setBackgroundImage:(UIImage *)image {\n    textViewBackgroundImage.image = image;\n}\n\n-(void)setKeyboardAppearance:(UIKeyboardAppearance)keyboardAppearance {\n    internalTextView.keyboardAppearance = keyboardAppearance;\n}\n\n-(UIKeyboardAppearance)keyboardAppearance {\n    return internalTextView.keyboardAppearance;\n}\n\n-(void)sizeToFit\n{\n    CGRect r = self.frame;\n    if ([self.text length] > 0) \n    {\n        /* No need to resize is text is not empty */\n        return;\n    }\n    r.size.height = minimumHeight + kTextInsetBottom;\n    self.frame = r;\n}\n\n-(void)setFrame:(CGRect)aframe\n{\n\t[super setFrame:aframe];\n    [self layoutSubviews];\n}\n\n-(void)layoutSubviews {\n    [super layoutSubviews];\n    CGRect backgroundFrame   = self.frame;\n    backgroundFrame.origin.y = 0;\n    backgroundFrame.origin.x = 0;\n    backgroundFrame.size.height  -= 8;\n    textViewBackgroundImage.frame = backgroundFrame;\n    backgroundFrame.origin.x -= 4;\n    backgroundFrame.size.width += 4;\n    CGRect textViewFrame = CGRectInset(backgroundFrame, kTextInsetX, 0);\n    internalTextView.frame   = textViewFrame;\n    forceSizeUpdate = YES;\n}\n\n-(void)clearText\n{\n    self.text = nil;\n    [self textViewDidChange:self.internalTextView];\n}\n     \n-(void)setMaximumNumberOfLines:(int)n\n{\n    if (maximumNumberOfLines == n)\n        return;\n    \n    NSRange saveSelection     = internalTextView.selectedRange;\n    NSString *saveText        = internalTextView.text;\n    NSString *newText         = @\"|W|\";\n    BOOL oldScrollEnabled     = internalTextView.scrollEnabled;\n    internalTextView.hidden   = YES;\n    internalTextView.delegate = nil;\n    internalTextView.scrollEnabled = NO;\n    for (int i = 2; i < n; ++i)\n    {\n        newText = [newText stringByAppendingString:@\"\\n|W|\"];\n    }\n    internalTextView.text     = newText;\n    maximumHeight             = internalTextView.intrinsicContentSize.height;\n    maximumNumberOfLines      = n;\n    internalTextView.scrollEnabled = oldScrollEnabled;\n    internalTextView.text     = saveText;\n    internalTextView.hidden   = NO;\n    internalTextView.selectedRange = saveSelection;\n    internalTextView.delegate = self;\n    forceSizeUpdate = YES;\n    [self textViewDidChange:self.internalTextView];\n}\n\n-(void)setMinimumNumberOfLines:(int)m\n{\n    if (minimumNumberOfLines == m)\n        return;\n    \n    NSRange saveSelection     = internalTextView.selectedRange;\n    NSString *saveText        = internalTextView.text;\n    NSString *newText         = @\"|W|\";\n    BOOL oldScrollEnabled     = internalTextView.scrollEnabled;\n    internalTextView.hidden   = YES;\n    internalTextView.delegate = nil;\n    internalTextView.scrollEnabled = NO;\n    for (int i = 2; i < m; ++i)\n    {\n        newText = [newText stringByAppendingString:@\"\\n|W|\"];\n    }\n    internalTextView.text     = newText;\n    minimumHeight             = internalTextView.intrinsicContentSize.height + 1;\n    internalTextView.scrollEnabled = oldScrollEnabled;\n    internalTextView.text     = saveText;\n    internalTextView.hidden   = NO;\n    internalTextView.selectedRange = saveSelection;\n    internalTextView.delegate = self;\n    [self sizeToFit];\n    minimumNumberOfLines = m;\n}\n\n- (void)textViewDidChange:(UITextView *)textView\n{\n    if(textView.text.length == 0) {\n        internalTextView.scrollEnabled = NO;\n        internalTextView.contentOffset = CGPointMake(0,0);\n        internalTextView.contentInset = UIEdgeInsetsMake(-1,0,-1,0);\n        placeholderLabel.alpha = 1;\n    } else {\n        placeholderLabel.alpha = 0;\n    }\n    \n    if(!textView.font)\n        return;\n    \n    NSInteger newHeight = ceil([textView.text boundingRectWithSize:CGSizeMake(internalTextView.bounds.size.width - 12, maximumHeight) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:textView.font} context:nil].size.height) + 17;\n    \n\tif(newHeight < minimumHeight || !internalTextView.hasText)\n    {\n        newHeight = minimumHeight;\n    }\n    \n\tif (internalTextView.frame.size.height != newHeight || forceSizeUpdate)\n\t{\n        forceSizeUpdate = NO;\n        if (newHeight > maximumHeight && internalTextView.frame.size.height <= maximumHeight)\n        {\n            newHeight = maximumHeight;\n        }\n\n        if(animateHeightChange)\n        {\n            [UIView beginAnimations:nil context:nil];\n            [UIView setAnimationDelegate:self];\n            [UIView setAnimationDidStopSelector:@selector(growDidStop)];\n            [UIView setAnimationBeginsFromCurrentState:YES];\n        }\n        \n        if ([delegate respondsToSelector:@selector(expandingTextView:willChangeHeight:)]) \n        {\n            [delegate expandingTextView:self willChangeHeight:(newHeight+ kTextInsetBottom)];\n        }\n        \n        /* Resize the frame */\n        CGRect r = self.frame;\n        r.size.height = (newHeight<maximumHeight)?newHeight:maximumHeight + kTextInsetBottom;\n        self.frame = r;\n        r.origin.y = 0;\n        r.origin.x = 0;\n        r.size.height -= 8;\n        textViewBackgroundImage.frame = r;\n        r.origin.x -= 4;\n        r.size.width += 4;\n        internalTextView.frame = CGRectInset(r, kTextInsetX, 0);\n        internalTextView.contentInset = UIEdgeInsetsMake(-1,0,-1,0);\n        \n        if(animateHeightChange)\n        {\n            [UIView commitAnimations];\n        }\n        else if ([delegate respondsToSelector:@selector(expandingTextView:didChangeHeight:)]) \n        {\n            [delegate expandingTextView:self didChangeHeight:(newHeight+ kTextInsetBottom)];\n        }\n\t\t\n        if (newHeight > minimumHeight)\n        {\n            if(!internalTextView.scrollEnabled)\n            {\n                internalTextView.scrollEnabled = YES;\n            }\n        } \n        else \n        {\n            internalTextView.scrollEnabled = NO;\n        }\n\t}\n\t\n\tif ([delegate respondsToSelector:@selector(expandingTextViewDidChange:)]) \n    {\n\t\t[delegate expandingTextViewDidChange:self];\n\t}\n}\n\n-(void)growDidStop\n{\n\tif ([delegate respondsToSelector:@selector(expandingTextView:didChangeHeight:)]) \n    {\n\t\t[delegate expandingTextView:self didChangeHeight:self.frame.size.height];\n\t}\n}\n\n-(BOOL)resignFirstResponder\n{\n\t[super resignFirstResponder];\n\treturn [internalTextView resignFirstResponder];\n}\n\n#pragma mark UITextView properties\n\n-(void)setText:(NSString *)atext\n{\n\tinternalTextView.text = atext;\n    [self performSelector:@selector(textViewDidChange:) withObject:internalTextView];\n}\n\n-(NSString*)text\n{\n\treturn internalTextView.text;\n}\n\n-(void)setAttributedText:(NSAttributedString *)atext\n{\n    internalTextView.attributedText = atext;\n    [self performSelector:@selector(textViewDidChange:) withObject:internalTextView];\n}\n\n-(NSAttributedString*)attributedText\n{\n    return internalTextView.attributedText;\n}\n\n-(void)setFont:(UIFont *)afont\n{\n\tinternalTextView.font= afont;\n\t[self setMaximumNumberOfLines:maximumNumberOfLines];\n\t[self setMinimumNumberOfLines:minimumNumberOfLines];\n}\n\n-(UIFont *)font\n{\n\treturn internalTextView.font;\n}\t\n\n-(void)setTextColor:(UIColor *)color\n{\n\tinternalTextView.textColor = color;\n}\n\n-(UIColor*)textColor\n{\n\treturn internalTextView.textColor;\n}\n\n-(void)setTextAlignment:(NSTextAlignment)aligment\n{\n\tinternalTextView.textAlignment = aligment;\n}\n\n-(NSTextAlignment)textAlignment\n{\n\treturn internalTextView.textAlignment;\n}\n\n-(void)setSelectedRange:(NSRange)range\n{\n\tinternalTextView.selectedRange = range;\n}\n\n-(NSRange)selectedRange\n{\n\treturn internalTextView.selectedRange;\n}\n\n-(void)setEditable:(BOOL)beditable\n{\n\tinternalTextView.editable = beditable;\n}\n\n-(BOOL)isEditable\n{\n\treturn internalTextView.editable;\n}\n\n-(void)setReturnKeyType:(UIReturnKeyType)keyType\n{\n\tinternalTextView.returnKeyType = keyType;\n}\n\n-(UIReturnKeyType)returnKeyType\n{\n\treturn internalTextView.returnKeyType;\n}\n\n-(void)setDataDetectorTypes:(UIDataDetectorTypes)datadetector\n{\n\tinternalTextView.dataDetectorTypes = datadetector;\n}\n\n-(UIDataDetectorTypes)dataDetectorTypes\n{\n\treturn internalTextView.dataDetectorTypes;\n}\n\n- (BOOL)hasText\n{\n\treturn [internalTextView hasText];\n}\n\n- (void)scrollRangeToVisible:(NSRange)range\n{\n\t[internalTextView scrollRangeToVisible:range];\n}\n\n#pragma mark -\n#pragma mark UIExpandingTextViewDelegate\n\n- (BOOL)textViewShouldBeginEditing:(UITextView *)textView \n{\n\tif ([delegate respondsToSelector:@selector(expandingTextViewShouldBeginEditing:)]) \n    {\n\t\treturn [delegate expandingTextViewShouldBeginEditing:self];\n\t} \n    else \n    {\n\t\treturn YES;\n\t}\n}\n\n- (BOOL)textViewShouldEndEditing:(UITextView *)textView \n{\n\tif ([delegate respondsToSelector:@selector(expandingTextViewShouldEndEditing:)]) \n    {\n\t\treturn [delegate expandingTextViewShouldEndEditing:self];\n\t} \n    else \n    {\n\t\treturn YES;\n\t}\n}\n\n- (void)textViewDidBeginEditing:(UITextView *)textView \n{\n\tif ([delegate respondsToSelector:@selector(expandingTextViewDidBeginEditing:)]) \n    {\n\t\t[delegate expandingTextViewDidBeginEditing:self];\n\t}\n}\n\n- (void)textViewDidEndEditing:(UITextView *)textView \n{\t\t\n\tif ([delegate respondsToSelector:@selector(expandingTextViewDidEndEditing:)]) \n    {\n\t\t[delegate expandingTextViewDidEndEditing:self];\n\t}\n}\n\n- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)atext \n{\n\tif(![textView hasText] && [atext isEqualToString:@\"\"]) \n    {\n        return NO;\n\t}\n    \n\tif ([atext isEqualToString:@\"\\n\"]) \n    {\n\t\tif ([delegate respondsToSelector:@selector(expandingTextViewShouldReturn:)]) \n        {\n\t\t\treturn [delegate expandingTextViewShouldReturn:self];\n        }\n\t}\n\n    if ([delegate respondsToSelector:@selector(expandingTextView:shouldChangeTextInRange:replacementText:)])\n    {\n        return [delegate expandingTextView:self shouldChangeTextInRange:range replacementText:atext];\n    }\n\treturn YES;\n}\n\n- (void)textViewDidChangeSelection:(UITextView *)textView \n{\n\tif ([delegate respondsToSelector:@selector(expandingTextViewDidChangeSelection:)]) \n    {\n\t\t[delegate expandingTextViewDidChangeSelection:self];\n\t}\n}\n\n- (BOOL)becomeFirstResponder\n{\n    return [internalTextView becomeFirstResponder];\n}\n\n- (CGSize)intrinsicContentSize\n{\n    return internalTextView.intrinsicContentSize;\n}\n\n@end\n"
  },
  {
    "path": "IRCCloud/UIExpandingTextViewInternal.h",
    "content": "/*\n *  UIExpandingTextViewInternal.h\n *  \n *  Created by Brandon Hamilton on 2011/05/03.\n *  Copyright 2011 Brandon Hamilton.\n *  \n *  Permission is hereby granted, free of charge, to any person obtaining a copy\n *  of this software and associated documentation files (the \"Software\"), to deal\n *  in the Software without restriction, including without limitation the rights\n *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n *  copies of the Software, and to permit persons to whom the Software is\n *  furnished to do so, subject to the following conditions:\n *  \n *  The above copyright notice and this permission notice shall be included in\n *  all copies or substantial portions of the Software.\n *  \n *  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n *  THE SOFTWARE.\n */\n\n#import <UIKit/UIKit.h>\n\n@interface UIExpandingTextViewInternal : UITextView { }\n\n@end\n"
  },
  {
    "path": "IRCCloud/UIExpandingTextViewInternal.m",
    "content": "/*\n *  UIExpandingTextViewInternal.m\n *  \n *  Created by Brandon Hamilton on 2011/05/03.\n *  Copyright 2011 Brandon Hamilton.\n *  \n *  Permission is hereby granted, free of charge, to any person obtaining a copy\n *  of this software and associated documentation files (the \"Software\"), to deal\n *  in the Software without restriction, including without limitation the rights\n *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n *  copies of the Software, and to permit persons to whom the Software is\n *  furnished to do so, subject to the following conditions:\n *  \n *  The above copyright notice and this permission notice shall be included in\n *  all copies or substantial portions of the Software.\n *  \n *  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n *  THE SOFTWARE.\n */\n\n#import \"UIExpandingTextViewInternal.h\"\n\n#define kTopContentInset -4\n#define lBottonContentInset 12\n\n@implementation UIExpandingTextViewInternal\n\n-(void)setContentOffset:(CGPoint)s\n{\n    /* Check if user scrolled */\n\tif(self.tracking || self.decelerating)\n    {\n\t\tself.contentInset = UIEdgeInsetsMake(kTopContentInset, 0, 0, 0);\n\t} \n    else \n    {\n\t\tfloat bottomContentOffset = (self.contentSize.height - self.frame.size.height + self.contentInset.bottom);\n\t\tif(s.y < bottomContentOffset && self.scrollEnabled) \n        {\n            self.contentInset = UIEdgeInsetsMake(kTopContentInset, 0, 4, 0);\n\t\t}\n\t}\n    if(self.scrollEnabled)\n        [super setContentOffset:s];\n    else {\n        [super setContentOffset:CGPointMake(0,4)];\n    }\n}\n\n-(void)setContentInset:(UIEdgeInsets)s\n{\n\tUIEdgeInsets edgeInsets = s;\n\tedgeInsets.top = kTopContentInset;\n\tif(s.bottom > 12) \n    {\n        edgeInsets.bottom = 4;\n    }\n\t[super setContentInset:edgeInsets];\n}\n\n- (CGRect)caretRectForPosition:(UITextPosition *)position {\n    CGRect originalRect = [super caretRectForPosition:position];\n    originalRect.size.height = self.font.pointSize + 6;\n    return originalRect;\n}\n\n- (void)paste:(id)sender {\n    UIResponder *next = self.nextResponder;\n    while(next != nil) {\n        if([next respondsToSelector:@selector(paste:)]) {\n            [next paste:sender];\n            return;\n        }\n        next = next.nextResponder;\n    }\n    [super paste:sender];\n}\n@end\n"
  },
  {
    "path": "IRCCloud/main.m",
    "content": "//\n//  main.m\n//  IRCCloud\n//\n//  Created by Sam Steele on 2/19/13.\n//  Copyright (c) 2013 IRCCloud, Ltd. 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": "IRCCloud.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 54;\n\tobjects = {\n\n/* Begin PBXAggregateTarget section */\n\t\t22DE05B118D8CA0700590FC3 /* GitRevision */ = {\n\t\t\tisa = PBXAggregateTarget;\n\t\t\tbuildConfigurationList = 22DE05B218D8CA0800590FC3 /* Build configuration list for PBXAggregateTarget \"GitRevision\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t22DE05B518D8CA2C00590FC3 /* ShellScript */,\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = GitRevision;\n\t\t\tproductName = GitRevision;\n\t\t};\n/* End PBXAggregateTarget section */\n\n/* Begin PBXBuildFile section */\n\t\t04F298BB0853A565665F1F57 /* Pods_IRCCloudUnitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 680E63BC56A1C3A1442F25DF /* Pods_IRCCloudUnitTests.framework */; };\n\t\t1A5703481A74145400D58225 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A5703471A74145400D58225 /* AdSupport.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t1A5703491A74145B00D58225 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A5703471A74145400D58225 /* AdSupport.framework */; };\n\t\t1A6141471E6EDF30004B6025 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A61413D1E6EDF30004B6025 /* AdSupport.framework */; };\n\t\t1A6141481E6EDF30004B6025 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A61413E1E6EDF30004B6025 /* AVFoundation.framework */; };\n\t\t1A6141491E6EDF30004B6025 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A61413F1E6EDF30004B6025 /* CFNetwork.framework */; };\n\t\t1A61414A1E6EDF30004B6025 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A6141401E6EDF30004B6025 /* CoreGraphics.framework */; };\n\t\t1A61414B1E6EDF30004B6025 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A6141411E6EDF30004B6025 /* CoreText.framework */; };\n\t\t1A61414C1E6EDF30004B6025 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A6141421E6EDF30004B6025 /* Foundation.framework */; };\n\t\t1A61414E1E6EDF30004B6025 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A6141441E6EDF30004B6025 /* Security.framework */; };\n\t\t1A61414F1E6EDF30004B6025 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A6141451E6EDF30004B6025 /* SystemConfiguration.framework */; };\n\t\t1A6141501E6EDF30004B6025 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A6141461E6EDF30004B6025 /* UIKit.framework */; };\n\t\t1A7382AC18D0A9A30039FDB3 /* Logo.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A7382AA18D0A9A30039FDB3 /* Logo.xcassets */; };\n\t\t1A7382AD18D0A9AC0039FDB3 /* EnterpriseLogo.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A7382A918D0A9A30039FDB3 /* EnterpriseLogo.xcassets */; };\n\t\t1ADCE22E1D2FCD78000B379F /* UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADCE22D1D2FCD78000B379F /* UITests.swift */; };\n\t\t2200DB4718B7EDF100343583 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2200DB4618B7EDF100343583 /* QuartzCore.framework */; };\n\t\t2200DB5118BCFA0E00343583 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2200DB4618B7EDF100343583 /* QuartzCore.framework */; };\n\t\t22032A6F1884529700BE4A10 /* NickCompletionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22032A6E1884529700BE4A10 /* NickCompletionView.m */; };\n\t\t2209B82D28C27A3B00D59B75 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 226E642223F1C6AA001CE069 /* GoogleService-Info.plist */; };\n\t\t221034ED197EFBAF00AB414F /* ShareViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221034EC197EFBAF00AB414F /* ShareViewController.m */; };\n\t\t221034F2197EFBAF00AB414F /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 221034E7197EFBAF00AB414F /* ShareExtension.appex */; };\n\t\t221034FA197EFC0500AB414F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2200DB4618B7EDF100343583 /* QuartzCore.framework */; };\n\t\t221034FB197EFC0500AB414F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2283322F17944E2B00ED22EA /* AudioToolbox.framework */; };\n\t\t221034FC197EFC0500AB414F /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05C916D3DCB60029769C /* CFNetwork.framework */; };\n\t\t221034FD197EFC0500AB414F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057316D3DABA0029769C /* CoreGraphics.framework */; };\n\t\t221034FE197EFC0500AB414F /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05D516D3DFD00029769C /* CoreText.framework */; };\n\t\t221034FF197EFC0500AB414F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057116D3DABA0029769C /* Foundation.framework */; };\n\t\t22103500197EFC0500AB414F /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2223C6B51768F4500032544B /* ImageIO.framework */; };\n\t\t22103501197EFC0500AB414F /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CD16D3DD310029769C /* libicucore.dylib */; };\n\t\t22103502197EFC0500AB414F /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2248DF3816EE375D0086BB42 /* libz.dylib */; };\n\t\t22103504197EFC0500AB414F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CB16D3DCE20029769C /* Security.framework */; };\n\t\t22103505197EFC0500AB414F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22324FDF177DE51A008B6912 /* SystemConfiguration.framework */; };\n\t\t22103506197EFC0500AB414F /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2250173F178340AB00066E71 /* Twitter.framework */; };\n\t\t22103507197EFC0500AB414F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A056F16D3DABA0029769C /* UIKit.framework */; };\n\t\t22103508197EFC6200AB414F /* BuffersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5FD16DA8928007BE535 /* BuffersDataSource.m */; };\n\t\t22103509197EFC6200AB414F /* ChannelsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60116DBC021007BE535 /* ChannelsDataSource.m */; };\n\t\t2210350A197EFC6200AB414F /* EventsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F9EE1B16DE6F21004615C0 /* EventsDataSource.m */; };\n\t\t2210350C197EFC6200AB414F /* IRCCloudJSONObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4288516D846BF00498507 /* IRCCloudJSONObject.m */; };\n\t\t2210350D197EFC6200AB414F /* NetworkConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4284716D7E36300498507 /* NetworkConnection.m */; };\n\t\t2210350E197EFC6200AB414F /* ServersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5F916DA765C007BE535 /* ServersDataSource.m */; };\n\t\t2210350F197EFC6200AB414F /* UsersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F64516DD138B007BE535 /* UsersDataSource.m */; };\n\t\t2210351F197EFC6200AB414F /* HandshakeHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285016D831A800498507 /* HandshakeHeader.m */; };\n\t\t22103520197EFC6200AB414F /* MutableQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285216D831A800498507 /* MutableQueue.m */; };\n\t\t22103521197EFC6200AB414F /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285416D831A800498507 /* NSData+Base64.m */; };\n\t\t22103522197EFC6200AB414F /* WebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285716D831A800498507 /* WebSocket.m */; };\n\t\t22103523197EFC6200AB414F /* WebSocketConnectConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286116D831A800498507 /* WebSocketConnectConfig.m */; };\n\t\t22103524197EFC6200AB414F /* WebSocketFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286316D831A800498507 /* WebSocketFragment.m */; };\n\t\t22103525197EFC6200AB414F /* WebSocketMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286516D831A800498507 /* WebSocketMessage.m */; };\n\t\t22103526197EFCCA00AB414F /* Ignore.m in Sources */ = {isa = PBXBuildFile; fileRef = 2230F8E717162ACC007F7C98 /* Ignore.m */; };\n\t\t22103527197EFCEB00AB414F /* Logo.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A7382AA18D0A9A30039FDB3 /* Logo.xcassets */; };\n\t\t22103528197EFCEE00AB414F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22EEA95018D0B117007D5022 /* Images.xcassets */; };\n\t\t22103529197EFCF100AB414F /* Icons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22EEA95318D0B198007D5022 /* Icons.xcassets */; };\n\t\t2210352A197EFE7800AB414F /* BuffersTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60516DBCA85007BE535 /* BuffersTableView.m */; };\n\t\t2210352B197EFEF600AB414F /* HighlightsCountView.m in Sources */ = {isa = PBXBuildFile; fileRef = 227FF2A016FA128B00DBE3C5 /* HighlightsCountView.m */; };\n\t\t2210352F197F1AD400AB414F /* UIColor+IRCCloud.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F63B16DBF3CB007BE535 /* UIColor+IRCCloud.m */; };\n\t\t221067201F28C3BB0075A18F /* Hack-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671C1F28C3BB0075A18F /* Hack-Bold.ttf */; };\n\t\t221067211F28C3BB0075A18F /* Hack-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671D1F28C3BB0075A18F /* Hack-BoldItalic.ttf */; };\n\t\t221067221F28C3BB0075A18F /* Hack-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671E1F28C3BB0075A18F /* Hack-Italic.ttf */; };\n\t\t221067231F28C3BB0075A18F /* Hack-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671F1F28C3BB0075A18F /* Hack-Regular.ttf */; };\n\t\t221067241F28C3F30075A18F /* Hack-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671C1F28C3BB0075A18F /* Hack-Bold.ttf */; };\n\t\t221067251F28C3F60075A18F /* Hack-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671D1F28C3BB0075A18F /* Hack-BoldItalic.ttf */; };\n\t\t221067261F28C3F90075A18F /* Hack-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671E1F28C3BB0075A18F /* Hack-Italic.ttf */; };\n\t\t221067271F28C3FB0075A18F /* Hack-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671F1F28C3BB0075A18F /* Hack-Regular.ttf */; };\n\t\t2212AF88175F82F900D08C7F /* ChannelInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2212AF87175F82F900D08C7F /* ChannelInfoViewController.m */; };\n\t\t221390FE1B115CD000ECF001 /* PastebinEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221390FD1B115CD000ECF001 /* PastebinEditorViewController.m */; };\n\t\t221390FF1B115CD000ECF001 /* PastebinEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221390FD1B115CD000ECF001 /* PastebinEditorViewController.m */; };\n\t\t221D4B861E1BE2F700D403E6 /* LinksListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221D4B851E1BE2F700D403E6 /* LinksListTableViewController.m */; };\n\t\t221D4B871E1BE2F700D403E6 /* LinksListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221D4B851E1BE2F700D403E6 /* LinksListTableViewController.m */; };\n\t\t221D4B911E23EAD700D403E6 /* NotificationService.m in Sources */ = {isa = PBXBuildFile; fileRef = 221D4B901E23EAD700D403E6 /* NotificationService.m */; };\n\t\t221D4B951E23EAD700D403E6 /* NotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 221D4B8D1E23EAD600D403E6 /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };\n\t\t221D4B9C1E23EB4900D403E6 /* NotificationService.m in Sources */ = {isa = PBXBuildFile; fileRef = 221D4B901E23EAD700D403E6 /* NotificationService.m */; };\n\t\t221D4BA71E23ECB200D403E6 /* NotificationService Enterprise.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 221D4BA31E23EB4900D403E6 /* NotificationService Enterprise.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };\n\t\t221D4BAE1E23F47900D403E6 /* NetworkConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4284716D7E36300498507 /* NetworkConnection.m */; };\n\t\t221D4BAF1E23F47900D403E6 /* NetworkConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4284716D7E36300498507 /* NetworkConnection.m */; };\n\t\t221D4BB01E23F48300D403E6 /* Ignore.m in Sources */ = {isa = PBXBuildFile; fileRef = 2230F8E717162ACC007F7C98 /* Ignore.m */; };\n\t\t221D4BB11E23F48300D403E6 /* Ignore.m in Sources */ = {isa = PBXBuildFile; fileRef = 2230F8E717162ACC007F7C98 /* Ignore.m */; };\n\t\t221D4BB21E23F48A00D403E6 /* BuffersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5FD16DA8928007BE535 /* BuffersDataSource.m */; };\n\t\t221D4BB31E23F48B00D403E6 /* BuffersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5FD16DA8928007BE535 /* BuffersDataSource.m */; };\n\t\t221D4BB41E23F48E00D403E6 /* ChannelsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60116DBC021007BE535 /* ChannelsDataSource.m */; };\n\t\t221D4BB51E23F48F00D403E6 /* ChannelsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60116DBC021007BE535 /* ChannelsDataSource.m */; };\n\t\t221D4BB61E23F49800D403E6 /* EventsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F9EE1B16DE6F21004615C0 /* EventsDataSource.m */; };\n\t\t221D4BB71E23F49800D403E6 /* EventsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F9EE1B16DE6F21004615C0 /* EventsDataSource.m */; };\n\t\t221D4BB81E23F4AF00D403E6 /* ColorFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2237E13C16E1214A00CA188F /* ColorFormatter.m */; };\n\t\t221D4BB91E23F4B000D403E6 /* ColorFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2237E13C16E1214A00CA188F /* ColorFormatter.m */; };\n\t\t221D4BBA1E23F4C000D403E6 /* IRCCloudJSONObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4288516D846BF00498507 /* IRCCloudJSONObject.m */; };\n\t\t221D4BBB1E23F4C000D403E6 /* IRCCloudJSONObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4288516D846BF00498507 /* IRCCloudJSONObject.m */; };\n\t\t221D4BBC1E23F4CD00D403E6 /* NotificationsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B2036D1B5FE3BE0058078D /* NotificationsDataSource.m */; };\n\t\t221D4BBD1E23F4CE00D403E6 /* NotificationsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B2036D1B5FE3BE0058078D /* NotificationsDataSource.m */; };\n\t\t221D4BBE1E23F4D700D403E6 /* ServersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5F916DA765C007BE535 /* ServersDataSource.m */; };\n\t\t221D4BBF1E23F4D800D403E6 /* ServersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5F916DA765C007BE535 /* ServersDataSource.m */; };\n\t\t221D4BC01E23F4DF00D403E6 /* UIColor+IRCCloud.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F63B16DBF3CB007BE535 /* UIColor+IRCCloud.m */; };\n\t\t221D4BC11E23F4DF00D403E6 /* UIColor+IRCCloud.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F63B16DBF3CB007BE535 /* UIColor+IRCCloud.m */; };\n\t\t221D4BC41E23F4FD00D403E6 /* UsersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F64516DD138B007BE535 /* UsersDataSource.m */; };\n\t\t221D4BC51E23F4FE00D403E6 /* UsersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F64516DD138B007BE535 /* UsersDataSource.m */; };\n\t\t221D4BC61E23F5EC00D403E6 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A5703471A74145400D58225 /* AdSupport.framework */; };\n\t\t221D4BC71E23F5EC00D403E6 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 226EB6001B4C2E8600C432C7 /* AVFoundation.framework */; };\n\t\t221D4BC81E23F5EC00D403E6 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05C916D3DCB60029769C /* CFNetwork.framework */; };\n\t\t221D4BC91E23F5EC00D403E6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057316D3DABA0029769C /* CoreGraphics.framework */; };\n\t\t221D4BCA1E23F5EC00D403E6 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05D516D3DFD00029769C /* CoreText.framework */; };\n\t\t221D4BCB1E23F5EC00D403E6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057116D3DABA0029769C /* Foundation.framework */; };\n\t\t221D4BCD1E23F5EC00D403E6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CB16D3DCE20029769C /* Security.framework */; };\n\t\t221D4BCE1E23F5EC00D403E6 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22324FDF177DE51A008B6912 /* SystemConfiguration.framework */; };\n\t\t221D4BCF1E23F5EC00D403E6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A056F16D3DABA0029769C /* UIKit.framework */; };\n\t\t221D4BD31E23F75300D403E6 /* HandshakeHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285016D831A800498507 /* HandshakeHeader.m */; };\n\t\t221D4BD41E23F75300D403E6 /* MutableQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285216D831A800498507 /* MutableQueue.m */; };\n\t\t221D4BD51E23F75300D403E6 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285416D831A800498507 /* NSData+Base64.m */; };\n\t\t221D4BD61E23F75300D403E6 /* WebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285716D831A800498507 /* WebSocket.m */; };\n\t\t221D4BD71E23F75300D403E6 /* WebSocketConnectConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286116D831A800498507 /* WebSocketConnectConfig.m */; };\n\t\t221D4BD81E23F75300D403E6 /* WebSocketFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286316D831A800498507 /* WebSocketFragment.m */; };\n\t\t221D4BD91E23F75300D403E6 /* WebSocketMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286516D831A800498507 /* WebSocketMessage.m */; };\n\t\t221D4BDB1E23F75400D403E6 /* HandshakeHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285016D831A800498507 /* HandshakeHeader.m */; };\n\t\t221D4BDC1E23F75400D403E6 /* MutableQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285216D831A800498507 /* MutableQueue.m */; };\n\t\t221D4BDD1E23F75400D403E6 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285416D831A800498507 /* NSData+Base64.m */; };\n\t\t221D4BDE1E23F75400D403E6 /* WebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285716D831A800498507 /* WebSocket.m */; };\n\t\t221D4BDF1E23F75400D403E6 /* WebSocketConnectConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286116D831A800498507 /* WebSocketConnectConfig.m */; };\n\t\t221D4BE01E23F75400D403E6 /* WebSocketFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286316D831A800498507 /* WebSocketFragment.m */; };\n\t\t221D4BE11E23F75400D403E6 /* WebSocketMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286516D831A800498507 /* WebSocketMessage.m */; };\n\t\t221D4BFC1E23FD3B00D403E6 /* NSURL+IDN.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293AEFF17F9CCD10022BD06 /* NSURL+IDN.m */; };\n\t\t221D4BFD1E23FD3B00D403E6 /* NSURL+IDN.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293AEFF17F9CCD10022BD06 /* NSURL+IDN.m */; };\n\t\t221D4BFE1E291C5300D403E6 /* CSURITemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D649231B1E0719003BFD86 /* CSURITemplate.m */; };\n\t\t221D4BFF1E291C5400D403E6 /* CSURITemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D649231B1E0719003BFD86 /* CSURITemplate.m */; };\n\t\t221E3F4C1AD2DEE00090934B /* FilesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221E3F4B1AD2DEE00090934B /* FilesTableViewController.m */; };\n\t\t221E3F4D1AD2DEE00090934B /* FilesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221E3F4B1AD2DEE00090934B /* FilesTableViewController.m */; };\n\t\t221E85F2241FBF3E00EB5120 /* PinReorderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221E85F0241FBD9300EB5120 /* PinReorderViewController.m */; };\n\t\t221E85F3241FBF3F00EB5120 /* PinReorderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221E85F0241FBD9300EB5120 /* PinReorderViewController.m */; };\n\t\t221EB2F01F8F965E00A71428 /* EventsTableCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 221EB2ED1F8F965E00A71428 /* EventsTableCell.xib */; };\n\t\t221EB2F11F8F965E00A71428 /* EventsTableCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 221EB2ED1F8F965E00A71428 /* EventsTableCell.xib */; };\n\t\t221EB2F41F962C2D00A71428 /* EventsTableCell_File.xib in Resources */ = {isa = PBXBuildFile; fileRef = 221EB2F21F962C2C00A71428 /* EventsTableCell_File.xib */; };\n\t\t221EB2F51F962C2D00A71428 /* EventsTableCell_File.xib in Resources */ = {isa = PBXBuildFile; fileRef = 221EB2F21F962C2C00A71428 /* EventsTableCell_File.xib */; };\n\t\t221EB2F61F962C2D00A71428 /* EventsTableCell_Thumbnail.xib in Resources */ = {isa = PBXBuildFile; fileRef = 221EB2F31F962C2D00A71428 /* EventsTableCell_Thumbnail.xib */; };\n\t\t221EB2F71F962C2D00A71428 /* EventsTableCell_Thumbnail.xib in Resources */ = {isa = PBXBuildFile; fileRef = 221EB2F31F962C2D00A71428 /* EventsTableCell_Thumbnail.xib */; };\n\t\t221F0BC5177368B40008EE04 /* CallerIDTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221F0BC4177368B40008EE04 /* CallerIDTableViewController.m */; };\n\t\t2223C6AA1768D7150032544B /* ImageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2223C6A81768D7150032544B /* ImageViewController.m */; };\n\t\t2223C6B61768F4500032544B /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2223C6B51768F4500032544B /* ImageIO.framework */; };\n\t\t222C80B61E48ABB200A243E7 /* ImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80B51E48ABB200A243E7 /* ImageCache.m */; };\n\t\t222C80B71E48ABB200A243E7 /* ImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80B51E48ABB200A243E7 /* ImageCache.m */; };\n\t\t222C80C91E4A0BB600A243E7 /* SBJson5Parser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BC1E4A0BB600A243E7 /* SBJson5Parser.m */; };\n\t\t222C80CA1E4A0BB600A243E7 /* SBJson5Parser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BC1E4A0BB600A243E7 /* SBJson5Parser.m */; };\n\t\t222C80CB1E4A0BB600A243E7 /* SBJson5StreamParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BE1E4A0BB600A243E7 /* SBJson5StreamParser.m */; };\n\t\t222C80CC1E4A0BB600A243E7 /* SBJson5StreamParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BE1E4A0BB600A243E7 /* SBJson5StreamParser.m */; };\n\t\t222C80CD1E4A0BB600A243E7 /* SBJson5StreamParserState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C01E4A0BB600A243E7 /* SBJson5StreamParserState.m */; };\n\t\t222C80CE1E4A0BB600A243E7 /* SBJson5StreamParserState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C01E4A0BB600A243E7 /* SBJson5StreamParserState.m */; };\n\t\t222C80CF1E4A0BB600A243E7 /* SBJson5StreamTokeniser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C21E4A0BB600A243E7 /* SBJson5StreamTokeniser.m */; };\n\t\t222C80D01E4A0BB600A243E7 /* SBJson5StreamTokeniser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C21E4A0BB600A243E7 /* SBJson5StreamTokeniser.m */; };\n\t\t222C80D11E4A0BB600A243E7 /* SBJson5StreamWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C41E4A0BB600A243E7 /* SBJson5StreamWriter.m */; };\n\t\t222C80D21E4A0BB600A243E7 /* SBJson5StreamWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C41E4A0BB600A243E7 /* SBJson5StreamWriter.m */; };\n\t\t222C80D31E4A0BB600A243E7 /* SBJson5StreamWriterState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C61E4A0BB600A243E7 /* SBJson5StreamWriterState.m */; };\n\t\t222C80D41E4A0BB600A243E7 /* SBJson5StreamWriterState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C61E4A0BB600A243E7 /* SBJson5StreamWriterState.m */; };\n\t\t222C80D51E4A0BB600A243E7 /* SBJson5Writer.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C81E4A0BB600A243E7 /* SBJson5Writer.m */; };\n\t\t222C80D61E4A0BB600A243E7 /* SBJson5Writer.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C81E4A0BB600A243E7 /* SBJson5Writer.m */; };\n\t\t222C80D71E4A111700A243E7 /* SBJson5Parser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BC1E4A0BB600A243E7 /* SBJson5Parser.m */; };\n\t\t222C80D81E4A111800A243E7 /* SBJson5Parser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BC1E4A0BB600A243E7 /* SBJson5Parser.m */; };\n\t\t222C80D91E4A111900A243E7 /* SBJson5Parser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BC1E4A0BB600A243E7 /* SBJson5Parser.m */; };\n\t\t222C80DA1E4A111A00A243E7 /* SBJson5Parser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BC1E4A0BB600A243E7 /* SBJson5Parser.m */; };\n\t\t222C80DB1E4A111D00A243E7 /* SBJson5StreamParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BE1E4A0BB600A243E7 /* SBJson5StreamParser.m */; };\n\t\t222C80DC1E4A111E00A243E7 /* SBJson5StreamParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BE1E4A0BB600A243E7 /* SBJson5StreamParser.m */; };\n\t\t222C80DD1E4A111F00A243E7 /* SBJson5StreamParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BE1E4A0BB600A243E7 /* SBJson5StreamParser.m */; };\n\t\t222C80DE1E4A112000A243E7 /* SBJson5StreamParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BE1E4A0BB600A243E7 /* SBJson5StreamParser.m */; };\n\t\t222C80DF1E4A112300A243E7 /* SBJson5StreamParserState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C01E4A0BB600A243E7 /* SBJson5StreamParserState.m */; };\n\t\t222C80E01E4A112300A243E7 /* SBJson5StreamParserState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C01E4A0BB600A243E7 /* SBJson5StreamParserState.m */; };\n\t\t222C80E11E4A112400A243E7 /* SBJson5StreamParserState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C01E4A0BB600A243E7 /* SBJson5StreamParserState.m */; };\n\t\t222C80E21E4A112500A243E7 /* SBJson5StreamParserState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C01E4A0BB600A243E7 /* SBJson5StreamParserState.m */; };\n\t\t222C80E31E4A112D00A243E7 /* SBJson5StreamTokeniser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C21E4A0BB600A243E7 /* SBJson5StreamTokeniser.m */; };\n\t\t222C80E41E4A112D00A243E7 /* SBJson5StreamWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C41E4A0BB600A243E7 /* SBJson5StreamWriter.m */; };\n\t\t222C80E51E4A112D00A243E7 /* SBJson5StreamWriterState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C61E4A0BB600A243E7 /* SBJson5StreamWriterState.m */; };\n\t\t222C80E61E4A112D00A243E7 /* SBJson5Writer.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C81E4A0BB600A243E7 /* SBJson5Writer.m */; };\n\t\t222C80E71E4A112D00A243E7 /* SBJson5StreamTokeniser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C21E4A0BB600A243E7 /* SBJson5StreamTokeniser.m */; };\n\t\t222C80E81E4A112D00A243E7 /* SBJson5StreamWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C41E4A0BB600A243E7 /* SBJson5StreamWriter.m */; };\n\t\t222C80E91E4A112D00A243E7 /* SBJson5StreamWriterState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C61E4A0BB600A243E7 /* SBJson5StreamWriterState.m */; };\n\t\t222C80EA1E4A112D00A243E7 /* SBJson5Writer.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C81E4A0BB600A243E7 /* SBJson5Writer.m */; };\n\t\t222C80EB1E4A112E00A243E7 /* SBJson5StreamTokeniser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C21E4A0BB600A243E7 /* SBJson5StreamTokeniser.m */; };\n\t\t222C80EC1E4A112E00A243E7 /* SBJson5StreamWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C41E4A0BB600A243E7 /* SBJson5StreamWriter.m */; };\n\t\t222C80ED1E4A112E00A243E7 /* SBJson5StreamWriterState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C61E4A0BB600A243E7 /* SBJson5StreamWriterState.m */; };\n\t\t222C80EE1E4A112E00A243E7 /* SBJson5Writer.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C81E4A0BB600A243E7 /* SBJson5Writer.m */; };\n\t\t222C80EF1E4A112F00A243E7 /* SBJson5StreamTokeniser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C21E4A0BB600A243E7 /* SBJson5StreamTokeniser.m */; };\n\t\t222C80F01E4A112F00A243E7 /* SBJson5StreamWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C41E4A0BB600A243E7 /* SBJson5StreamWriter.m */; };\n\t\t222C80F11E4A112F00A243E7 /* SBJson5StreamWriterState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C61E4A0BB600A243E7 /* SBJson5StreamWriterState.m */; };\n\t\t222C80F21E4A112F00A243E7 /* SBJson5Writer.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C81E4A0BB600A243E7 /* SBJson5Writer.m */; };\n\t\t2230F8E817162ACD007F7C98 /* Ignore.m in Sources */ = {isa = PBXBuildFile; fileRef = 2230F8E717162ACC007F7C98 /* Ignore.m */; };\n\t\t223154FD1F26245800BDE367 /* LogExportsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 223154FC1F26245800BDE367 /* LogExportsTableViewController.m */; };\n\t\t223154FE1F26245800BDE367 /* LogExportsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 223154FC1F26245800BDE367 /* LogExportsTableViewController.m */; };\n\t\t22324FE0177DE51A008B6912 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22324FDF177DE51A008B6912 /* SystemConfiguration.framework */; };\n\t\t2232ABD6230C1D66007431B5 /* UITableViewController+HeaderColorFix.m in Sources */ = {isa = PBXBuildFile; fileRef = 2232ABD5230C1D66007431B5 /* UITableViewController+HeaderColorFix.m */; };\n\t\t2232ABD7230C1D66007431B5 /* UITableViewController+HeaderColorFix.m in Sources */ = {isa = PBXBuildFile; fileRef = 2232ABD5230C1D66007431B5 /* UITableViewController+HeaderColorFix.m */; };\n\t\t2236193828B5435F0077C850 /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2236193728B5435F0077C850 /* Intents.framework */; };\n\t\t2236193A28B54D970077C850 /* IntentsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2236193928B54D970077C850 /* IntentsUI.framework */; };\n\t\t2236193B28B54DAC0077C850 /* IntentsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2236193928B54D970077C850 /* IntentsUI.framework */; };\n\t\t2236BD631BAA5E0900015753 /* FontAwesome.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD621BAA5E0900015753 /* FontAwesome.otf */; };\n\t\t2236BD641BAA5E0900015753 /* FontAwesome.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD621BAA5E0900015753 /* FontAwesome.otf */; };\n\t\t2236BD651BAA5E0900015753 /* FontAwesome.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD621BAA5E0900015753 /* FontAwesome.otf */; };\n\t\t2236BD661BAA5E0900015753 /* FontAwesome.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD621BAA5E0900015753 /* FontAwesome.otf */; };\n\t\t2236BD6A1BAC61A900015753 /* SourceSansPro-LightIt.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD681BAC61A900015753 /* SourceSansPro-LightIt.otf */; };\n\t\t2236BD6B1BAC61A900015753 /* SourceSansPro-LightIt.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD681BAC61A900015753 /* SourceSansPro-LightIt.otf */; };\n\t\t2236BD6C1BAC61A900015753 /* SourceSansPro-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD691BAC61A900015753 /* SourceSansPro-Regular.otf */; };\n\t\t2236BD6D1BAC61A900015753 /* SourceSansPro-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD691BAC61A900015753 /* SourceSansPro-Regular.otf */; };\n\t\t2236F5FA16DA765C007BE535 /* ServersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5F916DA765C007BE535 /* ServersDataSource.m */; };\n\t\t2236F5FE16DA8928007BE535 /* BuffersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5FD16DA8928007BE535 /* BuffersDataSource.m */; };\n\t\t2236F60216DBC021007BE535 /* ChannelsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60116DBC021007BE535 /* ChannelsDataSource.m */; };\n\t\t2236F60616DBCA85007BE535 /* BuffersTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60516DBCA85007BE535 /* BuffersTableView.m */; };\n\t\t2236F60B16DBCBC6007BE535 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60916DBCBC6007BE535 /* MainViewController.m */; };\n\t\t2236F63C16DBF3CC007BE535 /* UIColor+IRCCloud.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F63B16DBF3CB007BE535 /* UIColor+IRCCloud.m */; };\n\t\t2236F64616DD138C007BE535 /* UsersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F64516DD138B007BE535 /* UsersDataSource.m */; };\n\t\t2236F64A16DD30E5007BE535 /* UsersTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F64916DD30E3007BE535 /* UsersTableView.m */; };\n\t\t22374409252C9D3C0085D41C /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22374408252C9D3C0085D41C /* WebKit.framework */; };\n\t\t2237440A252C9D4B0085D41C /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22374408252C9D3C0085D41C /* WebKit.framework */; };\n\t\t2237440B252C9D580085D41C /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22374408252C9D3C0085D41C /* WebKit.framework */; };\n\t\t2237E13D16E1214A00CA188F /* ColorFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2237E13C16E1214A00CA188F /* ColorFormatter.m */; };\n\t\t2238761D1F70047D00943160 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876121F70035300943160 /* YYAnimatedImageView.m */; };\n\t\t2238761E1F70047D00943160 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876141F70035300943160 /* YYFrameImage.m */; };\n\t\t2238761F1F70047D00943160 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876161F70035300943160 /* YYImage.m */; };\n\t\t223876201F70047D00943160 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876181F70035300943160 /* YYImageCoder.m */; };\n\t\t223876211F70047D00943160 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 2238761A1F70035300943160 /* YYSpriteSheetImage.m */; };\n\t\t223876221F70047E00943160 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876121F70035300943160 /* YYAnimatedImageView.m */; };\n\t\t223876231F70047E00943160 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876141F70035300943160 /* YYFrameImage.m */; };\n\t\t223876241F70047E00943160 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876161F70035300943160 /* YYImage.m */; };\n\t\t223876251F70047E00943160 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876181F70035300943160 /* YYImageCoder.m */; };\n\t\t223876261F70047E00943160 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 2238761A1F70035300943160 /* YYSpriteSheetImage.m */; };\n\t\t223876271F70047F00943160 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876121F70035300943160 /* YYAnimatedImageView.m */; };\n\t\t223876281F70047F00943160 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876141F70035300943160 /* YYFrameImage.m */; };\n\t\t223876291F70047F00943160 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876161F70035300943160 /* YYImage.m */; };\n\t\t2238762A1F70047F00943160 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876181F70035300943160 /* YYImageCoder.m */; };\n\t\t2238762B1F70047F00943160 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 2238761A1F70035300943160 /* YYSpriteSheetImage.m */; };\n\t\t2238762C1F70047F00943160 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876121F70035300943160 /* YYAnimatedImageView.m */; };\n\t\t2238762D1F70047F00943160 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876141F70035300943160 /* YYFrameImage.m */; };\n\t\t2238762E1F70047F00943160 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876161F70035300943160 /* YYImage.m */; };\n\t\t2238762F1F70047F00943160 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876181F70035300943160 /* YYImageCoder.m */; };\n\t\t223876301F70047F00943160 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 2238761A1F70035300943160 /* YYSpriteSheetImage.m */; };\n\t\t223876311F70048000943160 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876121F70035300943160 /* YYAnimatedImageView.m */; };\n\t\t223876321F70048000943160 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876141F70035300943160 /* YYFrameImage.m */; };\n\t\t223876331F70048000943160 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876161F70035300943160 /* YYImage.m */; };\n\t\t223876341F70048000943160 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876181F70035300943160 /* YYImageCoder.m */; };\n\t\t223876351F70048000943160 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 2238761A1F70035300943160 /* YYSpriteSheetImage.m */; };\n\t\t223876361F70048100943160 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876121F70035300943160 /* YYAnimatedImageView.m */; };\n\t\t223876371F70048100943160 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876141F70035300943160 /* YYFrameImage.m */; };\n\t\t223876381F70048100943160 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876161F70035300943160 /* YYImage.m */; };\n\t\t223876391F70048100943160 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876181F70035300943160 /* YYImageCoder.m */; };\n\t\t2238763A1F70048100943160 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 2238761A1F70035300943160 /* YYSpriteSheetImage.m */; };\n\t\t2238763B1F70061C00943160 /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2238761C1F70038A00943160 /* WebP.framework */; platformFilter = ios; };\n\t\t2238763C1F70061F00943160 /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2238761C1F70038A00943160 /* WebP.framework */; };\n\t\t2238763D1F70062000943160 /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2238761C1F70038A00943160 /* WebP.framework */; platformFilter = ios; };\n\t\t2238763E1F70062100943160 /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2238761C1F70038A00943160 /* WebP.framework */; };\n\t\t2238763F1F70062200943160 /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2238761C1F70038A00943160 /* WebP.framework */; platformFilter = ios; };\n\t\t223876401F70062200943160 /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2238761C1F70038A00943160 /* WebP.framework */; };\n\t\t223C407C1C60FE880081B02B /* IRCCloudSafariViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 223C407B1C60FE880081B02B /* IRCCloudSafariViewController.m */; };\n\t\t223C407D1C60FE880081B02B /* IRCCloudSafariViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 223C407B1C60FE880081B02B /* IRCCloudSafariViewController.m */; };\n\t\t223DA90C16DFC626006FF808 /* EventsTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 223DA90B16DFC626006FF808 /* EventsTableView.m */; };\n\t\t224291651EB22B1000878455 /* URLtoBIDTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 224291641EB22B1000878455 /* URLtoBIDTests.m */; };\n\t\t224333D020162C1B0007A0D3 /* AvatarsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 224333CF20162C1B0007A0D3 /* AvatarsTableViewController.m */; };\n\t\t224333D120162C1B0007A0D3 /* AvatarsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 224333CF20162C1B0007A0D3 /* AvatarsTableViewController.m */; };\n\t\t224589C71DCA19BB00D3110A /* CollapsedEventsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 224589C61DCA19BB00D3110A /* CollapsedEventsTests.m */; };\n\t\t2245E3771B542D0200B763D7 /* AVKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2245E3761B542D0200B763D7 /* AVKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t2245E3781B542D0E00B763D7 /* AVKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2245E3761B542D0200B763D7 /* AVKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22462B5218906B03009EF986 /* ServerReorderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22462B5118906B03009EF986 /* ServerReorderViewController.m */; };\n\t\t2248DF3916EE375D0086BB42 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2248DF3816EE375D0086BB42 /* libz.dylib */; };\n\t\t2249867E1A95138800F6C3E2 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2249867D1A95138800F6C3E2 /* AssetsLibrary.framework */; platformFilter = ios; };\n\t\t2249867F1A95139400F6C3E2 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2249867D1A95138800F6C3E2 /* AssetsLibrary.framework */; };\n\t\t224FCF331787286000FC3879 /* licenses.txt in Resources */ = {isa = PBXBuildFile; fileRef = 224FCF321787286000FC3879 /* licenses.txt */; };\n\t\t224FCF361787288400FC3879 /* LicenseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 224FCF351787288400FC3879 /* LicenseViewController.m */; };\n\t\t22501740178340AB00066E71 /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2250173F178340AB00066E71 /* Twitter.framework */; platformFilter = ios; };\n\t\t225017631783434900066E71 /* ARChromeActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 225017431783434800066E71 /* ARChromeActivity.m */; };\n\t\t225017641783434900066E71 /* ARChromeActivity.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017441783434800066E71 /* ARChromeActivity.png */; };\n\t\t225017651783434900066E71 /* ARChromeActivity@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017451783434800066E71 /* ARChromeActivity@2x.png */; };\n\t\t225017661783434900066E71 /* ARChromeActivity@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017461783434800066E71 /* ARChromeActivity@2x~ipad.png */; };\n\t\t225017671783434900066E71 /* ARChromeActivity~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017471783434800066E71 /* ARChromeActivity~ipad.png */; };\n\t\t225017691783434900066E71 /* Safari.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017591783434900066E71 /* Safari.png */; };\n\t\t2250176A1783434900066E71 /* Safari@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2250175A1783434900066E71 /* Safari@2x.png */; };\n\t\t2250176B1783434900066E71 /* Safari@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 2250175B1783434900066E71 /* Safari@2x~ipad.png */; };\n\t\t2250176C1783434900066E71 /* Safari~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 2250175C1783434900066E71 /* Safari~ipad.png */; };\n\t\t2250176D1783434900066E71 /* TUSafariActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 225017601783434900066E71 /* TUSafariActivity.m */; };\n\t\t2251693317B5A8040093ADC5 /* TUSafariActivity.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2251693117B5A8040093ADC5 /* TUSafariActivity.strings */; };\n\t\t225173E71DB13A5500D63405 /* SourceSansPro-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 225173E21DB13A5500D63405 /* SourceSansPro-Semibold.otf */; };\n\t\t225173E81DB13A5500D63405 /* SourceSansPro-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 225173E21DB13A5500D63405 /* SourceSansPro-Semibold.otf */; };\n\t\t2252EE5B1F4485C000307010 /* MessageTypeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2252EE5A1F4485C000307010 /* MessageTypeTests.m */; };\n\t\t2253BA251770CD7200CCA77F /* ChannelListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2253BA241770CD7100CCA77F /* ChannelListTableViewController.m */; };\n\t\t225BEDC3252CB27F0050A8CC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 225BEDC2252CB27F0050A8CC /* CoreServices.framework */; };\n\t\t225BEDC4252CB29A0050A8CC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 225BEDC2252CB27F0050A8CC /* CoreServices.framework */; };\n\t\t225BEDC5252CB29F0050A8CC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 225BEDC2252CB27F0050A8CC /* CoreServices.framework */; };\n\t\t225BEDC6252CB2A00050A8CC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 225BEDC2252CB27F0050A8CC /* CoreServices.framework */; };\n\t\t225BEDC7252CB2A20050A8CC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 225BEDC2252CB27F0050A8CC /* CoreServices.framework */; };\n\t\t225BEDC8252CB2A30050A8CC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 225BEDC2252CB27F0050A8CC /* CoreServices.framework */; };\n\t\t225BEDC9252CB2A30050A8CC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 225BEDC2252CB27F0050A8CC /* CoreServices.framework */; };\n\t\t225D973818AA995900065087 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 228A057B16D3DABA0029769C /* main.m */; };\n\t\t225D973918AA995900065087 /* ServerReorderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22462B5118906B03009EF986 /* ServerReorderViewController.m */; };\n\t\t225D973A18AA995900065087 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 228A05AF16D3DB7B0029769C /* AppDelegate.m */; };\n\t\t225D973C18AA995900065087 /* LoginSplashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 228A05DC16D3E40E0029769C /* LoginSplashViewController.m */; };\n\t\t225D974718AA995900065087 /* NetworkConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4284716D7E36300498507 /* NetworkConnection.m */; };\n\t\t225D974A18AA995900065087 /* HandshakeHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285016D831A800498507 /* HandshakeHeader.m */; };\n\t\t225D974B18AA995900065087 /* MutableQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285216D831A800498507 /* MutableQueue.m */; };\n\t\t225D974C18AA995900065087 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285416D831A800498507 /* NSData+Base64.m */; };\n\t\t225D974D18AA995900065087 /* WebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285716D831A800498507 /* WebSocket.m */; };\n\t\t225D974E18AA995900065087 /* WebSocketConnectConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286116D831A800498507 /* WebSocketConnectConfig.m */; };\n\t\t225D974F18AA995900065087 /* WebSocketFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286316D831A800498507 /* WebSocketFragment.m */; };\n\t\t225D975018AA995900065087 /* WebSocketMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286516D831A800498507 /* WebSocketMessage.m */; };\n\t\t225D975118AA995900065087 /* IRCCloudJSONObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4288516D846BF00498507 /* IRCCloudJSONObject.m */; };\n\t\t225D975218AA995900065087 /* ServersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5F916DA765C007BE535 /* ServersDataSource.m */; };\n\t\t225D975318AA995900065087 /* NickCompletionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22032A6E1884529700BE4A10 /* NickCompletionView.m */; };\n\t\t225D975418AA995900065087 /* NSURL+IDN.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293AEFF17F9CCD10022BD06 /* NSURL+IDN.m */; };\n\t\t225D975518AA995900065087 /* BuffersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5FD16DA8928007BE535 /* BuffersDataSource.m */; };\n\t\t225D975618AA995900065087 /* ChannelsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60116DBC021007BE535 /* ChannelsDataSource.m */; };\n\t\t225D975718AA995900065087 /* BuffersTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60516DBCA85007BE535 /* BuffersTableView.m */; };\n\t\t225D975818AA995900065087 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60916DBCBC6007BE535 /* MainViewController.m */; };\n\t\t225D975918AA995900065087 /* UIColor+IRCCloud.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F63B16DBF3CB007BE535 /* UIColor+IRCCloud.m */; };\n\t\t225D975A18AA995900065087 /* UsersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F64516DD138B007BE535 /* UsersDataSource.m */; };\n\t\t225D975B18AA995900065087 /* UsersTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F64916DD30E3007BE535 /* UsersTableView.m */; };\n\t\t225D975C18AA995900065087 /* EventsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F9EE1B16DE6F21004615C0 /* EventsDataSource.m */; };\n\t\t225D975D18AA995900065087 /* EventsTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 223DA90B16DFC626006FF808 /* EventsTableView.m */; };\n\t\t225D975E18AA995900065087 /* ColorFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2237E13C16E1214A00CA188F /* ColorFormatter.m */; };\n\t\t225D975F18AA995900065087 /* CollapsedEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = 22695F5416E8FC9800E01DF8 /* CollapsedEvents.m */; };\n\t\t225D976018AA995900065087 /* HighlightsCountView.m in Sources */ = {isa = PBXBuildFile; fileRef = 227FF2A016FA128B00DBE3C5 /* HighlightsCountView.m */; };\n\t\t225D976118AA995900065087 /* Ignore.m in Sources */ = {isa = PBXBuildFile; fileRef = 2230F8E717162ACC007F7C98 /* Ignore.m */; };\n\t\t225D976218AA995900065087 /* ChannelModeListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22AD75EC1718567D00141257 /* ChannelModeListTableViewController.m */; };\n\t\t225D976318AA995900065087 /* IgnoresTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D4309F171C663A003C0684 /* IgnoresTableViewController.m */; };\n\t\t225D976418AA995900065087 /* UIExpandingTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D430A31725AAEA003C0684 /* UIExpandingTextView.m */; };\n\t\t225D976518AA995900065087 /* UIExpandingTextViewInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D430A51725AAEA003C0684 /* UIExpandingTextViewInternal.m */; };\n\t\t225D976618AA995900065087 /* EditConnectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B15CF3172ECCFF0075EBA7 /* EditConnectionViewController.m */; };\n\t\t225D976718AA995900065087 /* ECSlidingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B15CF817301BAF0075EBA7 /* ECSlidingViewController.m */; };\n\t\t225D976818AA995900065087 /* UIImage+ImageWithUIView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B15CFA17301BAF0075EBA7 /* UIImage+ImageWithUIView.m */; };\n\t\t225D976918AA995900065087 /* OpenInChromeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2274F49E1756723F0039B4CB /* OpenInChromeController.m */; };\n\t\t225D976A18AA995900065087 /* ChannelInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2212AF87175F82F900D08C7F /* ChannelInfoViewController.m */; };\n\t\t225D976B18AA995900065087 /* ImageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2223C6A81768D7150032544B /* ImageViewController.m */; };\n\t\t225D976D18AA995900065087 /* ChannelListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2253BA241770CD7100CCA77F /* ChannelListTableViewController.m */; };\n\t\t225D976E18AA995900065087 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 227FF8221772063F00394114 /* SettingsViewController.m */; };\n\t\t225D976F18AA995900065087 /* CallerIDTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221F0BC4177368B40008EE04 /* CallerIDTableViewController.m */; };\n\t\t225D977018AA995900065087 /* WhoisViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A1D0261778A86900F8A89C /* WhoisViewController.m */; };\n\t\t225D977118AA995900065087 /* DisplayOptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 228EFBC7177B4F7300B83A4C /* DisplayOptionsViewController.m */; };\n\t\t225D977218AA995900065087 /* ARChromeActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 225017431783434800066E71 /* ARChromeActivity.m */; };\n\t\t225D977318AA995900065087 /* TUSafariActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 225017601783434900066E71 /* TUSafariActivity.m */; };\n\t\t225D977418AA995900065087 /* LicenseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 224FCF351787288400FC3879 /* LicenseViewController.m */; };\n\t\t225D977518AA995900065087 /* WhoListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A35F25178A317100529CDA /* WhoListTableViewController.m */; };\n\t\t225D977618AA995900065087 /* NamesListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A35F28178A3F3500529CDA /* NamesListTableViewController.m */; };\n\t\t225D977718AA995900065087 /* UINavigationController+iPadSux.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A19C5F178FCCAB00772C60 /* UINavigationController+iPadSux.m */; };\n\t\t225D977918AA995900065087 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2283322F17944E2B00ED22EA /* AudioToolbox.framework */; };\n\t\t225D977A18AA995900065087 /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2250173F178340AB00066E71 /* Twitter.framework */; };\n\t\t225D977B18AA995900065087 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22324FDF177DE51A008B6912 /* SystemConfiguration.framework */; };\n\t\t225D977C18AA995900065087 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2223C6B51768F4500032544B /* ImageIO.framework */; };\n\t\t225D977E18AA995900065087 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2248DF3816EE375D0086BB42 /* libz.dylib */; };\n\t\t225D977F18AA995900065087 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05D516D3DFD00029769C /* CoreText.framework */; };\n\t\t225D978018AA995900065087 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CD16D3DD310029769C /* libicucore.dylib */; };\n\t\t225D978118AA995900065087 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CB16D3DCE20029769C /* Security.framework */; };\n\t\t225D978218AA995900065087 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A056F16D3DABA0029769C /* UIKit.framework */; };\n\t\t225D978318AA995900065087 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05C916D3DCB60029769C /* CFNetwork.framework */; };\n\t\t225D978418AA995900065087 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057116D3DABA0029769C /* Foundation.framework */; };\n\t\t225D978518AA995900065087 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057316D3DABA0029769C /* CoreGraphics.framework */; };\n\t\t225D978D18AA995900065087 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 22D4F9101743F3790095EE8F /* Localizable.strings */; };\n\t\t225D979018AA995900065087 /* ARChromeActivity.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017441783434800066E71 /* ARChromeActivity.png */; };\n\t\t225D979118AA995900065087 /* ARChromeActivity@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017451783434800066E71 /* ARChromeActivity@2x.png */; };\n\t\t225D979218AA995900065087 /* ARChromeActivity@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017461783434800066E71 /* ARChromeActivity@2x~ipad.png */; };\n\t\t225D979318AA995900065087 /* ARChromeActivity~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017471783434800066E71 /* ARChromeActivity~ipad.png */; };\n\t\t225D979418AA995900065087 /* Safari.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017591783434900066E71 /* Safari.png */; };\n\t\t225D979518AA995900065087 /* Safari@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2250175A1783434900066E71 /* Safari@2x.png */; };\n\t\t225D979618AA995900065087 /* Safari@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 2250175B1783434900066E71 /* Safari@2x~ipad.png */; };\n\t\t225D979718AA995900065087 /* Safari~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 2250175C1783434900066E71 /* Safari~ipad.png */; };\n\t\t225D979918AA995900065087 /* licenses.txt in Resources */ = {isa = PBXBuildFile; fileRef = 224FCF321787286000FC3879 /* licenses.txt */; };\n\t\t225D979A18AA995900065087 /* a.caf in Resources */ = {isa = PBXBuildFile; fileRef = 22F5C4BC1791F205005E09A9 /* a.caf */; };\n\t\t225D979B18AA995900065087 /* TUSafariActivity.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2251693117B5A8040093ADC5 /* TUSafariActivity.strings */; };\n\t\t225EC2BB2061678B00AA0C79 /* EventsTableCell_ReplyCount.xib in Resources */ = {isa = PBXBuildFile; fileRef = 225EC2BA2061678B00AA0C79 /* EventsTableCell_ReplyCount.xib */; };\n\t\t225EC2BC2061678B00AA0C79 /* EventsTableCell_ReplyCount.xib in Resources */ = {isa = PBXBuildFile; fileRef = 225EC2BA2061678B00AA0C79 /* EventsTableCell_ReplyCount.xib */; };\n\t\t2263D3A2290A979500692EEC /* NSString+Score.m in Sources */ = {isa = PBXBuildFile; fileRef = 2263D3A1290A979500692EEC /* NSString+Score.m */; };\n\t\t2263D3A3290A979500692EEC /* NSString+Score.m in Sources */ = {isa = PBXBuildFile; fileRef = 2263D3A1290A979500692EEC /* NSString+Score.m */; };\n\t\t2264A30119659BB100DCFDDD /* URLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 2264A30019659BB100DCFDDD /* URLHandler.m */; };\n\t\t2264A30219659BB100DCFDDD /* URLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 2264A30019659BB100DCFDDD /* URLHandler.m */; };\n\t\t2265DC891C722E6B00382C7C /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2265DC881C722E6B00382C7C /* MessageUI.framework */; };\n\t\t2265DC8A1C722E7A00382C7C /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2265DC881C722E6B00382C7C /* MessageUI.framework */; };\n\t\t22695F5516E8FC9900E01DF8 /* CollapsedEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = 22695F5416E8FC9800E01DF8 /* CollapsedEvents.m */; };\n\t\t226E642323F1C6AA001CE069 /* GoogleService-Info.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 226E642223F1C6AA001CE069 /* GoogleService-Info.plist */; };\n\t\t226EB6011B4C2E8600C432C7 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 226EB6001B4C2E8600C432C7 /* AVFoundation.framework */; };\n\t\t226EB6021B4C2E8C00C432C7 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 226EB6001B4C2E8600C432C7 /* AVFoundation.framework */; };\n\t\t226F080A1E5DFEC1003EED23 /* ImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80B51E48ABB200A243E7 /* ImageCache.m */; };\n\t\t226F080B1E5DFEC2003EED23 /* ImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80B51E48ABB200A243E7 /* ImageCache.m */; };\n\t\t226F080E1E6495C8003EED23 /* WhoWasTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 226F080D1E6495C8003EED23 /* WhoWasTableViewController.m */; };\n\t\t226F080F1E6495C8003EED23 /* WhoWasTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 226F080D1E6495C8003EED23 /* WhoWasTableViewController.m */; };\n\t\t2271FDA11DCDF45C00A39F84 /* TextTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2271FDA01DCDF45C00A39F84 /* TextTableViewController.m */; };\n\t\t2271FDA21DCDF45C00A39F84 /* TextTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2271FDA01DCDF45C00A39F84 /* TextTableViewController.m */; };\n\t\t2274F49F1756723F0039B4CB /* OpenInChromeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2274F49E1756723F0039B4CB /* OpenInChromeController.m */; };\n\t\t2275AF6C28D3679C00D11811 /* AvatarsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E54ADF1D10593B00891FE4 /* AvatarsDataSource.m */; };\n\t\t2275AF6D28D3679D00D11811 /* AvatarsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E54ADF1D10593B00891FE4 /* AvatarsDataSource.m */; };\n\t\t2275AF6E28D3679E00D11811 /* AvatarsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E54ADF1D10593B00891FE4 /* AvatarsDataSource.m */; };\n\t\t2275AF6F28D3679F00D11811 /* AvatarsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E54ADF1D10593B00891FE4 /* AvatarsDataSource.m */; };\n\t\t227C63BA1C7B8C4800B674D6 /* SafariServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22A1F1141C232B3A00AEC09A /* SafariServices.framework */; };\n\t\t227DA89E1CF381B60041B1BF /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 227DA89D1CF381B60041B1BF /* CoreTelephony.framework */; };\n\t\t227DA89F1CF381D70041B1BF /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 227DA89D1CF381B60041B1BF /* CoreTelephony.framework */; };\n\t\t227DA8A01CF381D90041B1BF /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 227DA89D1CF381B60041B1BF /* CoreTelephony.framework */; };\n\t\t227DA8A11CF381DA0041B1BF /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 227DA89D1CF381B60041B1BF /* CoreTelephony.framework */; };\n\t\t227FF2A116FA128B00DBE3C5 /* HighlightsCountView.m in Sources */ = {isa = PBXBuildFile; fileRef = 227FF2A016FA128B00DBE3C5 /* HighlightsCountView.m */; };\n\t\t227FF8231772063F00394114 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 227FF8221772063F00394114 /* SettingsViewController.m */; };\n\t\t2283323017944E2B00ED22EA /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2283322F17944E2B00ED22EA /* AudioToolbox.framework */; };\n\t\t2284EF721B4AD47F0058D483 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2284EF711B4AD47F0058D483 /* MediaPlayer.framework */; };\n\t\t2284EF731B4AD48E0058D483 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2284EF711B4AD47F0058D483 /* MediaPlayer.framework */; };\n\t\t2289EF631D7866BD00DB285E /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2289EF621D7866BD00DB285E /* UserNotifications.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t2289EF641D7866D200DB285E /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2289EF621D7866BD00DB285E /* UserNotifications.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t2289EF781D787CC500DB285E /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2289EF771D787CC500DB285E /* Intents.framework */; settings = {ATTRIBUTES = (Required, ); }; };\n\t\t2289EF791D787CD100DB285E /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2289EF771D787CC500DB285E /* Intents.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t228A057016D3DABA0029769C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A056F16D3DABA0029769C /* UIKit.framework */; };\n\t\t228A057216D3DABA0029769C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057116D3DABA0029769C /* Foundation.framework */; };\n\t\t228A057416D3DABA0029769C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057316D3DABA0029769C /* CoreGraphics.framework */; };\n\t\t228A057C16D3DABA0029769C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 228A057B16D3DABA0029769C /* main.m */; };\n\t\t228A05B216D3DB7B0029769C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 228A05AF16D3DB7B0029769C /* AppDelegate.m */; };\n\t\t228A05CA16D3DCB60029769C /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05C916D3DCB60029769C /* CFNetwork.framework */; };\n\t\t228A05CF16D3DD540029769C /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CD16D3DD310029769C /* libicucore.dylib */; };\n\t\t228A05D016D3DD570029769C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CB16D3DCE20029769C /* Security.framework */; };\n\t\t228A05D716D3DFDA0029769C /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05D516D3DFD00029769C /* CoreText.framework */; };\n\t\t228A05DE16D3E40F0029769C /* LoginSplashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 228A05DC16D3E40E0029769C /* LoginSplashViewController.m */; };\n\t\t228EFBC8177B4F7300B83A4C /* DisplayOptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 228EFBC7177B4F7300B83A4C /* DisplayOptionsViewController.m */; };\n\t\t228F69731DF8A3F30079E276 /* SpamViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 228F69721DF8A3F30079E276 /* SpamViewController.m */; };\n\t\t228F69741DF8A3F30079E276 /* SpamViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 228F69721DF8A3F30079E276 /* SpamViewController.m */; };\n\t\t2292AD591D5B55CC00BEE269 /* LinkLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 22CE91781D59160B0014B25C /* LinkLabel.m */; };\n\t\t2293240B1E8945D700ADAA22 /* configuration_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323D91E8945D700ADAA22 /* configuration_utils.m */; };\n\t\t2293240C1E8945D700ADAA22 /* configuration_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323D91E8945D700ADAA22 /* configuration_utils.m */; };\n\t\t2293240D1E8945D700ADAA22 /* configuration_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323D91E8945D700ADAA22 /* configuration_utils.m */; };\n\t\t2293240E1E8945D700ADAA22 /* configuration_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323D91E8945D700ADAA22 /* configuration_utils.m */; };\n\t\t2293240F1E8945D700ADAA22 /* configuration_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323D91E8945D700ADAA22 /* configuration_utils.m */; };\n\t\t229324101E8945D700ADAA22 /* configuration_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323D91E8945D700ADAA22 /* configuration_utils.m */; };\n\t\t229324111E8945D700ADAA22 /* assert.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323DE1E8945D700ADAA22 /* assert.c */; };\n\t\t229324121E8945D700ADAA22 /* assert.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323DE1E8945D700ADAA22 /* assert.c */; };\n\t\t229324131E8945D700ADAA22 /* assert.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323DE1E8945D700ADAA22 /* assert.c */; };\n\t\t229324141E8945D700ADAA22 /* assert.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323DE1E8945D700ADAA22 /* assert.c */; };\n\t\t229324151E8945D700ADAA22 /* assert.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323DE1E8945D700ADAA22 /* assert.c */; };\n\t\t229324161E8945D700ADAA22 /* assert.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323DE1E8945D700ADAA22 /* assert.c */; };\n\t\t229324171E8945D700ADAA22 /* init_registry_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E01E8945D700ADAA22 /* init_registry_tables.c */; };\n\t\t229324181E8945D700ADAA22 /* init_registry_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E01E8945D700ADAA22 /* init_registry_tables.c */; };\n\t\t229324191E8945D700ADAA22 /* init_registry_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E01E8945D700ADAA22 /* init_registry_tables.c */; };\n\t\t2293241A1E8945D700ADAA22 /* init_registry_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E01E8945D700ADAA22 /* init_registry_tables.c */; };\n\t\t2293241B1E8945D700ADAA22 /* init_registry_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E01E8945D700ADAA22 /* init_registry_tables.c */; };\n\t\t2293241C1E8945D700ADAA22 /* init_registry_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E01E8945D700ADAA22 /* init_registry_tables.c */; };\n\t\t2293241D1E8945D700ADAA22 /* registry_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E11E8945D700ADAA22 /* registry_search.c */; };\n\t\t2293241E1E8945D700ADAA22 /* registry_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E11E8945D700ADAA22 /* registry_search.c */; };\n\t\t2293241F1E8945D700ADAA22 /* registry_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E11E8945D700ADAA22 /* registry_search.c */; };\n\t\t229324201E8945D700ADAA22 /* registry_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E11E8945D700ADAA22 /* registry_search.c */; };\n\t\t229324211E8945D700ADAA22 /* registry_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E11E8945D700ADAA22 /* registry_search.c */; };\n\t\t229324221E8945D700ADAA22 /* registry_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E11E8945D700ADAA22 /* registry_search.c */; };\n\t\t229324231E8945D700ADAA22 /* trie_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E51E8945D700ADAA22 /* trie_search.c */; };\n\t\t229324241E8945D700ADAA22 /* trie_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E51E8945D700ADAA22 /* trie_search.c */; };\n\t\t229324251E8945D700ADAA22 /* trie_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E51E8945D700ADAA22 /* trie_search.c */; };\n\t\t229324261E8945D700ADAA22 /* trie_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E51E8945D700ADAA22 /* trie_search.c */; };\n\t\t229324271E8945D700ADAA22 /* trie_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E51E8945D700ADAA22 /* trie_search.c */; };\n\t\t229324281E8945D700ADAA22 /* trie_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E51E8945D700ADAA22 /* trie_search.c */; };\n\t\t2293242F1E8945D700ADAA22 /* RSSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323EC1E8945D700ADAA22 /* RSSwizzle.m */; };\n\t\t229324301E8945D700ADAA22 /* RSSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323EC1E8945D700ADAA22 /* RSSwizzle.m */; };\n\t\t229324311E8945D700ADAA22 /* RSSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323EC1E8945D700ADAA22 /* RSSwizzle.m */; };\n\t\t229324321E8945D700ADAA22 /* RSSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323EC1E8945D700ADAA22 /* RSSwizzle.m */; };\n\t\t229324331E8945D700ADAA22 /* RSSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323EC1E8945D700ADAA22 /* RSSwizzle.m */; };\n\t\t229324341E8945D700ADAA22 /* RSSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323EC1E8945D700ADAA22 /* RSSwizzle.m */; };\n\t\t2293243B1E8945D700ADAA22 /* parse_configuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F01E8945D700ADAA22 /* parse_configuration.m */; };\n\t\t2293243C1E8945D700ADAA22 /* parse_configuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F01E8945D700ADAA22 /* parse_configuration.m */; };\n\t\t2293243D1E8945D700ADAA22 /* parse_configuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F01E8945D700ADAA22 /* parse_configuration.m */; };\n\t\t2293243E1E8945D700ADAA22 /* parse_configuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F01E8945D700ADAA22 /* parse_configuration.m */; };\n\t\t2293243F1E8945D700ADAA22 /* parse_configuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F01E8945D700ADAA22 /* parse_configuration.m */; };\n\t\t229324401E8945D700ADAA22 /* parse_configuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F01E8945D700ADAA22 /* parse_configuration.m */; };\n\t\t229324411E8945D700ADAA22 /* public_key_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F31E8945D700ADAA22 /* public_key_utils.m */; };\n\t\t229324421E8945D700ADAA22 /* public_key_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F31E8945D700ADAA22 /* public_key_utils.m */; };\n\t\t229324431E8945D700ADAA22 /* public_key_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F31E8945D700ADAA22 /* public_key_utils.m */; };\n\t\t229324441E8945D700ADAA22 /* public_key_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F31E8945D700ADAA22 /* public_key_utils.m */; };\n\t\t229324451E8945D700ADAA22 /* public_key_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F31E8945D700ADAA22 /* public_key_utils.m */; };\n\t\t229324461E8945D700ADAA22 /* public_key_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F31E8945D700ADAA22 /* public_key_utils.m */; };\n\t\t229324471E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F51E8945D700ADAA22 /* ssl_pin_verifier.m */; };\n\t\t229324481E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F51E8945D700ADAA22 /* ssl_pin_verifier.m */; };\n\t\t229324491E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F51E8945D700ADAA22 /* ssl_pin_verifier.m */; };\n\t\t2293244A1E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F51E8945D700ADAA22 /* ssl_pin_verifier.m */; };\n\t\t2293244B1E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F51E8945D700ADAA22 /* ssl_pin_verifier.m */; };\n\t\t2293244C1E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F51E8945D700ADAA22 /* ssl_pin_verifier.m */; };\n\t\t2293244D1E8945D700ADAA22 /* reporting_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F81E8945D700ADAA22 /* reporting_utils.m */; };\n\t\t2293244E1E8945D700ADAA22 /* reporting_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F81E8945D700ADAA22 /* reporting_utils.m */; };\n\t\t2293244F1E8945D700ADAA22 /* reporting_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F81E8945D700ADAA22 /* reporting_utils.m */; };\n\t\t229324501E8945D700ADAA22 /* reporting_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F81E8945D700ADAA22 /* reporting_utils.m */; };\n\t\t229324511E8945D700ADAA22 /* reporting_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F81E8945D700ADAA22 /* reporting_utils.m */; };\n\t\t229324521E8945D700ADAA22 /* reporting_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F81E8945D700ADAA22 /* reporting_utils.m */; };\n\t\t229324531E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FA1E8945D700ADAA22 /* TSKBackgroundReporter.m */; };\n\t\t229324541E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FA1E8945D700ADAA22 /* TSKBackgroundReporter.m */; };\n\t\t229324551E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FA1E8945D700ADAA22 /* TSKBackgroundReporter.m */; };\n\t\t229324561E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FA1E8945D700ADAA22 /* TSKBackgroundReporter.m */; };\n\t\t229324571E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FA1E8945D700ADAA22 /* TSKBackgroundReporter.m */; };\n\t\t229324581E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FA1E8945D700ADAA22 /* TSKBackgroundReporter.m */; };\n\t\t229324591E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FC1E8945D700ADAA22 /* TSKPinFailureReport.m */; };\n\t\t2293245A1E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FC1E8945D700ADAA22 /* TSKPinFailureReport.m */; };\n\t\t2293245B1E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FC1E8945D700ADAA22 /* TSKPinFailureReport.m */; };\n\t\t2293245C1E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FC1E8945D700ADAA22 /* TSKPinFailureReport.m */; };\n\t\t2293245D1E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FC1E8945D700ADAA22 /* TSKPinFailureReport.m */; };\n\t\t2293245E1E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FC1E8945D700ADAA22 /* TSKPinFailureReport.m */; };\n\t\t2293245F1E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FE1E8945D700ADAA22 /* TSKReportsRateLimiter.m */; };\n\t\t229324601E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FE1E8945D700ADAA22 /* TSKReportsRateLimiter.m */; };\n\t\t229324611E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FE1E8945D700ADAA22 /* TSKReportsRateLimiter.m */; };\n\t\t229324621E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FE1E8945D700ADAA22 /* TSKReportsRateLimiter.m */; };\n\t\t229324631E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FE1E8945D700ADAA22 /* TSKReportsRateLimiter.m */; };\n\t\t229324641E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FE1E8945D700ADAA22 /* TSKReportsRateLimiter.m */; };\n\t\t229324651E8945D700ADAA22 /* vendor_identifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324001E8945D700ADAA22 /* vendor_identifier.m */; };\n\t\t229324661E8945D700ADAA22 /* vendor_identifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324001E8945D700ADAA22 /* vendor_identifier.m */; };\n\t\t229324671E8945D700ADAA22 /* vendor_identifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324001E8945D700ADAA22 /* vendor_identifier.m */; };\n\t\t229324681E8945D700ADAA22 /* vendor_identifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324001E8945D700ADAA22 /* vendor_identifier.m */; };\n\t\t229324691E8945D700ADAA22 /* vendor_identifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324001E8945D700ADAA22 /* vendor_identifier.m */; };\n\t\t2293246A1E8945D700ADAA22 /* vendor_identifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324001E8945D700ADAA22 /* vendor_identifier.m */; };\n\t\t2293246B1E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324031E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m */; };\n\t\t2293246C1E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324031E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m */; };\n\t\t2293246D1E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324031E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m */; };\n\t\t2293246E1E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324031E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m */; };\n\t\t2293246F1E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324031E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m */; };\n\t\t229324701E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324031E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m */; };\n\t\t229324711E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324051E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m */; };\n\t\t229324721E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324051E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m */; };\n\t\t229324731E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324051E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m */; };\n\t\t229324741E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324051E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m */; };\n\t\t229324751E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324051E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m */; };\n\t\t229324761E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324051E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m */; };\n\t\t229324771E8945D700ADAA22 /* TrustKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324081E8945D700ADAA22 /* TrustKit.m */; };\n\t\t229324781E8945D700ADAA22 /* TrustKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324081E8945D700ADAA22 /* TrustKit.m */; };\n\t\t229324791E8945D700ADAA22 /* TrustKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324081E8945D700ADAA22 /* TrustKit.m */; };\n\t\t2293247A1E8945D700ADAA22 /* TrustKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324081E8945D700ADAA22 /* TrustKit.m */; };\n\t\t2293247B1E8945D700ADAA22 /* TrustKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324081E8945D700ADAA22 /* TrustKit.m */; };\n\t\t2293247C1E8945D700ADAA22 /* TrustKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324081E8945D700ADAA22 /* TrustKit.m */; };\n\t\t2293247D1E8945D700ADAA22 /* TSKPinningValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293240A1E8945D700ADAA22 /* TSKPinningValidator.m */; };\n\t\t2293247E1E8945D700ADAA22 /* TSKPinningValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293240A1E8945D700ADAA22 /* TSKPinningValidator.m */; };\n\t\t2293247F1E8945D700ADAA22 /* TSKPinningValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293240A1E8945D700ADAA22 /* TSKPinningValidator.m */; };\n\t\t229324801E8945D700ADAA22 /* TSKPinningValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293240A1E8945D700ADAA22 /* TSKPinningValidator.m */; };\n\t\t229324811E8945D700ADAA22 /* TSKPinningValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293240A1E8945D700ADAA22 /* TSKPinningValidator.m */; };\n\t\t229324821E8945D700ADAA22 /* TSKPinningValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293240A1E8945D700ADAA22 /* TSKPinningValidator.m */; };\n\t\t2293AF0117F9CCD10022BD06 /* NSURL+IDN.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293AEFF17F9CCD10022BD06 /* NSURL+IDN.m */; };\n\t\t229C85411B502920004964DE /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 229C85401B502920004964DE /* CoreMedia.framework */; };\n\t\t229C85421B50292D004964DE /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 229C85401B502920004964DE /* CoreMedia.framework */; };\n\t\t229C85431B502934004964DE /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 226EB6001B4C2E8600C432C7 /* AVFoundation.framework */; };\n\t\t229C85441B50293B004964DE /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 229C85401B502920004964DE /* CoreMedia.framework */; };\n\t\t229C85451B502946004964DE /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 226EB6001B4C2E8600C432C7 /* AVFoundation.framework */; };\n\t\t229C85461B50294C004964DE /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 229C85401B502920004964DE /* CoreMedia.framework */; };\n\t\t22A19C60178FCCAC00772C60 /* UINavigationController+iPadSux.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A19C5F178FCCAB00772C60 /* UINavigationController+iPadSux.m */; };\n\t\t22A1D0271778A86900F8A89C /* WhoisViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A1D0261778A86900F8A89C /* WhoisViewController.m */; };\n\t\t22A1F1151C232B3A00AEC09A /* SafariServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22A1F1141C232B3A00AEC09A /* SafariServices.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22A35F26178A317100529CDA /* WhoListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A35F25178A317100529CDA /* WhoListTableViewController.m */; };\n\t\t22A35F29178A3F3500529CDA /* NamesListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A35F28178A3F3500529CDA /* NamesListTableViewController.m */; };\n\t\t22A363B219D0884D00500478 /* 1Password.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22A363AF19D0884D00500478 /* 1Password.xcassets */; };\n\t\t22A363B319D0884D00500478 /* 1Password.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22A363AF19D0884D00500478 /* 1Password.xcassets */; };\n\t\t22A363B419D0884D00500478 /* OnePasswordExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A363B119D0884D00500478 /* OnePasswordExtension.m */; };\n\t\t22A363B519D0884D00500478 /* OnePasswordExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A363B119D0884D00500478 /* OnePasswordExtension.m */; };\n\t\t22A363BC19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A363BB19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.m */; };\n\t\t22A363BD19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A363BB19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.m */; };\n\t\t22AD75ED1718567D00141257 /* ChannelModeListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22AD75EC1718567D00141257 /* ChannelModeListTableViewController.m */; };\n\t\t22B15CF4172ECCFF0075EBA7 /* EditConnectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B15CF3172ECCFF0075EBA7 /* EditConnectionViewController.m */; };\n\t\t22B15CFB17301BAF0075EBA7 /* ECSlidingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B15CF817301BAF0075EBA7 /* ECSlidingViewController.m */; };\n\t\t22B15CFD17301BAF0075EBA7 /* UIImage+ImageWithUIView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B15CFA17301BAF0075EBA7 /* UIImage+ImageWithUIView.m */; };\n\t\t22B2036E1B5FE3BE0058078D /* NotificationsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B2036D1B5FE3BE0058078D /* NotificationsDataSource.m */; };\n\t\t22B2036F1B5FE3BE0058078D /* NotificationsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B2036D1B5FE3BE0058078D /* NotificationsDataSource.m */; };\n\t\t22B203701B5FE3BE0058078D /* NotificationsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B2036D1B5FE3BE0058078D /* NotificationsDataSource.m */; };\n\t\t22B203711B5FE3BE0058078D /* NotificationsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B2036D1B5FE3BE0058078D /* NotificationsDataSource.m */; };\n\t\t22B4284816D7E36300498507 /* NetworkConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4284716D7E36300498507 /* NetworkConnection.m */; };\n\t\t22B4286A16D831A800498507 /* HandshakeHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285016D831A800498507 /* HandshakeHeader.m */; };\n\t\t22B4286C16D831A800498507 /* MutableQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285216D831A800498507 /* MutableQueue.m */; };\n\t\t22B4286E16D831A800498507 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285416D831A800498507 /* NSData+Base64.m */; };\n\t\t22B4287016D831A800498507 /* WebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285716D831A800498507 /* WebSocket.m */; };\n\t\t22B4287A16D831A800498507 /* WebSocketConnectConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286116D831A800498507 /* WebSocketConnectConfig.m */; };\n\t\t22B4287C16D831A800498507 /* WebSocketFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286316D831A800498507 /* WebSocketFragment.m */; };\n\t\t22B4287E16D831A800498507 /* WebSocketMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286516D831A800498507 /* WebSocketMessage.m */; };\n\t\t22B4288616D846BF00498507 /* IRCCloudJSONObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4288516D846BF00498507 /* IRCCloudJSONObject.m */; };\n\t\t22BB0A2A28C22FB2008EE509 /* SendMessageIntentHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 22BB0A2928C22FB2008EE509 /* SendMessageIntentHandler.m */; };\n\t\t22BB0A2B28C22FB2008EE509 /* SendMessageIntentHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 22BB0A2928C22FB2008EE509 /* SendMessageIntentHandler.m */; };\n\t\t22BB94AA1D425A4F00BFB6F0 /* SamlLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22BB94A81D425A4E00BFB6F0 /* SamlLoginViewController.m */; };\n\t\t22BB94AB1D425D3800BFB6F0 /* SamlLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22BB94A81D425A4E00BFB6F0 /* SamlLoginViewController.m */; };\n\t\t22C2075C1A19125700EDACA4 /* FileMetadataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22C2075B1A19125700EDACA4 /* FileMetadataViewController.m */; };\n\t\t22C2075D1A19125700EDACA4 /* FileMetadataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22C2075B1A19125700EDACA4 /* FileMetadataViewController.m */; };\n\t\t22C2E0581B0E2E4800387B4B /* PastebinViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22C2E0561B0E2E4800387B4B /* PastebinViewController.m */; };\n\t\t22C2E0591B0E2E4800387B4B /* PastebinViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22C2E0561B0E2E4800387B4B /* PastebinViewController.m */; };\n\t\t22C8CD711B01289900F637D2 /* libc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 22C8CD701B01289900F637D2 /* libc++.dylib */; };\n\t\t22C8CD721B01289900F637D2 /* libc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 22C8CD701B01289900F637D2 /* libc++.dylib */; };\n\t\t22C8CD731B01289900F637D2 /* libc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 22C8CD701B01289900F637D2 /* libc++.dylib */; };\n\t\t22C8CD741B01289900F637D2 /* libc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 22C8CD701B01289900F637D2 /* libc++.dylib */; };\n\t\t22C8DCF11A80154200199371 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A5703471A74145400D58225 /* AdSupport.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22C8DCF31A801A4500199371 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22C8DCF21A801A4500199371 /* CloudKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22C8DCF41A801A6300199371 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22C8DCF21A801A4500199371 /* CloudKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22CE2AE91D2AAA36001397C0 /* SnapshotHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22CE2AE81D2AAA36001397C0 /* SnapshotHelper.swift */; };\n\t\t22CE91751D58C81C0014B25C /* LinkTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22CE91741D58C81C0014B25C /* LinkTextView.m */; };\n\t\t22CE91761D58C81C0014B25C /* LinkTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22CE91741D58C81C0014B25C /* LinkTextView.m */; };\n\t\t22CE91791D59160B0014B25C /* LinkLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 22CE91781D59160B0014B25C /* LinkLabel.m */; };\n\t\t22D268C21BF4F40800B682AE /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 22D268C11BF4F40800B682AE /* MainStoryboard.storyboard */; };\n\t\t22D268C31BF4F40800B682AE /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 22D268C11BF4F40800B682AE /* MainStoryboard.storyboard */; };\n\t\t22D268C61BF4F95200B682AE /* SplashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D268C51BF4F95200B682AE /* SplashViewController.m */; };\n\t\t22D268C71BF4F95200B682AE /* SplashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D268C51BF4F95200B682AE /* SplashViewController.m */; };\n\t\t22D430A0171C663A003C0684 /* IgnoresTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D4309F171C663A003C0684 /* IgnoresTableViewController.m */; };\n\t\t22D430A61725AAEA003C0684 /* UIExpandingTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D430A31725AAEA003C0684 /* UIExpandingTextView.m */; };\n\t\t22D430A81725AAEA003C0684 /* UIExpandingTextViewInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D430A51725AAEA003C0684 /* UIExpandingTextViewInternal.m */; };\n\t\t22D46C671A13A9A900B142F7 /* FileUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D46C661A13A9A900B142F7 /* FileUploader.m */; };\n\t\t22D46C681A13A9A900B142F7 /* FileUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D46C661A13A9A900B142F7 /* FileUploader.m */; };\n\t\t22D46C691A13A9A900B142F7 /* FileUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D46C661A13A9A900B142F7 /* FileUploader.m */; };\n\t\t22D46C6A1A13A9A900B142F7 /* FileUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D46C661A13A9A900B142F7 /* FileUploader.m */; };\n\t\t22D4F9121743F3790095EE8F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 22D4F9101743F3790095EE8F /* Localizable.strings */; };\n\t\t22D649241B1E0719003BFD86 /* CSURITemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D649231B1E0719003BFD86 /* CSURITemplate.m */; };\n\t\t22D649251B1E0719003BFD86 /* CSURITemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D649231B1E0719003BFD86 /* CSURITemplate.m */; };\n\t\t22D649261B1E0719003BFD86 /* CSURITemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D649231B1E0719003BFD86 /* CSURITemplate.m */; };\n\t\t22D649271B1E0719003BFD86 /* CSURITemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D649231B1E0719003BFD86 /* CSURITemplate.m */; };\n\t\t22D6492A1B1E371D003BFD86 /* PastebinsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D649291B1E371D003BFD86 /* PastebinsTableViewController.m */; };\n\t\t22D6492B1B1E371D003BFD86 /* PastebinsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D649291B1E371D003BFD86 /* PastebinsTableViewController.m */; };\n\t\t22D76CCA208E288E005C34E5 /* ImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80B51E48ABB200A243E7 /* ImageCache.m */; };\n\t\t22D76CCB208E288F005C34E5 /* ImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80B51E48ABB200A243E7 /* ImageCache.m */; };\n\t\t22D76CCC208E289D005C34E5 /* ColorFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2237E13C16E1214A00CA188F /* ColorFormatter.m */; };\n\t\t22D76CCD208E289E005C34E5 /* ColorFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2237E13C16E1214A00CA188F /* ColorFormatter.m */; };\n\t\t22D9778E215BC910005C2713 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 228A057B16D3DABA0029769C /* main.m */; };\n\t\t22D9778F215BC910005C2713 /* PastebinEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221390FD1B115CD000ECF001 /* PastebinEditorViewController.m */; };\n\t\t22D97790215BC910005C2713 /* ServerReorderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22462B5118906B03009EF986 /* ServerReorderViewController.m */; };\n\t\t22D97791215BC910005C2713 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 228A05AF16D3DB7B0029769C /* AppDelegate.m */; };\n\t\t22D97792215BC910005C2713 /* URLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 2264A30019659BB100DCFDDD /* URLHandler.m */; };\n\t\t22D97797215BC910005C2713 /* LoginSplashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 228A05DC16D3E40E0029769C /* LoginSplashViewController.m */; };\n\t\t22D97799215BC910005C2713 /* NetworkConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4284716D7E36300498507 /* NetworkConnection.m */; };\n\t\t22D9779A215BC910005C2713 /* LinksListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221D4B851E1BE2F700D403E6 /* LinksListTableViewController.m */; };\n\t\t22D9779B215BC910005C2713 /* NotificationsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B2036D1B5FE3BE0058078D /* NotificationsDataSource.m */; };\n\t\t22D9779D215BC910005C2713 /* HandshakeHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285016D831A800498507 /* HandshakeHeader.m */; };\n\t\t22D977A1215BC910005C2713 /* TSKPinFailureReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FC1E8945D700ADAA22 /* TSKPinFailureReport.m */; };\n\t\t22D977A7215BC910005C2713 /* OpenInFirefoxControllerObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E9C0A81C9AF27800013456 /* OpenInFirefoxControllerObjC.m */; };\n\t\t22D977A9215BC910005C2713 /* MutableQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285216D831A800498507 /* MutableQueue.m */; };\n\t\t22D977AC215BC910005C2713 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285416D831A800498507 /* NSData+Base64.m */; };\n\t\t22D977AD215BC910005C2713 /* TSKBackgroundReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FA1E8945D700ADAA22 /* TSKBackgroundReporter.m */; };\n\t\t22D977AF215BC910005C2713 /* WebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285716D831A800498507 /* WebSocket.m */; };\n\t\t22D977B2215BC910005C2713 /* WebSocketConnectConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286116D831A800498507 /* WebSocketConnectConfig.m */; };\n\t\t22D977B3215BC910005C2713 /* WebSocketFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286316D831A800498507 /* WebSocketFragment.m */; };\n\t\t22D977B5215BC910005C2713 /* AvatarsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 224333CF20162C1B0007A0D3 /* AvatarsTableViewController.m */; };\n\t\t22D977B6215BC910005C2713 /* SamlLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22BB94A81D425A4E00BFB6F0 /* SamlLoginViewController.m */; };\n\t\t22D977BB215BC910005C2713 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876121F70035300943160 /* YYAnimatedImageView.m */; };\n\t\t22D977BC215BC910005C2713 /* WebSocketMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286516D831A800498507 /* WebSocketMessage.m */; };\n\t\t22D977BD215BC910005C2713 /* parse_configuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F01E8945D700ADAA22 /* parse_configuration.m */; };\n\t\t22D977BF215BC910005C2713 /* IRCCloudJSONObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4288516D846BF00498507 /* IRCCloudJSONObject.m */; };\n\t\t22D977C1215BC910005C2713 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876141F70035300943160 /* YYFrameImage.m */; };\n\t\t22D977C6215BC910005C2713 /* ServersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5F916DA765C007BE535 /* ServersDataSource.m */; };\n\t\t22D977C8215BC910005C2713 /* NickCompletionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22032A6E1884529700BE4A10 /* NickCompletionView.m */; };\n\t\t22D977C9215BC910005C2713 /* LogExportsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 223154FC1F26245800BDE367 /* LogExportsTableViewController.m */; };\n\t\t22D977CC215BC910005C2713 /* SBJson5Parser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BC1E4A0BB600A243E7 /* SBJson5Parser.m */; };\n\t\t22D977CD215BC910005C2713 /* assert.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323DE1E8945D700ADAA22 /* assert.c */; };\n\t\t22D977CE215BC910005C2713 /* LinkTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22CE91741D58C81C0014B25C /* LinkTextView.m */; };\n\t\t22D977CF215BC910005C2713 /* LinkLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 22CE91781D59160B0014B25C /* LinkLabel.m */; };\n\t\t22D977D0215BC910005C2713 /* YouTubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22DB8D6F1C441C3000302271 /* YouTubeViewController.m */; };\n\t\t22D977D1215BC910005C2713 /* NSURL+IDN.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293AEFF17F9CCD10022BD06 /* NSURL+IDN.m */; };\n\t\t22D977D5215BC910005C2713 /* BuffersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5FD16DA8928007BE535 /* BuffersDataSource.m */; };\n\t\t22D977D6215BC910005C2713 /* IRCColorPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22EE41F91F39F66E00D74E8C /* IRCColorPickerView.m */; };\n\t\t22D977D7215BC910005C2713 /* ChannelsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60116DBC021007BE535 /* ChannelsDataSource.m */; };\n\t\t22D977D8215BC910005C2713 /* BuffersTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60516DBCA85007BE535 /* BuffersTableView.m */; };\n\t\t22D977D9215BC910005C2713 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60916DBCBC6007BE535 /* MainViewController.m */; };\n\t\t22D977DC215BC910005C2713 /* TSKReportsRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323FE1E8945D700ADAA22 /* TSKReportsRateLimiter.m */; };\n\t\t22D977DD215BC910005C2713 /* configuration_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323D91E8945D700ADAA22 /* configuration_utils.m */; };\n\t\t22D977DF215BC910005C2713 /* public_key_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F31E8945D700ADAA22 /* public_key_utils.m */; };\n\t\t22D977E2215BC910005C2713 /* UIColor+IRCCloud.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F63B16DBF3CB007BE535 /* UIColor+IRCCloud.m */; };\n\t\t22D977E4215BC910005C2713 /* UsersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F64516DD138B007BE535 /* UsersDataSource.m */; };\n\t\t22D977E5215BC910005C2713 /* UsersTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F64916DD30E3007BE535 /* UsersTableView.m */; };\n\t\t22D977E7215BC910005C2713 /* trie_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E51E8945D700ADAA22 /* trie_search.c */; };\n\t\t22D977E8215BC910005C2713 /* init_registry_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E01E8945D700ADAA22 /* init_registry_tables.c */; };\n\t\t22D977E9215BC910005C2713 /* EventsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F9EE1B16DE6F21004615C0 /* EventsDataSource.m */; };\n\t\t22D977EB215BC910005C2713 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876181F70035300943160 /* YYImageCoder.m */; };\n\t\t22D977EF215BC910005C2713 /* EventsTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 223DA90B16DFC626006FF808 /* EventsTableView.m */; };\n\t\t22D977F0215BC910005C2713 /* vendor_identifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324001E8945D700ADAA22 /* vendor_identifier.m */; };\n\t\t22D977F2215BC910005C2713 /* RSSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323EC1E8945D700ADAA22 /* RSSwizzle.m */; };\n\t\t22D977F5215BC910005C2713 /* ColorFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2237E13C16E1214A00CA188F /* ColorFormatter.m */; };\n\t\t22D977F6215BC910005C2713 /* FileUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D46C661A13A9A900B142F7 /* FileUploader.m */; };\n\t\t22D977F8215BC910005C2713 /* FilesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221E3F4B1AD2DEE00090934B /* FilesTableViewController.m */; };\n\t\t22D977F9215BC910005C2713 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 223876161F70035300943160 /* YYImage.m */; };\n\t\t22D977FA215BC910005C2713 /* CollapsedEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = 22695F5416E8FC9800E01DF8 /* CollapsedEvents.m */; };\n\t\t22D977FB215BC910005C2713 /* TrustKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324081E8945D700ADAA22 /* TrustKit.m */; };\n\t\t22D977FC215BC910005C2713 /* HighlightsCountView.m in Sources */ = {isa = PBXBuildFile; fileRef = 227FF2A016FA128B00DBE3C5 /* HighlightsCountView.m */; };\n\t\t22D977FD215BC910005C2713 /* Ignore.m in Sources */ = {isa = PBXBuildFile; fileRef = 2230F8E717162ACC007F7C98 /* Ignore.m */; };\n\t\t22D977FE215BC910005C2713 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 2238761A1F70035300943160 /* YYSpriteSheetImage.m */; };\n\t\t22D97802215BC910005C2713 /* ChannelModeListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22AD75EC1718567D00141257 /* ChannelModeListTableViewController.m */; };\n\t\t22D97805215BC910005C2713 /* SplashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D268C51BF4F95200B682AE /* SplashViewController.m */; };\n\t\t22D97806215BC910005C2713 /* IgnoresTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D4309F171C663A003C0684 /* IgnoresTableViewController.m */; };\n\t\t22D97807215BC910005C2713 /* SpamViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 228F69721DF8A3F30079E276 /* SpamViewController.m */; };\n\t\t22D97809215BC910005C2713 /* SBJson5Writer.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C81E4A0BB600A243E7 /* SBJson5Writer.m */; };\n\t\t22D9780A215BC910005C2713 /* UIExpandingTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D430A31725AAEA003C0684 /* UIExpandingTextView.m */; };\n\t\t22D9780D215BC910005C2713 /* AvatarsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E54ADF1D10593B00891FE4 /* AvatarsDataSource.m */; };\n\t\t22D9780F215BC910005C2713 /* PastebinViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22C2E0561B0E2E4800387B4B /* PastebinViewController.m */; };\n\t\t22D97812215BC910005C2713 /* TSKNSURLSessionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324051E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m */; };\n\t\t22D97813215BC910005C2713 /* UIExpandingTextViewInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D430A51725AAEA003C0684 /* UIExpandingTextViewInternal.m */; };\n\t\t22D97814215BC910005C2713 /* OnePasswordExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A363B119D0884D00500478 /* OnePasswordExtension.m */; };\n\t\t22D97816215BC910005C2713 /* FileMetadataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22C2075B1A19125700EDACA4 /* FileMetadataViewController.m */; };\n\t\t22D97817215BC910005C2713 /* EditConnectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B15CF3172ECCFF0075EBA7 /* EditConnectionViewController.m */; };\n\t\t22D97818215BC910005C2713 /* reporting_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F81E8945D700ADAA22 /* reporting_utils.m */; };\n\t\t22D97819215BC910005C2713 /* ECSlidingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B15CF817301BAF0075EBA7 /* ECSlidingViewController.m */; };\n\t\t22D9781B215BC910005C2713 /* ssl_pin_verifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 229323F51E8945D700ADAA22 /* ssl_pin_verifier.m */; };\n\t\t22D9781C215BC910005C2713 /* CSURITemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D649231B1E0719003BFD86 /* CSURITemplate.m */; };\n\t\t22D97820215BC910005C2713 /* SBJson5StreamWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C41E4A0BB600A243E7 /* SBJson5StreamWriter.m */; };\n\t\t22D97821215BC910005C2713 /* SBJson5StreamParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80BE1E4A0BB600A243E7 /* SBJson5StreamParser.m */; };\n\t\t22D97822215BC910005C2713 /* PastebinsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D649291B1E371D003BFD86 /* PastebinsTableViewController.m */; };\n\t\t22D97824215BC910005C2713 /* UIImage+ImageWithUIView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B15CFA17301BAF0075EBA7 /* UIImage+ImageWithUIView.m */; };\n\t\t22D97825215BC910005C2713 /* OpenInChromeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2274F49E1756723F0039B4CB /* OpenInChromeController.m */; };\n\t\t22D97826215BC910005C2713 /* ChannelInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2212AF87175F82F900D08C7F /* ChannelInfoViewController.m */; };\n\t\t22D9782C215BC910005C2713 /* ImageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2223C6A81768D7150032544B /* ImageViewController.m */; };\n\t\t22D9782E215BC910005C2713 /* ChannelListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2253BA241770CD7100CCA77F /* ChannelListTableViewController.m */; };\n\t\t22D9782F215BC910005C2713 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 227FF8221772063F00394114 /* SettingsViewController.m */; };\n\t\t22D97830215BC910005C2713 /* CallerIDTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221F0BC4177368B40008EE04 /* CallerIDTableViewController.m */; };\n\t\t22D97831215BC910005C2713 /* WhoisViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A1D0261778A86900F8A89C /* WhoisViewController.m */; };\n\t\t22D97833215BC910005C2713 /* SBJson5StreamTokeniser.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C21E4A0BB600A243E7 /* SBJson5StreamTokeniser.m */; };\n\t\t22D97834215BC910005C2713 /* DisplayOptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 228EFBC7177B4F7300B83A4C /* DisplayOptionsViewController.m */; };\n\t\t22D97836215BC910005C2713 /* ARChromeActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 225017431783434800066E71 /* ARChromeActivity.m */; };\n\t\t22D97838215BC910005C2713 /* UIDevice+UIDevice_iPhone6Hax.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A363BB19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.m */; };\n\t\t22D9783A215BC910005C2713 /* TUSafariActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 225017601783434900066E71 /* TUSafariActivity.m */; };\n\t\t22D9783B215BC910005C2713 /* TSKPinningValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 2293240A1E8945D700ADAA22 /* TSKPinningValidator.m */; };\n\t\t22D9783C215BC910005C2713 /* WhoWasTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 226F080D1E6495C8003EED23 /* WhoWasTableViewController.m */; };\n\t\t22D9783D215BC910005C2713 /* LicenseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 224FCF351787288400FC3879 /* LicenseViewController.m */; };\n\t\t22D9783E215BC910005C2713 /* IRCCloudSafariViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 223C407B1C60FE880081B02B /* IRCCloudSafariViewController.m */; };\n\t\t22D9783F215BC910005C2713 /* WhoListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A35F25178A317100529CDA /* WhoListTableViewController.m */; };\n\t\t22D97843215BC910005C2713 /* registry_search.c in Sources */ = {isa = PBXBuildFile; fileRef = 229323E11E8945D700ADAA22 /* registry_search.c */; };\n\t\t22D97844215BC910005C2713 /* NamesListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A35F28178A3F3500529CDA /* NamesListTableViewController.m */; };\n\t\t22D97845215BC910005C2713 /* TextTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2271FDA01DCDF45C00A39F84 /* TextTableViewController.m */; };\n\t\t22D97846215BC910005C2713 /* SBJson5StreamWriterState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C61E4A0BB600A243E7 /* SBJson5StreamWriterState.m */; };\n\t\t22D97847215BC910005C2713 /* SBJson5StreamParserState.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80C01E4A0BB600A243E7 /* SBJson5StreamParserState.m */; };\n\t\t22D97848215BC910005C2713 /* TSKNSURLConnectionDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 229324031E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m */; };\n\t\t22D97849215BC910005C2713 /* ImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 222C80B51E48ABB200A243E7 /* ImageCache.m */; };\n\t\t22D9784D215BC910005C2713 /* UINavigationController+iPadSux.m in Sources */ = {isa = PBXBuildFile; fileRef = 22A19C5F178FCCAB00772C60 /* UINavigationController+iPadSux.m */; };\n\t\t22D9784F215BC910005C2713 /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2238761C1F70038A00943160 /* WebP.framework */; };\n\t\t22D97850215BC910005C2713 /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2289EF771D787CC500DB285E /* Intents.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22D97851215BC910005C2713 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2289EF621D7866BD00DB285E /* UserNotifications.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22D97852215BC910005C2713 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2265DC881C722E6B00382C7C /* MessageUI.framework */; };\n\t\t22D97853215BC910005C2713 /* SafariServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22A1F1141C232B3A00AEC09A /* SafariServices.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22D97854215BC910005C2713 /* AVKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2245E3761B542D0200B763D7 /* AVKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22D97855215BC910005C2713 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 229C85401B502920004964DE /* CoreMedia.framework */; };\n\t\t22D97856215BC910005C2713 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 226EB6001B4C2E8600C432C7 /* AVFoundation.framework */; };\n\t\t22D97857215BC910005C2713 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2284EF711B4AD47F0058D483 /* MediaPlayer.framework */; };\n\t\t22D97858215BC910005C2713 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2249867D1A95138800F6C3E2 /* AssetsLibrary.framework */; };\n\t\t22D97859215BC910005C2713 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A5703471A74145400D58225 /* AdSupport.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22D9785A215BC910005C2713 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22C8DCF21A801A4500199371 /* CloudKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\t22D9785B215BC910005C2713 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2200DB4618B7EDF100343583 /* QuartzCore.framework */; };\n\t\t22D9785C215BC910005C2713 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2283322F17944E2B00ED22EA /* AudioToolbox.framework */; };\n\t\t22D9785D215BC910005C2713 /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2250173F178340AB00066E71 /* Twitter.framework */; };\n\t\t22D9785E215BC910005C2713 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22324FDF177DE51A008B6912 /* SystemConfiguration.framework */; };\n\t\t22D9785F215BC910005C2713 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2223C6B51768F4500032544B /* ImageIO.framework */; };\n\t\t22D97861215BC910005C2713 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2248DF3816EE375D0086BB42 /* libz.dylib */; };\n\t\t22D97862215BC910005C2713 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 227DA89D1CF381B60041B1BF /* CoreTelephony.framework */; };\n\t\t22D97863215BC910005C2713 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05D516D3DFD00029769C /* CoreText.framework */; };\n\t\t22D97865215BC910005C2713 /* libc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 22C8CD701B01289900F637D2 /* libc++.dylib */; };\n\t\t22D97866215BC910005C2713 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CD16D3DD310029769C /* libicucore.dylib */; };\n\t\t22D97867215BC910005C2713 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CB16D3DCE20029769C /* Security.framework */; };\n\t\t22D97868215BC910005C2713 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A056F16D3DABA0029769C /* UIKit.framework */; };\n\t\t22D97869215BC910005C2713 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05C916D3DCB60029769C /* CFNetwork.framework */; };\n\t\t22D9786A215BC910005C2713 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057116D3DABA0029769C /* Foundation.framework */; };\n\t\t22D9786C215BC910005C2713 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057316D3DABA0029769C /* CoreGraphics.framework */; };\n\t\t22D9786F215BC910005C2713 /* Firefox.png in Resources */ = {isa = PBXBuildFile; fileRef = 22EE12811C9B20DF00E7AE8D /* Firefox.png */; };\n\t\t22D97870215BC910005C2713 /* Firefox@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 22EE12821C9B20DF00E7AE8D /* Firefox@2x.png */; };\n\t\t22D97871215BC910005C2713 /* Firefox@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 22EE12831C9B20DF00E7AE8D /* Firefox@3x.png */; };\n\t\t22D97872215BC910005C2713 /* SourceSansPro-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD691BAC61A900015753 /* SourceSansPro-Regular.otf */; };\n\t\t22D97873215BC910005C2713 /* SourceSansPro-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 225173E21DB13A5500D63405 /* SourceSansPro-Semibold.otf */; };\n\t\t22D97875215BC910005C2713 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 22D4F9101743F3790095EE8F /* Localizable.strings */; };\n\t\t22D97877215BC910005C2713 /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 22D268C11BF4F40800B682AE /* MainStoryboard.storyboard */; };\n\t\t22D97878215BC910005C2713 /* ARChromeActivity.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017441783434800066E71 /* ARChromeActivity.png */; };\n\t\t22D97879215BC910005C2713 /* ARChromeActivity@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017451783434800066E71 /* ARChromeActivity@2x.png */; };\n\t\t22D9787A215BC910005C2713 /* SourceSansPro-LightIt.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD681BAC61A900015753 /* SourceSansPro-LightIt.otf */; };\n\t\t22D9787B215BC910005C2713 /* Icons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22EEA95318D0B198007D5022 /* Icons.xcassets */; };\n\t\t22D9787C215BC910005C2713 /* FontAwesome.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2236BD621BAA5E0900015753 /* FontAwesome.otf */; };\n\t\t22D9787D215BC910005C2713 /* EventsTableCell_ReplyCount.xib in Resources */ = {isa = PBXBuildFile; fileRef = 225EC2BA2061678B00AA0C79 /* EventsTableCell_ReplyCount.xib */; };\n\t\t22D9787E215BC910005C2713 /* EventsTableCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 221EB2ED1F8F965E00A71428 /* EventsTableCell.xib */; };\n\t\t22D9787F215BC910005C2713 /* EventsTableCell_File.xib in Resources */ = {isa = PBXBuildFile; fileRef = 221EB2F21F962C2C00A71428 /* EventsTableCell_File.xib */; };\n\t\t22D97880215BC910005C2713 /* 1Password.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22A363AF19D0884D00500478 /* 1Password.xcassets */; };\n\t\t22D97881215BC910005C2713 /* Logo.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A7382AA18D0A9A30039FDB3 /* Logo.xcassets */; };\n\t\t22D97882215BC910005C2713 /* ARChromeActivity@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017461783434800066E71 /* ARChromeActivity@2x~ipad.png */; };\n\t\t22D97883215BC910005C2713 /* Hack-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671D1F28C3BB0075A18F /* Hack-BoldItalic.ttf */; };\n\t\t22D97884215BC910005C2713 /* ARChromeActivity~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017471783434800066E71 /* ARChromeActivity~ipad.png */; };\n\t\t22D97885215BC910005C2713 /* Safari.png in Resources */ = {isa = PBXBuildFile; fileRef = 225017591783434900066E71 /* Safari.png */; };\n\t\t22D97886215BC910005C2713 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22EEA95018D0B117007D5022 /* Images.xcassets */; };\n\t\t22D97887215BC910005C2713 /* EventsTableCell_Thumbnail.xib in Resources */ = {isa = PBXBuildFile; fileRef = 221EB2F31F962C2D00A71428 /* EventsTableCell_Thumbnail.xib */; };\n\t\t22D97888215BC910005C2713 /* ImageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 22EB4CF31CCEE296004F9CFC /* ImageViewController.xib */; };\n\t\t22D97889215BC910005C2713 /* Hack-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671E1F28C3BB0075A18F /* Hack-Italic.ttf */; };\n\t\t22D9788A215BC910005C2713 /* Safari@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2250175A1783434900066E71 /* Safari@2x.png */; };\n\t\t22D9788B215BC910005C2713 /* Safari@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 2250175B1783434900066E71 /* Safari@2x~ipad.png */; };\n\t\t22D9788C215BC910005C2713 /* Hack-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671C1F28C3BB0075A18F /* Hack-Bold.ttf */; };\n\t\t22D9788D215BC910005C2713 /* Launch.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 22F4A9C91CB5424F00359049 /* Launch.storyboard */; };\n\t\t22D9788E215BC910005C2713 /* Safari~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 2250175C1783434900066E71 /* Safari~ipad.png */; };\n\t\t22D9788F215BC910005C2713 /* licenses.txt in Resources */ = {isa = PBXBuildFile; fileRef = 224FCF321787286000FC3879 /* licenses.txt */; };\n\t\t22D97890215BC910005C2713 /* Hack-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2210671F1F28C3BB0075A18F /* Hack-Regular.ttf */; };\n\t\t22D97891215BC910005C2713 /* a.caf in Resources */ = {isa = PBXBuildFile; fileRef = 22F5C4BC1791F205005E09A9 /* a.caf */; };\n\t\t22D97892215BC910005C2713 /* TUSafariActivity.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2251693117B5A8040093ADC5 /* TUSafariActivity.strings */; };\n\t\t22D97895215BC910005C2713 /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 221034E7197EFBAF00AB414F /* ShareExtension.appex */; };\n\t\t22D97896215BC910005C2713 /* NotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 221D4B8D1E23EAD600D403E6 /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };\n\t\t22D9794A215BC979005C2713 /* FLEXArrayExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978A1215BC979005C2713 /* FLEXArrayExplorerViewController.m */; };\n\t\t22D9794B215BC979005C2713 /* FLEXObjectExplorerFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978A2215BC979005C2713 /* FLEXObjectExplorerFactory.m */; };\n\t\t22D9794C215BC979005C2713 /* FLEXGlobalsTableViewControllerEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978A5215BC979005C2713 /* FLEXGlobalsTableViewControllerEntry.m */; };\n\t\t22D9794D215BC979005C2713 /* FLEXImageExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978A6215BC979005C2713 /* FLEXImageExplorerViewController.m */; };\n\t\t22D9794E215BC979005C2713 /* FLEXClassExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978A8215BC979005C2713 /* FLEXClassExplorerViewController.m */; };\n\t\t22D9794F215BC979005C2713 /* FLEXDictionaryExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978A9215BC979005C2713 /* FLEXDictionaryExplorerViewController.m */; };\n\t\t22D97950215BC979005C2713 /* FLEXDefaultsExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978AA215BC979005C2713 /* FLEXDefaultsExplorerViewController.m */; };\n\t\t22D97951215BC979005C2713 /* FLEXViewControllerExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978AC215BC979005C2713 /* FLEXViewControllerExplorerViewController.m */; };\n\t\t22D97952215BC979005C2713 /* FLEXSetExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978AF215BC979005C2713 /* FLEXSetExplorerViewController.m */; };\n\t\t22D97953215BC979005C2713 /* FLEXLayerExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978B0215BC979005C2713 /* FLEXLayerExplorerViewController.m */; };\n\t\t22D97954215BC979005C2713 /* FLEXViewExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978B4215BC979005C2713 /* FLEXViewExplorerViewController.m */; };\n\t\t22D97955215BC979005C2713 /* FLEXObjectExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978B5215BC979005C2713 /* FLEXObjectExplorerViewController.m */; };\n\t\t22D97956215BC979005C2713 /* FLEXNetworkTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978BB215BC979005C2713 /* FLEXNetworkTransaction.m */; };\n\t\t22D97957215BC979005C2713 /* FLEXNetworkSettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978BD215BC979005C2713 /* FLEXNetworkSettingsTableViewController.m */; };\n\t\t22D97958215BC979005C2713 /* FLEXNetworkRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978BE215BC979005C2713 /* FLEXNetworkRecorder.m */; };\n\t\t22D97959215BC979005C2713 /* FLEXNetworkTransactionTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978C0215BC979005C2713 /* FLEXNetworkTransactionTableViewCell.m */; };\n\t\t22D9795A215BC979005C2713 /* FLEXNetworkCurlLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978C2215BC979005C2713 /* FLEXNetworkCurlLogger.m */; };\n\t\t22D9795B215BC979005C2713 /* FLEXNetworkTransactionDetailTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978C3215BC979005C2713 /* FLEXNetworkTransactionDetailTableViewController.m */; };\n\t\t22D9795C215BC979005C2713 /* FLEXNetworkHistoryTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978C6215BC979005C2713 /* FLEXNetworkHistoryTableViewController.m */; };\n\t\t22D9795D215BC979005C2713 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 22D978CA215BC979005C2713 /* LICENSE */; };\n\t\t22D9795E215BC979005C2713 /* FLEXNetworkObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978CB215BC979005C2713 /* FLEXNetworkObserver.m */; };\n\t\t22D9795F215BC979005C2713 /* FLEXToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978CD215BC979005C2713 /* FLEXToolbarItem.m */; };\n\t\t22D97960215BC979005C2713 /* FLEXExplorerToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978D0215BC979005C2713 /* FLEXExplorerToolbar.m */; };\n\t\t22D97961215BC979005C2713 /* FLEXManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978D3215BC979005C2713 /* FLEXManager.m */; };\n\t\t22D97962215BC979005C2713 /* FLEXPropertyEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978D6215BC979005C2713 /* FLEXPropertyEditorViewController.m */; };\n\t\t22D97963215BC979005C2713 /* FLEXDefaultEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978D7215BC979005C2713 /* FLEXDefaultEditorViewController.m */; };\n\t\t22D97964215BC979005C2713 /* FLEXMethodCallingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978DA215BC979005C2713 /* FLEXMethodCallingViewController.m */; };\n\t\t22D97965215BC979005C2713 /* FLEXIvarEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978DB215BC979005C2713 /* FLEXIvarEditorViewController.m */; };\n\t\t22D97966215BC979005C2713 /* FLEXFieldEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978DC215BC979005C2713 /* FLEXFieldEditorViewController.m */; };\n\t\t22D97967215BC979005C2713 /* FLEXArgumentInputStringView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978DF215BC979005C2713 /* FLEXArgumentInputStringView.m */; };\n\t\t22D97968215BC979005C2713 /* FLEXArgumentInputColorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978E0215BC979005C2713 /* FLEXArgumentInputColorView.m */; };\n\t\t22D97969215BC979005C2713 /* FLEXArgumentInputView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978E1215BC979005C2713 /* FLEXArgumentInputView.m */; };\n\t\t22D9796A215BC979005C2713 /* FLEXArgumentInputJSONObjectView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978E4215BC979005C2713 /* FLEXArgumentInputJSONObjectView.m */; };\n\t\t22D9796B215BC979005C2713 /* FLEXArgumentInputSwitchView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978E5215BC979005C2713 /* FLEXArgumentInputSwitchView.m */; };\n\t\t22D9796C215BC979005C2713 /* FLEXArgumentInputStructView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978E6215BC979005C2713 /* FLEXArgumentInputStructView.m */; };\n\t\t22D9796D215BC979005C2713 /* FLEXArgumentInputDateView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978E7215BC979005C2713 /* FLEXArgumentInputDateView.m */; };\n\t\t22D9796E215BC979005C2713 /* FLEXArgumentInputFontView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978EC215BC979005C2713 /* FLEXArgumentInputFontView.m */; };\n\t\t22D9796F215BC979005C2713 /* FLEXArgumentInputTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978F2215BC979005C2713 /* FLEXArgumentInputTextView.m */; };\n\t\t22D97970215BC979005C2713 /* FLEXArgumentInputFontsPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978F3215BC979005C2713 /* FLEXArgumentInputFontsPickerView.m */; };\n\t\t22D97971215BC979005C2713 /* FLEXArgumentInputNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978F4215BC979005C2713 /* FLEXArgumentInputNumberView.m */; };\n\t\t22D97972215BC979005C2713 /* FLEXArgumentInputViewFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978F7215BC979005C2713 /* FLEXArgumentInputViewFactory.m */; };\n\t\t22D97973215BC979005C2713 /* FLEXArgumentInputNotSupportedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978F8215BC979005C2713 /* FLEXArgumentInputNotSupportedView.m */; };\n\t\t22D97974215BC979005C2713 /* FLEXFieldEditorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978FB215BC979005C2713 /* FLEXFieldEditorView.m */; };\n\t\t22D97975215BC979005C2713 /* FLEXExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978FD215BC979005C2713 /* FLEXExplorerViewController.m */; };\n\t\t22D97976215BC979005C2713 /* FLEXWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D978FE215BC979005C2713 /* FLEXWindow.m */; };\n\t\t22D97977215BC979005C2713 /* FLEXFileBrowserSearchOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97904215BC979005C2713 /* FLEXFileBrowserSearchOperation.m */; };\n\t\t22D97978215BC979005C2713 /* FLEXObjectRef.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97905215BC979005C2713 /* FLEXObjectRef.m */; };\n\t\t22D97979215BC979005C2713 /* FLEXWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97906215BC979005C2713 /* FLEXWebViewController.m */; };\n\t\t22D9797A215BC979005C2713 /* FLEXInstancesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97907215BC979005C2713 /* FLEXInstancesTableViewController.m */; };\n\t\t22D9797B215BC979005C2713 /* FLEXFileBrowserTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D9790E215BC979005C2713 /* FLEXFileBrowserTableViewController.m */; };\n\t\t22D9797C215BC979005C2713 /* FLEXFileBrowserFileOperationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D9790F215BC979005C2713 /* FLEXFileBrowserFileOperationController.m */; };\n\t\t22D9797D215BC979005C2713 /* FLEXSystemLogTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97913215BC979005C2713 /* FLEXSystemLogTableViewController.m */; };\n\t\t22D9797E215BC979005C2713 /* FLEXSystemLogMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97915215BC979005C2713 /* FLEXSystemLogMessage.m */; };\n\t\t22D9797F215BC979005C2713 /* FLEXSystemLogTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97917215BC979005C2713 /* FLEXSystemLogTableViewCell.m */; };\n\t\t22D97980215BC979005C2713 /* FLEXTableLeftCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D9791B215BC979005C2713 /* FLEXTableLeftCell.m */; };\n\t\t22D97981215BC979005C2713 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 22D9791D215BC979005C2713 /* LICENSE */; };\n\t\t22D97982215BC979005C2713 /* FLEXTableContentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D9791F215BC979005C2713 /* FLEXTableContentViewController.m */; };\n\t\t22D97983215BC979005C2713 /* FLEXTableListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97920215BC979005C2713 /* FLEXTableListViewController.m */; };\n\t\t22D97984215BC979005C2713 /* FLEXTableColumnHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97921215BC979005C2713 /* FLEXTableColumnHeader.m */; };\n\t\t22D97985215BC979005C2713 /* FLEXMultiColumnTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97922215BC979005C2713 /* FLEXMultiColumnTableView.m */; };\n\t\t22D97986215BC979005C2713 /* FLEXTableContentCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97925215BC979005C2713 /* FLEXTableContentCell.m */; };\n\t\t22D97987215BC979005C2713 /* FLEXRealmDatabaseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97927215BC979005C2713 /* FLEXRealmDatabaseManager.m */; };\n\t\t22D97988215BC979005C2713 /* FLEXSQLiteDatabaseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97929215BC979005C2713 /* FLEXSQLiteDatabaseManager.m */; };\n\t\t22D97989215BC979005C2713 /* FLEXCookiesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D9792E215BC979005C2713 /* FLEXCookiesTableViewController.m */; };\n\t\t22D9798A215BC979005C2713 /* FLEXLibrariesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D9792F215BC979005C2713 /* FLEXLibrariesTableViewController.m */; };\n\t\t22D9798B215BC979005C2713 /* FLEXGlobalsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97930215BC979005C2713 /* FLEXGlobalsTableViewController.m */; };\n\t\t22D9798C215BC979005C2713 /* FLEXLiveObjectsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97931215BC979005C2713 /* FLEXLiveObjectsTableViewController.m */; };\n\t\t22D9798D215BC979005C2713 /* FLEXClassesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97932215BC979005C2713 /* FLEXClassesTableViewController.m */; };\n\t\t22D9798E215BC979005C2713 /* FLEXHierarchyTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97934215BC979005C2713 /* FLEXHierarchyTableViewCell.m */; };\n\t\t22D9798F215BC979005C2713 /* FLEXImagePreviewViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97935215BC979005C2713 /* FLEXImagePreviewViewController.m */; };\n\t\t22D97990215BC979005C2713 /* FLEXHierarchyTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97938215BC979005C2713 /* FLEXHierarchyTableViewController.m */; };\n\t\t22D97991215BC979005C2713 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 22D9793A215BC979005C2713 /* Info.plist */; };\n\t\t22D97992215BC979005C2713 /* FLEXUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D9793C215BC979005C2713 /* FLEXUtility.m */; };\n\t\t22D97993215BC979005C2713 /* FLEXHeapEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D9793D215BC979005C2713 /* FLEXHeapEnumerator.m */; };\n\t\t22D97994215BC979005C2713 /* FLEXRuntimeUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97940215BC979005C2713 /* FLEXRuntimeUtility.m */; };\n\t\t22D97995215BC979005C2713 /* FLEXKeyboardShortcutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97942215BC979005C2713 /* FLEXKeyboardShortcutManager.m */; };\n\t\t22D97996215BC979005C2713 /* FLEXKeyboardHelpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97945215BC979005C2713 /* FLEXKeyboardHelpViewController.m */; };\n\t\t22D97997215BC979005C2713 /* FLEXResources.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97946215BC979005C2713 /* FLEXResources.m */; };\n\t\t22D97998215BC979005C2713 /* FLEXMultilineTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 22D97949215BC979005C2713 /* FLEXMultilineTableViewCell.m */; };\n\t\t22DB24FC1982DF2B0008728E /* UIColor+IRCCloud.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F63B16DBF3CB007BE535 /* UIColor+IRCCloud.m */; };\n\t\t22DB24FD1982DF2B0008728E /* HighlightsCountView.m in Sources */ = {isa = PBXBuildFile; fileRef = 227FF2A016FA128B00DBE3C5 /* HighlightsCountView.m */; };\n\t\t22DB24FE1982DF2B0008728E /* BuffersTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60516DBCA85007BE535 /* BuffersTableView.m */; };\n\t\t22DB24FF1982DF2B0008728E /* Ignore.m in Sources */ = {isa = PBXBuildFile; fileRef = 2230F8E717162ACC007F7C98 /* Ignore.m */; };\n\t\t22DB25001982DF2B0008728E /* BuffersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5FD16DA8928007BE535 /* BuffersDataSource.m */; };\n\t\t22DB25011982DF2B0008728E /* ChannelsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F60116DBC021007BE535 /* ChannelsDataSource.m */; };\n\t\t22DB25021982DF2B0008728E /* EventsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F9EE1B16DE6F21004615C0 /* EventsDataSource.m */; };\n\t\t22DB25041982DF2B0008728E /* IRCCloudJSONObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4288516D846BF00498507 /* IRCCloudJSONObject.m */; };\n\t\t22DB25051982DF2B0008728E /* NetworkConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4284716D7E36300498507 /* NetworkConnection.m */; };\n\t\t22DB25061982DF2B0008728E /* ServersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F5F916DA765C007BE535 /* ServersDataSource.m */; };\n\t\t22DB25071982DF2B0008728E /* UsersDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 2236F64516DD138B007BE535 /* UsersDataSource.m */; };\n\t\t22DB25171982DF2B0008728E /* HandshakeHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285016D831A800498507 /* HandshakeHeader.m */; };\n\t\t22DB25181982DF2B0008728E /* MutableQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285216D831A800498507 /* MutableQueue.m */; };\n\t\t22DB25191982DF2B0008728E /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285416D831A800498507 /* NSData+Base64.m */; };\n\t\t22DB251A1982DF2B0008728E /* WebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4285716D831A800498507 /* WebSocket.m */; };\n\t\t22DB251B1982DF2B0008728E /* WebSocketConnectConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286116D831A800498507 /* WebSocketConnectConfig.m */; };\n\t\t22DB251C1982DF2B0008728E /* WebSocketFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286316D831A800498507 /* WebSocketFragment.m */; };\n\t\t22DB251D1982DF2B0008728E /* WebSocketMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 22B4286516D831A800498507 /* WebSocketMessage.m */; };\n\t\t22DB251E1982DF2B0008728E /* ShareViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 221034EC197EFBAF00AB414F /* ShareViewController.m */; };\n\t\t22DB25211982DF2B0008728E /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2200DB4618B7EDF100343583 /* QuartzCore.framework */; };\n\t\t22DB25221982DF2B0008728E /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2283322F17944E2B00ED22EA /* AudioToolbox.framework */; };\n\t\t22DB25231982DF2B0008728E /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05C916D3DCB60029769C /* CFNetwork.framework */; };\n\t\t22DB25241982DF2B0008728E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057316D3DABA0029769C /* CoreGraphics.framework */; };\n\t\t22DB25251982DF2B0008728E /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05D516D3DFD00029769C /* CoreText.framework */; };\n\t\t22DB25261982DF2B0008728E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A057116D3DABA0029769C /* Foundation.framework */; };\n\t\t22DB25271982DF2B0008728E /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2223C6B51768F4500032544B /* ImageIO.framework */; };\n\t\t22DB25281982DF2B0008728E /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CD16D3DD310029769C /* libicucore.dylib */; };\n\t\t22DB25291982DF2B0008728E /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2248DF3816EE375D0086BB42 /* libz.dylib */; };\n\t\t22DB252B1982DF2B0008728E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A05CB16D3DCE20029769C /* Security.framework */; };\n\t\t22DB252C1982DF2B0008728E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22324FDF177DE51A008B6912 /* SystemConfiguration.framework */; };\n\t\t22DB252D1982DF2B0008728E /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2250173F178340AB00066E71 /* Twitter.framework */; };\n\t\t22DB252E1982DF2B0008728E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228A056F16D3DABA0029769C /* UIKit.framework */; };\n\t\t22DB25301982DF2B0008728E /* Icons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22EEA95318D0B198007D5022 /* Icons.xcassets */; };\n\t\t22DB25391982DFFB0008728E /* ShareExtension Enterprise.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 22DB25371982DF2B0008728E /* ShareExtension Enterprise.appex */; };\n\t\t22DB253F1982E3100008728E /* EnterpriseLogo.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A7382A918D0A9A30039FDB3 /* EnterpriseLogo.xcassets */; };\n\t\t22DB25401982E3130008728E /* EnterpriseImages.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22EEA94D18D0AC08007D5022 /* EnterpriseImages.xcassets */; };\n\t\t22DB8D701C441C3000302271 /* YouTubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22DB8D6F1C441C3000302271 /* YouTubeViewController.m */; };\n\t\t22DB8D711C441C3000302271 /* YouTubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22DB8D6F1C441C3000302271 /* YouTubeViewController.m */; };\n\t\t22E54AE01D10593B00891FE4 /* AvatarsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E54ADF1D10593B00891FE4 /* AvatarsDataSource.m */; };\n\t\t22E54AE11D10593B00891FE4 /* AvatarsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E54ADF1D10593B00891FE4 /* AvatarsDataSource.m */; };\n\t\t22E9C0AB1C9AF27800013456 /* OpenInFirefoxControllerObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E9C0A81C9AF27800013456 /* OpenInFirefoxControllerObjC.m */; };\n\t\t22E9C0AC1C9AF27800013456 /* OpenInFirefoxControllerObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E9C0A81C9AF27800013456 /* OpenInFirefoxControllerObjC.m */; };\n\t\t22EB4CF41CCEE298004F9CFC /* ImageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 22EB4CF31CCEE296004F9CFC /* ImageViewController.xib */; };\n\t\t22EB4CF51CCEE2ED004F9CFC /* ImageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 22EB4CF31CCEE296004F9CFC /* ImageViewController.xib */; };\n\t\t22EE12841C9B20DF00E7AE8D /* Firefox.png in Resources */ = {isa = PBXBuildFile; fileRef = 22EE12811C9B20DF00E7AE8D /* Firefox.png */; };\n\t\t22EE12851C9B20DF00E7AE8D /* Firefox.png in Resources */ = {isa = PBXBuildFile; fileRef = 22EE12811C9B20DF00E7AE8D /* Firefox.png */; };\n\t\t22EE12861C9B20DF00E7AE8D /* Firefox@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 22EE12821C9B20DF00E7AE8D /* Firefox@2x.png */; };\n\t\t22EE12871C9B20DF00E7AE8D /* Firefox@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 22EE12821C9B20DF00E7AE8D /* Firefox@2x.png */; };\n\t\t22EE12881C9B20DF00E7AE8D /* Firefox@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 22EE12831C9B20DF00E7AE8D /* Firefox@3x.png */; };\n\t\t22EE12891C9B20DF00E7AE8D /* Firefox@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 22EE12831C9B20DF00E7AE8D /* Firefox@3x.png */; };\n\t\t22EE41FA1F39F66E00D74E8C /* IRCColorPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22EE41F91F39F66E00D74E8C /* IRCColorPickerView.m */; };\n\t\t22EE41FB1F39F66E00D74E8C /* IRCColorPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 22EE41F91F39F66E00D74E8C /* IRCColorPickerView.m */; };\n\t\t22EEA94E18D0AC08007D5022 /* EnterpriseImages.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22EEA94D18D0AC08007D5022 /* EnterpriseImages.xcassets */; };\n\t\t22EEA95118D0B117007D5022 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22EEA95018D0B117007D5022 /* Images.xcassets */; };\n\t\t22EEA95418D0B198007D5022 /* Icons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22EEA95318D0B198007D5022 /* Icons.xcassets */; };\n\t\t22EEA95518D0B198007D5022 /* Icons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22EEA95318D0B198007D5022 /* Icons.xcassets */; };\n\t\t22F4A9CA1CB5424F00359049 /* Launch.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 22F4A9C91CB5424F00359049 /* Launch.storyboard */; };\n\t\t22F4A9CB1CB5424F00359049 /* Launch.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 22F4A9C91CB5424F00359049 /* Launch.storyboard */; };\n\t\t22F5C4BD1791F205005E09A9 /* a.caf in Resources */ = {isa = PBXBuildFile; fileRef = 22F5C4BC1791F205005E09A9 /* a.caf */; };\n\t\t22F9EE1C16DE6F21004615C0 /* EventsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F9EE1B16DE6F21004615C0 /* EventsDataSource.m */; };\n\t\t826532809086053E3C7D2EB6 /* Pods_ShareExtension_Enterprise.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A73CF12F2D9AAE13001191EB /* Pods_ShareExtension_Enterprise.framework */; };\n\t\t87D94430F2552C5FA140827E /* Pods_IRCCloud.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF5FD1784D881FDA33CC2709 /* Pods_IRCCloud.framework */; };\n\t\t8B5FE5762F34C236ED73DA2C /* Pods_ShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE030EB298B99F1ED0BF22D4 /* Pods_ShareExtension.framework */; };\n\t\tE3825E2339F2B2720FC1A112 /* Pods_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CF6A7B20BFBB01BD7B6F779 /* Pods_NotificationService.framework */; };\n\t\tE547E10E785196EBC983B6FE /* Pods_IRCCloud_Enterprise.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9BC3C6EDB06DAA456CC4E8A /* Pods_IRCCloud_Enterprise.framework */; };\n\t\tE73463A6EBBD7BC26D20DE95 /* Pods_IRCCloud_FLEX.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9687F6412D04D07E40F1CA5D /* Pods_IRCCloud_FLEX.framework */; };\n\t\tF1777B5C1D0CB8498FBFCAF5 /* Pods_NotificationService_Enterprise.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 19B9BF768BEB6B7F454BD143 /* Pods_NotificationService_Enterprise.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t221034F0197EFBAF00AB414F /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 221034E6197EFBAF00AB414F;\n\t\t\tremoteInfo = ShareExtension;\n\t\t};\n\t\t221034F3197EFBAF00AB414F /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 221034E6197EFBAF00AB414F;\n\t\t\tremoteInfo = ShareExtension;\n\t\t};\n\t\t221D4B931E23EAD700D403E6 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 221D4B8C1E23EAD600D403E6;\n\t\t\tremoteInfo = NotificationService;\n\t\t};\n\t\t221D4BA81E23F0FC00D403E6 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 221D4B9A1E23EB4900D403E6;\n\t\t\tremoteInfo = \"NotificationService Enterprise\";\n\t\t};\n\t\t22322CC920E549AA00AC54CD /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 22DE05B118D8CA0700590FC3;\n\t\t\tremoteInfo = GitRevision;\n\t\t};\n\t\t22322CCB20E549B100AC54CD /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 22DE05B118D8CA0700590FC3;\n\t\t\tremoteInfo = GitRevision;\n\t\t};\n\t\t224589C91DCA19BB00D3110A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 228A056B16D3DABA0029769C;\n\t\t\tremoteInfo = IRCCloud;\n\t\t};\n\t\t22CE2AE11D2AA662001397C0 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 228A056B16D3DABA0029769C;\n\t\t\tremoteInfo = IRCCloud;\n\t\t};\n\t\t22D97786215BC910005C2713 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 22DE05B118D8CA0700590FC3;\n\t\t\tremoteInfo = GitRevision;\n\t\t};\n\t\t22D97788215BC910005C2713 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 221034E6197EFBAF00AB414F;\n\t\t\tremoteInfo = ShareExtension;\n\t\t};\n\t\t22D9778A215BC910005C2713 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 221034E6197EFBAF00AB414F;\n\t\t\tremoteInfo = ShareExtension;\n\t\t};\n\t\t22D9778C215BC910005C2713 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 221D4B8C1E23EAD600D403E6;\n\t\t\tremoteInfo = NotificationService;\n\t\t};\n\t\t22DB253A1982DFFB0008728E /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 22DB24FA1982DF2B0008728E;\n\t\t\tremoteInfo = \"ShareExtension Enterprise\";\n\t\t};\n\t\t22DE05B618D8CA4800590FC3 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 22DE05B118D8CA0700590FC3;\n\t\t\tremoteInfo = GitRevision;\n\t\t};\n\t\t22DE05B818D8CA4F00590FC3 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 22DE05B118D8CA0700590FC3;\n\t\t\tremoteInfo = GitRevision;\n\t\t};\n\t\t22E7140F19D9D18200E11D96 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 22DE05B118D8CA0700590FC3;\n\t\t\tremoteInfo = GitRevision;\n\t\t};\n\t\t22E7141119D9D18700E11D96 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 228A056416D3DABA0029769C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 22DE05B118D8CA0700590FC3;\n\t\t\tremoteInfo = GitRevision;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t226E642123F1C696001CE069 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 7;\n\t\t\tfiles = (\n\t\t\t\t226E642323F1C6AA001CE069 /* GoogleService-Info.plist in CopyFiles */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22772F91197EC42E001A9890 /* Embed Foundation Extensions */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 13;\n\t\t\tfiles = (\n\t\t\t\t221034F2197EFBAF00AB414F /* ShareExtension.appex in Embed Foundation Extensions */,\n\t\t\t\t221D4B951E23EAD700D403E6 /* NotificationService.appex in Embed Foundation Extensions */,\n\t\t\t);\n\t\t\tname = \"Embed Foundation Extensions\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22D97894215BC910005C2713 /* Embed Foundation Extensions */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 13;\n\t\t\tfiles = (\n\t\t\t\t22D97895215BC910005C2713 /* ShareExtension.appex in Embed Foundation Extensions */,\n\t\t\t\t22D97896215BC910005C2713 /* NotificationService.appex in Embed Foundation Extensions */,\n\t\t\t);\n\t\t\tname = \"Embed Foundation Extensions\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22DB253C1982DFFB0008728E /* Embed Foundation Extensions */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 13;\n\t\t\tfiles = (\n\t\t\t\t221D4BA71E23ECB200D403E6 /* NotificationService Enterprise.appex in Embed Foundation Extensions */,\n\t\t\t\t22DB25391982DFFB0008728E /* ShareExtension Enterprise.appex in Embed Foundation Extensions */,\n\t\t\t);\n\t\t\tname = \"Embed Foundation Extensions\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t096184601771D02417AC2EA7 /* Pods-IRCCloud Enterprise.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloud Enterprise.debug.xcconfig\"; path = \"Target Support Files/Pods-IRCCloud Enterprise/Pods-IRCCloud Enterprise.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t1235543CBD3AE11C697E1C64 /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-NotificationService.debug.xcconfig\"; path = \"Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t19B9BF768BEB6B7F454BD143 /* Pods_NotificationService_Enterprise.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService_Enterprise.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t1A5703471A74145400D58225 /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; };\n\t\t1A61413D1E6EDF30004B6025 /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/AdSupport.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1A61413E1E6EDF30004B6025 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/AVFoundation.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1A61413F1E6EDF30004B6025 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1A6141401E6EDF30004B6025 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1A6141411E6EDF30004B6025 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/CoreText.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1A6141421E6EDF30004B6025 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1A6141431E6EDF30004B6025 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1A6141441E6EDF30004B6025 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1A6141451E6EDF30004B6025 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1A6141461E6EDF30004B6025 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1A7382A918D0A9A30039FDB3 /* EnterpriseLogo.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = EnterpriseLogo.xcassets; sourceTree = \"<group>\"; };\n\t\t1A7382AA18D0A9A30039FDB3 /* Logo.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Logo.xcassets; sourceTree = \"<group>\"; };\n\t\t1ADCE22D1D2FCD78000B379F /* UITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UITests.swift; sourceTree = \"<group>\"; };\n\t\t1BBDF60D720CF290BFDB54FA /* Pods-IRCCloud Enterprise.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloud Enterprise.appstore.xcconfig\"; path = \"Target Support Files/Pods-IRCCloud Enterprise/Pods-IRCCloud Enterprise.appstore.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t1C7FC0255C6F93D841E44603 /* Pods-IRCCloud FLEX.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloud FLEX.release.xcconfig\"; path = \"Target Support Files/Pods-IRCCloud FLEX/Pods-IRCCloud FLEX.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t2200DB4618B7EDF100343583 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };\n\t\t2200DB4D18B81BEB00343583 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = \"<group>\"; };\n\t\t22032A6D1884529700BE4A10 /* NickCompletionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NickCompletionView.h; sourceTree = \"<group>\"; };\n\t\t22032A6E1884529700BE4A10 /* NickCompletionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NickCompletionView.m; sourceTree = \"<group>\"; };\n\t\t220E79AB2D0A095C00414B0F /* VERSION */ = {isa = PBXFileReference; lastKnownFileType = text; name = VERSION; path = \"build-scripts/VERSION\"; sourceTree = SOURCE_ROOT; };\n\t\t221034E7197EFBAF00AB414F /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = \"wrapper.app-extension\"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t221034EA197EFBAF00AB414F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t221034EB197EFBAF00AB414F /* ShareViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShareViewController.h; sourceTree = \"<group>\"; };\n\t\t221034EC197EFBAF00AB414F /* ShareViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ShareViewController.m; sourceTree = \"<group>\"; };\n\t\t2210671C1F28C3BB0075A18F /* Hack-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"Hack-Bold.ttf\"; sourceTree = \"<group>\"; };\n\t\t2210671D1F28C3BB0075A18F /* Hack-BoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"Hack-BoldItalic.ttf\"; sourceTree = \"<group>\"; };\n\t\t2210671E1F28C3BB0075A18F /* Hack-Italic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"Hack-Italic.ttf\"; sourceTree = \"<group>\"; };\n\t\t2210671F1F28C3BB0075A18F /* Hack-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"Hack-Regular.ttf\"; sourceTree = \"<group>\"; };\n\t\t2212AF86175F82F900D08C7F /* ChannelInfoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChannelInfoViewController.h; sourceTree = \"<group>\"; };\n\t\t2212AF87175F82F900D08C7F /* ChannelInfoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChannelInfoViewController.m; sourceTree = \"<group>\"; };\n\t\t221390FC1B115CD000ECF001 /* PastebinEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PastebinEditorViewController.h; sourceTree = \"<group>\"; };\n\t\t221390FD1B115CD000ECF001 /* PastebinEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PastebinEditorViewController.m; sourceTree = \"<group>\"; };\n\t\t221D4B851E1BE2F700D403E6 /* LinksListTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LinksListTableViewController.m; sourceTree = \"<group>\"; };\n\t\t221D4B881E1BE30700D403E6 /* LinksListTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinksListTableViewController.h; sourceTree = \"<group>\"; };\n\t\t221D4B8D1E23EAD600D403E6 /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = \"wrapper.app-extension\"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t221D4B8F1E23EAD700D403E6 /* NotificationService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NotificationService.h; sourceTree = \"<group>\"; };\n\t\t221D4B901E23EAD700D403E6 /* NotificationService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NotificationService.m; sourceTree = \"<group>\"; };\n\t\t221D4B921E23EAD700D403E6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t221D4BA31E23EB4900D403E6 /* NotificationService Enterprise.appex */ = {isa = PBXFileReference; explicitFileType = \"wrapper.app-extension\"; includeInIndex = 0; path = \"NotificationService Enterprise.appex\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t221D4BAA1E23F24000D403E6 /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = \"<group>\"; };\n\t\t221D4BAB1E23F24F00D403E6 /* NotificationService Enterprise.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = \"NotificationService Enterprise.entitlements\"; sourceTree = SOURCE_ROOT; };\n\t\t221E3F4A1AD2DEE00090934B /* FilesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilesTableViewController.h; sourceTree = \"<group>\"; };\n\t\t221E3F4B1AD2DEE00090934B /* FilesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FilesTableViewController.m; sourceTree = \"<group>\"; };\n\t\t221E85F0241FBD9300EB5120 /* PinReorderViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PinReorderViewController.m; sourceTree = \"<group>\"; };\n\t\t221E85F1241FBD9300EB5120 /* PinReorderViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PinReorderViewController.h; sourceTree = \"<group>\"; };\n\t\t221EB2ED1F8F965E00A71428 /* EventsTableCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EventsTableCell.xib; sourceTree = \"<group>\"; };\n\t\t221EB2F21F962C2C00A71428 /* EventsTableCell_File.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EventsTableCell_File.xib; sourceTree = \"<group>\"; };\n\t\t221EB2F31F962C2D00A71428 /* EventsTableCell_Thumbnail.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EventsTableCell_Thumbnail.xib; sourceTree = \"<group>\"; };\n\t\t221F0BC3177368A20008EE04 /* CallerIDTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallerIDTableViewController.h; sourceTree = \"<group>\"; };\n\t\t221F0BC4177368B40008EE04 /* CallerIDTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CallerIDTableViewController.m; sourceTree = \"<group>\"; };\n\t\t2223C6A71768D7150032544B /* ImageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageViewController.h; sourceTree = \"<group>\"; };\n\t\t2223C6A81768D7150032544B /* ImageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageViewController.m; sourceTree = \"<group>\"; };\n\t\t2223C6B51768F4500032544B /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; };\n\t\t222C80B41E48ABB200A243E7 /* ImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageCache.h; sourceTree = \"<group>\"; };\n\t\t222C80B51E48ABB200A243E7 /* ImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageCache.m; sourceTree = \"<group>\"; };\n\t\t222C80BA1E4A0BB600A243E7 /* SBJson5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJson5.h; sourceTree = \"<group>\"; };\n\t\t222C80BB1E4A0BB600A243E7 /* SBJson5Parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJson5Parser.h; sourceTree = \"<group>\"; };\n\t\t222C80BC1E4A0BB600A243E7 /* SBJson5Parser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJson5Parser.m; sourceTree = \"<group>\"; };\n\t\t222C80BD1E4A0BB600A243E7 /* SBJson5StreamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJson5StreamParser.h; sourceTree = \"<group>\"; };\n\t\t222C80BE1E4A0BB600A243E7 /* SBJson5StreamParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJson5StreamParser.m; sourceTree = \"<group>\"; };\n\t\t222C80BF1E4A0BB600A243E7 /* SBJson5StreamParserState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJson5StreamParserState.h; sourceTree = \"<group>\"; };\n\t\t222C80C01E4A0BB600A243E7 /* SBJson5StreamParserState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJson5StreamParserState.m; sourceTree = \"<group>\"; };\n\t\t222C80C11E4A0BB600A243E7 /* SBJson5StreamTokeniser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJson5StreamTokeniser.h; sourceTree = \"<group>\"; };\n\t\t222C80C21E4A0BB600A243E7 /* SBJson5StreamTokeniser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJson5StreamTokeniser.m; sourceTree = \"<group>\"; };\n\t\t222C80C31E4A0BB600A243E7 /* SBJson5StreamWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJson5StreamWriter.h; sourceTree = \"<group>\"; };\n\t\t222C80C41E4A0BB600A243E7 /* SBJson5StreamWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJson5StreamWriter.m; sourceTree = \"<group>\"; };\n\t\t222C80C51E4A0BB600A243E7 /* SBJson5StreamWriterState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJson5StreamWriterState.h; sourceTree = \"<group>\"; };\n\t\t222C80C61E4A0BB600A243E7 /* SBJson5StreamWriterState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJson5StreamWriterState.m; sourceTree = \"<group>\"; };\n\t\t222C80C71E4A0BB600A243E7 /* SBJson5Writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJson5Writer.h; sourceTree = \"<group>\"; };\n\t\t222C80C81E4A0BB600A243E7 /* SBJson5Writer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJson5Writer.m; sourceTree = \"<group>\"; };\n\t\t2230F8E41715E61F007F7C98 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };\n\t\t2230F8E617162ACC007F7C98 /* Ignore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Ignore.h; sourceTree = \"<group>\"; };\n\t\t2230F8E717162ACC007F7C98 /* Ignore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Ignore.m; sourceTree = \"<group>\"; };\n\t\t223154FB1F26245800BDE367 /* LogExportsTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogExportsTableViewController.h; sourceTree = \"<group>\"; };\n\t\t223154FC1F26245800BDE367 /* LogExportsTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LogExportsTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22324FDF177DE51A008B6912 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };\n\t\t2232ABD4230C1D66007431B5 /* UITableViewController+HeaderColorFix.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"UITableViewController+HeaderColorFix.h\"; sourceTree = \"<group>\"; };\n\t\t2232ABD5230C1D66007431B5 /* UITableViewController+HeaderColorFix.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = \"UITableViewController+HeaderColorFix.m\"; sourceTree = \"<group>\"; };\n\t\t2236193728B5435F0077C850 /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/System/Library/Frameworks/Intents.framework; sourceTree = DEVELOPER_DIR; };\n\t\t2236193928B54D970077C850 /* IntentsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IntentsUI.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/System/iOSSupport/System/Library/Frameworks/IntentsUI.framework; sourceTree = DEVELOPER_DIR; };\n\t\t2236BD621BAA5E0900015753 /* FontAwesome.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = FontAwesome.otf; sourceTree = \"<group>\"; };\n\t\t2236BD671BAA600900015753 /* FontAwesome.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FontAwesome.h; path = Classes/FontAwesome.h; sourceTree = \"<group>\"; };\n\t\t2236BD681BAC61A900015753 /* SourceSansPro-LightIt.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"SourceSansPro-LightIt.otf\"; sourceTree = \"<group>\"; };\n\t\t2236BD691BAC61A900015753 /* SourceSansPro-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"SourceSansPro-Regular.otf\"; sourceTree = \"<group>\"; };\n\t\t2236F5F816DA765C007BE535 /* ServersDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServersDataSource.h; sourceTree = \"<group>\"; };\n\t\t2236F5F916DA765C007BE535 /* ServersDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ServersDataSource.m; sourceTree = \"<group>\"; };\n\t\t2236F5FC16DA8928007BE535 /* BuffersDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuffersDataSource.h; sourceTree = \"<group>\"; };\n\t\t2236F5FD16DA8928007BE535 /* BuffersDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BuffersDataSource.m; sourceTree = \"<group>\"; };\n\t\t2236F60016DBC020007BE535 /* ChannelsDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChannelsDataSource.h; sourceTree = \"<group>\"; };\n\t\t2236F60116DBC021007BE535 /* ChannelsDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChannelsDataSource.m; sourceTree = \"<group>\"; };\n\t\t2236F60416DBCA85007BE535 /* BuffersTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuffersTableView.h; sourceTree = \"<group>\"; };\n\t\t2236F60516DBCA85007BE535 /* BuffersTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BuffersTableView.m; sourceTree = \"<group>\"; };\n\t\t2236F60816DBCBC6007BE535 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = \"<group>\"; };\n\t\t2236F60916DBCBC6007BE535 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = \"<group>\"; };\n\t\t2236F63A16DBF3CA007BE535 /* UIColor+IRCCloud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"UIColor+IRCCloud.h\"; sourceTree = \"<group>\"; };\n\t\t2236F63B16DBF3CB007BE535 /* UIColor+IRCCloud.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"UIColor+IRCCloud.m\"; sourceTree = \"<group>\"; };\n\t\t2236F64416DD138A007BE535 /* UsersDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UsersDataSource.h; sourceTree = \"<group>\"; };\n\t\t2236F64516DD138B007BE535 /* UsersDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UsersDataSource.m; sourceTree = \"<group>\"; };\n\t\t2236F64816DD30E0007BE535 /* UsersTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UsersTableView.h; sourceTree = \"<group>\"; };\n\t\t2236F64916DD30E3007BE535 /* UsersTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UsersTableView.m; sourceTree = \"<group>\"; };\n\t\t22374408252C9D3C0085D41C /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };\n\t\t2237E13B16E1214A00CA188F /* ColorFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorFormatter.h; sourceTree = \"<group>\"; };\n\t\t2237E13C16E1214A00CA188F /* ColorFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ColorFormatter.m; sourceTree = \"<group>\"; };\n\t\t223876111F70035300943160 /* YYAnimatedImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YYAnimatedImageView.h; sourceTree = \"<group>\"; };\n\t\t223876121F70035300943160 /* YYAnimatedImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YYAnimatedImageView.m; sourceTree = \"<group>\"; };\n\t\t223876131F70035300943160 /* YYFrameImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YYFrameImage.h; sourceTree = \"<group>\"; };\n\t\t223876141F70035300943160 /* YYFrameImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YYFrameImage.m; sourceTree = \"<group>\"; };\n\t\t223876151F70035300943160 /* YYImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YYImage.h; sourceTree = \"<group>\"; };\n\t\t223876161F70035300943160 /* YYImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YYImage.m; sourceTree = \"<group>\"; };\n\t\t223876171F70035300943160 /* YYImageCoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YYImageCoder.h; sourceTree = \"<group>\"; };\n\t\t223876181F70035300943160 /* YYImageCoder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YYImageCoder.m; sourceTree = \"<group>\"; };\n\t\t223876191F70035300943160 /* YYSpriteSheetImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YYSpriteSheetImage.h; sourceTree = \"<group>\"; };\n\t\t2238761A1F70035300943160 /* YYSpriteSheetImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YYSpriteSheetImage.m; sourceTree = \"<group>\"; };\n\t\t2238761B1F70036900943160 /* WebP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebP.framework; sourceTree = SOURCE_ROOT; };\n\t\t2238761C1F70038A00943160 /* WebP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebP.framework; sourceTree = \"<group>\"; };\n\t\t223C407A1C60FE880081B02B /* IRCCloudSafariViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRCCloudSafariViewController.h; sourceTree = \"<group>\"; };\n\t\t223C407B1C60FE880081B02B /* IRCCloudSafariViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IRCCloudSafariViewController.m; sourceTree = \"<group>\"; };\n\t\t223DA90A16DFC626006FF808 /* EventsTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventsTableView.h; sourceTree = \"<group>\"; };\n\t\t223DA90B16DFC626006FF808 /* EventsTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EventsTableView.m; sourceTree = \"<group>\"; };\n\t\t224291641EB22B1000878455 /* URLtoBIDTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = URLtoBIDTests.m; sourceTree = \"<group>\"; };\n\t\t224333CE20162C1B0007A0D3 /* AvatarsTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvatarsTableViewController.h; sourceTree = \"<group>\"; };\n\t\t224333CF20162C1B0007A0D3 /* AvatarsTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AvatarsTableViewController.m; sourceTree = \"<group>\"; };\n\t\t224589C41DCA19BB00D3110A /* IRCCloudUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IRCCloudUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t224589C61DCA19BB00D3110A /* CollapsedEventsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CollapsedEventsTests.m; sourceTree = \"<group>\"; };\n\t\t224589C81DCA19BB00D3110A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t2245E3761B542D0200B763D7 /* AVKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVKit.framework; path = System/Library/Frameworks/AVKit.framework; sourceTree = SDKROOT; };\n\t\t22462B5018906B03009EF986 /* ServerReorderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServerReorderViewController.h; sourceTree = \"<group>\"; };\n\t\t22462B5118906B03009EF986 /* ServerReorderViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ServerReorderViewController.m; sourceTree = \"<group>\"; };\n\t\t2248DF3816EE375D0086BB42 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };\n\t\t2249867D1A95138800F6C3E2 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; };\n\t\t224FCF321787286000FC3879 /* licenses.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = licenses.txt; sourceTree = \"<group>\"; };\n\t\t224FCF341787288400FC3879 /* LicenseViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LicenseViewController.h; sourceTree = \"<group>\"; };\n\t\t224FCF351787288400FC3879 /* LicenseViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LicenseViewController.m; sourceTree = \"<group>\"; };\n\t\t2250173F178340AB00066E71 /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; };\n\t\t225017421783434800066E71 /* ARChromeActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARChromeActivity.h; sourceTree = \"<group>\"; };\n\t\t225017431783434800066E71 /* ARChromeActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARChromeActivity.m; sourceTree = \"<group>\"; };\n\t\t225017441783434800066E71 /* ARChromeActivity.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ARChromeActivity.png; sourceTree = \"<group>\"; };\n\t\t225017451783434800066E71 /* ARChromeActivity@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"ARChromeActivity@2x.png\"; sourceTree = \"<group>\"; };\n\t\t225017461783434800066E71 /* ARChromeActivity@2x~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"ARChromeActivity@2x~ipad.png\"; sourceTree = \"<group>\"; };\n\t\t225017471783434800066E71 /* ARChromeActivity~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"ARChromeActivity~ipad.png\"; sourceTree = \"<group>\"; };\n\t\t225017591783434900066E71 /* Safari.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Safari.png; sourceTree = \"<group>\"; };\n\t\t2250175A1783434900066E71 /* Safari@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"Safari@2x.png\"; sourceTree = \"<group>\"; };\n\t\t2250175B1783434900066E71 /* Safari@2x~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"Safari@2x~ipad.png\"; sourceTree = \"<group>\"; };\n\t\t2250175C1783434900066E71 /* Safari~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"Safari~ipad.png\"; sourceTree = \"<group>\"; };\n\t\t2250175F1783434900066E71 /* TUSafariActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUSafariActivity.h; sourceTree = \"<group>\"; };\n\t\t225017601783434900066E71 /* TUSafariActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUSafariActivity.m; sourceTree = \"<group>\"; };\n\t\t2251693217B5A8040093ADC5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/TUSafariActivity.strings; sourceTree = \"<group>\"; };\n\t\t225173E21DB13A5500D63405 /* SourceSansPro-Semibold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"SourceSansPro-Semibold.otf\"; sourceTree = \"<group>\"; };\n\t\t2252EE5A1F4485C000307010 /* MessageTypeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MessageTypeTests.m; sourceTree = \"<group>\"; };\n\t\t2253BA241770CD7100CCA77F /* ChannelListTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChannelListTableViewController.m; sourceTree = \"<group>\"; };\n\t\t2253BA261770CDC500CCA77F /* ChannelListTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChannelListTableViewController.h; sourceTree = \"<group>\"; };\n\t\t225BEDC2252CB27F0050A8CC /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };\n\t\t225D979F18AA995900065087 /* IRCEnterprise.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IRCEnterprise.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t225D97A118AA9EBC00065087 /* IRCCloud-Enterprise-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = \"IRCCloud-Enterprise-Info.plist\"; sourceTree = \"<group>\"; };\n\t\t225EC2BA2061678B00AA0C79 /* EventsTableCell_ReplyCount.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EventsTableCell_ReplyCount.xib; sourceTree = \"<group>\"; };\n\t\t2263D3A0290A979500692EEC /* NSString+Score.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"NSString+Score.h\"; sourceTree = \"<group>\"; };\n\t\t2263D3A1290A979500692EEC /* NSString+Score.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"NSString+Score.m\"; sourceTree = \"<group>\"; };\n\t\t2264A2FF19659BB100DCFDDD /* URLHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLHandler.h; sourceTree = \"<group>\"; };\n\t\t2264A30019659BB100DCFDDD /* URLHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = URLHandler.m; sourceTree = \"<group>\"; };\n\t\t2265DC881C722E6B00382C7C /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };\n\t\t22695F5316E8FC9800E01DF8 /* CollapsedEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollapsedEvents.h; sourceTree = \"<group>\"; };\n\t\t22695F5416E8FC9800E01DF8 /* CollapsedEvents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CollapsedEvents.m; sourceTree = \"<group>\"; };\n\t\t226E642223F1C6AA001CE069 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = \"GoogleService-Info.plist\"; sourceTree = \"<group>\"; };\n\t\t226EB6001B4C2E8600C432C7 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };\n\t\t226F080C1E6495C8003EED23 /* WhoWasTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WhoWasTableViewController.h; sourceTree = \"<group>\"; };\n\t\t226F080D1E6495C8003EED23 /* WhoWasTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WhoWasTableViewController.m; sourceTree = \"<group>\"; };\n\t\t2271FD9F1DCDF45C00A39F84 /* TextTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextTableViewController.h; sourceTree = \"<group>\"; };\n\t\t2271FDA01DCDF45C00A39F84 /* TextTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextTableViewController.m; sourceTree = \"<group>\"; };\n\t\t2274F49D1756723F0039B4CB /* OpenInChromeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenInChromeController.h; path = OpenInChrome/OpenInChromeController.h; sourceTree = SOURCE_ROOT; };\n\t\t2274F49E1756723F0039B4CB /* OpenInChromeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OpenInChromeController.m; path = OpenInChrome/OpenInChromeController.m; sourceTree = SOURCE_ROOT; };\n\t\t227DA89D1CF381B60041B1BF /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };\n\t\t227FF29F16FA128A00DBE3C5 /* HighlightsCountView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HighlightsCountView.h; sourceTree = \"<group>\"; };\n\t\t227FF2A016FA128B00DBE3C5 /* HighlightsCountView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HighlightsCountView.m; sourceTree = \"<group>\"; };\n\t\t227FF8211772062E00394114 /* SettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsViewController.h; sourceTree = \"<group>\"; };\n\t\t227FF8221772063F00394114 /* SettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsViewController.m; sourceTree = \"<group>\"; };\n\t\t2283322F17944E2B00ED22EA /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };\n\t\t2284EF711B4AD47F0058D483 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };\n\t\t2289EF621D7866BD00DB285E /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };\n\t\t2289EF771D787CC500DB285E /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; };\n\t\t228A056C16D3DABA0029769C /* IRCCloud.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IRCCloud.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t228A056F16D3DABA0029769C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };\n\t\t228A057116D3DABA0029769C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };\n\t\t228A057316D3DABA0029769C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };\n\t\t228A057716D3DABA0029769C /* IRCCloud-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = \"IRCCloud-Info.plist\"; sourceTree = \"<group>\"; };\n\t\t228A057B16D3DABA0029769C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t228A057D16D3DABA0029769C /* IRCCloud-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"IRCCloud-Prefix.pch\"; sourceTree = \"<group>\"; };\n\t\t228A05AE16D3DB7B0029769C /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\t228A05AF16D3DB7B0029769C /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\t228A05C916D3DCB60029769C /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };\n\t\t228A05CB16D3DCE20029769C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };\n\t\t228A05CD16D3DD310029769C /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; };\n\t\t228A05D516D3DFD00029769C /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };\n\t\t228A05DB16D3E40E0029769C /* LoginSplashViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoginSplashViewController.h; sourceTree = \"<group>\"; };\n\t\t228A05DC16D3E40E0029769C /* LoginSplashViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoginSplashViewController.m; sourceTree = \"<group>\"; };\n\t\t228B908F29E597D9001CBACB /* emocode-data.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = \"emocode-data.js\"; path = \"build-scripts/emocode-data.js\"; sourceTree = SOURCE_ROOT; };\n\t\t228B909229E5980F001CBACB /* ace-modes.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = \"ace-modes.js\"; path = \"build-scripts/ace-modes.js\"; sourceTree = SOURCE_ROOT; };\n\t\t228EFBC6177B4F6000B83A4C /* DisplayOptionsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayOptionsViewController.h; sourceTree = \"<group>\"; };\n\t\t228EFBC7177B4F7300B83A4C /* DisplayOptionsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DisplayOptionsViewController.m; sourceTree = \"<group>\"; };\n\t\t228F69711DF8A3F30079E276 /* SpamViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpamViewController.h; sourceTree = \"<group>\"; };\n\t\t228F69721DF8A3F30079E276 /* SpamViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpamViewController.m; sourceTree = \"<group>\"; };\n\t\t229323D81E8945D700ADAA22 /* configuration_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = configuration_utils.h; sourceTree = \"<group>\"; };\n\t\t229323D91E8945D700ADAA22 /* configuration_utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = configuration_utils.m; sourceTree = \"<group>\"; };\n\t\t229323DC1E8945D700ADAA22 /* domain_registry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = domain_registry.h; sourceTree = \"<group>\"; };\n\t\t229323DE1E8945D700ADAA22 /* assert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = assert.c; sourceTree = \"<group>\"; };\n\t\t229323DF1E8945D700ADAA22 /* assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assert.h; sourceTree = \"<group>\"; };\n\t\t229323E01E8945D700ADAA22 /* init_registry_tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = init_registry_tables.c; sourceTree = \"<group>\"; };\n\t\t229323E11E8945D700ADAA22 /* registry_search.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = registry_search.c; sourceTree = \"<group>\"; };\n\t\t229323E21E8945D700ADAA22 /* registry_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = registry_types.h; sourceTree = \"<group>\"; };\n\t\t229323E31E8945D700ADAA22 /* string_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_util.h; sourceTree = \"<group>\"; };\n\t\t229323E41E8945D700ADAA22 /* trie_node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trie_node.h; sourceTree = \"<group>\"; };\n\t\t229323E51E8945D700ADAA22 /* trie_search.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = trie_search.c; sourceTree = \"<group>\"; };\n\t\t229323E61E8945D700ADAA22 /* trie_search.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trie_search.h; sourceTree = \"<group>\"; };\n\t\t229323E81E8945D700ADAA22 /* registry_tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = registry_tables.h; sourceTree = \"<group>\"; };\n\t\t229323EB1E8945D700ADAA22 /* RSSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSSwizzle.h; sourceTree = \"<group>\"; };\n\t\t229323EC1E8945D700ADAA22 /* RSSwizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSSwizzle.m; sourceTree = \"<group>\"; };\n\t\t229323EF1E8945D700ADAA22 /* parse_configuration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parse_configuration.h; sourceTree = \"<group>\"; };\n\t\t229323F01E8945D700ADAA22 /* parse_configuration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = parse_configuration.m; sourceTree = \"<group>\"; };\n\t\t229323F21E8945D700ADAA22 /* public_key_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = public_key_utils.h; sourceTree = \"<group>\"; };\n\t\t229323F31E8945D700ADAA22 /* public_key_utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = public_key_utils.m; sourceTree = \"<group>\"; };\n\t\t229323F41E8945D700ADAA22 /* ssl_pin_verifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ssl_pin_verifier.h; sourceTree = \"<group>\"; };\n\t\t229323F51E8945D700ADAA22 /* ssl_pin_verifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ssl_pin_verifier.m; sourceTree = \"<group>\"; };\n\t\t229323F71E8945D700ADAA22 /* reporting_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reporting_utils.h; sourceTree = \"<group>\"; };\n\t\t229323F81E8945D700ADAA22 /* reporting_utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = reporting_utils.m; sourceTree = \"<group>\"; };\n\t\t229323F91E8945D700ADAA22 /* TSKBackgroundReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSKBackgroundReporter.h; sourceTree = \"<group>\"; };\n\t\t229323FA1E8945D700ADAA22 /* TSKBackgroundReporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSKBackgroundReporter.m; sourceTree = \"<group>\"; };\n\t\t229323FB1E8945D700ADAA22 /* TSKPinFailureReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSKPinFailureReport.h; sourceTree = \"<group>\"; };\n\t\t229323FC1E8945D700ADAA22 /* TSKPinFailureReport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSKPinFailureReport.m; sourceTree = \"<group>\"; };\n\t\t229323FD1E8945D700ADAA22 /* TSKReportsRateLimiter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSKReportsRateLimiter.h; sourceTree = \"<group>\"; };\n\t\t229323FE1E8945D700ADAA22 /* TSKReportsRateLimiter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSKReportsRateLimiter.m; sourceTree = \"<group>\"; };\n\t\t229323FF1E8945D700ADAA22 /* vendor_identifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vendor_identifier.h; sourceTree = \"<group>\"; };\n\t\t229324001E8945D700ADAA22 /* vendor_identifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = vendor_identifier.m; sourceTree = \"<group>\"; };\n\t\t229324021E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSKNSURLConnectionDelegateProxy.h; sourceTree = \"<group>\"; };\n\t\t229324031E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSKNSURLConnectionDelegateProxy.m; sourceTree = \"<group>\"; };\n\t\t229324041E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSKNSURLSessionDelegateProxy.h; sourceTree = \"<group>\"; };\n\t\t229324051E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSKNSURLSessionDelegateProxy.m; sourceTree = \"<group>\"; };\n\t\t229324061E8945D700ADAA22 /* TrustKit+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"TrustKit+Private.h\"; sourceTree = \"<group>\"; };\n\t\t229324071E8945D700ADAA22 /* TrustKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrustKit.h; sourceTree = \"<group>\"; };\n\t\t229324081E8945D700ADAA22 /* TrustKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TrustKit.m; sourceTree = \"<group>\"; };\n\t\t229324091E8945D700ADAA22 /* TSKPinningValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSKPinningValidator.h; sourceTree = \"<group>\"; };\n\t\t2293240A1E8945D700ADAA22 /* TSKPinningValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSKPinningValidator.m; sourceTree = \"<group>\"; };\n\t\t2293AEFF17F9CCD10022BD06 /* NSURL+IDN.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = \"NSURL+IDN.m\"; path = \"NSURL+IDN/NSURL+IDN.m\"; sourceTree = SOURCE_ROOT; };\n\t\t2293AF0017F9CCD10022BD06 /* NSURL+IDN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = \"NSURL+IDN.h\"; path = \"NSURL+IDN/NSURL+IDN.h\"; sourceTree = SOURCE_ROOT; };\n\t\t2296E0B619805751002D59E3 /* ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = ShareExtension.entitlements; sourceTree = \"<group>\"; };\n\t\t2296E0B719805767002D59E3 /* IRCCloud.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = IRCCloud.entitlements; sourceTree = \"<group>\"; };\n\t\t229C85401B502920004964DE /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };\n\t\t22A19C5E178FCCAB00772C60 /* UINavigationController+iPadSux.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"UINavigationController+iPadSux.h\"; sourceTree = \"<group>\"; };\n\t\t22A19C5F178FCCAB00772C60 /* UINavigationController+iPadSux.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"UINavigationController+iPadSux.m\"; sourceTree = \"<group>\"; };\n\t\t22A1D0251778A86900F8A89C /* WhoisViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WhoisViewController.h; sourceTree = \"<group>\"; };\n\t\t22A1D0261778A86900F8A89C /* WhoisViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WhoisViewController.m; sourceTree = \"<group>\"; };\n\t\t22A1F1141C232B3A00AEC09A /* SafariServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SafariServices.framework; path = System/Library/Frameworks/SafariServices.framework; sourceTree = SDKROOT; };\n\t\t22A35F24178A316300529CDA /* WhoListTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WhoListTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22A35F25178A317100529CDA /* WhoListTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WhoListTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22A35F27178A3F2B00529CDA /* NamesListTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NamesListTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22A35F28178A3F3500529CDA /* NamesListTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NamesListTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22A363AF19D0884D00500478 /* 1Password.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = 1Password.xcassets; sourceTree = \"<group>\"; };\n\t\t22A363B019D0884D00500478 /* OnePasswordExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnePasswordExtension.h; sourceTree = \"<group>\"; };\n\t\t22A363B119D0884D00500478 /* OnePasswordExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OnePasswordExtension.m; sourceTree = \"<group>\"; };\n\t\t22A363BA19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"UIDevice+UIDevice_iPhone6Hax.h\"; sourceTree = \"<group>\"; };\n\t\t22A363BB19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"UIDevice+UIDevice_iPhone6Hax.m\"; sourceTree = \"<group>\"; };\n\t\t22AD75EB1718567D00141257 /* ChannelModeListTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChannelModeListTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22AD75EC1718567D00141257 /* ChannelModeListTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChannelModeListTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22B15CF2172ECCFF0075EBA7 /* EditConnectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditConnectionViewController.h; sourceTree = \"<group>\"; };\n\t\t22B15CF3172ECCFF0075EBA7 /* EditConnectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EditConnectionViewController.m; sourceTree = \"<group>\"; };\n\t\t22B15CF717301BAF0075EBA7 /* ECSlidingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ECSlidingViewController.h; sourceTree = \"<group>\"; };\n\t\t22B15CF817301BAF0075EBA7 /* ECSlidingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ECSlidingViewController.m; sourceTree = \"<group>\"; };\n\t\t22B15CF917301BAF0075EBA7 /* UIImage+ImageWithUIView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"UIImage+ImageWithUIView.h\"; sourceTree = \"<group>\"; };\n\t\t22B15CFA17301BAF0075EBA7 /* UIImage+ImageWithUIView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"UIImage+ImageWithUIView.m\"; sourceTree = \"<group>\"; };\n\t\t22B2036C1B5FE3BE0058078D /* NotificationsDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationsDataSource.h; sourceTree = \"<group>\"; };\n\t\t22B2036D1B5FE3BE0058078D /* NotificationsDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationsDataSource.m; sourceTree = \"<group>\"; };\n\t\t22B4284616D7E36300498507 /* NetworkConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkConnection.h; sourceTree = \"<group>\"; };\n\t\t22B4284716D7E36300498507 /* NetworkConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NetworkConnection.m; sourceTree = \"<group>\"; };\n\t\t22B4284F16D831A800498507 /* HandshakeHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandshakeHeader.h; sourceTree = \"<group>\"; };\n\t\t22B4285016D831A800498507 /* HandshakeHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HandshakeHeader.m; sourceTree = \"<group>\"; };\n\t\t22B4285116D831A800498507 /* MutableQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MutableQueue.h; sourceTree = \"<group>\"; };\n\t\t22B4285216D831A800498507 /* MutableQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MutableQueue.m; sourceTree = \"<group>\"; };\n\t\t22B4285316D831A800498507 /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"NSData+Base64.h\"; sourceTree = \"<group>\"; };\n\t\t22B4285416D831A800498507 /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"NSData+Base64.m\"; sourceTree = \"<group>\"; };\n\t\t22B4285516D831A800498507 /* UnittWebSocketClient-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"UnittWebSocketClient-Prefix.pch\"; sourceTree = \"<group>\"; };\n\t\t22B4285616D831A800498507 /* WebSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocket.h; sourceTree = \"<group>\"; };\n\t\t22B4285716D831A800498507 /* WebSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebSocket.m; sourceTree = \"<group>\"; };\n\t\t22B4286016D831A800498507 /* WebSocketConnectConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketConnectConfig.h; sourceTree = \"<group>\"; };\n\t\t22B4286116D831A800498507 /* WebSocketConnectConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebSocketConnectConfig.m; sourceTree = \"<group>\"; };\n\t\t22B4286216D831A800498507 /* WebSocketFragment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketFragment.h; sourceTree = \"<group>\"; };\n\t\t22B4286316D831A800498507 /* WebSocketFragment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebSocketFragment.m; sourceTree = \"<group>\"; };\n\t\t22B4286416D831A800498507 /* WebSocketMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketMessage.h; sourceTree = \"<group>\"; };\n\t\t22B4286516D831A800498507 /* WebSocketMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebSocketMessage.m; sourceTree = \"<group>\"; };\n\t\t22B4288416D846BF00498507 /* IRCCloudJSONObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRCCloudJSONObject.h; sourceTree = \"<group>\"; };\n\t\t22B4288516D846BF00498507 /* IRCCloudJSONObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IRCCloudJSONObject.m; sourceTree = \"<group>\"; };\n\t\t22B6F9771982F47E004C291C /* ShareExtension Enterprise.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = \"ShareExtension Enterprise.entitlements\"; sourceTree = SOURCE_ROOT; };\n\t\t22BB0A2828C22FB2008EE509 /* SendMessageIntentHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SendMessageIntentHandler.h; sourceTree = \"<group>\"; };\n\t\t22BB0A2928C22FB2008EE509 /* SendMessageIntentHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SendMessageIntentHandler.m; sourceTree = \"<group>\"; };\n\t\t22BB94A81D425A4E00BFB6F0 /* SamlLoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SamlLoginViewController.m; sourceTree = \"<group>\"; };\n\t\t22BB94A91D425A4E00BFB6F0 /* SamlLoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamlLoginViewController.h; sourceTree = \"<group>\"; };\n\t\t22C2075A1A19125700EDACA4 /* FileMetadataViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileMetadataViewController.h; sourceTree = \"<group>\"; };\n\t\t22C2075B1A19125700EDACA4 /* FileMetadataViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FileMetadataViewController.m; sourceTree = \"<group>\"; };\n\t\t22C2E0551B0E2E4800387B4B /* PastebinViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PastebinViewController.h; sourceTree = \"<group>\"; };\n\t\t22C2E0561B0E2E4800387B4B /* PastebinViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PastebinViewController.m; sourceTree = \"<group>\"; };\n\t\t22C8CD701B01289900F637D2 /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = \"libc++.dylib\"; path = \"usr/lib/libc++.dylib\"; sourceTree = SDKROOT; };\n\t\t22C8DCF21A801A4500199371 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };\n\t\t22CE2ADC1D2AA65A001397C0 /* UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t22CE2AE01D2AA662001397C0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t22CE2AE71D2AA9E3001397C0 /* UITests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"UITests-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\t22CE2AE81D2AAA36001397C0 /* SnapshotHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnapshotHelper.swift; sourceTree = \"<group>\"; };\n\t\t22CE91731D58C81C0014B25C /* LinkTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkTextView.h; sourceTree = \"<group>\"; };\n\t\t22CE91741D58C81C0014B25C /* LinkTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LinkTextView.m; sourceTree = \"<group>\"; };\n\t\t22CE91771D59160B0014B25C /* LinkLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkLabel.h; sourceTree = \"<group>\"; };\n\t\t22CE91781D59160B0014B25C /* LinkLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LinkLabel.m; sourceTree = \"<group>\"; };\n\t\t22D268C11BF4F40800B682AE /* MainStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainStoryboard.storyboard; sourceTree = \"<group>\"; };\n\t\t22D268C41BF4F95200B682AE /* SplashViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SplashViewController.h; sourceTree = \"<group>\"; };\n\t\t22D268C51BF4F95200B682AE /* SplashViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SplashViewController.m; sourceTree = \"<group>\"; };\n\t\t22D4309E171C663A003C0684 /* IgnoresTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IgnoresTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D4309F171C663A003C0684 /* IgnoresTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IgnoresTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D430A21725AAE9003C0684 /* UIExpandingTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIExpandingTextView.h; sourceTree = \"<group>\"; };\n\t\t22D430A31725AAEA003C0684 /* UIExpandingTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExpandingTextView.m; sourceTree = \"<group>\"; };\n\t\t22D430A41725AAEA003C0684 /* UIExpandingTextViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIExpandingTextViewInternal.h; sourceTree = \"<group>\"; };\n\t\t22D430A51725AAEA003C0684 /* UIExpandingTextViewInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExpandingTextViewInternal.m; sourceTree = \"<group>\"; };\n\t\t22D46C651A13A9A900B142F7 /* FileUploader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileUploader.h; sourceTree = \"<group>\"; };\n\t\t22D46C661A13A9A900B142F7 /* FileUploader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FileUploader.m; sourceTree = \"<group>\"; };\n\t\t22D4F9111743F3790095EE8F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = \"<group>\"; };\n\t\t22D649221B1E0719003BFD86 /* CSURITemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSURITemplate.h; sourceTree = \"<group>\"; };\n\t\t22D649231B1E0719003BFD86 /* CSURITemplate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSURITemplate.m; sourceTree = \"<group>\"; };\n\t\t22D649281B1E371D003BFD86 /* PastebinsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PastebinsTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D649291B1E371D003BFD86 /* PastebinsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PastebinsTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D9789B215BC910005C2713 /* IRCCloud FLEX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = \"IRCCloud FLEX.app\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t22D9789E215BC979005C2713 /* FLEXManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXManager.h; sourceTree = \"<group>\"; };\n\t\t22D9789F215BC979005C2713 /* FLEX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEX.h; sourceTree = \"<group>\"; };\n\t\t22D978A1215BC979005C2713 /* FLEXArrayExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArrayExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978A2215BC979005C2713 /* FLEXObjectExplorerFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXObjectExplorerFactory.m; sourceTree = \"<group>\"; };\n\t\t22D978A3215BC979005C2713 /* FLEXLayerExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXLayerExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978A4215BC979005C2713 /* FLEXSetExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSetExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978A5215BC979005C2713 /* FLEXGlobalsTableViewControllerEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXGlobalsTableViewControllerEntry.m; sourceTree = \"<group>\"; };\n\t\t22D978A6215BC979005C2713 /* FLEXImageExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXImageExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978A7215BC979005C2713 /* FLEXViewExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXViewExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978A8215BC979005C2713 /* FLEXClassExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXClassExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978A9215BC979005C2713 /* FLEXDictionaryExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXDictionaryExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978AA215BC979005C2713 /* FLEXDefaultsExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXDefaultsExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978AB215BC979005C2713 /* FLEXObjectExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXObjectExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978AC215BC979005C2713 /* FLEXViewControllerExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXViewControllerExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978AD215BC979005C2713 /* FLEXGlobalsTableViewControllerEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXGlobalsTableViewControllerEntry.h; sourceTree = \"<group>\"; };\n\t\t22D978AE215BC979005C2713 /* FLEXImageExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXImageExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978AF215BC979005C2713 /* FLEXSetExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXSetExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978B0215BC979005C2713 /* FLEXLayerExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXLayerExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978B1215BC979005C2713 /* FLEXObjectExplorerFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXObjectExplorerFactory.h; sourceTree = \"<group>\"; };\n\t\t22D978B2215BC979005C2713 /* FLEXArrayExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArrayExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978B3215BC979005C2713 /* FLEXClassExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXClassExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978B4215BC979005C2713 /* FLEXViewExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXViewExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978B5215BC979005C2713 /* FLEXObjectExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXObjectExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978B6215BC979005C2713 /* FLEXDictionaryExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXDictionaryExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978B7215BC979005C2713 /* FLEXDefaultsExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXDefaultsExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978B8215BC979005C2713 /* FLEXViewControllerExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXViewControllerExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978BA215BC979005C2713 /* FLEXNetworkCurlLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkCurlLogger.h; sourceTree = \"<group>\"; };\n\t\t22D978BB215BC979005C2713 /* FLEXNetworkTransaction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkTransaction.m; sourceTree = \"<group>\"; };\n\t\t22D978BC215BC979005C2713 /* FLEXNetworkHistoryTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkHistoryTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978BD215BC979005C2713 /* FLEXNetworkSettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkSettingsTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978BE215BC979005C2713 /* FLEXNetworkRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkRecorder.m; sourceTree = \"<group>\"; };\n\t\t22D978BF215BC979005C2713 /* FLEXNetworkTransactionDetailTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkTransactionDetailTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978C0215BC979005C2713 /* FLEXNetworkTransactionTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkTransactionTableViewCell.m; sourceTree = \"<group>\"; };\n\t\t22D978C1215BC979005C2713 /* FLEXNetworkTransaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkTransaction.h; sourceTree = \"<group>\"; };\n\t\t22D978C2215BC979005C2713 /* FLEXNetworkCurlLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkCurlLogger.m; sourceTree = \"<group>\"; };\n\t\t22D978C3215BC979005C2713 /* FLEXNetworkTransactionDetailTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkTransactionDetailTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978C4215BC979005C2713 /* FLEXNetworkRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkRecorder.h; sourceTree = \"<group>\"; };\n\t\t22D978C5215BC979005C2713 /* FLEXNetworkSettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkSettingsTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978C6215BC979005C2713 /* FLEXNetworkHistoryTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkHistoryTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978C7215BC979005C2713 /* FLEXNetworkTransactionTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkTransactionTableViewCell.h; sourceTree = \"<group>\"; };\n\t\t22D978C9215BC979005C2713 /* FLEXNetworkObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkObserver.h; sourceTree = \"<group>\"; };\n\t\t22D978CA215BC979005C2713 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = \"<group>\"; };\n\t\t22D978CB215BC979005C2713 /* FLEXNetworkObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkObserver.m; sourceTree = \"<group>\"; };\n\t\t22D978CD215BC979005C2713 /* FLEXToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXToolbarItem.m; sourceTree = \"<group>\"; };\n\t\t22D978CE215BC979005C2713 /* FLEXExplorerToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXExplorerToolbar.h; sourceTree = \"<group>\"; };\n\t\t22D978CF215BC979005C2713 /* FLEXToolbarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXToolbarItem.h; sourceTree = \"<group>\"; };\n\t\t22D978D0215BC979005C2713 /* FLEXExplorerToolbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXExplorerToolbar.m; sourceTree = \"<group>\"; };\n\t\t22D978D2215BC979005C2713 /* FLEXManager+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"FLEXManager+Private.h\"; sourceTree = \"<group>\"; };\n\t\t22D978D3215BC979005C2713 /* FLEXManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXManager.m; sourceTree = \"<group>\"; };\n\t\t22D978D5215BC979005C2713 /* FLEXIvarEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXIvarEditorViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978D6215BC979005C2713 /* FLEXPropertyEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXPropertyEditorViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978D7215BC979005C2713 /* FLEXDefaultEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXDefaultEditorViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978D8215BC979005C2713 /* FLEXFieldEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFieldEditorViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978D9215BC979005C2713 /* FLEXFieldEditorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFieldEditorView.h; sourceTree = \"<group>\"; };\n\t\t22D978DA215BC979005C2713 /* FLEXMethodCallingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMethodCallingViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978DB215BC979005C2713 /* FLEXIvarEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXIvarEditorViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978DC215BC979005C2713 /* FLEXFieldEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFieldEditorViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978DD215BC979005C2713 /* FLEXDefaultEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXDefaultEditorViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978DF215BC979005C2713 /* FLEXArgumentInputStringView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputStringView.m; sourceTree = \"<group>\"; };\n\t\t22D978E0215BC979005C2713 /* FLEXArgumentInputColorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputColorView.m; sourceTree = \"<group>\"; };\n\t\t22D978E1215BC979005C2713 /* FLEXArgumentInputView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputView.m; sourceTree = \"<group>\"; };\n\t\t22D978E2215BC979005C2713 /* FLEXArgumentInputFontView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputFontView.h; sourceTree = \"<group>\"; };\n\t\t22D978E3215BC979005C2713 /* FLEXArgumentInputTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputTextView.h; sourceTree = \"<group>\"; };\n\t\t22D978E4215BC979005C2713 /* FLEXArgumentInputJSONObjectView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputJSONObjectView.m; sourceTree = \"<group>\"; };\n\t\t22D978E5215BC979005C2713 /* FLEXArgumentInputSwitchView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputSwitchView.m; sourceTree = \"<group>\"; };\n\t\t22D978E6215BC979005C2713 /* FLEXArgumentInputStructView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputStructView.m; sourceTree = \"<group>\"; };\n\t\t22D978E7215BC979005C2713 /* FLEXArgumentInputDateView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputDateView.m; sourceTree = \"<group>\"; };\n\t\t22D978E8215BC979005C2713 /* FLEXArgumentInputNumberView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputNumberView.h; sourceTree = \"<group>\"; };\n\t\t22D978E9215BC979005C2713 /* FLEXArgumentInputFontsPickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputFontsPickerView.h; sourceTree = \"<group>\"; };\n\t\t22D978EA215BC979005C2713 /* FLEXArgumentInputNotSupportedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputNotSupportedView.h; sourceTree = \"<group>\"; };\n\t\t22D978EB215BC979005C2713 /* FLEXArgumentInputViewFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputViewFactory.h; sourceTree = \"<group>\"; };\n\t\t22D978EC215BC979005C2713 /* FLEXArgumentInputFontView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputFontView.m; sourceTree = \"<group>\"; };\n\t\t22D978ED215BC979005C2713 /* FLEXArgumentInputView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputView.h; sourceTree = \"<group>\"; };\n\t\t22D978EE215BC979005C2713 /* FLEXArgumentInputColorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputColorView.h; sourceTree = \"<group>\"; };\n\t\t22D978EF215BC979005C2713 /* FLEXArgumentInputStringView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputStringView.h; sourceTree = \"<group>\"; };\n\t\t22D978F0215BC979005C2713 /* FLEXArgumentInputSwitchView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputSwitchView.h; sourceTree = \"<group>\"; };\n\t\t22D978F1215BC979005C2713 /* FLEXArgumentInputJSONObjectView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputJSONObjectView.h; sourceTree = \"<group>\"; };\n\t\t22D978F2215BC979005C2713 /* FLEXArgumentInputTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputTextView.m; sourceTree = \"<group>\"; };\n\t\t22D978F3215BC979005C2713 /* FLEXArgumentInputFontsPickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputFontsPickerView.m; sourceTree = \"<group>\"; };\n\t\t22D978F4215BC979005C2713 /* FLEXArgumentInputNumberView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputNumberView.m; sourceTree = \"<group>\"; };\n\t\t22D978F5215BC979005C2713 /* FLEXArgumentInputDateView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputDateView.h; sourceTree = \"<group>\"; };\n\t\t22D978F6215BC979005C2713 /* FLEXArgumentInputStructView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputStructView.h; sourceTree = \"<group>\"; };\n\t\t22D978F7215BC979005C2713 /* FLEXArgumentInputViewFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputViewFactory.m; sourceTree = \"<group>\"; };\n\t\t22D978F8215BC979005C2713 /* FLEXArgumentInputNotSupportedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputNotSupportedView.m; sourceTree = \"<group>\"; };\n\t\t22D978F9215BC979005C2713 /* FLEXPropertyEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXPropertyEditorViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978FA215BC979005C2713 /* FLEXMethodCallingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXMethodCallingViewController.h; sourceTree = \"<group>\"; };\n\t\t22D978FB215BC979005C2713 /* FLEXFieldEditorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFieldEditorView.m; sourceTree = \"<group>\"; };\n\t\t22D978FD215BC979005C2713 /* FLEXExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXExplorerViewController.m; sourceTree = \"<group>\"; };\n\t\t22D978FE215BC979005C2713 /* FLEXWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXWindow.m; sourceTree = \"<group>\"; };\n\t\t22D978FF215BC979005C2713 /* FLEXExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXExplorerViewController.h; sourceTree = \"<group>\"; };\n\t\t22D97900215BC979005C2713 /* FLEXWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXWindow.h; sourceTree = \"<group>\"; };\n\t\t22D97902215BC979005C2713 /* FLEXFileBrowserFileOperationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserFileOperationController.h; sourceTree = \"<group>\"; };\n\t\t22D97903215BC979005C2713 /* FLEXFileBrowserTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D97904215BC979005C2713 /* FLEXFileBrowserSearchOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFileBrowserSearchOperation.m; sourceTree = \"<group>\"; };\n\t\t22D97905215BC979005C2713 /* FLEXObjectRef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXObjectRef.m; sourceTree = \"<group>\"; };\n\t\t22D97906215BC979005C2713 /* FLEXWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXWebViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97907215BC979005C2713 /* FLEXInstancesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXInstancesTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97908215BC979005C2713 /* FLEXClassesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXClassesTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D97909215BC979005C2713 /* FLEXLiveObjectsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXLiveObjectsTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D9790A215BC979005C2713 /* FLEXGlobalsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXGlobalsTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D9790B215BC979005C2713 /* FLEXLibrariesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXLibrariesTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D9790C215BC979005C2713 /* FLEXCookiesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXCookiesTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D9790D215BC979005C2713 /* FLEXFileBrowserSearchOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserSearchOperation.h; sourceTree = \"<group>\"; };\n\t\t22D9790E215BC979005C2713 /* FLEXFileBrowserTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFileBrowserTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D9790F215BC979005C2713 /* FLEXFileBrowserFileOperationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFileBrowserFileOperationController.m; sourceTree = \"<group>\"; };\n\t\t22D97910215BC979005C2713 /* FLEXObjectRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXObjectRef.h; sourceTree = \"<group>\"; };\n\t\t22D97911215BC979005C2713 /* FLEXInstancesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXInstancesTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D97913215BC979005C2713 /* FLEXSystemLogTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXSystemLogTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97914215BC979005C2713 /* FLEXSystemLogTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSystemLogTableViewCell.h; sourceTree = \"<group>\"; };\n\t\t22D97915215BC979005C2713 /* FLEXSystemLogMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXSystemLogMessage.m; sourceTree = \"<group>\"; };\n\t\t22D97916215BC979005C2713 /* FLEXSystemLogTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSystemLogTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D97917215BC979005C2713 /* FLEXSystemLogTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXSystemLogTableViewCell.m; sourceTree = \"<group>\"; };\n\t\t22D97918215BC979005C2713 /* FLEXSystemLogMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSystemLogMessage.h; sourceTree = \"<group>\"; };\n\t\t22D9791A215BC979005C2713 /* FLEXRealmDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXRealmDefines.h; sourceTree = \"<group>\"; };\n\t\t22D9791B215BC979005C2713 /* FLEXTableLeftCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableLeftCell.m; sourceTree = \"<group>\"; };\n\t\t22D9791C215BC979005C2713 /* FLEXRealmDatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXRealmDatabaseManager.h; sourceTree = \"<group>\"; };\n\t\t22D9791D215BC979005C2713 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = \"<group>\"; };\n\t\t22D9791E215BC979005C2713 /* FLEXTableContentCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableContentCell.h; sourceTree = \"<group>\"; };\n\t\t22D9791F215BC979005C2713 /* FLEXTableContentViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableContentViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97920215BC979005C2713 /* FLEXTableListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableListViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97921215BC979005C2713 /* FLEXTableColumnHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableColumnHeader.m; sourceTree = \"<group>\"; };\n\t\t22D97922215BC979005C2713 /* FLEXMultiColumnTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMultiColumnTableView.m; sourceTree = \"<group>\"; };\n\t\t22D97923215BC979005C2713 /* FLEXSQLiteDatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSQLiteDatabaseManager.h; sourceTree = \"<group>\"; };\n\t\t22D97924215BC979005C2713 /* FLEXTableLeftCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableLeftCell.h; sourceTree = \"<group>\"; };\n\t\t22D97925215BC979005C2713 /* FLEXTableContentCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableContentCell.m; sourceTree = \"<group>\"; };\n\t\t22D97926215BC979005C2713 /* FLEXDatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXDatabaseManager.h; sourceTree = \"<group>\"; };\n\t\t22D97927215BC979005C2713 /* FLEXRealmDatabaseManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXRealmDatabaseManager.m; sourceTree = \"<group>\"; };\n\t\t22D97928215BC979005C2713 /* FLEXTableContentViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableContentViewController.h; sourceTree = \"<group>\"; };\n\t\t22D97929215BC979005C2713 /* FLEXSQLiteDatabaseManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXSQLiteDatabaseManager.m; sourceTree = \"<group>\"; };\n\t\t22D9792A215BC979005C2713 /* FLEXMultiColumnTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXMultiColumnTableView.h; sourceTree = \"<group>\"; };\n\t\t22D9792B215BC979005C2713 /* FLEXTableColumnHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableColumnHeader.h; sourceTree = \"<group>\"; };\n\t\t22D9792C215BC979005C2713 /* FLEXTableListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableListViewController.h; sourceTree = \"<group>\"; };\n\t\t22D9792D215BC979005C2713 /* FLEXWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXWebViewController.h; sourceTree = \"<group>\"; };\n\t\t22D9792E215BC979005C2713 /* FLEXCookiesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXCookiesTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D9792F215BC979005C2713 /* FLEXLibrariesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXLibrariesTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97930215BC979005C2713 /* FLEXGlobalsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXGlobalsTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97931215BC979005C2713 /* FLEXLiveObjectsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXLiveObjectsTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97932215BC979005C2713 /* FLEXClassesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXClassesTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97934215BC979005C2713 /* FLEXHierarchyTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXHierarchyTableViewCell.m; sourceTree = \"<group>\"; };\n\t\t22D97935215BC979005C2713 /* FLEXImagePreviewViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXImagePreviewViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97936215BC979005C2713 /* FLEXHierarchyTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXHierarchyTableViewController.h; sourceTree = \"<group>\"; };\n\t\t22D97937215BC979005C2713 /* FLEXHierarchyTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXHierarchyTableViewCell.h; sourceTree = \"<group>\"; };\n\t\t22D97938215BC979005C2713 /* FLEXHierarchyTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXHierarchyTableViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97939215BC979005C2713 /* FLEXImagePreviewViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXImagePreviewViewController.h; sourceTree = \"<group>\"; };\n\t\t22D9793A215BC979005C2713 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t22D9793C215BC979005C2713 /* FLEXUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXUtility.m; sourceTree = \"<group>\"; };\n\t\t22D9793D215BC979005C2713 /* FLEXHeapEnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXHeapEnumerator.m; sourceTree = \"<group>\"; };\n\t\t22D9793E215BC979005C2713 /* FLEXResources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXResources.h; sourceTree = \"<group>\"; };\n\t\t22D9793F215BC979005C2713 /* FLEXKeyboardHelpViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeyboardHelpViewController.h; sourceTree = \"<group>\"; };\n\t\t22D97940215BC979005C2713 /* FLEXRuntimeUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXRuntimeUtility.m; sourceTree = \"<group>\"; };\n\t\t22D97941215BC979005C2713 /* FLEXMultilineTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXMultilineTableViewCell.h; sourceTree = \"<group>\"; };\n\t\t22D97942215BC979005C2713 /* FLEXKeyboardShortcutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeyboardShortcutManager.m; sourceTree = \"<group>\"; };\n\t\t22D97943215BC979005C2713 /* FLEXHeapEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXHeapEnumerator.h; sourceTree = \"<group>\"; };\n\t\t22D97944215BC979005C2713 /* FLEXUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXUtility.h; sourceTree = \"<group>\"; };\n\t\t22D97945215BC979005C2713 /* FLEXKeyboardHelpViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeyboardHelpViewController.m; sourceTree = \"<group>\"; };\n\t\t22D97946215BC979005C2713 /* FLEXResources.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXResources.m; sourceTree = \"<group>\"; };\n\t\t22D97947215BC979005C2713 /* FLEXRuntimeUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXRuntimeUtility.h; sourceTree = \"<group>\"; };\n\t\t22D97948215BC979005C2713 /* FLEXKeyboardShortcutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeyboardShortcutManager.h; sourceTree = \"<group>\"; };\n\t\t22D97949215BC979005C2713 /* FLEXMultilineTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMultilineTableViewCell.m; sourceTree = \"<group>\"; };\n\t\t22DB24F91982DF070008728E /* Info-Enterprise.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = \"Info-Enterprise.plist\"; sourceTree = \"<group>\"; };\n\t\t22DB25371982DF2B0008728E /* ShareExtension Enterprise.appex */ = {isa = PBXFileReference; explicitFileType = \"wrapper.app-extension\"; includeInIndex = 0; path = \"ShareExtension Enterprise.appex\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t22DB253D1982E2890008728E /* IRCEnterprise.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = IRCEnterprise.entitlements; path = ../IRCEnterprise.entitlements; sourceTree = \"<group>\"; };\n\t\t22DB8D6E1C441C3000302271 /* YouTubeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YouTubeViewController.h; sourceTree = \"<group>\"; };\n\t\t22DB8D6F1C441C3000302271 /* YouTubeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YouTubeViewController.m; sourceTree = \"<group>\"; };\n\t\t22E54ADE1D10593B00891FE4 /* AvatarsDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvatarsDataSource.h; sourceTree = \"<group>\"; };\n\t\t22E54ADF1D10593B00891FE4 /* AvatarsDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AvatarsDataSource.m; sourceTree = \"<group>\"; };\n\t\t22E9C0A71C9AF27800013456 /* OpenInFirefoxControllerObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenInFirefoxControllerObjC.h; path = OpenInFirefoxClient/OpenInFirefoxControllerObjC.h; sourceTree = SOURCE_ROOT; };\n\t\t22E9C0A81C9AF27800013456 /* OpenInFirefoxControllerObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OpenInFirefoxControllerObjC.m; path = OpenInFirefoxClient/OpenInFirefoxControllerObjC.m; sourceTree = SOURCE_ROOT; };\n\t\t22EB4CF31CCEE296004F9CFC /* ImageViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ImageViewController.xib; path = Classes/ImageViewController.xib; sourceTree = \"<group>\"; };\n\t\t22EE12811C9B20DF00E7AE8D /* Firefox.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Firefox.png; path = OpenInFirefoxClient/Firefox.png; sourceTree = SOURCE_ROOT; };\n\t\t22EE12821C9B20DF00E7AE8D /* Firefox@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = \"Firefox@2x.png\"; path = \"OpenInFirefoxClient/Firefox@2x.png\"; sourceTree = SOURCE_ROOT; };\n\t\t22EE12831C9B20DF00E7AE8D /* Firefox@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = \"Firefox@3x.png\"; path = \"OpenInFirefoxClient/Firefox@3x.png\"; sourceTree = SOURCE_ROOT; };\n\t\t22EE41F81F39F66E00D74E8C /* IRCColorPickerView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IRCColorPickerView.h; sourceTree = \"<group>\"; };\n\t\t22EE41F91F39F66E00D74E8C /* IRCColorPickerView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IRCColorPickerView.m; sourceTree = \"<group>\"; };\n\t\t22EEA94D18D0AC08007D5022 /* EnterpriseImages.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = EnterpriseImages.xcassets; sourceTree = \"<group>\"; };\n\t\t22EEA95018D0B117007D5022 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = \"<group>\"; };\n\t\t22EEA95318D0B198007D5022 /* Icons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Icons.xcassets; sourceTree = \"<group>\"; };\n\t\t22F4A9C91CB5424F00359049 /* Launch.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Launch.storyboard; sourceTree = \"<group>\"; };\n\t\t22F5C4BC1791F205005E09A9 /* a.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = a.caf; sourceTree = \"<group>\"; };\n\t\t22F9EE1A16DE6F21004615C0 /* EventsDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventsDataSource.h; sourceTree = \"<group>\"; };\n\t\t22F9EE1B16DE6F21004615C0 /* EventsDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EventsDataSource.m; sourceTree = \"<group>\"; };\n\t\t26CA7871B88FD75900DEEA57 /* Pods-IRCCloud.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloud.appstore.xcconfig\"; path = \"Target Support Files/Pods-IRCCloud/Pods-IRCCloud.appstore.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t2D34900179BBF7DB46AC6ABF /* Pods-NotificationService Enterprise.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-NotificationService Enterprise.appstore.xcconfig\"; path = \"Target Support Files/Pods-NotificationService Enterprise/Pods-NotificationService Enterprise.appstore.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t312A65F8D9286A2A8D9E9C43 /* Pods-ShareExtension Enterprise.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-ShareExtension Enterprise.debug.xcconfig\"; path = \"Target Support Files/Pods-ShareExtension Enterprise/Pods-ShareExtension Enterprise.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t3CF6A7B20BFBB01BD7B6F779 /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t42EA3F8746F7A000AFEB8A4F /* Pods-ShareExtension Enterprise.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-ShareExtension Enterprise.release.xcconfig\"; path = \"Target Support Files/Pods-ShareExtension Enterprise/Pods-ShareExtension Enterprise.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t4F27E14C033710EC4B42D049 /* Pods-NotificationService.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-NotificationService.appstore.xcconfig\"; path = \"Target Support Files/Pods-NotificationService/Pods-NotificationService.appstore.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t501E461E42461CCDCA1FEA73 /* Pods-IRCCloud FLEX.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloud FLEX.appstore.xcconfig\"; path = \"Target Support Files/Pods-IRCCloud FLEX/Pods-IRCCloud FLEX.appstore.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t680E63BC56A1C3A1442F25DF /* Pods_IRCCloudUnitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_IRCCloudUnitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t72EF5BEF0B6805E196076677 /* Pods-ShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-ShareExtension.debug.xcconfig\"; path = \"Target Support Files/Pods-ShareExtension/Pods-ShareExtension.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t734B6CF2BBC243289BBDFE3E /* Pods-IRCCloudUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloudUnitTests.debug.xcconfig\"; path = \"Target Support Files/Pods-IRCCloudUnitTests/Pods-IRCCloudUnitTests.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t747834BB92EAB6AFAEC360EA /* Pods-IRCCloud FLEX.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloud FLEX.debug.xcconfig\"; path = \"Target Support Files/Pods-IRCCloud FLEX/Pods-IRCCloud FLEX.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t750FA24A88594B10FEDE6646 /* Pods-ShareExtension.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-ShareExtension.appstore.xcconfig\"; path = \"Target Support Files/Pods-ShareExtension/Pods-ShareExtension.appstore.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t7CFB3E8BA47C29791F69E532 /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-NotificationService.release.xcconfig\"; path = \"Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t7E8BEE7BE95EE6C639899F19 /* Pods-IRCCloudUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloudUnitTests.release.xcconfig\"; path = \"Target Support Files/Pods-IRCCloudUnitTests/Pods-IRCCloudUnitTests.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t8B18E14B6DD31D7CDE986D5B /* Pods-IRCCloud.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloud.release.xcconfig\"; path = \"Target Support Files/Pods-IRCCloud/Pods-IRCCloud.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t9687F6412D04D07E40F1CA5D /* Pods_IRCCloud_FLEX.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_IRCCloud_FLEX.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tA2393D6BBB8E07F3DE0D5379 /* Pods-NotificationService Enterprise.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-NotificationService Enterprise.release.xcconfig\"; path = \"Target Support Files/Pods-NotificationService Enterprise/Pods-NotificationService Enterprise.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tA73CF12F2D9AAE13001191EB /* Pods_ShareExtension_Enterprise.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShareExtension_Enterprise.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tA760D4C60BC249A2F3CC3524 /* Pods-ShareExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-ShareExtension.release.xcconfig\"; path = \"Target Support Files/Pods-ShareExtension/Pods-ShareExtension.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tB9BC3C6EDB06DAA456CC4E8A /* Pods_IRCCloud_Enterprise.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_IRCCloud_Enterprise.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBB5BF7CE5566B5B9E80ACC95 /* Pods-IRCCloud.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloud.debug.xcconfig\"; path = \"Target Support Files/Pods-IRCCloud/Pods-IRCCloud.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tBFED8175E3E7FAD3E4906856 /* Pods-NotificationService Enterprise.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-NotificationService Enterprise.debug.xcconfig\"; path = \"Target Support Files/Pods-NotificationService Enterprise/Pods-NotificationService Enterprise.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tEB28B506CCB1E9844E1A26E4 /* Pods-ShareExtension Enterprise.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-ShareExtension Enterprise.appstore.xcconfig\"; path = \"Target Support Files/Pods-ShareExtension Enterprise/Pods-ShareExtension Enterprise.appstore.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tEE030EB298B99F1ED0BF22D4 /* Pods_ShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tEF5FD1784D881FDA33CC2709 /* Pods_IRCCloud.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_IRCCloud.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tF4F652185AA9F602056FD25B /* Pods-IRCCloudUnitTests.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloudUnitTests.appstore.xcconfig\"; path = \"Target Support Files/Pods-IRCCloudUnitTests/Pods-IRCCloudUnitTests.appstore.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tF7E442A5DB675C1935189274 /* Pods-IRCCloud Enterprise.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-IRCCloud Enterprise.release.xcconfig\"; path = \"Target Support Files/Pods-IRCCloud Enterprise/Pods-IRCCloud Enterprise.release.xcconfig\"; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t221034E4197EFBAF00AB414F /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t2236193B28B54DAC0077C850 /* IntentsUI.framework in Frameworks */,\n\t\t\t\t2236193828B5435F0077C850 /* Intents.framework in Frameworks */,\n\t\t\t\t229C85441B50293B004964DE /* CoreMedia.framework in Frameworks */,\n\t\t\t\t229C85431B502934004964DE /* AVFoundation.framework in Frameworks */,\n\t\t\t\t221034FA197EFC0500AB414F /* QuartzCore.framework in Frameworks */,\n\t\t\t\t221034FB197EFC0500AB414F /* AudioToolbox.framework in Frameworks */,\n\t\t\t\t22C8CD731B01289900F637D2 /* libc++.dylib in Frameworks */,\n\t\t\t\t225BEDC5252CB29F0050A8CC /* CoreServices.framework in Frameworks */,\n\t\t\t\t221034FC197EFC0500AB414F /* CFNetwork.framework in Frameworks */,\n\t\t\t\t221034FD197EFC0500AB414F /* CoreGraphics.framework in Frameworks */,\n\t\t\t\t221034FE197EFC0500AB414F /* CoreText.framework in Frameworks */,\n\t\t\t\t221034FF197EFC0500AB414F /* Foundation.framework in Frameworks */,\n\t\t\t\t22103500197EFC0500AB414F /* ImageIO.framework in Frameworks */,\n\t\t\t\t22103501197EFC0500AB414F /* libicucore.dylib in Frameworks */,\n\t\t\t\t22103502197EFC0500AB414F /* libz.dylib in Frameworks */,\n\t\t\t\t22103504197EFC0500AB414F /* Security.framework in Frameworks */,\n\t\t\t\t227DA89F1CF381D70041B1BF /* CoreTelephony.framework in Frameworks */,\n\t\t\t\t22103505197EFC0500AB414F /* SystemConfiguration.framework in Frameworks */,\n\t\t\t\t1A5703491A74145B00D58225 /* AdSupport.framework in Frameworks */,\n\t\t\t\t22103506197EFC0500AB414F /* Twitter.framework in Frameworks */,\n\t\t\t\t2238763D1F70062000943160 /* WebP.framework in Frameworks */,\n\t\t\t\t22103507197EFC0500AB414F /* UIKit.framework in Frameworks */,\n\t\t\t\t8B5FE5762F34C236ED73DA2C /* Pods_ShareExtension.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t221D4B8A1E23EAD600D403E6 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t221D4BCF1E23F5EC00D403E6 /* UIKit.framework in Frameworks */,\n\t\t\t\t221D4BC61E23F5EC00D403E6 /* AdSupport.framework in Frameworks */,\n\t\t\t\t221D4BC71E23F5EC00D403E6 /* AVFoundation.framework in Frameworks */,\n\t\t\t\t221D4BC81E23F5EC00D403E6 /* CFNetwork.framework in Frameworks */,\n\t\t\t\t221D4BC91E23F5EC00D403E6 /* CoreGraphics.framework in Frameworks */,\n\t\t\t\t221D4BCA1E23F5EC00D403E6 /* CoreText.framework in Frameworks */,\n\t\t\t\t221D4BCB1E23F5EC00D403E6 /* Foundation.framework in Frameworks */,\n\t\t\t\t221D4BCD1E23F5EC00D403E6 /* Security.framework in Frameworks */,\n\t\t\t\t221D4BCE1E23F5EC00D403E6 /* SystemConfiguration.framework in Frameworks */,\n\t\t\t\t2238763F1F70062200943160 /* WebP.framework in Frameworks */,\n\t\t\t\t225BEDC7252CB2A20050A8CC /* CoreServices.framework in Frameworks */,\n\t\t\t\tE3825E2339F2B2720FC1A112 /* Pods_NotificationService.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t221D4B9D1E23EB4900D403E6 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t1A6141501E6EDF30004B6025 /* UIKit.framework in Frameworks */,\n\t\t\t\t1A6141471E6EDF30004B6025 /* AdSupport.framework in Frameworks */,\n\t\t\t\t1A6141481E6EDF30004B6025 /* AVFoundation.framework in Frameworks */,\n\t\t\t\t1A6141491E6EDF30004B6025 /* CFNetwork.framework in Frameworks */,\n\t\t\t\t1A61414A1E6EDF30004B6025 /* CoreGraphics.framework in Frameworks */,\n\t\t\t\t1A61414B1E6EDF30004B6025 /* CoreText.framework in Frameworks */,\n\t\t\t\t1A61414C1E6EDF30004B6025 /* Foundation.framework in Frameworks */,\n\t\t\t\t1A61414E1E6EDF30004B6025 /* Security.framework in Frameworks */,\n\t\t\t\t1A61414F1E6EDF30004B6025 /* SystemConfiguration.framework in Frameworks */,\n\t\t\t\t223876401F70062200943160 /* WebP.framework in Frameworks */,\n\t\t\t\t225BEDC8252CB2A30050A8CC /* CoreServices.framework in Frameworks */,\n\t\t\t\tF1777B5C1D0CB8498FBFCAF5 /* Pods_NotificationService_Enterprise.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t224589C11DCA19BB00D3110A /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t04F298BB0853A565665F1F57 /* Pods_IRCCloudUnitTests.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t225D977818AA995900065087 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t2238763C1F70061F00943160 /* WebP.framework in Frameworks */,\n\t\t\t\t2289EF791D787CD100DB285E /* Intents.framework in Frameworks */,\n\t\t\t\t2289EF641D7866D200DB285E /* UserNotifications.framework in Frameworks */,\n\t\t\t\t227C63BA1C7B8C4800B674D6 /* SafariServices.framework in Frameworks */,\n\t\t\t\t2265DC8A1C722E7A00382C7C /* MessageUI.framework in Frameworks */,\n\t\t\t\t2245E3781B542D0E00B763D7 /* AVKit.framework in Frameworks */,\n\t\t\t\t229C85421B50292D004964DE /* CoreMedia.framework in Frameworks */,\n\t\t\t\t226EB6021B4C2E8C00C432C7 /* AVFoundation.framework in Frameworks */,\n\t\t\t\t2284EF731B4AD48E0058D483 /* MediaPlayer.framework in Frameworks */,\n\t\t\t\t2249867F1A95139400F6C3E2 /* AssetsLibrary.framework in Frameworks */,\n\t\t\t\t22C8DCF11A80154200199371 /* AdSupport.framework in Frameworks */,\n\t\t\t\t2200DB5118BCFA0E00343583 /* QuartzCore.framework in Frameworks */,\n\t\t\t\t225D977918AA995900065087 /* AudioToolbox.framework in Frameworks */,\n\t\t\t\t22C8DCF31A801A4500199371 /* CloudKit.framework in Frameworks */,\n\t\t\t\t225D977A18AA995900065087 /* Twitter.framework in Frameworks */,\n\t\t\t\t225D977B18AA995900065087 /* SystemConfiguration.framework in Frameworks */,\n\t\t\t\t225D977C18AA995900065087 /* ImageIO.framework in Frameworks */,\n\t\t\t\t225D977E18AA995900065087 /* libz.dylib in Frameworks */,\n\t\t\t\t227DA8A01CF381D90041B1BF /* CoreTelephony.framework in Frameworks */,\n\t\t\t\t2237440A252C9D4B0085D41C /* WebKit.framework in Frameworks */,\n\t\t\t\t225D977F18AA995900065087 /* CoreText.framework in Frameworks */,\n\t\t\t\t225D978018AA995900065087 /* libicucore.dylib in Frameworks */,\n\t\t\t\t22C8CD721B01289900F637D2 /* libc++.dylib in Frameworks */,\n\t\t\t\t225D978118AA995900065087 /* Security.framework in Frameworks */,\n\t\t\t\t225D978218AA995900065087 /* UIKit.framework in Frameworks */,\n\t\t\t\t225D978318AA995900065087 /* CFNetwork.framework in Frameworks */,\n\t\t\t\t225D978418AA995900065087 /* Foundation.framework in Frameworks */,\n\t\t\t\t225D978518AA995900065087 /* CoreGraphics.framework in Frameworks */,\n\t\t\t\t225BEDC4252CB29A0050A8CC /* CoreServices.framework in Frameworks */,\n\t\t\t\tE547E10E785196EBC983B6FE /* Pods_IRCCloud_Enterprise.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t228A056916D3DABA0029769C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t2236193A28B54D970077C850 /* IntentsUI.framework in Frameworks */,\n\t\t\t\t2238763B1F70061C00943160 /* WebP.framework in Frameworks */,\n\t\t\t\t2289EF781D787CC500DB285E /* Intents.framework in Frameworks */,\n\t\t\t\t2289EF631D7866BD00DB285E /* UserNotifications.framework in Frameworks */,\n\t\t\t\t2265DC891C722E6B00382C7C /* MessageUI.framework in Frameworks */,\n\t\t\t\t22A1F1151C232B3A00AEC09A /* SafariServices.framework in Frameworks */,\n\t\t\t\t2245E3771B542D0200B763D7 /* AVKit.framework in Frameworks */,\n\t\t\t\t229C85411B502920004964DE /* CoreMedia.framework in Frameworks */,\n\t\t\t\t226EB6011B4C2E8600C432C7 /* AVFoundation.framework in Frameworks */,\n\t\t\t\t2284EF721B4AD47F0058D483 /* MediaPlayer.framework in Frameworks */,\n\t\t\t\t2249867E1A95138800F6C3E2 /* AssetsLibrary.framework in Frameworks */,\n\t\t\t\t1A5703481A74145400D58225 /* AdSupport.framework in Frameworks */,\n\t\t\t\t22C8DCF41A801A6300199371 /* CloudKit.framework in Frameworks */,\n\t\t\t\t2200DB4718B7EDF100343583 /* QuartzCore.framework in Frameworks */,\n\t\t\t\t225BEDC3252CB27F0050A8CC /* CoreServices.framework in Frameworks */,\n\t\t\t\t2283323017944E2B00ED22EA /* AudioToolbox.framework in Frameworks */,\n\t\t\t\t22501740178340AB00066E71 /* Twitter.framework in Frameworks */,\n\t\t\t\t22324FE0177DE51A008B6912 /* SystemConfiguration.framework in Frameworks */,\n\t\t\t\t2223C6B61768F4500032544B /* ImageIO.framework in Frameworks */,\n\t\t\t\t2248DF3916EE375D0086BB42 /* libz.dylib in Frameworks */,\n\t\t\t\t227DA8A11CF381DA0041B1BF /* CoreTelephony.framework in Frameworks */,\n\t\t\t\t22374409252C9D3C0085D41C /* WebKit.framework in Frameworks */,\n\t\t\t\t228A05D716D3DFDA0029769C /* CoreText.framework in Frameworks */,\n\t\t\t\t22C8CD711B01289900F637D2 /* libc++.dylib in Frameworks */,\n\t\t\t\t228A05CF16D3DD540029769C /* libicucore.dylib in Frameworks */,\n\t\t\t\t228A05D016D3DD570029769C /* Security.framework in Frameworks */,\n\t\t\t\t228A057016D3DABA0029769C /* UIKit.framework in Frameworks */,\n\t\t\t\t228A05CA16D3DCB60029769C /* CFNetwork.framework in Frameworks */,\n\t\t\t\t228A057216D3DABA0029769C /* Foundation.framework in Frameworks */,\n\t\t\t\t228A057416D3DABA0029769C /* CoreGraphics.framework in Frameworks */,\n\t\t\t\t87D94430F2552C5FA140827E /* Pods_IRCCloud.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22CE2AD91D2AA659001397C0 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22D9784E215BC910005C2713 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t22D9784F215BC910005C2713 /* WebP.framework in Frameworks */,\n\t\t\t\t22D97850215BC910005C2713 /* Intents.framework in Frameworks */,\n\t\t\t\t22D97851215BC910005C2713 /* UserNotifications.framework in Frameworks */,\n\t\t\t\t22D97852215BC910005C2713 /* MessageUI.framework in Frameworks */,\n\t\t\t\t22D97853215BC910005C2713 /* SafariServices.framework in Frameworks */,\n\t\t\t\t22D97854215BC910005C2713 /* AVKit.framework in Frameworks */,\n\t\t\t\t22D97855215BC910005C2713 /* CoreMedia.framework in Frameworks */,\n\t\t\t\t22D97856215BC910005C2713 /* AVFoundation.framework in Frameworks */,\n\t\t\t\t22D97857215BC910005C2713 /* MediaPlayer.framework in Frameworks */,\n\t\t\t\t22D97858215BC910005C2713 /* AssetsLibrary.framework in Frameworks */,\n\t\t\t\t22D97859215BC910005C2713 /* AdSupport.framework in Frameworks */,\n\t\t\t\t22D9785A215BC910005C2713 /* CloudKit.framework in Frameworks */,\n\t\t\t\t22D9785B215BC910005C2713 /* QuartzCore.framework in Frameworks */,\n\t\t\t\t22D9785C215BC910005C2713 /* AudioToolbox.framework in Frameworks */,\n\t\t\t\t22D9785D215BC910005C2713 /* Twitter.framework in Frameworks */,\n\t\t\t\t22D9785E215BC910005C2713 /* SystemConfiguration.framework in Frameworks */,\n\t\t\t\t22D9785F215BC910005C2713 /* ImageIO.framework in Frameworks */,\n\t\t\t\t22D97861215BC910005C2713 /* libz.dylib in Frameworks */,\n\t\t\t\t22D97862215BC910005C2713 /* CoreTelephony.framework in Frameworks */,\n\t\t\t\t2237440B252C9D580085D41C /* WebKit.framework in Frameworks */,\n\t\t\t\t22D97863215BC910005C2713 /* CoreText.framework in Frameworks */,\n\t\t\t\t22D97865215BC910005C2713 /* libc++.dylib in Frameworks */,\n\t\t\t\t22D97866215BC910005C2713 /* libicucore.dylib in Frameworks */,\n\t\t\t\t22D97867215BC910005C2713 /* Security.framework in Frameworks */,\n\t\t\t\t22D97868215BC910005C2713 /* UIKit.framework in Frameworks */,\n\t\t\t\t22D97869215BC910005C2713 /* CFNetwork.framework in Frameworks */,\n\t\t\t\t22D9786A215BC910005C2713 /* Foundation.framework in Frameworks */,\n\t\t\t\t22D9786C215BC910005C2713 /* CoreGraphics.framework in Frameworks */,\n\t\t\t\t225BEDC9252CB2A30050A8CC /* CoreServices.framework in Frameworks */,\n\t\t\t\tE73463A6EBBD7BC26D20DE95 /* Pods_IRCCloud_FLEX.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22DB251F1982DF2B0008728E /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t227DA89E1CF381B60041B1BF /* CoreTelephony.framework in Frameworks */,\n\t\t\t\t229C85461B50294C004964DE /* CoreMedia.framework in Frameworks */,\n\t\t\t\t229C85451B502946004964DE /* AVFoundation.framework in Frameworks */,\n\t\t\t\t22DB25211982DF2B0008728E /* QuartzCore.framework in Frameworks */,\n\t\t\t\t22DB25221982DF2B0008728E /* AudioToolbox.framework in Frameworks */,\n\t\t\t\t22C8CD741B01289900F637D2 /* libc++.dylib in Frameworks */,\n\t\t\t\t22DB25231982DF2B0008728E /* CFNetwork.framework in Frameworks */,\n\t\t\t\t22DB25241982DF2B0008728E /* CoreGraphics.framework in Frameworks */,\n\t\t\t\t22DB25251982DF2B0008728E /* CoreText.framework in Frameworks */,\n\t\t\t\t22DB25261982DF2B0008728E /* Foundation.framework in Frameworks */,\n\t\t\t\t2238763E1F70062100943160 /* WebP.framework in Frameworks */,\n\t\t\t\t22DB25271982DF2B0008728E /* ImageIO.framework in Frameworks */,\n\t\t\t\t22DB25281982DF2B0008728E /* libicucore.dylib in Frameworks */,\n\t\t\t\t22DB25291982DF2B0008728E /* libz.dylib in Frameworks */,\n\t\t\t\t22DB252B1982DF2B0008728E /* Security.framework in Frameworks */,\n\t\t\t\t22DB252C1982DF2B0008728E /* SystemConfiguration.framework in Frameworks */,\n\t\t\t\t22DB252D1982DF2B0008728E /* Twitter.framework in Frameworks */,\n\t\t\t\t22DB252E1982DF2B0008728E /* UIKit.framework in Frameworks */,\n\t\t\t\t225BEDC6252CB2A00050A8CC /* CoreServices.framework in Frameworks */,\n\t\t\t\t826532809086053E3C7D2EB6 /* Pods_ShareExtension_Enterprise.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\t221034E8197EFBAF00AB414F /* ShareExtension */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2296E0B619805751002D59E3 /* ShareExtension.entitlements */,\n\t\t\t\t22B6F9771982F47E004C291C /* ShareExtension Enterprise.entitlements */,\n\t\t\t\t221034EB197EFBAF00AB414F /* ShareViewController.h */,\n\t\t\t\t221034EC197EFBAF00AB414F /* ShareViewController.m */,\n\t\t\t\t221034E9197EFBAF00AB414F /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = ShareExtension;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t221034E9197EFBAF00AB414F /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22DB24F91982DF070008728E /* Info-Enterprise.plist */,\n\t\t\t\t221034EA197EFBAF00AB414F /* Info.plist */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t221D4B8E1E23EAD700D403E6 /* NotificationService */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t221D4BAA1E23F24000D403E6 /* NotificationService.entitlements */,\n\t\t\t\t221D4BAB1E23F24F00D403E6 /* NotificationService Enterprise.entitlements */,\n\t\t\t\t221D4B8F1E23EAD700D403E6 /* NotificationService.h */,\n\t\t\t\t221D4B901E23EAD700D403E6 /* NotificationService.m */,\n\t\t\t\t221D4B921E23EAD700D403E6 /* Info.plist */,\n\t\t\t);\n\t\t\tpath = NotificationService;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t223876101F70035300943160 /* YYImage */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t223876111F70035300943160 /* YYAnimatedImageView.h */,\n\t\t\t\t223876121F70035300943160 /* YYAnimatedImageView.m */,\n\t\t\t\t223876131F70035300943160 /* YYFrameImage.h */,\n\t\t\t\t223876141F70035300943160 /* YYFrameImage.m */,\n\t\t\t\t223876151F70035300943160 /* YYImage.h */,\n\t\t\t\t223876161F70035300943160 /* YYImage.m */,\n\t\t\t\t223876171F70035300943160 /* YYImageCoder.h */,\n\t\t\t\t223876181F70035300943160 /* YYImageCoder.m */,\n\t\t\t\t223876191F70035300943160 /* YYSpriteSheetImage.h */,\n\t\t\t\t2238761A1F70035300943160 /* YYSpriteSheetImage.m */,\n\t\t\t);\n\t\t\tpath = YYImage;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t224589C51DCA19BB00D3110A /* IRCCloudUnitTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t224589C61DCA19BB00D3110A /* CollapsedEventsTests.m */,\n\t\t\t\t224291641EB22B1000878455 /* URLtoBIDTests.m */,\n\t\t\t\t224589C81DCA19BB00D3110A /* Info.plist */,\n\t\t\t\t2252EE5A1F4485C000307010 /* MessageTypeTests.m */,\n\t\t\t);\n\t\t\tpath = IRCCloudUnitTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t225017411783434800066E71 /* ARChromeActivity */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t225017421783434800066E71 /* ARChromeActivity.h */,\n\t\t\t\t225017431783434800066E71 /* ARChromeActivity.m */,\n\t\t\t\t225017441783434800066E71 /* ARChromeActivity.png */,\n\t\t\t\t225017451783434800066E71 /* ARChromeActivity@2x.png */,\n\t\t\t\t225017461783434800066E71 /* ARChromeActivity@2x~ipad.png */,\n\t\t\t\t225017471783434800066E71 /* ARChromeActivity~ipad.png */,\n\t\t\t);\n\t\t\tpath = ARChromeActivity;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t225017481783434800066E71 /* TUSafariActivity */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2251693117B5A8040093ADC5 /* TUSafariActivity.strings */,\n\t\t\t\t225017591783434900066E71 /* Safari.png */,\n\t\t\t\t2250175A1783434900066E71 /* Safari@2x.png */,\n\t\t\t\t2250175B1783434900066E71 /* Safari@2x~ipad.png */,\n\t\t\t\t2250175C1783434900066E71 /* Safari~ipad.png */,\n\t\t\t\t2250175F1783434900066E71 /* TUSafariActivity.h */,\n\t\t\t\t225017601783434900066E71 /* TUSafariActivity.m */,\n\t\t\t);\n\t\t\tpath = TUSafariActivity;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t2263D39F290A979500692EEC /* StringScore */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2263D3A0290A979500692EEC /* NSString+Score.h */,\n\t\t\t\t2263D3A1290A979500692EEC /* NSString+Score.m */,\n\t\t\t);\n\t\t\tpath = StringScore;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t228A056316D3DABA0029769C = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t228A057516D3DABA0029769C /* IRCCloud */,\n\t\t\t\t221034E8197EFBAF00AB414F /* ShareExtension */,\n\t\t\t\t22CE2ADD1D2AA660001397C0 /* UITests */,\n\t\t\t\t224589C51DCA19BB00D3110A /* IRCCloudUnitTests */,\n\t\t\t\t221D4B8E1E23EAD700D403E6 /* NotificationService */,\n\t\t\t\t228A056E16D3DABA0029769C /* Frameworks */,\n\t\t\t\t228A056D16D3DABA0029769C /* Products */,\n\t\t\t\t7CF0BE4739CE6912111DBBD1 /* Pods */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t228A056D16D3DABA0029769C /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t228A056C16D3DABA0029769C /* IRCCloud.app */,\n\t\t\t\t225D979F18AA995900065087 /* IRCEnterprise.app */,\n\t\t\t\t221034E7197EFBAF00AB414F /* ShareExtension.appex */,\n\t\t\t\t22DB25371982DF2B0008728E /* ShareExtension Enterprise.appex */,\n\t\t\t\t22CE2ADC1D2AA65A001397C0 /* UITests.xctest */,\n\t\t\t\t224589C41DCA19BB00D3110A /* IRCCloudUnitTests.xctest */,\n\t\t\t\t221D4B8D1E23EAD600D403E6 /* NotificationService.appex */,\n\t\t\t\t221D4BA31E23EB4900D403E6 /* NotificationService Enterprise.appex */,\n\t\t\t\t22D9789B215BC910005C2713 /* IRCCloud FLEX.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t228A056E16D3DABA0029769C /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2236193928B54D970077C850 /* IntentsUI.framework */,\n\t\t\t\t2236193728B5435F0077C850 /* Intents.framework */,\n\t\t\t\t225BEDC2252CB27F0050A8CC /* CoreServices.framework */,\n\t\t\t\t22374408252C9D3C0085D41C /* WebKit.framework */,\n\t\t\t\t2238761C1F70038A00943160 /* WebP.framework */,\n\t\t\t\t1A61413D1E6EDF30004B6025 /* AdSupport.framework */,\n\t\t\t\t1A61413E1E6EDF30004B6025 /* AVFoundation.framework */,\n\t\t\t\t1A61413F1E6EDF30004B6025 /* CFNetwork.framework */,\n\t\t\t\t1A6141401E6EDF30004B6025 /* CoreGraphics.framework */,\n\t\t\t\t1A6141411E6EDF30004B6025 /* CoreText.framework */,\n\t\t\t\t1A6141421E6EDF30004B6025 /* Foundation.framework */,\n\t\t\t\t1A6141431E6EDF30004B6025 /* MobileCoreServices.framework */,\n\t\t\t\t1A6141441E6EDF30004B6025 /* Security.framework */,\n\t\t\t\t1A6141451E6EDF30004B6025 /* SystemConfiguration.framework */,\n\t\t\t\t1A6141461E6EDF30004B6025 /* UIKit.framework */,\n\t\t\t\t2289EF771D787CC500DB285E /* Intents.framework */,\n\t\t\t\t2289EF621D7866BD00DB285E /* UserNotifications.framework */,\n\t\t\t\t227DA89D1CF381B60041B1BF /* CoreTelephony.framework */,\n\t\t\t\t2265DC881C722E6B00382C7C /* MessageUI.framework */,\n\t\t\t\t22A1F1141C232B3A00AEC09A /* SafariServices.framework */,\n\t\t\t\t2245E3761B542D0200B763D7 /* AVKit.framework */,\n\t\t\t\t229C85401B502920004964DE /* CoreMedia.framework */,\n\t\t\t\t226EB6001B4C2E8600C432C7 /* AVFoundation.framework */,\n\t\t\t\t2284EF711B4AD47F0058D483 /* MediaPlayer.framework */,\n\t\t\t\t2249867D1A95138800F6C3E2 /* AssetsLibrary.framework */,\n\t\t\t\t22C8DCF21A801A4500199371 /* CloudKit.framework */,\n\t\t\t\t1A5703471A74145400D58225 /* AdSupport.framework */,\n\t\t\t\t2200DB4618B7EDF100343583 /* QuartzCore.framework */,\n\t\t\t\t2283322F17944E2B00ED22EA /* AudioToolbox.framework */,\n\t\t\t\t228A05C916D3DCB60029769C /* CFNetwork.framework */,\n\t\t\t\t228A057316D3DABA0029769C /* CoreGraphics.framework */,\n\t\t\t\t228A05D516D3DFD00029769C /* CoreText.framework */,\n\t\t\t\t228A057116D3DABA0029769C /* Foundation.framework */,\n\t\t\t\t2223C6B51768F4500032544B /* ImageIO.framework */,\n\t\t\t\t228A05CD16D3DD310029769C /* libicucore.dylib */,\n\t\t\t\t22C8CD701B01289900F637D2 /* libc++.dylib */,\n\t\t\t\t2248DF3816EE375D0086BB42 /* libz.dylib */,\n\t\t\t\t2230F8E41715E61F007F7C98 /* MobileCoreServices.framework */,\n\t\t\t\t228A05CB16D3DCE20029769C /* Security.framework */,\n\t\t\t\t22324FDF177DE51A008B6912 /* SystemConfiguration.framework */,\n\t\t\t\t2250173F178340AB00066E71 /* Twitter.framework */,\n\t\t\t\t228A056F16D3DABA0029769C /* UIKit.framework */,\n\t\t\t\tEF5FD1784D881FDA33CC2709 /* Pods_IRCCloud.framework */,\n\t\t\t\tB9BC3C6EDB06DAA456CC4E8A /* Pods_IRCCloud_Enterprise.framework */,\n\t\t\t\t9687F6412D04D07E40F1CA5D /* Pods_IRCCloud_FLEX.framework */,\n\t\t\t\t680E63BC56A1C3A1442F25DF /* Pods_IRCCloudUnitTests.framework */,\n\t\t\t\t3CF6A7B20BFBB01BD7B6F779 /* Pods_NotificationService.framework */,\n\t\t\t\t19B9BF768BEB6B7F454BD143 /* Pods_NotificationService_Enterprise.framework */,\n\t\t\t\tEE030EB298B99F1ED0BF22D4 /* Pods_ShareExtension.framework */,\n\t\t\t\tA73CF12F2D9AAE13001191EB /* Pods_ShareExtension_Enterprise.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t228A057516D3DABA0029769C /* IRCCloud */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t221EB2F21F962C2C00A71428 /* EventsTableCell_File.xib */,\n\t\t\t\t221EB2F31F962C2D00A71428 /* EventsTableCell_Thumbnail.xib */,\n\t\t\t\t225EC2BA2061678B00AA0C79 /* EventsTableCell_ReplyCount.xib */,\n\t\t\t\t221EB2ED1F8F965E00A71428 /* EventsTableCell.xib */,\n\t\t\t\t22EB4CF31CCEE296004F9CFC /* ImageViewController.xib */,\n\t\t\t\t22DB253D1982E2890008728E /* IRCEnterprise.entitlements */,\n\t\t\t\t2296E0B719805767002D59E3 /* IRCCloud.entitlements */,\n\t\t\t\t22F4A9C91CB5424F00359049 /* Launch.storyboard */,\n\t\t\t\t22D268C11BF4F40800B682AE /* MainStoryboard.storyboard */,\n\t\t\t\t228A05AD16D3DB7B0029769C /* Classes */,\n\t\t\t\t228A05B416D3DB930029769C /* Resources */,\n\t\t\t\t228A057616D3DABA0029769C /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = IRCCloud;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t228A057616D3DABA0029769C /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t220E79AB2D0A095C00414B0F /* VERSION */,\n\t\t\t\t228B909229E5980F001CBACB /* ace-modes.js */,\n\t\t\t\t228B908F29E597D9001CBACB /* emocode-data.js */,\n\t\t\t\t2263D39F290A979500692EEC /* StringScore */,\n\t\t\t\t226E642223F1C6AA001CE069 /* GoogleService-Info.plist */,\n\t\t\t\t22D9789D215BC979005C2713 /* FLEX */,\n\t\t\t\t2238761B1F70036900943160 /* WebP.framework */,\n\t\t\t\t223876101F70035300943160 /* YYImage */,\n\t\t\t\t229323D71E8945D700ADAA22 /* TrustKit */,\n\t\t\t\t22EE12801C9B1DE000E7AE8D /* OpenInFirefoxClient */,\n\t\t\t\t2236BD671BAA600900015753 /* FontAwesome.h */,\n\t\t\t\t22D649201B1E0719003BFD86 /* CSURITemplate */,\n\t\t\t\t22A363AF19D0884D00500478 /* 1Password.xcassets */,\n\t\t\t\t22A363B019D0884D00500478 /* OnePasswordExtension.h */,\n\t\t\t\t22A363B119D0884D00500478 /* OnePasswordExtension.m */,\n\t\t\t\t2200DB4D18B81BEB00343583 /* config.h */,\n\t\t\t\t225017411783434800066E71 /* ARChromeActivity */,\n\t\t\t\t22B15CF617301BAE0075EBA7 /* ECSlidingViewController */,\n\t\t\t\t228A057716D3DABA0029769C /* IRCCloud-Info.plist */,\n\t\t\t\t225D97A118AA9EBC00065087 /* IRCCloud-Enterprise-Info.plist */,\n\t\t\t\t228A057D16D3DABA0029769C /* IRCCloud-Prefix.pch */,\n\t\t\t\t228A057B16D3DABA0029769C /* main.m */,\n\t\t\t\t2293AF0017F9CCD10022BD06 /* NSURL+IDN.h */,\n\t\t\t\t2293AEFF17F9CCD10022BD06 /* NSURL+IDN.m */,\n\t\t\t\t2274F49D1756723F0039B4CB /* OpenInChromeController.h */,\n\t\t\t\t2274F49E1756723F0039B4CB /* OpenInChromeController.m */,\n\t\t\t\t22B4280416D7E21100498507 /* SBJson */,\n\t\t\t\t225017481783434800066E71 /* TUSafariActivity */,\n\t\t\t\t22D430A21725AAE9003C0684 /* UIExpandingTextView.h */,\n\t\t\t\t22D430A31725AAEA003C0684 /* UIExpandingTextView.m */,\n\t\t\t\t22D430A41725AAEA003C0684 /* UIExpandingTextViewInternal.h */,\n\t\t\t\t22D430A51725AAEA003C0684 /* UIExpandingTextViewInternal.m */,\n\t\t\t\t22B4284A16D831A800498507 /* WebSocket */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t228A05AD16D3DB7B0029769C /* Classes */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t228A05AE16D3DB7B0029769C /* AppDelegate.h */,\n\t\t\t\t228A05AF16D3DB7B0029769C /* AppDelegate.m */,\n\t\t\t\t22E54ADE1D10593B00891FE4 /* AvatarsDataSource.h */,\n\t\t\t\t22E54ADF1D10593B00891FE4 /* AvatarsDataSource.m */,\n\t\t\t\t224333CE20162C1B0007A0D3 /* AvatarsTableViewController.h */,\n\t\t\t\t224333CF20162C1B0007A0D3 /* AvatarsTableViewController.m */,\n\t\t\t\t2236F5FC16DA8928007BE535 /* BuffersDataSource.h */,\n\t\t\t\t2236F5FD16DA8928007BE535 /* BuffersDataSource.m */,\n\t\t\t\t2236F60416DBCA85007BE535 /* BuffersTableView.h */,\n\t\t\t\t2236F60516DBCA85007BE535 /* BuffersTableView.m */,\n\t\t\t\t221F0BC3177368A20008EE04 /* CallerIDTableViewController.h */,\n\t\t\t\t221F0BC4177368B40008EE04 /* CallerIDTableViewController.m */,\n\t\t\t\t2212AF86175F82F900D08C7F /* ChannelInfoViewController.h */,\n\t\t\t\t2212AF87175F82F900D08C7F /* ChannelInfoViewController.m */,\n\t\t\t\t2253BA261770CDC500CCA77F /* ChannelListTableViewController.h */,\n\t\t\t\t2253BA241770CD7100CCA77F /* ChannelListTableViewController.m */,\n\t\t\t\t22AD75EB1718567D00141257 /* ChannelModeListTableViewController.h */,\n\t\t\t\t22AD75EC1718567D00141257 /* ChannelModeListTableViewController.m */,\n\t\t\t\t2236F60016DBC020007BE535 /* ChannelsDataSource.h */,\n\t\t\t\t2236F60116DBC021007BE535 /* ChannelsDataSource.m */,\n\t\t\t\t22695F5316E8FC9800E01DF8 /* CollapsedEvents.h */,\n\t\t\t\t22695F5416E8FC9800E01DF8 /* CollapsedEvents.m */,\n\t\t\t\t2237E13B16E1214A00CA188F /* ColorFormatter.h */,\n\t\t\t\t2237E13C16E1214A00CA188F /* ColorFormatter.m */,\n\t\t\t\t228EFBC6177B4F6000B83A4C /* DisplayOptionsViewController.h */,\n\t\t\t\t228EFBC7177B4F7300B83A4C /* DisplayOptionsViewController.m */,\n\t\t\t\t22B15CF2172ECCFF0075EBA7 /* EditConnectionViewController.h */,\n\t\t\t\t22B15CF3172ECCFF0075EBA7 /* EditConnectionViewController.m */,\n\t\t\t\t22F9EE1A16DE6F21004615C0 /* EventsDataSource.h */,\n\t\t\t\t22F9EE1B16DE6F21004615C0 /* EventsDataSource.m */,\n\t\t\t\t223DA90A16DFC626006FF808 /* EventsTableView.h */,\n\t\t\t\t223DA90B16DFC626006FF808 /* EventsTableView.m */,\n\t\t\t\t22C2075A1A19125700EDACA4 /* FileMetadataViewController.h */,\n\t\t\t\t22C2075B1A19125700EDACA4 /* FileMetadataViewController.m */,\n\t\t\t\t22D46C651A13A9A900B142F7 /* FileUploader.h */,\n\t\t\t\t22D46C661A13A9A900B142F7 /* FileUploader.m */,\n\t\t\t\t221E3F4A1AD2DEE00090934B /* FilesTableViewController.h */,\n\t\t\t\t221E3F4B1AD2DEE00090934B /* FilesTableViewController.m */,\n\t\t\t\t227FF29F16FA128A00DBE3C5 /* HighlightsCountView.h */,\n\t\t\t\t227FF2A016FA128B00DBE3C5 /* HighlightsCountView.m */,\n\t\t\t\t2230F8E617162ACC007F7C98 /* Ignore.h */,\n\t\t\t\t2230F8E717162ACC007F7C98 /* Ignore.m */,\n\t\t\t\t22D4309E171C663A003C0684 /* IgnoresTableViewController.h */,\n\t\t\t\t22D4309F171C663A003C0684 /* IgnoresTableViewController.m */,\n\t\t\t\t222C80B41E48ABB200A243E7 /* ImageCache.h */,\n\t\t\t\t222C80B51E48ABB200A243E7 /* ImageCache.m */,\n\t\t\t\t2223C6A71768D7150032544B /* ImageViewController.h */,\n\t\t\t\t2223C6A81768D7150032544B /* ImageViewController.m */,\n\t\t\t\t22B4288416D846BF00498507 /* IRCCloudJSONObject.h */,\n\t\t\t\t22B4288516D846BF00498507 /* IRCCloudJSONObject.m */,\n\t\t\t\t223C407A1C60FE880081B02B /* IRCCloudSafariViewController.h */,\n\t\t\t\t223C407B1C60FE880081B02B /* IRCCloudSafariViewController.m */,\n\t\t\t\t22EE41F81F39F66E00D74E8C /* IRCColorPickerView.h */,\n\t\t\t\t22EE41F91F39F66E00D74E8C /* IRCColorPickerView.m */,\n\t\t\t\t224FCF341787288400FC3879 /* LicenseViewController.h */,\n\t\t\t\t224FCF351787288400FC3879 /* LicenseViewController.m */,\n\t\t\t\t22CE91771D59160B0014B25C /* LinkLabel.h */,\n\t\t\t\t22CE91781D59160B0014B25C /* LinkLabel.m */,\n\t\t\t\t22CE91731D58C81C0014B25C /* LinkTextView.h */,\n\t\t\t\t22CE91741D58C81C0014B25C /* LinkTextView.m */,\n\t\t\t\t221D4B881E1BE30700D403E6 /* LinksListTableViewController.h */,\n\t\t\t\t221D4B851E1BE2F700D403E6 /* LinksListTableViewController.m */,\n\t\t\t\t223154FB1F26245800BDE367 /* LogExportsTableViewController.h */,\n\t\t\t\t223154FC1F26245800BDE367 /* LogExportsTableViewController.m */,\n\t\t\t\t228A05DB16D3E40E0029769C /* LoginSplashViewController.h */,\n\t\t\t\t228A05DC16D3E40E0029769C /* LoginSplashViewController.m */,\n\t\t\t\t2236F60816DBCBC6007BE535 /* MainViewController.h */,\n\t\t\t\t2236F60916DBCBC6007BE535 /* MainViewController.m */,\n\t\t\t\t22A35F27178A3F2B00529CDA /* NamesListTableViewController.h */,\n\t\t\t\t22A35F28178A3F3500529CDA /* NamesListTableViewController.m */,\n\t\t\t\t22032A6D1884529700BE4A10 /* NickCompletionView.h */,\n\t\t\t\t22032A6E1884529700BE4A10 /* NickCompletionView.m */,\n\t\t\t\t22B4284616D7E36300498507 /* NetworkConnection.h */,\n\t\t\t\t22B4284716D7E36300498507 /* NetworkConnection.m */,\n\t\t\t\t22B2036C1B5FE3BE0058078D /* NotificationsDataSource.h */,\n\t\t\t\t22B2036D1B5FE3BE0058078D /* NotificationsDataSource.m */,\n\t\t\t\t22D649281B1E371D003BFD86 /* PastebinsTableViewController.h */,\n\t\t\t\t22D649291B1E371D003BFD86 /* PastebinsTableViewController.m */,\n\t\t\t\t221390FC1B115CD000ECF001 /* PastebinEditorViewController.h */,\n\t\t\t\t221390FD1B115CD000ECF001 /* PastebinEditorViewController.m */,\n\t\t\t\t22C2E0551B0E2E4800387B4B /* PastebinViewController.h */,\n\t\t\t\t22C2E0561B0E2E4800387B4B /* PastebinViewController.m */,\n\t\t\t\t221E85F1241FBD9300EB5120 /* PinReorderViewController.h */,\n\t\t\t\t221E85F0241FBD9300EB5120 /* PinReorderViewController.m */,\n\t\t\t\t22BB94A91D425A4E00BFB6F0 /* SamlLoginViewController.h */,\n\t\t\t\t22BB94A81D425A4E00BFB6F0 /* SamlLoginViewController.m */,\n\t\t\t\t22BB0A2828C22FB2008EE509 /* SendMessageIntentHandler.h */,\n\t\t\t\t22BB0A2928C22FB2008EE509 /* SendMessageIntentHandler.m */,\n\t\t\t\t22462B5018906B03009EF986 /* ServerReorderViewController.h */,\n\t\t\t\t22462B5118906B03009EF986 /* ServerReorderViewController.m */,\n\t\t\t\t2236F5F816DA765C007BE535 /* ServersDataSource.h */,\n\t\t\t\t2236F5F916DA765C007BE535 /* ServersDataSource.m */,\n\t\t\t\t227FF8211772062E00394114 /* SettingsViewController.h */,\n\t\t\t\t227FF8221772063F00394114 /* SettingsViewController.m */,\n\t\t\t\t228F69711DF8A3F30079E276 /* SpamViewController.h */,\n\t\t\t\t228F69721DF8A3F30079E276 /* SpamViewController.m */,\n\t\t\t\t22D268C41BF4F95200B682AE /* SplashViewController.h */,\n\t\t\t\t22D268C51BF4F95200B682AE /* SplashViewController.m */,\n\t\t\t\t2271FD9F1DCDF45C00A39F84 /* TextTableViewController.h */,\n\t\t\t\t2271FDA01DCDF45C00A39F84 /* TextTableViewController.m */,\n\t\t\t\t2236F63A16DBF3CA007BE535 /* UIColor+IRCCloud.h */,\n\t\t\t\t2236F63B16DBF3CB007BE535 /* UIColor+IRCCloud.m */,\n\t\t\t\t22A363BA19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.h */,\n\t\t\t\t22A363BB19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.m */,\n\t\t\t\t22A19C5E178FCCAB00772C60 /* UINavigationController+iPadSux.h */,\n\t\t\t\t22A19C5F178FCCAB00772C60 /* UINavigationController+iPadSux.m */,\n\t\t\t\t2232ABD4230C1D66007431B5 /* UITableViewController+HeaderColorFix.h */,\n\t\t\t\t2232ABD5230C1D66007431B5 /* UITableViewController+HeaderColorFix.m */,\n\t\t\t\t2264A2FF19659BB100DCFDDD /* URLHandler.h */,\n\t\t\t\t2264A30019659BB100DCFDDD /* URLHandler.m */,\n\t\t\t\t2236F64416DD138A007BE535 /* UsersDataSource.h */,\n\t\t\t\t2236F64516DD138B007BE535 /* UsersDataSource.m */,\n\t\t\t\t2236F64816DD30E0007BE535 /* UsersTableView.h */,\n\t\t\t\t2236F64916DD30E3007BE535 /* UsersTableView.m */,\n\t\t\t\t22A1D0251778A86900F8A89C /* WhoisViewController.h */,\n\t\t\t\t22A1D0261778A86900F8A89C /* WhoisViewController.m */,\n\t\t\t\t22A35F24178A316300529CDA /* WhoListTableViewController.h */,\n\t\t\t\t22A35F25178A317100529CDA /* WhoListTableViewController.m */,\n\t\t\t\t226F080C1E6495C8003EED23 /* WhoWasTableViewController.h */,\n\t\t\t\t226F080D1E6495C8003EED23 /* WhoWasTableViewController.m */,\n\t\t\t\t22DB8D6E1C441C3000302271 /* YouTubeViewController.h */,\n\t\t\t\t22DB8D6F1C441C3000302271 /* YouTubeViewController.m */,\n\t\t\t);\n\t\t\tpath = Classes;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t228A05B416D3DB930029769C /* Resources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2210671C1F28C3BB0075A18F /* Hack-Bold.ttf */,\n\t\t\t\t2210671D1F28C3BB0075A18F /* Hack-BoldItalic.ttf */,\n\t\t\t\t2210671E1F28C3BB0075A18F /* Hack-Italic.ttf */,\n\t\t\t\t2210671F1F28C3BB0075A18F /* Hack-Regular.ttf */,\n\t\t\t\t2236BD621BAA5E0900015753 /* FontAwesome.otf */,\n\t\t\t\t2236BD681BAC61A900015753 /* SourceSansPro-LightIt.otf */,\n\t\t\t\t2236BD691BAC61A900015753 /* SourceSansPro-Regular.otf */,\n\t\t\t\t225173E21DB13A5500D63405 /* SourceSansPro-Semibold.otf */,\n\t\t\t\t1A7382A918D0A9A30039FDB3 /* EnterpriseLogo.xcassets */,\n\t\t\t\t22EEA94D18D0AC08007D5022 /* EnterpriseImages.xcassets */,\n\t\t\t\t1A7382AA18D0A9A30039FDB3 /* Logo.xcassets */,\n\t\t\t\t22EEA95018D0B117007D5022 /* Images.xcassets */,\n\t\t\t\t22EEA95318D0B198007D5022 /* Icons.xcassets */,\n\t\t\t\t22F5C4BC1791F205005E09A9 /* a.caf */,\n\t\t\t\t224FCF321787286000FC3879 /* licenses.txt */,\n\t\t\t\t22D4F9101743F3790095EE8F /* Localizable.strings */,\n\t\t\t);\n\t\t\tpath = Resources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t229323D71E8945D700ADAA22 /* TrustKit */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t229323D81E8945D700ADAA22 /* configuration_utils.h */,\n\t\t\t\t229323D91E8945D700ADAA22 /* configuration_utils.m */,\n\t\t\t\t229323DA1E8945D700ADAA22 /* Dependencies */,\n\t\t\t\t229323EF1E8945D700ADAA22 /* parse_configuration.h */,\n\t\t\t\t229323F01E8945D700ADAA22 /* parse_configuration.m */,\n\t\t\t\t229323F11E8945D700ADAA22 /* Pinning */,\n\t\t\t\t229323F61E8945D700ADAA22 /* Reporting */,\n\t\t\t\t229324011E8945D700ADAA22 /* Swizzling */,\n\t\t\t\t229324061E8945D700ADAA22 /* TrustKit+Private.h */,\n\t\t\t\t229324071E8945D700ADAA22 /* TrustKit.h */,\n\t\t\t\t229324081E8945D700ADAA22 /* TrustKit.m */,\n\t\t\t\t229324091E8945D700ADAA22 /* TSKPinningValidator.h */,\n\t\t\t\t2293240A1E8945D700ADAA22 /* TSKPinningValidator.m */,\n\t\t\t);\n\t\t\tpath = TrustKit;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t229323DA1E8945D700ADAA22 /* Dependencies */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t229323DB1E8945D700ADAA22 /* domain_registry */,\n\t\t\t\t229323EA1E8945D700ADAA22 /* RSSwizzle */,\n\t\t\t);\n\t\t\tpath = Dependencies;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t229323DB1E8945D700ADAA22 /* domain_registry */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t229323DC1E8945D700ADAA22 /* domain_registry.h */,\n\t\t\t\t229323DD1E8945D700ADAA22 /* private */,\n\t\t\t\t229323E71E8945D700ADAA22 /* registry_tables_genfiles */,\n\t\t\t);\n\t\t\tpath = domain_registry;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t229323DD1E8945D700ADAA22 /* private */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t229323DE1E8945D700ADAA22 /* assert.c */,\n\t\t\t\t229323DF1E8945D700ADAA22 /* assert.h */,\n\t\t\t\t229323E01E8945D700ADAA22 /* init_registry_tables.c */,\n\t\t\t\t229323E11E8945D700ADAA22 /* registry_search.c */,\n\t\t\t\t229323E21E8945D700ADAA22 /* registry_types.h */,\n\t\t\t\t229323E31E8945D700ADAA22 /* string_util.h */,\n\t\t\t\t229323E41E8945D700ADAA22 /* trie_node.h */,\n\t\t\t\t229323E51E8945D700ADAA22 /* trie_search.c */,\n\t\t\t\t229323E61E8945D700ADAA22 /* trie_search.h */,\n\t\t\t);\n\t\t\tpath = private;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t229323E71E8945D700ADAA22 /* registry_tables_genfiles */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t229323E81E8945D700ADAA22 /* registry_tables.h */,\n\t\t\t);\n\t\t\tpath = registry_tables_genfiles;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t229323EA1E8945D700ADAA22 /* RSSwizzle */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t229323EB1E8945D700ADAA22 /* RSSwizzle.h */,\n\t\t\t\t229323EC1E8945D700ADAA22 /* RSSwizzle.m */,\n\t\t\t);\n\t\t\tpath = RSSwizzle;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t229323F11E8945D700ADAA22 /* Pinning */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t229323F21E8945D700ADAA22 /* public_key_utils.h */,\n\t\t\t\t229323F31E8945D700ADAA22 /* public_key_utils.m */,\n\t\t\t\t229323F41E8945D700ADAA22 /* ssl_pin_verifier.h */,\n\t\t\t\t229323F51E8945D700ADAA22 /* ssl_pin_verifier.m */,\n\t\t\t);\n\t\t\tpath = Pinning;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t229323F61E8945D700ADAA22 /* Reporting */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t229323F71E8945D700ADAA22 /* reporting_utils.h */,\n\t\t\t\t229323F81E8945D700ADAA22 /* reporting_utils.m */,\n\t\t\t\t229323F91E8945D700ADAA22 /* TSKBackgroundReporter.h */,\n\t\t\t\t229323FA1E8945D700ADAA22 /* TSKBackgroundReporter.m */,\n\t\t\t\t229323FB1E8945D700ADAA22 /* TSKPinFailureReport.h */,\n\t\t\t\t229323FC1E8945D700ADAA22 /* TSKPinFailureReport.m */,\n\t\t\t\t229323FD1E8945D700ADAA22 /* TSKReportsRateLimiter.h */,\n\t\t\t\t229323FE1E8945D700ADAA22 /* TSKReportsRateLimiter.m */,\n\t\t\t\t229323FF1E8945D700ADAA22 /* vendor_identifier.h */,\n\t\t\t\t229324001E8945D700ADAA22 /* vendor_identifier.m */,\n\t\t\t);\n\t\t\tpath = Reporting;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t229324011E8945D700ADAA22 /* Swizzling */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t229324021E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.h */,\n\t\t\t\t229324031E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m */,\n\t\t\t\t229324041E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.h */,\n\t\t\t\t229324051E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m */,\n\t\t\t);\n\t\t\tpath = Swizzling;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22B15CF617301BAE0075EBA7 /* ECSlidingViewController */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22B15CF717301BAF0075EBA7 /* ECSlidingViewController.h */,\n\t\t\t\t22B15CF817301BAF0075EBA7 /* ECSlidingViewController.m */,\n\t\t\t\t22B15CF917301BAF0075EBA7 /* UIImage+ImageWithUIView.h */,\n\t\t\t\t22B15CFA17301BAF0075EBA7 /* UIImage+ImageWithUIView.m */,\n\t\t\t);\n\t\t\tpath = ECSlidingViewController;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t22B4280416D7E21100498507 /* SBJson */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t222C80BA1E4A0BB600A243E7 /* SBJson5.h */,\n\t\t\t\t222C80BB1E4A0BB600A243E7 /* SBJson5Parser.h */,\n\t\t\t\t222C80BC1E4A0BB600A243E7 /* SBJson5Parser.m */,\n\t\t\t\t222C80BD1E4A0BB600A243E7 /* SBJson5StreamParser.h */,\n\t\t\t\t222C80BE1E4A0BB600A243E7 /* SBJson5StreamParser.m */,\n\t\t\t\t222C80BF1E4A0BB600A243E7 /* SBJson5StreamParserState.h */,\n\t\t\t\t222C80C01E4A0BB600A243E7 /* SBJson5StreamParserState.m */,\n\t\t\t\t222C80C11E4A0BB600A243E7 /* SBJson5StreamTokeniser.h */,\n\t\t\t\t222C80C21E4A0BB600A243E7 /* SBJson5StreamTokeniser.m */,\n\t\t\t\t222C80C31E4A0BB600A243E7 /* SBJson5StreamWriter.h */,\n\t\t\t\t222C80C41E4A0BB600A243E7 /* SBJson5StreamWriter.m */,\n\t\t\t\t222C80C51E4A0BB600A243E7 /* SBJson5StreamWriterState.h */,\n\t\t\t\t222C80C61E4A0BB600A243E7 /* SBJson5StreamWriterState.m */,\n\t\t\t\t222C80C71E4A0BB600A243E7 /* SBJson5Writer.h */,\n\t\t\t\t222C80C81E4A0BB600A243E7 /* SBJson5Writer.m */,\n\t\t\t);\n\t\t\tpath = SBJson;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t22B4284A16D831A800498507 /* WebSocket */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22B4284F16D831A800498507 /* HandshakeHeader.h */,\n\t\t\t\t22B4285016D831A800498507 /* HandshakeHeader.m */,\n\t\t\t\t22B4285116D831A800498507 /* MutableQueue.h */,\n\t\t\t\t22B4285216D831A800498507 /* MutableQueue.m */,\n\t\t\t\t22B4285316D831A800498507 /* NSData+Base64.h */,\n\t\t\t\t22B4285416D831A800498507 /* NSData+Base64.m */,\n\t\t\t\t22B4285516D831A800498507 /* UnittWebSocketClient-Prefix.pch */,\n\t\t\t\t22B4285616D831A800498507 /* WebSocket.h */,\n\t\t\t\t22B4285716D831A800498507 /* WebSocket.m */,\n\t\t\t\t22B4286016D831A800498507 /* WebSocketConnectConfig.h */,\n\t\t\t\t22B4286116D831A800498507 /* WebSocketConnectConfig.m */,\n\t\t\t\t22B4286216D831A800498507 /* WebSocketFragment.h */,\n\t\t\t\t22B4286316D831A800498507 /* WebSocketFragment.m */,\n\t\t\t\t22B4286416D831A800498507 /* WebSocketMessage.h */,\n\t\t\t\t22B4286516D831A800498507 /* WebSocketMessage.m */,\n\t\t\t);\n\t\t\tpath = WebSocket;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t22CE2ADD1D2AA660001397C0 /* UITests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22CE2AE81D2AAA36001397C0 /* SnapshotHelper.swift */,\n\t\t\t\t1ADCE22D1D2FCD78000B379F /* UITests.swift */,\n\t\t\t\t22CE2AE01D2AA662001397C0 /* Info.plist */,\n\t\t\t\t22CE2AE71D2AA9E3001397C0 /* UITests-Bridging-Header.h */,\n\t\t\t);\n\t\t\tpath = UITests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D649201B1E0719003BFD86 /* CSURITemplate */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D649221B1E0719003BFD86 /* CSURITemplate.h */,\n\t\t\t\t22D649231B1E0719003BFD86 /* CSURITemplate.m */,\n\t\t\t);\n\t\t\tpath = CSURITemplate;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t22D9789D215BC979005C2713 /* FLEX */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D9789E215BC979005C2713 /* FLEXManager.h */,\n\t\t\t\t22D9789F215BC979005C2713 /* FLEX.h */,\n\t\t\t\t22D978A0215BC979005C2713 /* ObjectExplorers */,\n\t\t\t\t22D978B9215BC979005C2713 /* Network */,\n\t\t\t\t22D978CC215BC979005C2713 /* Toolbar */,\n\t\t\t\t22D978D1215BC979005C2713 /* Manager */,\n\t\t\t\t22D978D4215BC979005C2713 /* Editing */,\n\t\t\t\t22D978FC215BC979005C2713 /* ExplorerInterface */,\n\t\t\t\t22D97901215BC979005C2713 /* GlobalStateExplorers */,\n\t\t\t\t22D97933215BC979005C2713 /* ViewHierarchy */,\n\t\t\t\t22D9793A215BC979005C2713 /* Info.plist */,\n\t\t\t\t22D9793B215BC979005C2713 /* Utility */,\n\t\t\t);\n\t\t\tpath = FLEX;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t22D978A0215BC979005C2713 /* ObjectExplorers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D978A1215BC979005C2713 /* FLEXArrayExplorerViewController.m */,\n\t\t\t\t22D978A2215BC979005C2713 /* FLEXObjectExplorerFactory.m */,\n\t\t\t\t22D978A3215BC979005C2713 /* FLEXLayerExplorerViewController.h */,\n\t\t\t\t22D978A4215BC979005C2713 /* FLEXSetExplorerViewController.h */,\n\t\t\t\t22D978A5215BC979005C2713 /* FLEXGlobalsTableViewControllerEntry.m */,\n\t\t\t\t22D978A6215BC979005C2713 /* FLEXImageExplorerViewController.m */,\n\t\t\t\t22D978A7215BC979005C2713 /* FLEXViewExplorerViewController.h */,\n\t\t\t\t22D978A8215BC979005C2713 /* FLEXClassExplorerViewController.m */,\n\t\t\t\t22D978A9215BC979005C2713 /* FLEXDictionaryExplorerViewController.m */,\n\t\t\t\t22D978AA215BC979005C2713 /* FLEXDefaultsExplorerViewController.m */,\n\t\t\t\t22D978AB215BC979005C2713 /* FLEXObjectExplorerViewController.h */,\n\t\t\t\t22D978AC215BC979005C2713 /* FLEXViewControllerExplorerViewController.m */,\n\t\t\t\t22D978AD215BC979005C2713 /* FLEXGlobalsTableViewControllerEntry.h */,\n\t\t\t\t22D978AE215BC979005C2713 /* FLEXImageExplorerViewController.h */,\n\t\t\t\t22D978AF215BC979005C2713 /* FLEXSetExplorerViewController.m */,\n\t\t\t\t22D978B0215BC979005C2713 /* FLEXLayerExplorerViewController.m */,\n\t\t\t\t22D978B1215BC979005C2713 /* FLEXObjectExplorerFactory.h */,\n\t\t\t\t22D978B2215BC979005C2713 /* FLEXArrayExplorerViewController.h */,\n\t\t\t\t22D978B3215BC979005C2713 /* FLEXClassExplorerViewController.h */,\n\t\t\t\t22D978B4215BC979005C2713 /* FLEXViewExplorerViewController.m */,\n\t\t\t\t22D978B5215BC979005C2713 /* FLEXObjectExplorerViewController.m */,\n\t\t\t\t22D978B6215BC979005C2713 /* FLEXDictionaryExplorerViewController.h */,\n\t\t\t\t22D978B7215BC979005C2713 /* FLEXDefaultsExplorerViewController.h */,\n\t\t\t\t22D978B8215BC979005C2713 /* FLEXViewControllerExplorerViewController.h */,\n\t\t\t);\n\t\t\tpath = ObjectExplorers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D978B9215BC979005C2713 /* Network */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D978BA215BC979005C2713 /* FLEXNetworkCurlLogger.h */,\n\t\t\t\t22D978BB215BC979005C2713 /* FLEXNetworkTransaction.m */,\n\t\t\t\t22D978BC215BC979005C2713 /* FLEXNetworkHistoryTableViewController.h */,\n\t\t\t\t22D978BD215BC979005C2713 /* FLEXNetworkSettingsTableViewController.m */,\n\t\t\t\t22D978BE215BC979005C2713 /* FLEXNetworkRecorder.m */,\n\t\t\t\t22D978BF215BC979005C2713 /* FLEXNetworkTransactionDetailTableViewController.h */,\n\t\t\t\t22D978C0215BC979005C2713 /* FLEXNetworkTransactionTableViewCell.m */,\n\t\t\t\t22D978C1215BC979005C2713 /* FLEXNetworkTransaction.h */,\n\t\t\t\t22D978C2215BC979005C2713 /* FLEXNetworkCurlLogger.m */,\n\t\t\t\t22D978C3215BC979005C2713 /* FLEXNetworkTransactionDetailTableViewController.m */,\n\t\t\t\t22D978C4215BC979005C2713 /* FLEXNetworkRecorder.h */,\n\t\t\t\t22D978C5215BC979005C2713 /* FLEXNetworkSettingsTableViewController.h */,\n\t\t\t\t22D978C6215BC979005C2713 /* FLEXNetworkHistoryTableViewController.m */,\n\t\t\t\t22D978C7215BC979005C2713 /* FLEXNetworkTransactionTableViewCell.h */,\n\t\t\t\t22D978C8215BC979005C2713 /* PonyDebugger */,\n\t\t\t);\n\t\t\tpath = Network;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D978C8215BC979005C2713 /* PonyDebugger */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D978C9215BC979005C2713 /* FLEXNetworkObserver.h */,\n\t\t\t\t22D978CA215BC979005C2713 /* LICENSE */,\n\t\t\t\t22D978CB215BC979005C2713 /* FLEXNetworkObserver.m */,\n\t\t\t);\n\t\t\tpath = PonyDebugger;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D978CC215BC979005C2713 /* Toolbar */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D978CD215BC979005C2713 /* FLEXToolbarItem.m */,\n\t\t\t\t22D978CE215BC979005C2713 /* FLEXExplorerToolbar.h */,\n\t\t\t\t22D978CF215BC979005C2713 /* FLEXToolbarItem.h */,\n\t\t\t\t22D978D0215BC979005C2713 /* FLEXExplorerToolbar.m */,\n\t\t\t);\n\t\t\tpath = Toolbar;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D978D1215BC979005C2713 /* Manager */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D978D2215BC979005C2713 /* FLEXManager+Private.h */,\n\t\t\t\t22D978D3215BC979005C2713 /* FLEXManager.m */,\n\t\t\t);\n\t\t\tpath = Manager;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D978D4215BC979005C2713 /* Editing */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D978D5215BC979005C2713 /* FLEXIvarEditorViewController.h */,\n\t\t\t\t22D978D6215BC979005C2713 /* FLEXPropertyEditorViewController.m */,\n\t\t\t\t22D978D7215BC979005C2713 /* FLEXDefaultEditorViewController.m */,\n\t\t\t\t22D978D8215BC979005C2713 /* FLEXFieldEditorViewController.h */,\n\t\t\t\t22D978D9215BC979005C2713 /* FLEXFieldEditorView.h */,\n\t\t\t\t22D978DA215BC979005C2713 /* FLEXMethodCallingViewController.m */,\n\t\t\t\t22D978DB215BC979005C2713 /* FLEXIvarEditorViewController.m */,\n\t\t\t\t22D978DC215BC979005C2713 /* FLEXFieldEditorViewController.m */,\n\t\t\t\t22D978DD215BC979005C2713 /* FLEXDefaultEditorViewController.h */,\n\t\t\t\t22D978DE215BC979005C2713 /* ArgumentInputViews */,\n\t\t\t\t22D978F9215BC979005C2713 /* FLEXPropertyEditorViewController.h */,\n\t\t\t\t22D978FA215BC979005C2713 /* FLEXMethodCallingViewController.h */,\n\t\t\t\t22D978FB215BC979005C2713 /* FLEXFieldEditorView.m */,\n\t\t\t);\n\t\t\tpath = Editing;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D978DE215BC979005C2713 /* ArgumentInputViews */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D978DF215BC979005C2713 /* FLEXArgumentInputStringView.m */,\n\t\t\t\t22D978E0215BC979005C2713 /* FLEXArgumentInputColorView.m */,\n\t\t\t\t22D978E1215BC979005C2713 /* FLEXArgumentInputView.m */,\n\t\t\t\t22D978E2215BC979005C2713 /* FLEXArgumentInputFontView.h */,\n\t\t\t\t22D978E3215BC979005C2713 /* FLEXArgumentInputTextView.h */,\n\t\t\t\t22D978E4215BC979005C2713 /* FLEXArgumentInputJSONObjectView.m */,\n\t\t\t\t22D978E5215BC979005C2713 /* FLEXArgumentInputSwitchView.m */,\n\t\t\t\t22D978E6215BC979005C2713 /* FLEXArgumentInputStructView.m */,\n\t\t\t\t22D978E7215BC979005C2713 /* FLEXArgumentInputDateView.m */,\n\t\t\t\t22D978E8215BC979005C2713 /* FLEXArgumentInputNumberView.h */,\n\t\t\t\t22D978E9215BC979005C2713 /* FLEXArgumentInputFontsPickerView.h */,\n\t\t\t\t22D978EA215BC979005C2713 /* FLEXArgumentInputNotSupportedView.h */,\n\t\t\t\t22D978EB215BC979005C2713 /* FLEXArgumentInputViewFactory.h */,\n\t\t\t\t22D978EC215BC979005C2713 /* FLEXArgumentInputFontView.m */,\n\t\t\t\t22D978ED215BC979005C2713 /* FLEXArgumentInputView.h */,\n\t\t\t\t22D978EE215BC979005C2713 /* FLEXArgumentInputColorView.h */,\n\t\t\t\t22D978EF215BC979005C2713 /* FLEXArgumentInputStringView.h */,\n\t\t\t\t22D978F0215BC979005C2713 /* FLEXArgumentInputSwitchView.h */,\n\t\t\t\t22D978F1215BC979005C2713 /* FLEXArgumentInputJSONObjectView.h */,\n\t\t\t\t22D978F2215BC979005C2713 /* FLEXArgumentInputTextView.m */,\n\t\t\t\t22D978F3215BC979005C2713 /* FLEXArgumentInputFontsPickerView.m */,\n\t\t\t\t22D978F4215BC979005C2713 /* FLEXArgumentInputNumberView.m */,\n\t\t\t\t22D978F5215BC979005C2713 /* FLEXArgumentInputDateView.h */,\n\t\t\t\t22D978F6215BC979005C2713 /* FLEXArgumentInputStructView.h */,\n\t\t\t\t22D978F7215BC979005C2713 /* FLEXArgumentInputViewFactory.m */,\n\t\t\t\t22D978F8215BC979005C2713 /* FLEXArgumentInputNotSupportedView.m */,\n\t\t\t);\n\t\t\tpath = ArgumentInputViews;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D978FC215BC979005C2713 /* ExplorerInterface */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D978FD215BC979005C2713 /* FLEXExplorerViewController.m */,\n\t\t\t\t22D978FE215BC979005C2713 /* FLEXWindow.m */,\n\t\t\t\t22D978FF215BC979005C2713 /* FLEXExplorerViewController.h */,\n\t\t\t\t22D97900215BC979005C2713 /* FLEXWindow.h */,\n\t\t\t);\n\t\t\tpath = ExplorerInterface;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D97901215BC979005C2713 /* GlobalStateExplorers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D97902215BC979005C2713 /* FLEXFileBrowserFileOperationController.h */,\n\t\t\t\t22D97903215BC979005C2713 /* FLEXFileBrowserTableViewController.h */,\n\t\t\t\t22D97904215BC979005C2713 /* FLEXFileBrowserSearchOperation.m */,\n\t\t\t\t22D97905215BC979005C2713 /* FLEXObjectRef.m */,\n\t\t\t\t22D97906215BC979005C2713 /* FLEXWebViewController.m */,\n\t\t\t\t22D97907215BC979005C2713 /* FLEXInstancesTableViewController.m */,\n\t\t\t\t22D97908215BC979005C2713 /* FLEXClassesTableViewController.h */,\n\t\t\t\t22D97909215BC979005C2713 /* FLEXLiveObjectsTableViewController.h */,\n\t\t\t\t22D9790A215BC979005C2713 /* FLEXGlobalsTableViewController.h */,\n\t\t\t\t22D9790B215BC979005C2713 /* FLEXLibrariesTableViewController.h */,\n\t\t\t\t22D9790C215BC979005C2713 /* FLEXCookiesTableViewController.h */,\n\t\t\t\t22D9790D215BC979005C2713 /* FLEXFileBrowserSearchOperation.h */,\n\t\t\t\t22D9790E215BC979005C2713 /* FLEXFileBrowserTableViewController.m */,\n\t\t\t\t22D9790F215BC979005C2713 /* FLEXFileBrowserFileOperationController.m */,\n\t\t\t\t22D97910215BC979005C2713 /* FLEXObjectRef.h */,\n\t\t\t\t22D97911215BC979005C2713 /* FLEXInstancesTableViewController.h */,\n\t\t\t\t22D97912215BC979005C2713 /* SystemLog */,\n\t\t\t\t22D97919215BC979005C2713 /* DatabaseBrowser */,\n\t\t\t\t22D9792D215BC979005C2713 /* FLEXWebViewController.h */,\n\t\t\t\t22D9792E215BC979005C2713 /* FLEXCookiesTableViewController.m */,\n\t\t\t\t22D9792F215BC979005C2713 /* FLEXLibrariesTableViewController.m */,\n\t\t\t\t22D97930215BC979005C2713 /* FLEXGlobalsTableViewController.m */,\n\t\t\t\t22D97931215BC979005C2713 /* FLEXLiveObjectsTableViewController.m */,\n\t\t\t\t22D97932215BC979005C2713 /* FLEXClassesTableViewController.m */,\n\t\t\t);\n\t\t\tpath = GlobalStateExplorers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D97912215BC979005C2713 /* SystemLog */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D97913215BC979005C2713 /* FLEXSystemLogTableViewController.m */,\n\t\t\t\t22D97914215BC979005C2713 /* FLEXSystemLogTableViewCell.h */,\n\t\t\t\t22D97915215BC979005C2713 /* FLEXSystemLogMessage.m */,\n\t\t\t\t22D97916215BC979005C2713 /* FLEXSystemLogTableViewController.h */,\n\t\t\t\t22D97917215BC979005C2713 /* FLEXSystemLogTableViewCell.m */,\n\t\t\t\t22D97918215BC979005C2713 /* FLEXSystemLogMessage.h */,\n\t\t\t);\n\t\t\tpath = SystemLog;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D97919215BC979005C2713 /* DatabaseBrowser */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D9791A215BC979005C2713 /* FLEXRealmDefines.h */,\n\t\t\t\t22D9791B215BC979005C2713 /* FLEXTableLeftCell.m */,\n\t\t\t\t22D9791C215BC979005C2713 /* FLEXRealmDatabaseManager.h */,\n\t\t\t\t22D9791D215BC979005C2713 /* LICENSE */,\n\t\t\t\t22D9791E215BC979005C2713 /* FLEXTableContentCell.h */,\n\t\t\t\t22D9791F215BC979005C2713 /* FLEXTableContentViewController.m */,\n\t\t\t\t22D97920215BC979005C2713 /* FLEXTableListViewController.m */,\n\t\t\t\t22D97921215BC979005C2713 /* FLEXTableColumnHeader.m */,\n\t\t\t\t22D97922215BC979005C2713 /* FLEXMultiColumnTableView.m */,\n\t\t\t\t22D97923215BC979005C2713 /* FLEXSQLiteDatabaseManager.h */,\n\t\t\t\t22D97924215BC979005C2713 /* FLEXTableLeftCell.h */,\n\t\t\t\t22D97925215BC979005C2713 /* FLEXTableContentCell.m */,\n\t\t\t\t22D97926215BC979005C2713 /* FLEXDatabaseManager.h */,\n\t\t\t\t22D97927215BC979005C2713 /* FLEXRealmDatabaseManager.m */,\n\t\t\t\t22D97928215BC979005C2713 /* FLEXTableContentViewController.h */,\n\t\t\t\t22D97929215BC979005C2713 /* FLEXSQLiteDatabaseManager.m */,\n\t\t\t\t22D9792A215BC979005C2713 /* FLEXMultiColumnTableView.h */,\n\t\t\t\t22D9792B215BC979005C2713 /* FLEXTableColumnHeader.h */,\n\t\t\t\t22D9792C215BC979005C2713 /* FLEXTableListViewController.h */,\n\t\t\t);\n\t\t\tpath = DatabaseBrowser;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D97933215BC979005C2713 /* ViewHierarchy */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D97934215BC979005C2713 /* FLEXHierarchyTableViewCell.m */,\n\t\t\t\t22D97935215BC979005C2713 /* FLEXImagePreviewViewController.m */,\n\t\t\t\t22D97936215BC979005C2713 /* FLEXHierarchyTableViewController.h */,\n\t\t\t\t22D97937215BC979005C2713 /* FLEXHierarchyTableViewCell.h */,\n\t\t\t\t22D97938215BC979005C2713 /* FLEXHierarchyTableViewController.m */,\n\t\t\t\t22D97939215BC979005C2713 /* FLEXImagePreviewViewController.h */,\n\t\t\t);\n\t\t\tpath = ViewHierarchy;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D9793B215BC979005C2713 /* Utility */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22D9793C215BC979005C2713 /* FLEXUtility.m */,\n\t\t\t\t22D9793D215BC979005C2713 /* FLEXHeapEnumerator.m */,\n\t\t\t\t22D9793E215BC979005C2713 /* FLEXResources.h */,\n\t\t\t\t22D9793F215BC979005C2713 /* FLEXKeyboardHelpViewController.h */,\n\t\t\t\t22D97940215BC979005C2713 /* FLEXRuntimeUtility.m */,\n\t\t\t\t22D97941215BC979005C2713 /* FLEXMultilineTableViewCell.h */,\n\t\t\t\t22D97942215BC979005C2713 /* FLEXKeyboardShortcutManager.m */,\n\t\t\t\t22D97943215BC979005C2713 /* FLEXHeapEnumerator.h */,\n\t\t\t\t22D97944215BC979005C2713 /* FLEXUtility.h */,\n\t\t\t\t22D97945215BC979005C2713 /* FLEXKeyboardHelpViewController.m */,\n\t\t\t\t22D97946215BC979005C2713 /* FLEXResources.m */,\n\t\t\t\t22D97947215BC979005C2713 /* FLEXRuntimeUtility.h */,\n\t\t\t\t22D97948215BC979005C2713 /* FLEXKeyboardShortcutManager.h */,\n\t\t\t\t22D97949215BC979005C2713 /* FLEXMultilineTableViewCell.m */,\n\t\t\t);\n\t\t\tpath = Utility;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22EE12801C9B1DE000E7AE8D /* OpenInFirefoxClient */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t22EE12811C9B20DF00E7AE8D /* Firefox.png */,\n\t\t\t\t22EE12821C9B20DF00E7AE8D /* Firefox@2x.png */,\n\t\t\t\t22EE12831C9B20DF00E7AE8D /* Firefox@3x.png */,\n\t\t\t\t22E9C0A71C9AF27800013456 /* OpenInFirefoxControllerObjC.h */,\n\t\t\t\t22E9C0A81C9AF27800013456 /* OpenInFirefoxControllerObjC.m */,\n\t\t\t);\n\t\t\tname = OpenInFirefoxClient;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7CF0BE4739CE6912111DBBD1 /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB5BF7CE5566B5B9E80ACC95 /* Pods-IRCCloud.debug.xcconfig */,\n\t\t\t\t8B18E14B6DD31D7CDE986D5B /* Pods-IRCCloud.release.xcconfig */,\n\t\t\t\t26CA7871B88FD75900DEEA57 /* Pods-IRCCloud.appstore.xcconfig */,\n\t\t\t\t096184601771D02417AC2EA7 /* Pods-IRCCloud Enterprise.debug.xcconfig */,\n\t\t\t\tF7E442A5DB675C1935189274 /* Pods-IRCCloud Enterprise.release.xcconfig */,\n\t\t\t\t1BBDF60D720CF290BFDB54FA /* Pods-IRCCloud Enterprise.appstore.xcconfig */,\n\t\t\t\t747834BB92EAB6AFAEC360EA /* Pods-IRCCloud FLEX.debug.xcconfig */,\n\t\t\t\t1C7FC0255C6F93D841E44603 /* Pods-IRCCloud FLEX.release.xcconfig */,\n\t\t\t\t501E461E42461CCDCA1FEA73 /* Pods-IRCCloud FLEX.appstore.xcconfig */,\n\t\t\t\t734B6CF2BBC243289BBDFE3E /* Pods-IRCCloudUnitTests.debug.xcconfig */,\n\t\t\t\t7E8BEE7BE95EE6C639899F19 /* Pods-IRCCloudUnitTests.release.xcconfig */,\n\t\t\t\tF4F652185AA9F602056FD25B /* Pods-IRCCloudUnitTests.appstore.xcconfig */,\n\t\t\t\t1235543CBD3AE11C697E1C64 /* Pods-NotificationService.debug.xcconfig */,\n\t\t\t\t7CFB3E8BA47C29791F69E532 /* Pods-NotificationService.release.xcconfig */,\n\t\t\t\t4F27E14C033710EC4B42D049 /* Pods-NotificationService.appstore.xcconfig */,\n\t\t\t\tBFED8175E3E7FAD3E4906856 /* Pods-NotificationService Enterprise.debug.xcconfig */,\n\t\t\t\tA2393D6BBB8E07F3DE0D5379 /* Pods-NotificationService Enterprise.release.xcconfig */,\n\t\t\t\t2D34900179BBF7DB46AC6ABF /* Pods-NotificationService Enterprise.appstore.xcconfig */,\n\t\t\t\t72EF5BEF0B6805E196076677 /* Pods-ShareExtension.debug.xcconfig */,\n\t\t\t\tA760D4C60BC249A2F3CC3524 /* Pods-ShareExtension.release.xcconfig */,\n\t\t\t\t750FA24A88594B10FEDE6646 /* Pods-ShareExtension.appstore.xcconfig */,\n\t\t\t\t312A65F8D9286A2A8D9E9C43 /* Pods-ShareExtension Enterprise.debug.xcconfig */,\n\t\t\t\t42EA3F8746F7A000AFEB8A4F /* Pods-ShareExtension Enterprise.release.xcconfig */,\n\t\t\t\tEB28B506CCB1E9844E1A26E4 /* Pods-ShareExtension Enterprise.appstore.xcconfig */,\n\t\t\t);\n\t\t\tpath = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t221034E6197EFBAF00AB414F /* ShareExtension */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 221034F5197EFBAF00AB414F /* Build configuration list for PBXNativeTarget \"ShareExtension\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t37515BB7F069B847C3BD521A /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t221034E3197EFBAF00AB414F /* Sources */,\n\t\t\t\t221034E4197EFBAF00AB414F /* Frameworks */,\n\t\t\t\t221034E5197EFBAF00AB414F /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t22E7141019D9D18200E11D96 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = ShareExtension;\n\t\t\tproductName = ShareExtension;\n\t\t\tproductReference = 221034E7197EFBAF00AB414F /* ShareExtension.appex */;\n\t\t\tproductType = \"com.apple.product-type.app-extension\";\n\t\t};\n\t\t221D4B8C1E23EAD600D403E6 /* NotificationService */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 221D4B961E23EAD700D403E6 /* Build configuration list for PBXNativeTarget \"NotificationService\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tB7FC4D6CFDE6C0FB433A0A72 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t221D4B891E23EAD600D403E6 /* Sources */,\n\t\t\t\t221D4B8A1E23EAD600D403E6 /* Frameworks */,\n\t\t\t\t221D4B8B1E23EAD600D403E6 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t22322CCA20E549AA00AC54CD /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = NotificationService;\n\t\t\tproductName = NotificationService;\n\t\t\tproductReference = 221D4B8D1E23EAD600D403E6 /* NotificationService.appex */;\n\t\t\tproductType = \"com.apple.product-type.app-extension\";\n\t\t};\n\t\t221D4B9A1E23EB4900D403E6 /* NotificationService Enterprise */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 221D4B9F1E23EB4900D403E6 /* Build configuration list for PBXNativeTarget \"NotificationService Enterprise\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tD45D12B0AC30951AB647C066 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t221D4B9B1E23EB4900D403E6 /* Sources */,\n\t\t\t\t221D4B9D1E23EB4900D403E6 /* Frameworks */,\n\t\t\t\t221D4B9E1E23EB4900D403E6 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t22322CCC20E549B100AC54CD /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"NotificationService Enterprise\";\n\t\t\tproductName = NotificationService;\n\t\t\tproductReference = 221D4BA31E23EB4900D403E6 /* NotificationService Enterprise.appex */;\n\t\t\tproductType = \"com.apple.product-type.app-extension\";\n\t\t};\n\t\t224589C31DCA19BB00D3110A /* IRCCloudUnitTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 224589CE1DCA19BB00D3110A /* Build configuration list for PBXNativeTarget \"IRCCloudUnitTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t26D820C8C944726C00471F03 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t224589C01DCA19BB00D3110A /* Sources */,\n\t\t\t\t224589C11DCA19BB00D3110A /* Frameworks */,\n\t\t\t\t224589C21DCA19BB00D3110A /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t224589CA1DCA19BB00D3110A /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = IRCCloudUnitTests;\n\t\t\tproductName = IRCCloudUnitTests;\n\t\t\tproductReference = 224589C41DCA19BB00D3110A /* IRCCloudUnitTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t225D973618AA995900065087 /* IRCCloud Enterprise */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 225D979C18AA995900065087 /* Build configuration list for PBXNativeTarget \"IRCCloud Enterprise\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tB40D65DB0EDA3E08FC2602A0 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t225D973718AA995900065087 /* Sources */,\n\t\t\t\t225D977818AA995900065087 /* Frameworks */,\n\t\t\t\t225D978718AA995900065087 /* Resources */,\n\t\t\t\t22DB253C1982DFFB0008728E /* Embed Foundation Extensions */,\n\t\t\t\tD14C8BA1619831C6D365647F /* [CP] Embed Pods Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t221D4BA91E23F0FC00D403E6 /* PBXTargetDependency */,\n\t\t\t\t22DE05B918D8CA4F00590FC3 /* PBXTargetDependency */,\n\t\t\t\t22DB253B1982DFFB0008728E /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"IRCCloud Enterprise\";\n\t\t\tproductName = IRCCloud;\n\t\t\tproductReference = 225D979F18AA995900065087 /* IRCEnterprise.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t228A056B16D3DABA0029769C /* IRCCloud */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 228A05A716D3DABB0029769C /* Build configuration list for PBXNativeTarget \"IRCCloud\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tF0B9418E621953688187C7E6 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t228A056816D3DABA0029769C /* Sources */,\n\t\t\t\t228A056916D3DABA0029769C /* Frameworks */,\n\t\t\t\t228A056A16D3DABA0029769C /* Resources */,\n\t\t\t\t22772F91197EC42E001A9890 /* Embed Foundation Extensions */,\n\t\t\t\t226E642423F1C91F001CE069 /* ShellScript */,\n\t\t\t\t226E642123F1C696001CE069 /* CopyFiles */,\n\t\t\t\tD5FE5004D02B6D866851DCEC /* [CP] Embed Pods Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t22DE05B718D8CA4800590FC3 /* PBXTargetDependency */,\n\t\t\t\t221034F1197EFBAF00AB414F /* PBXTargetDependency */,\n\t\t\t\t221034F4197EFBAF00AB414F /* PBXTargetDependency */,\n\t\t\t\t221D4B941E23EAD700D403E6 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = IRCCloud;\n\t\t\tproductName = IRCCloud;\n\t\t\tproductReference = 228A056C16D3DABA0029769C /* IRCCloud.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t22CE2ADB1D2AA659001397C0 /* UITests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 22CE2AE61D2AA663001397C0 /* Build configuration list for PBXNativeTarget \"UITests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t22CE2AD81D2AA659001397C0 /* Sources */,\n\t\t\t\t22CE2AD91D2AA659001397C0 /* Frameworks */,\n\t\t\t\t22CE2ADA1D2AA659001397C0 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t22CE2AE21D2AA662001397C0 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = UITests;\n\t\t\tproductName = UITests;\n\t\t\tproductReference = 22CE2ADC1D2AA65A001397C0 /* UITests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.ui-testing\";\n\t\t};\n\t\t22D97784215BC910005C2713 /* IRCCloud FLEX */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 22D97897215BC910005C2713 /* Build configuration list for PBXNativeTarget \"IRCCloud FLEX\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t08BBD7D08822C3E4F8767F4D /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t22D9778D215BC910005C2713 /* Sources */,\n\t\t\t\t22D9784E215BC910005C2713 /* Frameworks */,\n\t\t\t\t22D9786D215BC910005C2713 /* Resources */,\n\t\t\t\t22D97893215BC910005C2713 /* ShellScript */,\n\t\t\t\t22D97894215BC910005C2713 /* Embed Foundation Extensions */,\n\t\t\t\tF4F5092F64004755EE174E93 /* [CP] Embed Pods Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t22D97785215BC910005C2713 /* PBXTargetDependency */,\n\t\t\t\t22D97787215BC910005C2713 /* PBXTargetDependency */,\n\t\t\t\t22D97789215BC910005C2713 /* PBXTargetDependency */,\n\t\t\t\t22D9778B215BC910005C2713 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"IRCCloud FLEX\";\n\t\t\tproductName = IRCCloud;\n\t\t\tproductReference = 22D9789B215BC910005C2713 /* IRCCloud FLEX.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t22DB24FA1982DF2B0008728E /* ShareExtension Enterprise */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 22DB25331982DF2B0008728E /* Build configuration list for PBXNativeTarget \"ShareExtension Enterprise\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t25237AFEA31945A9773DC05B /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t22DB24FB1982DF2B0008728E /* Sources */,\n\t\t\t\t22DB251F1982DF2B0008728E /* Frameworks */,\n\t\t\t\t22DB252F1982DF2B0008728E /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t22E7141219D9D18700E11D96 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"ShareExtension Enterprise\";\n\t\t\tproductName = ShareExtension;\n\t\t\tproductReference = 22DB25371982DF2B0008728E /* ShareExtension Enterprise.appex */;\n\t\t\tproductType = \"com.apple.product-type.app-extension\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t228A056416D3DABA0029769C /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0730;\n\t\t\t\tLastTestingUpgradeCheck = 0510;\n\t\t\t\tLastUpgradeCheck = 1400;\n\t\t\t\tORGANIZATIONNAME = \"IRCCloud, Ltd.\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t221034E6197EFBAF00AB414F = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.0;\n\t\t\t\t\t\tDevelopmentTeam = GED45EQAGA;\n\t\t\t\t\t\tSystemCapabilities = {\n\t\t\t\t\t\t\tcom.apple.ApplicationGroups.iOS = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.BackgroundModes = {\n\t\t\t\t\t\t\t\tenabled = 0;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.Keychain = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t\t221D4B8C1E23EAD600D403E6 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 8.2.1;\n\t\t\t\t\t\tDevelopmentTeam = GED45EQAGA;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t\tSystemCapabilities = {\n\t\t\t\t\t\t\tcom.apple.ApplicationGroups.iOS = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.Keychain = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t\t221D4B9A1E23EB4900D403E6 = {\n\t\t\t\t\t\tDevelopmentTeam = GED45EQAGA;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t\tSystemCapabilities = {\n\t\t\t\t\t\t\tcom.apple.ApplicationGroups.iOS = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.Keychain = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t\t224589C31DCA19BB00D3110A = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 8.1;\n\t\t\t\t\t\tDevelopmentTeam = GED45EQAGA;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t\tTestTargetID = 228A056B16D3DABA0029769C;\n\t\t\t\t\t};\n\t\t\t\t\t225D973618AA995900065087 = {\n\t\t\t\t\t\tDevelopmentTeam = GED45EQAGA;\n\t\t\t\t\t\tSystemCapabilities = {\n\t\t\t\t\t\t\tcom.apple.ApplicationGroups.iOS = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.BackgroundModes = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.InAppPurchase = {\n\t\t\t\t\t\t\t\tenabled = 0;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.Keychain = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.Push = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.iCloud = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t\t228A056B16D3DABA0029769C = {\n\t\t\t\t\t\tDevelopmentTeam = GED45EQAGA;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t\tSystemCapabilities = {\n\t\t\t\t\t\t\tcom.apple.ApplicationGroups.iOS = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.BackgroundModes = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.Keychain = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.Push = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.SafariKeychain = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.iCloud = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t\t22CE2ADB1D2AA659001397C0 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3.1;\n\t\t\t\t\t\tLastSwiftMigration = 1010;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t\tTestTargetID = 228A056B16D3DABA0029769C;\n\t\t\t\t\t};\n\t\t\t\t\t22D97784215BC910005C2713 = {\n\t\t\t\t\t\tDevelopmentTeam = GED45EQAGA;\n\t\t\t\t\t};\n\t\t\t\t\t22DB24FA1982DF2B0008728E = {\n\t\t\t\t\t\tDevelopmentTeam = GED45EQAGA;\n\t\t\t\t\t\tSystemCapabilities = {\n\t\t\t\t\t\t\tcom.apple.ApplicationGroups.iOS = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcom.apple.Keychain = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t\t22DE05B118D8CA0700590FC3 = {\n\t\t\t\t\t\tDevelopmentTeam = GED45EQAGA;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 228A056716D3DABA0029769C /* Build configuration list for PBXProject \"IRCCloud\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tcs,\n\t\t\t\tde,\n\t\t\t\tes,\n\t\t\t\teu,\n\t\t\t\tfi,\n\t\t\t\tfr,\n\t\t\t\tit,\n\t\t\t\tja,\n\t\t\t\tko,\n\t\t\t\tnl,\n\t\t\t\tno,\n\t\t\t\tpl,\n\t\t\t\tpt,\n\t\t\t\tru,\n\t\t\t\tsk,\n\t\t\t\tsv,\n\t\t\t\tvi,\n\t\t\t\tzh_CN,\n\t\t\t);\n\t\t\tmainGroup = 228A056316D3DABA0029769C;\n\t\t\tproductRefGroup = 228A056D16D3DABA0029769C /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t228A056B16D3DABA0029769C /* IRCCloud */,\n\t\t\t\t225D973618AA995900065087 /* IRCCloud Enterprise */,\n\t\t\t\t22DE05B118D8CA0700590FC3 /* GitRevision */,\n\t\t\t\t221034E6197EFBAF00AB414F /* ShareExtension */,\n\t\t\t\t22DB24FA1982DF2B0008728E /* ShareExtension Enterprise */,\n\t\t\t\t22CE2ADB1D2AA659001397C0 /* UITests */,\n\t\t\t\t224589C31DCA19BB00D3110A /* IRCCloudUnitTests */,\n\t\t\t\t221D4B8C1E23EAD600D403E6 /* NotificationService */,\n\t\t\t\t221D4B9A1E23EB4900D403E6 /* NotificationService Enterprise */,\n\t\t\t\t22D97784215BC910005C2713 /* IRCCloud FLEX */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t221034E5197EFBAF00AB414F /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t22103529197EFCF100AB414F /* Icons.xcassets in Resources */,\n\t\t\t\t22103527197EFCEB00AB414F /* Logo.xcassets in Resources */,\n\t\t\t\t2209B82D28C27A3B00D59B75 /* GoogleService-Info.plist in Resources */,\n\t\t\t\t2236BD651BAA5E0900015753 /* FontAwesome.otf in Resources */,\n\t\t\t\t22103528197EFCEE00AB414F /* Images.xcassets in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t221D4B8B1E23EAD600D403E6 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t221D4B9E1E23EB4900D403E6 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t224589C21DCA19BB00D3110A /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t225D978718AA995900065087 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t22EEA94E18D0AC08007D5022 /* EnterpriseImages.xcassets in Resources */,\n\t\t\t\t22F4A9CB1CB5424F00359049 /* Launch.storyboard in Resources */,\n\t\t\t\t1A7382AD18D0A9AC0039FDB3 /* EnterpriseLogo.xcassets in Resources */,\n\t\t\t\t225D978D18AA995900065087 /* Localizable.strings in Resources */,\n\t\t\t\t225D979018AA995900065087 /* ARChromeActivity.png in Resources */,\n\t\t\t\t225D979118AA995900065087 /* ARChromeActivity@2x.png in Resources */,\n\t\t\t\t225173E81DB13A5500D63405 /* SourceSansPro-Semibold.otf in Resources */,\n\t\t\t\t225D979218AA995900065087 /* ARChromeActivity@2x~ipad.png in Resources */,\n\t\t\t\t22A363B319D0884D00500478 /* 1Password.xcassets in Resources */,\n\t\t\t\t22EB4CF51CCEE2ED004F9CFC /* ImageViewController.xib in Resources */,\n\t\t\t\t225D979318AA995900065087 /* ARChromeActivity~ipad.png in Resources */,\n\t\t\t\t22D268C31BF4F40800B682AE /* MainStoryboard.storyboard in Resources */,\n\t\t\t\t22EE12851C9B20DF00E7AE8D /* Firefox.png in Resources */,\n\t\t\t\t225EC2BC2061678B00AA0C79 /* EventsTableCell_ReplyCount.xib in Resources */,\n\t\t\t\t221EB2F11F8F965E00A71428 /* EventsTableCell.xib in Resources */,\n\t\t\t\t221EB2F51F962C2D00A71428 /* EventsTableCell_File.xib in Resources */,\n\t\t\t\t225D979418AA995900065087 /* Safari.png in Resources */,\n\t\t\t\t2236BD6B1BAC61A900015753 /* SourceSansPro-LightIt.otf in Resources */,\n\t\t\t\t22EE12891C9B20DF00E7AE8D /* Firefox@3x.png in Resources */,\n\t\t\t\t221067251F28C3F60075A18F /* Hack-BoldItalic.ttf in Resources */,\n\t\t\t\t225D979518AA995900065087 /* Safari@2x.png in Resources */,\n\t\t\t\t2236BD6D1BAC61A900015753 /* SourceSansPro-Regular.otf in Resources */,\n\t\t\t\t2236BD641BAA5E0900015753 /* FontAwesome.otf in Resources */,\n\t\t\t\t221EB2F71F962C2D00A71428 /* EventsTableCell_Thumbnail.xib in Resources */,\n\t\t\t\t225D979618AA995900065087 /* Safari@2x~ipad.png in Resources */,\n\t\t\t\t221067261F28C3F90075A18F /* Hack-Italic.ttf in Resources */,\n\t\t\t\t22EE12871C9B20DF00E7AE8D /* Firefox@2x.png in Resources */,\n\t\t\t\t225D979718AA995900065087 /* Safari~ipad.png in Resources */,\n\t\t\t\t221067241F28C3F30075A18F /* Hack-Bold.ttf in Resources */,\n\t\t\t\t22EEA95518D0B198007D5022 /* Icons.xcassets in Resources */,\n\t\t\t\t225D979918AA995900065087 /* licenses.txt in Resources */,\n\t\t\t\t225D979A18AA995900065087 /* a.caf in Resources */,\n\t\t\t\t221067271F28C3FB0075A18F /* Hack-Regular.ttf in Resources */,\n\t\t\t\t225D979B18AA995900065087 /* TUSafariActivity.strings in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t228A056A16D3DABA0029769C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t22EE12841C9B20DF00E7AE8D /* Firefox.png in Resources */,\n\t\t\t\t22EE12861C9B20DF00E7AE8D /* Firefox@2x.png in Resources */,\n\t\t\t\t22EE12881C9B20DF00E7AE8D /* Firefox@3x.png in Resources */,\n\t\t\t\t2236BD6C1BAC61A900015753 /* SourceSansPro-Regular.otf in Resources */,\n\t\t\t\t225173E71DB13A5500D63405 /* SourceSansPro-Semibold.otf in Resources */,\n\t\t\t\t22D4F9121743F3790095EE8F /* Localizable.strings in Resources */,\n\t\t\t\t22D268C21BF4F40800B682AE /* MainStoryboard.storyboard in Resources */,\n\t\t\t\t225017641783434900066E71 /* ARChromeActivity.png in Resources */,\n\t\t\t\t225017651783434900066E71 /* ARChromeActivity@2x.png in Resources */,\n\t\t\t\t2236BD6A1BAC61A900015753 /* SourceSansPro-LightIt.otf in Resources */,\n\t\t\t\t22EEA95418D0B198007D5022 /* Icons.xcassets in Resources */,\n\t\t\t\t2236BD631BAA5E0900015753 /* FontAwesome.otf in Resources */,\n\t\t\t\t225EC2BB2061678B00AA0C79 /* EventsTableCell_ReplyCount.xib in Resources */,\n\t\t\t\t221EB2F01F8F965E00A71428 /* EventsTableCell.xib in Resources */,\n\t\t\t\t221EB2F41F962C2D00A71428 /* EventsTableCell_File.xib in Resources */,\n\t\t\t\t22A363B219D0884D00500478 /* 1Password.xcassets in Resources */,\n\t\t\t\t1A7382AC18D0A9A30039FDB3 /* Logo.xcassets in Resources */,\n\t\t\t\t225017661783434900066E71 /* ARChromeActivity@2x~ipad.png in Resources */,\n\t\t\t\t221067211F28C3BB0075A18F /* Hack-BoldItalic.ttf in Resources */,\n\t\t\t\t225017671783434900066E71 /* ARChromeActivity~ipad.png in Resources */,\n\t\t\t\t225017691783434900066E71 /* Safari.png in Resources */,\n\t\t\t\t22EEA95118D0B117007D5022 /* Images.xcassets in Resources */,\n\t\t\t\t221EB2F61F962C2D00A71428 /* EventsTableCell_Thumbnail.xib in Resources */,\n\t\t\t\t22EB4CF41CCEE298004F9CFC /* ImageViewController.xib in Resources */,\n\t\t\t\t221067221F28C3BB0075A18F /* Hack-Italic.ttf in Resources */,\n\t\t\t\t2250176A1783434900066E71 /* Safari@2x.png in Resources */,\n\t\t\t\t2250176B1783434900066E71 /* Safari@2x~ipad.png in Resources */,\n\t\t\t\t221067201F28C3BB0075A18F /* Hack-Bold.ttf in Resources */,\n\t\t\t\t22F4A9CA1CB5424F00359049 /* Launch.storyboard in Resources */,\n\t\t\t\t2250176C1783434900066E71 /* Safari~ipad.png in Resources */,\n\t\t\t\t224FCF331787286000FC3879 /* licenses.txt in Resources */,\n\t\t\t\t221067231F28C3BB0075A18F /* Hack-Regular.ttf in Resources */,\n\t\t\t\t22F5C4BD1791F205005E09A9 /* a.caf in Resources */,\n\t\t\t\t2251693317B5A8040093ADC5 /* TUSafariActivity.strings in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22CE2ADA1D2AA659001397C0 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22D9786D215BC910005C2713 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t22D9786F215BC910005C2713 /* Firefox.png in Resources */,\n\t\t\t\t22D97870215BC910005C2713 /* Firefox@2x.png in Resources */,\n\t\t\t\t22D97871215BC910005C2713 /* Firefox@3x.png in Resources */,\n\t\t\t\t22D97872215BC910005C2713 /* SourceSansPro-Regular.otf in Resources */,\n\t\t\t\t22D97873215BC910005C2713 /* SourceSansPro-Semibold.otf in Resources */,\n\t\t\t\t22D9795D215BC979005C2713 /* LICENSE in Resources */,\n\t\t\t\t22D97875215BC910005C2713 /* Localizable.strings in Resources */,\n\t\t\t\t22D97981215BC979005C2713 /* LICENSE in Resources */,\n\t\t\t\t22D97877215BC910005C2713 /* MainStoryboard.storyboard in Resources */,\n\t\t\t\t22D97878215BC910005C2713 /* ARChromeActivity.png in Resources */,\n\t\t\t\t22D97879215BC910005C2713 /* ARChromeActivity@2x.png in Resources */,\n\t\t\t\t22D9787A215BC910005C2713 /* SourceSansPro-LightIt.otf in Resources */,\n\t\t\t\t22D9787B215BC910005C2713 /* Icons.xcassets in Resources */,\n\t\t\t\t22D9787C215BC910005C2713 /* FontAwesome.otf in Resources */,\n\t\t\t\t22D9787D215BC910005C2713 /* EventsTableCell_ReplyCount.xib in Resources */,\n\t\t\t\t22D9787E215BC910005C2713 /* EventsTableCell.xib in Resources */,\n\t\t\t\t22D9787F215BC910005C2713 /* EventsTableCell_File.xib in Resources */,\n\t\t\t\t22D97880215BC910005C2713 /* 1Password.xcassets in Resources */,\n\t\t\t\t22D97881215BC910005C2713 /* Logo.xcassets in Resources */,\n\t\t\t\t22D97882215BC910005C2713 /* ARChromeActivity@2x~ipad.png in Resources */,\n\t\t\t\t22D97883215BC910005C2713 /* Hack-BoldItalic.ttf in Resources */,\n\t\t\t\t22D97884215BC910005C2713 /* ARChromeActivity~ipad.png in Resources */,\n\t\t\t\t22D97885215BC910005C2713 /* Safari.png in Resources */,\n\t\t\t\t22D97886215BC910005C2713 /* Images.xcassets in Resources */,\n\t\t\t\t22D97887215BC910005C2713 /* EventsTableCell_Thumbnail.xib in Resources */,\n\t\t\t\t22D97888215BC910005C2713 /* ImageViewController.xib in Resources */,\n\t\t\t\t22D97889215BC910005C2713 /* Hack-Italic.ttf in Resources */,\n\t\t\t\t22D97991215BC979005C2713 /* Info.plist in Resources */,\n\t\t\t\t22D9788A215BC910005C2713 /* Safari@2x.png in Resources */,\n\t\t\t\t22D9788B215BC910005C2713 /* Safari@2x~ipad.png in Resources */,\n\t\t\t\t22D9788C215BC910005C2713 /* Hack-Bold.ttf in Resources */,\n\t\t\t\t22D9788D215BC910005C2713 /* Launch.storyboard in Resources */,\n\t\t\t\t22D9788E215BC910005C2713 /* Safari~ipad.png in Resources */,\n\t\t\t\t22D9788F215BC910005C2713 /* licenses.txt in Resources */,\n\t\t\t\t22D97890215BC910005C2713 /* Hack-Regular.ttf in Resources */,\n\t\t\t\t22D97891215BC910005C2713 /* a.caf in Resources */,\n\t\t\t\t22D97892215BC910005C2713 /* TUSafariActivity.strings in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22DB252F1982DF2B0008728E /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t22DB25301982DF2B0008728E /* Icons.xcassets in Resources */,\n\t\t\t\t22DB25401982E3130008728E /* EnterpriseImages.xcassets in Resources */,\n\t\t\t\t2236BD661BAA5E0900015753 /* FontAwesome.otf in Resources */,\n\t\t\t\t22DB253F1982E3100008728E /* EnterpriseLogo.xcassets 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\t08BBD7D08822C3E4F8767F4D /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-IRCCloud FLEX-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t226E642423F1C91F001CE069 /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\talwaysOutOfDate = 1;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\toutputFileListPaths = (\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 = \"echo touch $SRCROOT/IRCCloud/GoogleService-Info.plist\\ntouch $SRCROOT/IRCCloud/GoogleService-Info.plist\\n\";\n\t\t};\n\t\t22D97893215BC910005C2713 /* 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 = \"$SRCROOT/build-scripts/crashlytics.sh\";\n\t\t};\n\t\t22DE05B518D8CA2C00590FC3 /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\talwaysOutOfDate = 1;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\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/bash;\n\t\t\tshellScript = \"$SRCROOT/build-scripts/git-revision.sh\\n\";\n\t\t};\n\t\t25237AFEA31945A9773DC05B /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-ShareExtension Enterprise-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t26D820C8C944726C00471F03 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-IRCCloudUnitTests-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t37515BB7F069B847C3BD521A /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-ShareExtension-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tB40D65DB0EDA3E08FC2602A0 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-IRCCloud Enterprise-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tB7FC4D6CFDE6C0FB433A0A72 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-NotificationService-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tD14C8BA1619831C6D365647F /* [CP] Embed Pods Frameworks */ = {\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\t\"${PODS_ROOT}/Target Support Files/Pods-IRCCloud Enterprise/Pods-IRCCloud Enterprise-frameworks.sh\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCore-framework/FirebaseCore.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCoreExtension-framework/FirebaseCoreExtension.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal-framework/FirebaseCoreInternal.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCrashlytics-framework/FirebaseCrashlytics.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseInstallations-framework/FirebaseInstallations.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseRemoteConfigInterop-framework/FirebaseRemoteConfigInterop.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseSessions-framework/FirebaseSessions.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/GoogleDataTransport-framework/GoogleDataTransport.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/GoogleUtilities-framework/GoogleUtilities.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/PromisesObjC-framework/FBLPromises.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/PromisesSwift-framework/Promises.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/SSZipArchive-framework/SSZipArchive.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/nanopb-framework/nanopb.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/youtube-ios-player-helper/youtube_ios_player_helper.framework\",\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputPaths = (\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreExtension.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCrashlytics.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseRemoteConfigInterop.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseSessions.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Promises.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SSZipArchive.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/youtube_ios_player_helper.framework\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-IRCCloud Enterprise/Pods-IRCCloud Enterprise-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tD45D12B0AC30951AB647C066 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-NotificationService Enterprise-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tD5FE5004D02B6D866851DCEC /* [CP] Embed Pods Frameworks */ = {\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\t\"${PODS_ROOT}/Target Support Files/Pods-IRCCloud/Pods-IRCCloud-frameworks.sh\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCore-framework/FirebaseCore.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCoreExtension-framework/FirebaseCoreExtension.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal-framework/FirebaseCoreInternal.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCrashlytics-framework/FirebaseCrashlytics.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseInstallations-framework/FirebaseInstallations.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseRemoteConfigInterop-framework/FirebaseRemoteConfigInterop.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseSessions-framework/FirebaseSessions.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/GoogleDataTransport-framework/GoogleDataTransport.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/GoogleUtilities-framework/GoogleUtilities.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/PromisesObjC-framework/FBLPromises.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/PromisesSwift-framework/Promises.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/SSZipArchive-framework/SSZipArchive.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/nanopb-framework/nanopb.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/youtube-ios-player-helper/youtube_ios_player_helper.framework\",\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputPaths = (\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreExtension.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCrashlytics.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseRemoteConfigInterop.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseSessions.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Promises.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SSZipArchive.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/youtube_ios_player_helper.framework\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-IRCCloud/Pods-IRCCloud-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tF0B9418E621953688187C7E6 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-IRCCloud-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tF4F5092F64004755EE174E93 /* [CP] Embed Pods Frameworks */ = {\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\t\"${PODS_ROOT}/Target Support Files/Pods-IRCCloud FLEX/Pods-IRCCloud FLEX-frameworks.sh\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCore-framework/FirebaseCore.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCoreExtension-framework/FirebaseCoreExtension.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal-framework/FirebaseCoreInternal.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseCrashlytics-framework/FirebaseCrashlytics.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseInstallations-framework/FirebaseInstallations.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseRemoteConfigInterop-framework/FirebaseRemoteConfigInterop.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseSessions-framework/FirebaseSessions.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/GoogleDataTransport-framework/GoogleDataTransport.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/GoogleUtilities-framework/GoogleUtilities.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/PromisesObjC-framework/FBLPromises.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/PromisesSwift-framework/Promises.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/SSZipArchive-framework/SSZipArchive.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/nanopb-framework/nanopb.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/youtube-ios-player-helper/youtube_ios_player_helper.framework\",\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputPaths = (\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreExtension.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCrashlytics.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseRemoteConfigInterop.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseSessions.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Promises.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SSZipArchive.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/youtube_ios_player_helper.framework\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-IRCCloud FLEX/Pods-IRCCloud FLEX-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t221034E3197EFBAF00AB414F /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t229324191E8945D700ADAA22 /* init_registry_tables.c in Sources */,\n\t\t\t\t2210352F197F1AD400AB414F /* UIColor+IRCCloud.m in Sources */,\n\t\t\t\t2210352B197EFEF600AB414F /* HighlightsCountView.m in Sources */,\n\t\t\t\t2210352A197EFE7800AB414F /* BuffersTableView.m in Sources */,\n\t\t\t\t223876271F70047F00943160 /* YYAnimatedImageView.m in Sources */,\n\t\t\t\t22103526197EFCCA00AB414F /* Ignore.m in Sources */,\n\t\t\t\t222C80E51E4A112D00A243E7 /* SBJson5StreamWriterState.m in Sources */,\n\t\t\t\t229324311E8945D700ADAA22 /* RSSwizzle.m in Sources */,\n\t\t\t\t22103508197EFC6200AB414F /* BuffersDataSource.m in Sources */,\n\t\t\t\t222C80E31E4A112D00A243E7 /* SBJson5StreamTokeniser.m in Sources */,\n\t\t\t\t22D76CCC208E289D005C34E5 /* ColorFormatter.m in Sources */,\n\t\t\t\t2293241F1E8945D700ADAA22 /* registry_search.c in Sources */,\n\t\t\t\t2293243D1E8945D700ADAA22 /* parse_configuration.m in Sources */,\n\t\t\t\t222C80D71E4A111700A243E7 /* SBJson5Parser.m in Sources */,\n\t\t\t\t22103509197EFC6200AB414F /* ChannelsDataSource.m in Sources */,\n\t\t\t\t229324671E8945D700ADAA22 /* vendor_identifier.m in Sources */,\n\t\t\t\t2210350A197EFC6200AB414F /* EventsDataSource.m in Sources */,\n\t\t\t\t2210350C197EFC6200AB414F /* IRCCloudJSONObject.m in Sources */,\n\t\t\t\t229324611E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */,\n\t\t\t\t229324131E8945D700ADAA22 /* assert.c in Sources */,\n\t\t\t\t2210350D197EFC6200AB414F /* NetworkConnection.m in Sources */,\n\t\t\t\t22D76CCA208E288E005C34E5 /* ImageCache.m in Sources */,\n\t\t\t\t2210350E197EFC6200AB414F /* ServersDataSource.m in Sources */,\n\t\t\t\t222C80E61E4A112D00A243E7 /* SBJson5Writer.m in Sources */,\n\t\t\t\t229324791E8945D700ADAA22 /* TrustKit.m in Sources */,\n\t\t\t\t223876281F70047F00943160 /* YYFrameImage.m in Sources */,\n\t\t\t\t229324431E8945D700ADAA22 /* public_key_utils.m in Sources */,\n\t\t\t\t2210350F197EFC6200AB414F /* UsersDataSource.m in Sources */,\n\t\t\t\t22B203701B5FE3BE0058078D /* NotificationsDataSource.m in Sources */,\n\t\t\t\t22D649261B1E0719003BFD86 /* CSURITemplate.m in Sources */,\n\t\t\t\t22D46C691A13A9A900B142F7 /* FileUploader.m in Sources */,\n\t\t\t\t2238762B1F70047F00943160 /* YYSpriteSheetImage.m in Sources */,\n\t\t\t\t2293245B1E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */,\n\t\t\t\t222C80DF1E4A112300A243E7 /* SBJson5StreamParserState.m in Sources */,\n\t\t\t\t2210351F197EFC6200AB414F /* HandshakeHeader.m in Sources */,\n\t\t\t\t222C80DB1E4A111D00A243E7 /* SBJson5StreamParser.m in Sources */,\n\t\t\t\t22103520197EFC6200AB414F /* MutableQueue.m in Sources */,\n\t\t\t\t229324491E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */,\n\t\t\t\t2293244F1E8945D700ADAA22 /* reporting_utils.m in Sources */,\n\t\t\t\t2238762A1F70047F00943160 /* YYImageCoder.m in Sources */,\n\t\t\t\t22103521197EFC6200AB414F /* NSData+Base64.m in Sources */,\n\t\t\t\t22103522197EFC6200AB414F /* WebSocket.m in Sources */,\n\t\t\t\t2275AF6C28D3679C00D11811 /* AvatarsDataSource.m in Sources */,\n\t\t\t\t2293247F1E8945D700ADAA22 /* TSKPinningValidator.m in Sources */,\n\t\t\t\t22103523197EFC6200AB414F /* WebSocketConnectConfig.m in Sources */,\n\t\t\t\t229324551E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */,\n\t\t\t\t22103524197EFC6200AB414F /* WebSocketFragment.m in Sources */,\n\t\t\t\t2293246D1E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */,\n\t\t\t\t229324731E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */,\n\t\t\t\t229324251E8945D700ADAA22 /* trie_search.c in Sources */,\n\t\t\t\t2293240D1E8945D700ADAA22 /* configuration_utils.m in Sources */,\n\t\t\t\t223876291F70047F00943160 /* YYImage.m in Sources */,\n\t\t\t\t22103525197EFC6200AB414F /* WebSocketMessage.m in Sources */,\n\t\t\t\t221034ED197EFBAF00AB414F /* ShareViewController.m in Sources */,\n\t\t\t\t222C80E41E4A112D00A243E7 /* SBJson5StreamWriter.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t221D4B891E23EAD600D403E6 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t2293244B1E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */,\n\t\t\t\t229324631E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */,\n\t\t\t\t223876311F70048000943160 /* YYAnimatedImageView.m in Sources */,\n\t\t\t\t2275AF6E28D3679E00D11811 /* AvatarsDataSource.m in Sources */,\n\t\t\t\t221D4BD31E23F75300D403E6 /* HandshakeHeader.m in Sources */,\n\t\t\t\t222C80EB1E4A112E00A243E7 /* SBJson5StreamTokeniser.m in Sources */,\n\t\t\t\t229324571E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */,\n\t\t\t\t221D4BB01E23F48300D403E6 /* Ignore.m in Sources */,\n\t\t\t\t221D4BBE1E23F4D700D403E6 /* ServersDataSource.m in Sources */,\n\t\t\t\t221D4BAE1E23F47900D403E6 /* NetworkConnection.m in Sources */,\n\t\t\t\t221D4BD51E23F75300D403E6 /* NSData+Base64.m in Sources */,\n\t\t\t\t229324811E8945D700ADAA22 /* TSKPinningValidator.m in Sources */,\n\t\t\t\t223876331F70048000943160 /* YYImage.m in Sources */,\n\t\t\t\t223876321F70048000943160 /* YYFrameImage.m in Sources */,\n\t\t\t\t221D4BC01E23F4DF00D403E6 /* UIColor+IRCCloud.m in Sources */,\n\t\t\t\t229324271E8945D700ADAA22 /* trie_search.c in Sources */,\n\t\t\t\t229324451E8945D700ADAA22 /* public_key_utils.m in Sources */,\n\t\t\t\t2293246F1E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */,\n\t\t\t\t2293245D1E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */,\n\t\t\t\t221D4BB21E23F48A00D403E6 /* BuffersDataSource.m in Sources */,\n\t\t\t\t221D4BFE1E291C5300D403E6 /* CSURITemplate.m in Sources */,\n\t\t\t\t221D4BB61E23F49800D403E6 /* EventsDataSource.m in Sources */,\n\t\t\t\t229324751E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */,\n\t\t\t\t221D4BB81E23F4AF00D403E6 /* ColorFormatter.m in Sources */,\n\t\t\t\t229324151E8945D700ADAA22 /* assert.c in Sources */,\n\t\t\t\t2293243F1E8945D700ADAA22 /* parse_configuration.m in Sources */,\n\t\t\t\t222C80ED1E4A112E00A243E7 /* SBJson5StreamWriterState.m in Sources */,\n\t\t\t\t221D4BD41E23F75300D403E6 /* MutableQueue.m in Sources */,\n\t\t\t\t222C80E11E4A112400A243E7 /* SBJson5StreamParserState.m in Sources */,\n\t\t\t\t221D4BBA1E23F4C000D403E6 /* IRCCloudJSONObject.m in Sources */,\n\t\t\t\t221D4BFC1E23FD3B00D403E6 /* NSURL+IDN.m in Sources */,\n\t\t\t\t222C80DD1E4A111F00A243E7 /* SBJson5StreamParser.m in Sources */,\n\t\t\t\t223876341F70048000943160 /* YYImageCoder.m in Sources */,\n\t\t\t\t222C80EC1E4A112E00A243E7 /* SBJson5StreamWriter.m in Sources */,\n\t\t\t\t221D4BD91E23F75300D403E6 /* WebSocketMessage.m in Sources */,\n\t\t\t\t221D4BBC1E23F4CD00D403E6 /* NotificationsDataSource.m in Sources */,\n\t\t\t\t221D4BD81E23F75300D403E6 /* WebSocketFragment.m in Sources */,\n\t\t\t\t221D4BB41E23F48E00D403E6 /* ChannelsDataSource.m in Sources */,\n\t\t\t\t226F080A1E5DFEC1003EED23 /* ImageCache.m in Sources */,\n\t\t\t\t2293241B1E8945D700ADAA22 /* init_registry_tables.c in Sources */,\n\t\t\t\t221D4BD71E23F75300D403E6 /* WebSocketConnectConfig.m in Sources */,\n\t\t\t\t229324511E8945D700ADAA22 /* reporting_utils.m in Sources */,\n\t\t\t\t229324211E8945D700ADAA22 /* registry_search.c in Sources */,\n\t\t\t\t221D4BC41E23F4FD00D403E6 /* UsersDataSource.m in Sources */,\n\t\t\t\t223876351F70048000943160 /* YYSpriteSheetImage.m in Sources */,\n\t\t\t\t221D4B911E23EAD700D403E6 /* NotificationService.m in Sources */,\n\t\t\t\t222C80EE1E4A112E00A243E7 /* SBJson5Writer.m in Sources */,\n\t\t\t\t229324691E8945D700ADAA22 /* vendor_identifier.m in Sources */,\n\t\t\t\t221D4BD61E23F75300D403E6 /* WebSocket.m in Sources */,\n\t\t\t\t229324331E8945D700ADAA22 /* RSSwizzle.m in Sources */,\n\t\t\t\t222C80D91E4A111900A243E7 /* SBJson5Parser.m in Sources */,\n\t\t\t\t2293240F1E8945D700ADAA22 /* configuration_utils.m in Sources */,\n\t\t\t\t2293247B1E8945D700ADAA22 /* TrustKit.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t221D4B9B1E23EB4900D403E6 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t2293244C1E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */,\n\t\t\t\t229324641E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */,\n\t\t\t\t223876361F70048100943160 /* YYAnimatedImageView.m in Sources */,\n\t\t\t\t2275AF6F28D3679F00D11811 /* AvatarsDataSource.m in Sources */,\n\t\t\t\t221D4BDB1E23F75400D403E6 /* HandshakeHeader.m in Sources */,\n\t\t\t\t222C80EF1E4A112F00A243E7 /* SBJson5StreamTokeniser.m in Sources */,\n\t\t\t\t229324581E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */,\n\t\t\t\t221D4BB11E23F48300D403E6 /* Ignore.m in Sources */,\n\t\t\t\t221D4BBF1E23F4D800D403E6 /* ServersDataSource.m in Sources */,\n\t\t\t\t221D4BAF1E23F47900D403E6 /* NetworkConnection.m in Sources */,\n\t\t\t\t221D4BDD1E23F75400D403E6 /* NSData+Base64.m in Sources */,\n\t\t\t\t229324821E8945D700ADAA22 /* TSKPinningValidator.m in Sources */,\n\t\t\t\t223876381F70048100943160 /* YYImage.m in Sources */,\n\t\t\t\t223876371F70048100943160 /* YYFrameImage.m in Sources */,\n\t\t\t\t221D4BC11E23F4DF00D403E6 /* UIColor+IRCCloud.m in Sources */,\n\t\t\t\t229324281E8945D700ADAA22 /* trie_search.c in Sources */,\n\t\t\t\t229324461E8945D700ADAA22 /* public_key_utils.m in Sources */,\n\t\t\t\t229324701E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */,\n\t\t\t\t2293245E1E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */,\n\t\t\t\t221D4BB31E23F48B00D403E6 /* BuffersDataSource.m in Sources */,\n\t\t\t\t221D4BFF1E291C5400D403E6 /* CSURITemplate.m in Sources */,\n\t\t\t\t221D4BB71E23F49800D403E6 /* EventsDataSource.m in Sources */,\n\t\t\t\t229324761E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */,\n\t\t\t\t221D4BB91E23F4B000D403E6 /* ColorFormatter.m in Sources */,\n\t\t\t\t229324161E8945D700ADAA22 /* assert.c in Sources */,\n\t\t\t\t229324401E8945D700ADAA22 /* parse_configuration.m in Sources */,\n\t\t\t\t222C80F11E4A112F00A243E7 /* SBJson5StreamWriterState.m in Sources */,\n\t\t\t\t221D4BDC1E23F75400D403E6 /* MutableQueue.m in Sources */,\n\t\t\t\t222C80E21E4A112500A243E7 /* SBJson5StreamParserState.m in Sources */,\n\t\t\t\t221D4BBB1E23F4C000D403E6 /* IRCCloudJSONObject.m in Sources */,\n\t\t\t\t221D4BFD1E23FD3B00D403E6 /* NSURL+IDN.m in Sources */,\n\t\t\t\t222C80DE1E4A112000A243E7 /* SBJson5StreamParser.m in Sources */,\n\t\t\t\t223876391F70048100943160 /* YYImageCoder.m in Sources */,\n\t\t\t\t222C80F01E4A112F00A243E7 /* SBJson5StreamWriter.m in Sources */,\n\t\t\t\t221D4BE11E23F75400D403E6 /* WebSocketMessage.m in Sources */,\n\t\t\t\t221D4BBD1E23F4CE00D403E6 /* NotificationsDataSource.m in Sources */,\n\t\t\t\t221D4BE01E23F75400D403E6 /* WebSocketFragment.m in Sources */,\n\t\t\t\t221D4BB51E23F48F00D403E6 /* ChannelsDataSource.m in Sources */,\n\t\t\t\t226F080B1E5DFEC2003EED23 /* ImageCache.m in Sources */,\n\t\t\t\t2293241C1E8945D700ADAA22 /* init_registry_tables.c in Sources */,\n\t\t\t\t221D4BDF1E23F75400D403E6 /* WebSocketConnectConfig.m in Sources */,\n\t\t\t\t229324521E8945D700ADAA22 /* reporting_utils.m in Sources */,\n\t\t\t\t229324221E8945D700ADAA22 /* registry_search.c in Sources */,\n\t\t\t\t221D4BC51E23F4FE00D403E6 /* UsersDataSource.m in Sources */,\n\t\t\t\t2238763A1F70048100943160 /* YYSpriteSheetImage.m in Sources */,\n\t\t\t\t221D4B9C1E23EB4900D403E6 /* NotificationService.m in Sources */,\n\t\t\t\t222C80F21E4A112F00A243E7 /* SBJson5Writer.m in Sources */,\n\t\t\t\t2293246A1E8945D700ADAA22 /* vendor_identifier.m in Sources */,\n\t\t\t\t221D4BDE1E23F75400D403E6 /* WebSocket.m in Sources */,\n\t\t\t\t229324341E8945D700ADAA22 /* RSSwizzle.m in Sources */,\n\t\t\t\t222C80DA1E4A111A00A243E7 /* SBJson5Parser.m in Sources */,\n\t\t\t\t229324101E8945D700ADAA22 /* configuration_utils.m in Sources */,\n\t\t\t\t2293247C1E8945D700ADAA22 /* TrustKit.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t224589C01DCA19BB00D3110A /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t224291651EB22B1000878455 /* URLtoBIDTests.m in Sources */,\n\t\t\t\t2252EE5B1F4485C000307010 /* MessageTypeTests.m in Sources */,\n\t\t\t\t224589C71DCA19BB00D3110A /* CollapsedEventsTests.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t225D973718AA995900065087 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t225D973818AA995900065087 /* main.m in Sources */,\n\t\t\t\t221390FF1B115CD000ECF001 /* PastebinEditorViewController.m in Sources */,\n\t\t\t\t225D973918AA995900065087 /* ServerReorderViewController.m in Sources */,\n\t\t\t\t225D973A18AA995900065087 /* AppDelegate.m in Sources */,\n\t\t\t\t2264A30219659BB100DCFDDD /* URLHandler.m in Sources */,\n\t\t\t\t225D973C18AA995900065087 /* LoginSplashViewController.m in Sources */,\n\t\t\t\t225D974718AA995900065087 /* NetworkConnection.m in Sources */,\n\t\t\t\t221D4B871E1BE2F700D403E6 /* LinksListTableViewController.m in Sources */,\n\t\t\t\t22B2036F1B5FE3BE0058078D /* NotificationsDataSource.m in Sources */,\n\t\t\t\t225D974A18AA995900065087 /* HandshakeHeader.m in Sources */,\n\t\t\t\t2293245A1E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */,\n\t\t\t\t22E9C0AC1C9AF27800013456 /* OpenInFirefoxControllerObjC.m in Sources */,\n\t\t\t\t225D974B18AA995900065087 /* MutableQueue.m in Sources */,\n\t\t\t\t225D974C18AA995900065087 /* NSData+Base64.m in Sources */,\n\t\t\t\t229324541E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */,\n\t\t\t\t225D974D18AA995900065087 /* WebSocket.m in Sources */,\n\t\t\t\t225D974E18AA995900065087 /* WebSocketConnectConfig.m in Sources */,\n\t\t\t\t2232ABD7230C1D66007431B5 /* UITableViewController+HeaderColorFix.m in Sources */,\n\t\t\t\t225D974F18AA995900065087 /* WebSocketFragment.m in Sources */,\n\t\t\t\t224333D120162C1B0007A0D3 /* AvatarsTableViewController.m in Sources */,\n\t\t\t\t22BB94AB1D425D3800BFB6F0 /* SamlLoginViewController.m in Sources */,\n\t\t\t\t223876221F70047E00943160 /* YYAnimatedImageView.m in Sources */,\n\t\t\t\t221E85F3241FBF3F00EB5120 /* PinReorderViewController.m in Sources */,\n\t\t\t\t225D975018AA995900065087 /* WebSocketMessage.m in Sources */,\n\t\t\t\t2293243C1E8945D700ADAA22 /* parse_configuration.m in Sources */,\n\t\t\t\t225D975118AA995900065087 /* IRCCloudJSONObject.m in Sources */,\n\t\t\t\t223876231F70047E00943160 /* YYFrameImage.m in Sources */,\n\t\t\t\t225D975218AA995900065087 /* ServersDataSource.m in Sources */,\n\t\t\t\t225D975318AA995900065087 /* NickCompletionView.m in Sources */,\n\t\t\t\t223154FE1F26245800BDE367 /* LogExportsTableViewController.m in Sources */,\n\t\t\t\t222C80CA1E4A0BB600A243E7 /* SBJson5Parser.m in Sources */,\n\t\t\t\t229324121E8945D700ADAA22 /* assert.c in Sources */,\n\t\t\t\t22CE91761D58C81C0014B25C /* LinkTextView.m in Sources */,\n\t\t\t\t2292AD591D5B55CC00BEE269 /* LinkLabel.m in Sources */,\n\t\t\t\t22DB8D711C441C3000302271 /* YouTubeViewController.m in Sources */,\n\t\t\t\t225D975418AA995900065087 /* NSURL+IDN.m in Sources */,\n\t\t\t\t225D975518AA995900065087 /* BuffersDataSource.m in Sources */,\n\t\t\t\t22EE41FB1F39F66E00D74E8C /* IRCColorPickerView.m in Sources */,\n\t\t\t\t225D975618AA995900065087 /* ChannelsDataSource.m in Sources */,\n\t\t\t\t225D975718AA995900065087 /* BuffersTableView.m in Sources */,\n\t\t\t\t225D975818AA995900065087 /* MainViewController.m in Sources */,\n\t\t\t\t229324601E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */,\n\t\t\t\t2293240C1E8945D700ADAA22 /* configuration_utils.m in Sources */,\n\t\t\t\t229324421E8945D700ADAA22 /* public_key_utils.m in Sources */,\n\t\t\t\t225D975918AA995900065087 /* UIColor+IRCCloud.m in Sources */,\n\t\t\t\t225D975A18AA995900065087 /* UsersDataSource.m in Sources */,\n\t\t\t\t225D975B18AA995900065087 /* UsersTableView.m in Sources */,\n\t\t\t\t229324241E8945D700ADAA22 /* trie_search.c in Sources */,\n\t\t\t\t229324181E8945D700ADAA22 /* init_registry_tables.c in Sources */,\n\t\t\t\t225D975C18AA995900065087 /* EventsDataSource.m in Sources */,\n\t\t\t\t223876251F70047E00943160 /* YYImageCoder.m in Sources */,\n\t\t\t\t225D975D18AA995900065087 /* EventsTableView.m in Sources */,\n\t\t\t\t229324661E8945D700ADAA22 /* vendor_identifier.m in Sources */,\n\t\t\t\t229324301E8945D700ADAA22 /* RSSwizzle.m in Sources */,\n\t\t\t\t225D975E18AA995900065087 /* ColorFormatter.m in Sources */,\n\t\t\t\t22D46C681A13A9A900B142F7 /* FileUploader.m in Sources */,\n\t\t\t\t221E3F4D1AD2DEE00090934B /* FilesTableViewController.m in Sources */,\n\t\t\t\t223876241F70047E00943160 /* YYImage.m in Sources */,\n\t\t\t\t225D975F18AA995900065087 /* CollapsedEvents.m in Sources */,\n\t\t\t\t229324781E8945D700ADAA22 /* TrustKit.m in Sources */,\n\t\t\t\t225D976018AA995900065087 /* HighlightsCountView.m in Sources */,\n\t\t\t\t225D976118AA995900065087 /* Ignore.m in Sources */,\n\t\t\t\t223876261F70047E00943160 /* YYSpriteSheetImage.m in Sources */,\n\t\t\t\t225D976218AA995900065087 /* ChannelModeListTableViewController.m in Sources */,\n\t\t\t\t22D268C71BF4F95200B682AE /* SplashViewController.m in Sources */,\n\t\t\t\t225D976318AA995900065087 /* IgnoresTableViewController.m in Sources */,\n\t\t\t\t228F69741DF8A3F30079E276 /* SpamViewController.m in Sources */,\n\t\t\t\t22BB0A2B28C22FB2008EE509 /* SendMessageIntentHandler.m in Sources */,\n\t\t\t\t222C80D61E4A0BB600A243E7 /* SBJson5Writer.m in Sources */,\n\t\t\t\t225D976418AA995900065087 /* UIExpandingTextView.m in Sources */,\n\t\t\t\t22E54AE11D10593B00891FE4 /* AvatarsDataSource.m in Sources */,\n\t\t\t\t22C2E0591B0E2E4800387B4B /* PastebinViewController.m in Sources */,\n\t\t\t\t229324721E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */,\n\t\t\t\t225D976518AA995900065087 /* UIExpandingTextViewInternal.m in Sources */,\n\t\t\t\t22A363B519D0884D00500478 /* OnePasswordExtension.m in Sources */,\n\t\t\t\t22C2075D1A19125700EDACA4 /* FileMetadataViewController.m in Sources */,\n\t\t\t\t225D976618AA995900065087 /* EditConnectionViewController.m in Sources */,\n\t\t\t\t2293244E1E8945D700ADAA22 /* reporting_utils.m in Sources */,\n\t\t\t\t225D976718AA995900065087 /* ECSlidingViewController.m in Sources */,\n\t\t\t\t229324481E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */,\n\t\t\t\t22D649251B1E0719003BFD86 /* CSURITemplate.m in Sources */,\n\t\t\t\t222C80D21E4A0BB600A243E7 /* SBJson5StreamWriter.m in Sources */,\n\t\t\t\t222C80CC1E4A0BB600A243E7 /* SBJson5StreamParser.m in Sources */,\n\t\t\t\t22D6492B1B1E371D003BFD86 /* PastebinsTableViewController.m in Sources */,\n\t\t\t\t225D976818AA995900065087 /* UIImage+ImageWithUIView.m in Sources */,\n\t\t\t\t225D976918AA995900065087 /* OpenInChromeController.m in Sources */,\n\t\t\t\t225D976A18AA995900065087 /* ChannelInfoViewController.m in Sources */,\n\t\t\t\t225D976B18AA995900065087 /* ImageViewController.m in Sources */,\n\t\t\t\t225D976D18AA995900065087 /* ChannelListTableViewController.m in Sources */,\n\t\t\t\t225D976E18AA995900065087 /* SettingsViewController.m in Sources */,\n\t\t\t\t225D976F18AA995900065087 /* CallerIDTableViewController.m in Sources */,\n\t\t\t\t225D977018AA995900065087 /* WhoisViewController.m in Sources */,\n\t\t\t\t222C80D01E4A0BB600A243E7 /* SBJson5StreamTokeniser.m in Sources */,\n\t\t\t\t225D977118AA995900065087 /* DisplayOptionsViewController.m in Sources */,\n\t\t\t\t225D977218AA995900065087 /* ARChromeActivity.m in Sources */,\n\t\t\t\t22A363BD19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.m in Sources */,\n\t\t\t\t225D977318AA995900065087 /* TUSafariActivity.m in Sources */,\n\t\t\t\t2293247E1E8945D700ADAA22 /* TSKPinningValidator.m in Sources */,\n\t\t\t\t2263D3A3290A979500692EEC /* NSString+Score.m in Sources */,\n\t\t\t\t226F080F1E6495C8003EED23 /* WhoWasTableViewController.m in Sources */,\n\t\t\t\t225D977418AA995900065087 /* LicenseViewController.m in Sources */,\n\t\t\t\t223C407D1C60FE880081B02B /* IRCCloudSafariViewController.m in Sources */,\n\t\t\t\t225D977518AA995900065087 /* WhoListTableViewController.m in Sources */,\n\t\t\t\t2293241E1E8945D700ADAA22 /* registry_search.c in Sources */,\n\t\t\t\t225D977618AA995900065087 /* NamesListTableViewController.m in Sources */,\n\t\t\t\t2271FDA21DCDF45C00A39F84 /* TextTableViewController.m in Sources */,\n\t\t\t\t222C80D41E4A0BB600A243E7 /* SBJson5StreamWriterState.m in Sources */,\n\t\t\t\t222C80CE1E4A0BB600A243E7 /* SBJson5StreamParserState.m in Sources */,\n\t\t\t\t2293246C1E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */,\n\t\t\t\t222C80B71E48ABB200A243E7 /* ImageCache.m in Sources */,\n\t\t\t\t225D977718AA995900065087 /* UINavigationController+iPadSux.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t228A056816D3DABA0029769C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t228A057C16D3DABA0029769C /* main.m in Sources */,\n\t\t\t\t221390FE1B115CD000ECF001 /* PastebinEditorViewController.m in Sources */,\n\t\t\t\t22462B5218906B03009EF986 /* ServerReorderViewController.m in Sources */,\n\t\t\t\t228A05B216D3DB7B0029769C /* AppDelegate.m in Sources */,\n\t\t\t\t2264A30119659BB100DCFDDD /* URLHandler.m in Sources */,\n\t\t\t\t228A05DE16D3E40F0029769C /* LoginSplashViewController.m in Sources */,\n\t\t\t\t22B4284816D7E36300498507 /* NetworkConnection.m in Sources */,\n\t\t\t\t221D4B861E1BE2F700D403E6 /* LinksListTableViewController.m in Sources */,\n\t\t\t\t22B2036E1B5FE3BE0058078D /* NotificationsDataSource.m in Sources */,\n\t\t\t\t22B4286A16D831A800498507 /* HandshakeHeader.m in Sources */,\n\t\t\t\t229324591E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */,\n\t\t\t\t22E9C0AB1C9AF27800013456 /* OpenInFirefoxControllerObjC.m in Sources */,\n\t\t\t\t22B4286C16D831A800498507 /* MutableQueue.m in Sources */,\n\t\t\t\t22B4286E16D831A800498507 /* NSData+Base64.m in Sources */,\n\t\t\t\t229324531E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */,\n\t\t\t\t22B4287016D831A800498507 /* WebSocket.m in Sources */,\n\t\t\t\t22B4287A16D831A800498507 /* WebSocketConnectConfig.m in Sources */,\n\t\t\t\t2232ABD6230C1D66007431B5 /* UITableViewController+HeaderColorFix.m in Sources */,\n\t\t\t\t22B4287C16D831A800498507 /* WebSocketFragment.m in Sources */,\n\t\t\t\t224333D020162C1B0007A0D3 /* AvatarsTableViewController.m in Sources */,\n\t\t\t\t22BB94AA1D425A4F00BFB6F0 /* SamlLoginViewController.m in Sources */,\n\t\t\t\t2238761D1F70047D00943160 /* YYAnimatedImageView.m in Sources */,\n\t\t\t\t221E85F2241FBF3E00EB5120 /* PinReorderViewController.m in Sources */,\n\t\t\t\t22B4287E16D831A800498507 /* WebSocketMessage.m in Sources */,\n\t\t\t\t2293243B1E8945D700ADAA22 /* parse_configuration.m in Sources */,\n\t\t\t\t22B4288616D846BF00498507 /* IRCCloudJSONObject.m in Sources */,\n\t\t\t\t2238761E1F70047D00943160 /* YYFrameImage.m in Sources */,\n\t\t\t\t2236F5FA16DA765C007BE535 /* ServersDataSource.m in Sources */,\n\t\t\t\t22032A6F1884529700BE4A10 /* NickCompletionView.m in Sources */,\n\t\t\t\t223154FD1F26245800BDE367 /* LogExportsTableViewController.m in Sources */,\n\t\t\t\t222C80C91E4A0BB600A243E7 /* SBJson5Parser.m in Sources */,\n\t\t\t\t229324111E8945D700ADAA22 /* assert.c in Sources */,\n\t\t\t\t22CE91751D58C81C0014B25C /* LinkTextView.m in Sources */,\n\t\t\t\t22CE91791D59160B0014B25C /* LinkLabel.m in Sources */,\n\t\t\t\t22DB8D701C441C3000302271 /* YouTubeViewController.m in Sources */,\n\t\t\t\t2293AF0117F9CCD10022BD06 /* NSURL+IDN.m in Sources */,\n\t\t\t\t2236F5FE16DA8928007BE535 /* BuffersDataSource.m in Sources */,\n\t\t\t\t22EE41FA1F39F66E00D74E8C /* IRCColorPickerView.m in Sources */,\n\t\t\t\t2236F60216DBC021007BE535 /* ChannelsDataSource.m in Sources */,\n\t\t\t\t2236F60616DBCA85007BE535 /* BuffersTableView.m in Sources */,\n\t\t\t\t2236F60B16DBCBC6007BE535 /* MainViewController.m in Sources */,\n\t\t\t\t2293245F1E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */,\n\t\t\t\t2293240B1E8945D700ADAA22 /* configuration_utils.m in Sources */,\n\t\t\t\t229324411E8945D700ADAA22 /* public_key_utils.m in Sources */,\n\t\t\t\t2236F63C16DBF3CC007BE535 /* UIColor+IRCCloud.m in Sources */,\n\t\t\t\t2236F64616DD138C007BE535 /* UsersDataSource.m in Sources */,\n\t\t\t\t2236F64A16DD30E5007BE535 /* UsersTableView.m in Sources */,\n\t\t\t\t229324231E8945D700ADAA22 /* trie_search.c in Sources */,\n\t\t\t\t229324171E8945D700ADAA22 /* init_registry_tables.c in Sources */,\n\t\t\t\t22F9EE1C16DE6F21004615C0 /* EventsDataSource.m in Sources */,\n\t\t\t\t223876201F70047D00943160 /* YYImageCoder.m in Sources */,\n\t\t\t\t223DA90C16DFC626006FF808 /* EventsTableView.m in Sources */,\n\t\t\t\t229324651E8945D700ADAA22 /* vendor_identifier.m in Sources */,\n\t\t\t\t2293242F1E8945D700ADAA22 /* RSSwizzle.m in Sources */,\n\t\t\t\t2237E13D16E1214A00CA188F /* ColorFormatter.m in Sources */,\n\t\t\t\t22D46C671A13A9A900B142F7 /* FileUploader.m in Sources */,\n\t\t\t\t221E3F4C1AD2DEE00090934B /* FilesTableViewController.m in Sources */,\n\t\t\t\t2238761F1F70047D00943160 /* YYImage.m in Sources */,\n\t\t\t\t22695F5516E8FC9900E01DF8 /* CollapsedEvents.m in Sources */,\n\t\t\t\t229324771E8945D700ADAA22 /* TrustKit.m in Sources */,\n\t\t\t\t227FF2A116FA128B00DBE3C5 /* HighlightsCountView.m in Sources */,\n\t\t\t\t2230F8E817162ACD007F7C98 /* Ignore.m in Sources */,\n\t\t\t\t223876211F70047D00943160 /* YYSpriteSheetImage.m in Sources */,\n\t\t\t\t22AD75ED1718567D00141257 /* ChannelModeListTableViewController.m in Sources */,\n\t\t\t\t22D268C61BF4F95200B682AE /* SplashViewController.m in Sources */,\n\t\t\t\t22D430A0171C663A003C0684 /* IgnoresTableViewController.m in Sources */,\n\t\t\t\t228F69731DF8A3F30079E276 /* SpamViewController.m in Sources */,\n\t\t\t\t22BB0A2A28C22FB2008EE509 /* SendMessageIntentHandler.m in Sources */,\n\t\t\t\t222C80D51E4A0BB600A243E7 /* SBJson5Writer.m in Sources */,\n\t\t\t\t22D430A61725AAEA003C0684 /* UIExpandingTextView.m in Sources */,\n\t\t\t\t22E54AE01D10593B00891FE4 /* AvatarsDataSource.m in Sources */,\n\t\t\t\t22C2E0581B0E2E4800387B4B /* PastebinViewController.m in Sources */,\n\t\t\t\t229324711E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */,\n\t\t\t\t22D430A81725AAEA003C0684 /* UIExpandingTextViewInternal.m in Sources */,\n\t\t\t\t22A363B419D0884D00500478 /* OnePasswordExtension.m in Sources */,\n\t\t\t\t22C2075C1A19125700EDACA4 /* FileMetadataViewController.m in Sources */,\n\t\t\t\t22B15CF4172ECCFF0075EBA7 /* EditConnectionViewController.m in Sources */,\n\t\t\t\t2293244D1E8945D700ADAA22 /* reporting_utils.m in Sources */,\n\t\t\t\t22B15CFB17301BAF0075EBA7 /* ECSlidingViewController.m in Sources */,\n\t\t\t\t229324471E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */,\n\t\t\t\t22D649241B1E0719003BFD86 /* CSURITemplate.m in Sources */,\n\t\t\t\t222C80D11E4A0BB600A243E7 /* SBJson5StreamWriter.m in Sources */,\n\t\t\t\t222C80CB1E4A0BB600A243E7 /* SBJson5StreamParser.m in Sources */,\n\t\t\t\t22D6492A1B1E371D003BFD86 /* PastebinsTableViewController.m in Sources */,\n\t\t\t\t22B15CFD17301BAF0075EBA7 /* UIImage+ImageWithUIView.m in Sources */,\n\t\t\t\t2274F49F1756723F0039B4CB /* OpenInChromeController.m in Sources */,\n\t\t\t\t2212AF88175F82F900D08C7F /* ChannelInfoViewController.m in Sources */,\n\t\t\t\t2223C6AA1768D7150032544B /* ImageViewController.m in Sources */,\n\t\t\t\t2253BA251770CD7200CCA77F /* ChannelListTableViewController.m in Sources */,\n\t\t\t\t227FF8231772063F00394114 /* SettingsViewController.m in Sources */,\n\t\t\t\t221F0BC5177368B40008EE04 /* CallerIDTableViewController.m in Sources */,\n\t\t\t\t22A1D0271778A86900F8A89C /* WhoisViewController.m in Sources */,\n\t\t\t\t222C80CF1E4A0BB600A243E7 /* SBJson5StreamTokeniser.m in Sources */,\n\t\t\t\t228EFBC8177B4F7300B83A4C /* DisplayOptionsViewController.m in Sources */,\n\t\t\t\t225017631783434900066E71 /* ARChromeActivity.m in Sources */,\n\t\t\t\t22A363BC19D0A7A700500478 /* UIDevice+UIDevice_iPhone6Hax.m in Sources */,\n\t\t\t\t2250176D1783434900066E71 /* TUSafariActivity.m in Sources */,\n\t\t\t\t2293247D1E8945D700ADAA22 /* TSKPinningValidator.m in Sources */,\n\t\t\t\t2263D3A2290A979500692EEC /* NSString+Score.m in Sources */,\n\t\t\t\t226F080E1E6495C8003EED23 /* WhoWasTableViewController.m in Sources */,\n\t\t\t\t224FCF361787288400FC3879 /* LicenseViewController.m in Sources */,\n\t\t\t\t223C407C1C60FE880081B02B /* IRCCloudSafariViewController.m in Sources */,\n\t\t\t\t22A35F26178A317100529CDA /* WhoListTableViewController.m in Sources */,\n\t\t\t\t2293241D1E8945D700ADAA22 /* registry_search.c in Sources */,\n\t\t\t\t22A35F29178A3F3500529CDA /* NamesListTableViewController.m in Sources */,\n\t\t\t\t2271FDA11DCDF45C00A39F84 /* TextTableViewController.m in Sources */,\n\t\t\t\t222C80D31E4A0BB600A243E7 /* SBJson5StreamWriterState.m in Sources */,\n\t\t\t\t222C80CD1E4A0BB600A243E7 /* SBJson5StreamParserState.m in Sources */,\n\t\t\t\t2293246B1E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */,\n\t\t\t\t222C80B61E48ABB200A243E7 /* ImageCache.m in Sources */,\n\t\t\t\t22A19C60178FCCAC00772C60 /* UINavigationController+iPadSux.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22CE2AD81D2AA659001397C0 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t1ADCE22E1D2FCD78000B379F /* UITests.swift in Sources */,\n\t\t\t\t22CE2AE91D2AAA36001397C0 /* SnapshotHelper.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22D9778D215BC910005C2713 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t22D9778E215BC910005C2713 /* main.m in Sources */,\n\t\t\t\t22D9778F215BC910005C2713 /* PastebinEditorViewController.m in Sources */,\n\t\t\t\t22D97790215BC910005C2713 /* ServerReorderViewController.m in Sources */,\n\t\t\t\t22D97791215BC910005C2713 /* AppDelegate.m in Sources */,\n\t\t\t\t22D97792215BC910005C2713 /* URLHandler.m in Sources */,\n\t\t\t\t22D97987215BC979005C2713 /* FLEXRealmDatabaseManager.m in Sources */,\n\t\t\t\t22D9794B215BC979005C2713 /* FLEXObjectExplorerFactory.m in Sources */,\n\t\t\t\t22D9798E215BC979005C2713 /* FLEXHierarchyTableViewCell.m in Sources */,\n\t\t\t\t22D97996215BC979005C2713 /* FLEXKeyboardHelpViewController.m in Sources */,\n\t\t\t\t22D97797215BC910005C2713 /* LoginSplashViewController.m in Sources */,\n\t\t\t\t22D9795B215BC979005C2713 /* FLEXNetworkTransactionDetailTableViewController.m in Sources */,\n\t\t\t\t22D97799215BC910005C2713 /* NetworkConnection.m in Sources */,\n\t\t\t\t22D9779A215BC910005C2713 /* LinksListTableViewController.m in Sources */,\n\t\t\t\t22D9779B215BC910005C2713 /* NotificationsDataSource.m in Sources */,\n\t\t\t\t22D9779D215BC910005C2713 /* HandshakeHeader.m in Sources */,\n\t\t\t\t22D97957215BC979005C2713 /* FLEXNetworkSettingsTableViewController.m in Sources */,\n\t\t\t\t22D97972215BC979005C2713 /* FLEXArgumentInputViewFactory.m in Sources */,\n\t\t\t\t22D977A1215BC910005C2713 /* TSKPinFailureReport.m in Sources */,\n\t\t\t\t22D9794F215BC979005C2713 /* FLEXDictionaryExplorerViewController.m in Sources */,\n\t\t\t\t22D9797D215BC979005C2713 /* FLEXSystemLogTableViewController.m in Sources */,\n\t\t\t\t22D9795E215BC979005C2713 /* FLEXNetworkObserver.m in Sources */,\n\t\t\t\t22D97990215BC979005C2713 /* FLEXHierarchyTableViewController.m in Sources */,\n\t\t\t\t22D9796C215BC979005C2713 /* FLEXArgumentInputStructView.m in Sources */,\n\t\t\t\t22D977A7215BC910005C2713 /* OpenInFirefoxControllerObjC.m in Sources */,\n\t\t\t\t22D9794C215BC979005C2713 /* FLEXGlobalsTableViewControllerEntry.m in Sources */,\n\t\t\t\t22D977A9215BC910005C2713 /* MutableQueue.m in Sources */,\n\t\t\t\t22D97998215BC979005C2713 /* FLEXMultilineTableViewCell.m in Sources */,\n\t\t\t\t22D9797A215BC979005C2713 /* FLEXInstancesTableViewController.m in Sources */,\n\t\t\t\t22D977AC215BC910005C2713 /* NSData+Base64.m in Sources */,\n\t\t\t\t22D977AD215BC910005C2713 /* TSKBackgroundReporter.m in Sources */,\n\t\t\t\t22D97968215BC979005C2713 /* FLEXArgumentInputColorView.m in Sources */,\n\t\t\t\t22D977AF215BC910005C2713 /* WebSocket.m in Sources */,\n\t\t\t\t22D9795F215BC979005C2713 /* FLEXToolbarItem.m in Sources */,\n\t\t\t\t22D97973215BC979005C2713 /* FLEXArgumentInputNotSupportedView.m in Sources */,\n\t\t\t\t22D977B2215BC910005C2713 /* WebSocketConnectConfig.m in Sources */,\n\t\t\t\t22D977B3215BC910005C2713 /* WebSocketFragment.m in Sources */,\n\t\t\t\t22D97951215BC979005C2713 /* FLEXViewControllerExplorerViewController.m in Sources */,\n\t\t\t\t22D977B5215BC910005C2713 /* AvatarsTableViewController.m in Sources */,\n\t\t\t\t22D977B6215BC910005C2713 /* SamlLoginViewController.m in Sources */,\n\t\t\t\t22D97993215BC979005C2713 /* FLEXHeapEnumerator.m in Sources */,\n\t\t\t\t22D97980215BC979005C2713 /* FLEXTableLeftCell.m in Sources */,\n\t\t\t\t22D9797E215BC979005C2713 /* FLEXSystemLogMessage.m in Sources */,\n\t\t\t\t22D97969215BC979005C2713 /* FLEXArgumentInputView.m in Sources */,\n\t\t\t\t22D977BB215BC910005C2713 /* YYAnimatedImageView.m in Sources */,\n\t\t\t\t22D977BC215BC910005C2713 /* WebSocketMessage.m in Sources */,\n\t\t\t\t22D977BD215BC910005C2713 /* parse_configuration.m in Sources */,\n\t\t\t\t22D97956215BC979005C2713 /* FLEXNetworkTransaction.m in Sources */,\n\t\t\t\t22D977BF215BC910005C2713 /* IRCCloudJSONObject.m in Sources */,\n\t\t\t\t22D9798C215BC979005C2713 /* FLEXLiveObjectsTableViewController.m in Sources */,\n\t\t\t\t22D977C1215BC910005C2713 /* YYFrameImage.m in Sources */,\n\t\t\t\t22D97995215BC979005C2713 /* FLEXKeyboardShortcutManager.m in Sources */,\n\t\t\t\t22D9796A215BC979005C2713 /* FLEXArgumentInputJSONObjectView.m in Sources */,\n\t\t\t\t22D97955215BC979005C2713 /* FLEXObjectExplorerViewController.m in Sources */,\n\t\t\t\t22D97959215BC979005C2713 /* FLEXNetworkTransactionTableViewCell.m in Sources */,\n\t\t\t\t22D977C6215BC910005C2713 /* ServersDataSource.m in Sources */,\n\t\t\t\t22D97962215BC979005C2713 /* FLEXPropertyEditorViewController.m in Sources */,\n\t\t\t\t22D977C8215BC910005C2713 /* NickCompletionView.m in Sources */,\n\t\t\t\t22D977C9215BC910005C2713 /* LogExportsTableViewController.m in Sources */,\n\t\t\t\t22D9795A215BC979005C2713 /* FLEXNetworkCurlLogger.m in Sources */,\n\t\t\t\t22D97992215BC979005C2713 /* FLEXUtility.m in Sources */,\n\t\t\t\t22D977CC215BC910005C2713 /* SBJson5Parser.m in Sources */,\n\t\t\t\t22D977CD215BC910005C2713 /* assert.c in Sources */,\n\t\t\t\t22D977CE215BC910005C2713 /* LinkTextView.m in Sources */,\n\t\t\t\t22D977CF215BC910005C2713 /* LinkLabel.m in Sources */,\n\t\t\t\t22D977D0215BC910005C2713 /* YouTubeViewController.m in Sources */,\n\t\t\t\t22D977D1215BC910005C2713 /* NSURL+IDN.m in Sources */,\n\t\t\t\t22D97978215BC979005C2713 /* FLEXObjectRef.m in Sources */,\n\t\t\t\t22D97974215BC979005C2713 /* FLEXFieldEditorView.m in Sources */,\n\t\t\t\t22D9798B215BC979005C2713 /* FLEXGlobalsTableViewController.m in Sources */,\n\t\t\t\t22D977D5215BC910005C2713 /* BuffersDataSource.m in Sources */,\n\t\t\t\t22D977D6215BC910005C2713 /* IRCColorPickerView.m in Sources */,\n\t\t\t\t22D977D7215BC910005C2713 /* ChannelsDataSource.m in Sources */,\n\t\t\t\t22D977D8215BC910005C2713 /* BuffersTableView.m in Sources */,\n\t\t\t\t22D977D9215BC910005C2713 /* MainViewController.m in Sources */,\n\t\t\t\t22D97971215BC979005C2713 /* FLEXArgumentInputNumberView.m in Sources */,\n\t\t\t\t22D9794A215BC979005C2713 /* FLEXArrayExplorerViewController.m in Sources */,\n\t\t\t\t22D977DC215BC910005C2713 /* TSKReportsRateLimiter.m in Sources */,\n\t\t\t\t22D977DD215BC910005C2713 /* configuration_utils.m in Sources */,\n\t\t\t\t22D97986215BC979005C2713 /* FLEXTableContentCell.m in Sources */,\n\t\t\t\t22D977DF215BC910005C2713 /* public_key_utils.m in Sources */,\n\t\t\t\t22D97963215BC979005C2713 /* FLEXDefaultEditorViewController.m in Sources */,\n\t\t\t\t22D977E2215BC910005C2713 /* UIColor+IRCCloud.m in Sources */,\n\t\t\t\t22D977E4215BC910005C2713 /* UsersDataSource.m in Sources */,\n\t\t\t\t22D977E5215BC910005C2713 /* UsersTableView.m in Sources */,\n\t\t\t\t22D9796B215BC979005C2713 /* FLEXArgumentInputSwitchView.m in Sources */,\n\t\t\t\t22D977E7215BC910005C2713 /* trie_search.c in Sources */,\n\t\t\t\t22D977E8215BC910005C2713 /* init_registry_tables.c in Sources */,\n\t\t\t\t22D977E9215BC910005C2713 /* EventsDataSource.m in Sources */,\n\t\t\t\t22D97966215BC979005C2713 /* FLEXFieldEditorViewController.m in Sources */,\n\t\t\t\t22D977EB215BC910005C2713 /* YYImageCoder.m in Sources */,\n\t\t\t\t22D97976215BC979005C2713 /* FLEXWindow.m in Sources */,\n\t\t\t\t22D97975215BC979005C2713 /* FLEXExplorerViewController.m in Sources */,\n\t\t\t\t22D977EF215BC910005C2713 /* EventsTableView.m in Sources */,\n\t\t\t\t22D977F0215BC910005C2713 /* vendor_identifier.m in Sources */,\n\t\t\t\t22D97979215BC979005C2713 /* FLEXWebViewController.m in Sources */,\n\t\t\t\t22D977F2215BC910005C2713 /* RSSwizzle.m in Sources */,\n\t\t\t\t22D97994215BC979005C2713 /* FLEXRuntimeUtility.m in Sources */,\n\t\t\t\t22D97985215BC979005C2713 /* FLEXMultiColumnTableView.m in Sources */,\n\t\t\t\t22D977F5215BC910005C2713 /* ColorFormatter.m in Sources */,\n\t\t\t\t22D977F6215BC910005C2713 /* FileUploader.m in Sources */,\n\t\t\t\t22D9796F215BC979005C2713 /* FLEXArgumentInputTextView.m in Sources */,\n\t\t\t\t22D977F8215BC910005C2713 /* FilesTableViewController.m in Sources */,\n\t\t\t\t22D977F9215BC910005C2713 /* YYImage.m in Sources */,\n\t\t\t\t22D977FA215BC910005C2713 /* CollapsedEvents.m in Sources */,\n\t\t\t\t22D977FB215BC910005C2713 /* TrustKit.m in Sources */,\n\t\t\t\t22D977FC215BC910005C2713 /* HighlightsCountView.m in Sources */,\n\t\t\t\t22D977FD215BC910005C2713 /* Ignore.m in Sources */,\n\t\t\t\t22D977FE215BC910005C2713 /* YYSpriteSheetImage.m in Sources */,\n\t\t\t\t22D9794E215BC979005C2713 /* FLEXClassExplorerViewController.m in Sources */,\n\t\t\t\t22D97960215BC979005C2713 /* FLEXExplorerToolbar.m in Sources */,\n\t\t\t\t22D97802215BC910005C2713 /* ChannelModeListTableViewController.m in Sources */,\n\t\t\t\t22D97988215BC979005C2713 /* FLEXSQLiteDatabaseManager.m in Sources */,\n\t\t\t\t22D9798D215BC979005C2713 /* FLEXClassesTableViewController.m in Sources */,\n\t\t\t\t22D97805215BC910005C2713 /* SplashViewController.m in Sources */,\n\t\t\t\t22D97806215BC910005C2713 /* IgnoresTableViewController.m in Sources */,\n\t\t\t\t22D97807215BC910005C2713 /* SpamViewController.m in Sources */,\n\t\t\t\t22D9794D215BC979005C2713 /* FLEXImageExplorerViewController.m in Sources */,\n\t\t\t\t22D97809215BC910005C2713 /* SBJson5Writer.m in Sources */,\n\t\t\t\t22D9780A215BC910005C2713 /* UIExpandingTextView.m in Sources */,\n\t\t\t\t22D97983215BC979005C2713 /* FLEXTableListViewController.m in Sources */,\n\t\t\t\t22D97958215BC979005C2713 /* FLEXNetworkRecorder.m in Sources */,\n\t\t\t\t22D9780D215BC910005C2713 /* AvatarsDataSource.m in Sources */,\n\t\t\t\t22D97997215BC979005C2713 /* FLEXResources.m in Sources */,\n\t\t\t\t22D9780F215BC910005C2713 /* PastebinViewController.m in Sources */,\n\t\t\t\t22D97961215BC979005C2713 /* FLEXManager.m in Sources */,\n\t\t\t\t22D97812215BC910005C2713 /* TSKNSURLSessionDelegateProxy.m in Sources */,\n\t\t\t\t22D97813215BC910005C2713 /* UIExpandingTextViewInternal.m in Sources */,\n\t\t\t\t22D97814215BC910005C2713 /* OnePasswordExtension.m in Sources */,\n\t\t\t\t22D97967215BC979005C2713 /* FLEXArgumentInputStringView.m in Sources */,\n\t\t\t\t22D97816215BC910005C2713 /* FileMetadataViewController.m in Sources */,\n\t\t\t\t22D97817215BC910005C2713 /* EditConnectionViewController.m in Sources */,\n\t\t\t\t22D97818215BC910005C2713 /* reporting_utils.m in Sources */,\n\t\t\t\t22D97819215BC910005C2713 /* ECSlidingViewController.m in Sources */,\n\t\t\t\t22D9798F215BC979005C2713 /* FLEXImagePreviewViewController.m in Sources */,\n\t\t\t\t22D9781B215BC910005C2713 /* ssl_pin_verifier.m in Sources */,\n\t\t\t\t22D9781C215BC910005C2713 /* CSURITemplate.m in Sources */,\n\t\t\t\t22D97989215BC979005C2713 /* FLEXCookiesTableViewController.m in Sources */,\n\t\t\t\t22D97952215BC979005C2713 /* FLEXSetExplorerViewController.m in Sources */,\n\t\t\t\t22D97954215BC979005C2713 /* FLEXViewExplorerViewController.m in Sources */,\n\t\t\t\t22D97820215BC910005C2713 /* SBJson5StreamWriter.m in Sources */,\n\t\t\t\t22D97821215BC910005C2713 /* SBJson5StreamParser.m in Sources */,\n\t\t\t\t22D97822215BC910005C2713 /* PastebinsTableViewController.m in Sources */,\n\t\t\t\t22D97977215BC979005C2713 /* FLEXFileBrowserSearchOperation.m in Sources */,\n\t\t\t\t22D97824215BC910005C2713 /* UIImage+ImageWithUIView.m in Sources */,\n\t\t\t\t22D97825215BC910005C2713 /* OpenInChromeController.m in Sources */,\n\t\t\t\t22D97826215BC910005C2713 /* ChannelInfoViewController.m in Sources */,\n\t\t\t\t22D97970215BC979005C2713 /* FLEXArgumentInputFontsPickerView.m in Sources */,\n\t\t\t\t22D9796E215BC979005C2713 /* FLEXArgumentInputFontView.m in Sources */,\n\t\t\t\t22D97984215BC979005C2713 /* FLEXTableColumnHeader.m in Sources */,\n\t\t\t\t22D9782C215BC910005C2713 /* ImageViewController.m in Sources */,\n\t\t\t\t22D97953215BC979005C2713 /* FLEXLayerExplorerViewController.m in Sources */,\n\t\t\t\t22D9782E215BC910005C2713 /* ChannelListTableViewController.m in Sources */,\n\t\t\t\t22D9782F215BC910005C2713 /* SettingsViewController.m in Sources */,\n\t\t\t\t22D97830215BC910005C2713 /* CallerIDTableViewController.m in Sources */,\n\t\t\t\t22D97831215BC910005C2713 /* WhoisViewController.m in Sources */,\n\t\t\t\t22D97964215BC979005C2713 /* FLEXMethodCallingViewController.m in Sources */,\n\t\t\t\t22D97833215BC910005C2713 /* SBJson5StreamTokeniser.m in Sources */,\n\t\t\t\t22D97834215BC910005C2713 /* DisplayOptionsViewController.m in Sources */,\n\t\t\t\t22D9797F215BC979005C2713 /* FLEXSystemLogTableViewCell.m in Sources */,\n\t\t\t\t22D97836215BC910005C2713 /* ARChromeActivity.m in Sources */,\n\t\t\t\t22D9798A215BC979005C2713 /* FLEXLibrariesTableViewController.m in Sources */,\n\t\t\t\t22D97838215BC910005C2713 /* UIDevice+UIDevice_iPhone6Hax.m in Sources */,\n\t\t\t\t22D9795C215BC979005C2713 /* FLEXNetworkHistoryTableViewController.m in Sources */,\n\t\t\t\t22D9783A215BC910005C2713 /* TUSafariActivity.m in Sources */,\n\t\t\t\t22D9783B215BC910005C2713 /* TSKPinningValidator.m in Sources */,\n\t\t\t\t22D9783C215BC910005C2713 /* WhoWasTableViewController.m in Sources */,\n\t\t\t\t22D9783D215BC910005C2713 /* LicenseViewController.m in Sources */,\n\t\t\t\t22D9783E215BC910005C2713 /* IRCCloudSafariViewController.m in Sources */,\n\t\t\t\t22D9783F215BC910005C2713 /* WhoListTableViewController.m in Sources */,\n\t\t\t\t22D9797C215BC979005C2713 /* FLEXFileBrowserFileOperationController.m in Sources */,\n\t\t\t\t22D97965215BC979005C2713 /* FLEXIvarEditorViewController.m in Sources */,\n\t\t\t\t22D9796D215BC979005C2713 /* FLEXArgumentInputDateView.m in Sources */,\n\t\t\t\t22D97843215BC910005C2713 /* registry_search.c in Sources */,\n\t\t\t\t22D97844215BC910005C2713 /* NamesListTableViewController.m in Sources */,\n\t\t\t\t22D97845215BC910005C2713 /* TextTableViewController.m in Sources */,\n\t\t\t\t22D97846215BC910005C2713 /* SBJson5StreamWriterState.m in Sources */,\n\t\t\t\t22D97847215BC910005C2713 /* SBJson5StreamParserState.m in Sources */,\n\t\t\t\t22D97848215BC910005C2713 /* TSKNSURLConnectionDelegateProxy.m in Sources */,\n\t\t\t\t22D97849215BC910005C2713 /* ImageCache.m in Sources */,\n\t\t\t\t22D97950215BC979005C2713 /* FLEXDefaultsExplorerViewController.m in Sources */,\n\t\t\t\t22D9797B215BC979005C2713 /* FLEXFileBrowserTableViewController.m in Sources */,\n\t\t\t\t22D97982215BC979005C2713 /* FLEXTableContentViewController.m in Sources */,\n\t\t\t\t22D9784D215BC910005C2713 /* UINavigationController+iPadSux.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t22DB24FB1982DF2B0008728E /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t2293241A1E8945D700ADAA22 /* init_registry_tables.c in Sources */,\n\t\t\t\t22DB24FC1982DF2B0008728E /* UIColor+IRCCloud.m in Sources */,\n\t\t\t\t22DB24FD1982DF2B0008728E /* HighlightsCountView.m in Sources */,\n\t\t\t\t22DB24FE1982DF2B0008728E /* BuffersTableView.m in Sources */,\n\t\t\t\t2238762C1F70047F00943160 /* YYAnimatedImageView.m in Sources */,\n\t\t\t\t22DB24FF1982DF2B0008728E /* Ignore.m in Sources */,\n\t\t\t\t222C80E91E4A112D00A243E7 /* SBJson5StreamWriterState.m in Sources */,\n\t\t\t\t229324321E8945D700ADAA22 /* RSSwizzle.m in Sources */,\n\t\t\t\t22DB25001982DF2B0008728E /* BuffersDataSource.m in Sources */,\n\t\t\t\t222C80E71E4A112D00A243E7 /* SBJson5StreamTokeniser.m in Sources */,\n\t\t\t\t22D76CCD208E289E005C34E5 /* ColorFormatter.m in Sources */,\n\t\t\t\t229324201E8945D700ADAA22 /* registry_search.c in Sources */,\n\t\t\t\t2293243E1E8945D700ADAA22 /* parse_configuration.m in Sources */,\n\t\t\t\t222C80D81E4A111800A243E7 /* SBJson5Parser.m in Sources */,\n\t\t\t\t22DB25011982DF2B0008728E /* ChannelsDataSource.m in Sources */,\n\t\t\t\t229324681E8945D700ADAA22 /* vendor_identifier.m in Sources */,\n\t\t\t\t22DB25021982DF2B0008728E /* EventsDataSource.m in Sources */,\n\t\t\t\t22DB25041982DF2B0008728E /* IRCCloudJSONObject.m in Sources */,\n\t\t\t\t229324621E8945D700ADAA22 /* TSKReportsRateLimiter.m in Sources */,\n\t\t\t\t229324141E8945D700ADAA22 /* assert.c in Sources */,\n\t\t\t\t22DB25051982DF2B0008728E /* NetworkConnection.m in Sources */,\n\t\t\t\t22D76CCB208E288F005C34E5 /* ImageCache.m in Sources */,\n\t\t\t\t22DB25061982DF2B0008728E /* ServersDataSource.m in Sources */,\n\t\t\t\t222C80EA1E4A112D00A243E7 /* SBJson5Writer.m in Sources */,\n\t\t\t\t2293247A1E8945D700ADAA22 /* TrustKit.m in Sources */,\n\t\t\t\t2238762D1F70047F00943160 /* YYFrameImage.m in Sources */,\n\t\t\t\t229324441E8945D700ADAA22 /* public_key_utils.m in Sources */,\n\t\t\t\t22DB25071982DF2B0008728E /* UsersDataSource.m in Sources */,\n\t\t\t\t22B203711B5FE3BE0058078D /* NotificationsDataSource.m in Sources */,\n\t\t\t\t22D649271B1E0719003BFD86 /* CSURITemplate.m in Sources */,\n\t\t\t\t22D46C6A1A13A9A900B142F7 /* FileUploader.m in Sources */,\n\t\t\t\t223876301F70047F00943160 /* YYSpriteSheetImage.m in Sources */,\n\t\t\t\t2293245C1E8945D700ADAA22 /* TSKPinFailureReport.m in Sources */,\n\t\t\t\t222C80E01E4A112300A243E7 /* SBJson5StreamParserState.m in Sources */,\n\t\t\t\t22DB25171982DF2B0008728E /* HandshakeHeader.m in Sources */,\n\t\t\t\t222C80DC1E4A111E00A243E7 /* SBJson5StreamParser.m in Sources */,\n\t\t\t\t22DB25181982DF2B0008728E /* MutableQueue.m in Sources */,\n\t\t\t\t2293244A1E8945D700ADAA22 /* ssl_pin_verifier.m in Sources */,\n\t\t\t\t229324501E8945D700ADAA22 /* reporting_utils.m in Sources */,\n\t\t\t\t2238762F1F70047F00943160 /* YYImageCoder.m in Sources */,\n\t\t\t\t22DB25191982DF2B0008728E /* NSData+Base64.m in Sources */,\n\t\t\t\t22DB251A1982DF2B0008728E /* WebSocket.m in Sources */,\n\t\t\t\t2275AF6D28D3679D00D11811 /* AvatarsDataSource.m in Sources */,\n\t\t\t\t229324801E8945D700ADAA22 /* TSKPinningValidator.m in Sources */,\n\t\t\t\t22DB251B1982DF2B0008728E /* WebSocketConnectConfig.m in Sources */,\n\t\t\t\t229324561E8945D700ADAA22 /* TSKBackgroundReporter.m in Sources */,\n\t\t\t\t22DB251C1982DF2B0008728E /* WebSocketFragment.m in Sources */,\n\t\t\t\t2293246E1E8945D700ADAA22 /* TSKNSURLConnectionDelegateProxy.m in Sources */,\n\t\t\t\t229324741E8945D700ADAA22 /* TSKNSURLSessionDelegateProxy.m in Sources */,\n\t\t\t\t229324261E8945D700ADAA22 /* trie_search.c in Sources */,\n\t\t\t\t2293240E1E8945D700ADAA22 /* configuration_utils.m in Sources */,\n\t\t\t\t2238762E1F70047F00943160 /* YYImage.m in Sources */,\n\t\t\t\t22DB251D1982DF2B0008728E /* WebSocketMessage.m in Sources */,\n\t\t\t\t22DB251E1982DF2B0008728E /* ShareViewController.m in Sources */,\n\t\t\t\t222C80E81E4A112D00A243E7 /* SBJson5StreamWriter.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\t221034F1197EFBAF00AB414F /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 221034E6197EFBAF00AB414F /* ShareExtension */;\n\t\t\ttargetProxy = 221034F0197EFBAF00AB414F /* PBXContainerItemProxy */;\n\t\t};\n\t\t221034F4197EFBAF00AB414F /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 221034E6197EFBAF00AB414F /* ShareExtension */;\n\t\t\ttargetProxy = 221034F3197EFBAF00AB414F /* PBXContainerItemProxy */;\n\t\t};\n\t\t221D4B941E23EAD700D403E6 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 221D4B8C1E23EAD600D403E6 /* NotificationService */;\n\t\t\ttargetProxy = 221D4B931E23EAD700D403E6 /* PBXContainerItemProxy */;\n\t\t};\n\t\t221D4BA91E23F0FC00D403E6 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 221D4B9A1E23EB4900D403E6 /* NotificationService Enterprise */;\n\t\t\ttargetProxy = 221D4BA81E23F0FC00D403E6 /* PBXContainerItemProxy */;\n\t\t};\n\t\t22322CCA20E549AA00AC54CD /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 22DE05B118D8CA0700590FC3 /* GitRevision */;\n\t\t\ttargetProxy = 22322CC920E549AA00AC54CD /* PBXContainerItemProxy */;\n\t\t};\n\t\t22322CCC20E549B100AC54CD /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 22DE05B118D8CA0700590FC3 /* GitRevision */;\n\t\t\ttargetProxy = 22322CCB20E549B100AC54CD /* PBXContainerItemProxy */;\n\t\t};\n\t\t224589CA1DCA19BB00D3110A /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 228A056B16D3DABA0029769C /* IRCCloud */;\n\t\t\ttargetProxy = 224589C91DCA19BB00D3110A /* PBXContainerItemProxy */;\n\t\t};\n\t\t22CE2AE21D2AA662001397C0 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 228A056B16D3DABA0029769C /* IRCCloud */;\n\t\t\ttargetProxy = 22CE2AE11D2AA662001397C0 /* PBXContainerItemProxy */;\n\t\t};\n\t\t22D97785215BC910005C2713 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 22DE05B118D8CA0700590FC3 /* GitRevision */;\n\t\t\ttargetProxy = 22D97786215BC910005C2713 /* PBXContainerItemProxy */;\n\t\t};\n\t\t22D97787215BC910005C2713 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 221034E6197EFBAF00AB414F /* ShareExtension */;\n\t\t\ttargetProxy = 22D97788215BC910005C2713 /* PBXContainerItemProxy */;\n\t\t};\n\t\t22D97789215BC910005C2713 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 221034E6197EFBAF00AB414F /* ShareExtension */;\n\t\t\ttargetProxy = 22D9778A215BC910005C2713 /* PBXContainerItemProxy */;\n\t\t};\n\t\t22D9778B215BC910005C2713 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 221D4B8C1E23EAD600D403E6 /* NotificationService */;\n\t\t\ttargetProxy = 22D9778C215BC910005C2713 /* PBXContainerItemProxy */;\n\t\t};\n\t\t22DB253B1982DFFB0008728E /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 22DB24FA1982DF2B0008728E /* ShareExtension Enterprise */;\n\t\t\ttargetProxy = 22DB253A1982DFFB0008728E /* PBXContainerItemProxy */;\n\t\t};\n\t\t22DE05B718D8CA4800590FC3 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 22DE05B118D8CA0700590FC3 /* GitRevision */;\n\t\t\ttargetProxy = 22DE05B618D8CA4800590FC3 /* PBXContainerItemProxy */;\n\t\t};\n\t\t22DE05B918D8CA4F00590FC3 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 22DE05B118D8CA0700590FC3 /* GitRevision */;\n\t\t\ttargetProxy = 22DE05B818D8CA4F00590FC3 /* PBXContainerItemProxy */;\n\t\t};\n\t\t22E7141019D9D18200E11D96 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 22DE05B118D8CA0700590FC3 /* GitRevision */;\n\t\t\ttargetProxy = 22E7140F19D9D18200E11D96 /* PBXContainerItemProxy */;\n\t\t};\n\t\t22E7141219D9D18700E11D96 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 22DE05B118D8CA0700590FC3 /* GitRevision */;\n\t\t\ttargetProxy = 22E7141119D9D18700E11D96 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t2251693117B5A8040093ADC5 /* TUSafariActivity.strings */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t2251693217B5A8040093ADC5 /* en */,\n\t\t\t);\n\t\t\tname = TUSafariActivity.strings;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t22D4F9101743F3790095EE8F /* Localizable.strings */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t22D4F9111743F3790095EE8F /* en */,\n\t\t\t);\n\t\t\tname = Localizable.strings;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t221034F6197EFBAF00AB414F /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 72EF5BEF0B6805E196076677 /* Pods-ShareExtension.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=macosx*]\" = \"Apple Development\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\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_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tINFOPLIST_FILE = ShareExtension/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tOTHER_CFLAGS = \"-DEXTENSION\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloud.ShareExtension;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"match Development com.irccloud.IRCCloud.ShareExtension\";\n\t\t\t\t\"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]\" = \"Catalyst Development ShareExtension\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSUPPORTS_MACCATALYST = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t221034F7197EFBAF00AB414F /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = A760D4C60BC249A2F3CC3524 /* Pods-ShareExtension.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tINFOPLIST_FILE = ShareExtension/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DEXTENSION\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloud.ShareExtension;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"Crashlytics ShareExtension\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSUPPORTS_MACCATALYST = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t221034F8197EFBAF00AB414F /* AppStore */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 750FA24A88594B10FEDE6646 /* Pods-ShareExtension.appstore.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=macosx*]\" = \"Apple Distribution\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tINFOPLIST_FILE = ShareExtension/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DAPPSTORE\",\n\t\t\t\t\t\"-DEXTENSION\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloud.ShareExtension;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"App Store ShareExtension\";\n\t\t\t\t\"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]\" = \"Catalyst ShareExtension\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSUPPORTS_MACCATALYST = YES;\n\t\t\t};\n\t\t\tname = AppStore;\n\t\t};\n\t\t221D4B971E23EAD700D403E6 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 1235543CBD3AE11C697E1C64 /* Pods-NotificationService.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=macosx*]\" = \"Apple Development\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tINFOPLIST_FILE = NotificationService/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tOTHER_CFLAGS = \"-DEXTENSION\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloud.NotificationService;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"match Development com.irccloud.IRCCloud.NotificationService\";\n\t\t\t\t\"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]\" = \"Catalyst Development NotificationService\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSUPPORTS_MACCATALYST = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t221D4B981E23EAD700D403E6 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7CFB3E8BA47C29791F69E532 /* Pods-NotificationService.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tINFOPLIST_FILE = NotificationService/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DEXTENSION\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloud.NotificationService;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"Crashlytics NotificationService\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSUPPORTS_MACCATALYST = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t221D4B991E23EAD700D403E6 /* AppStore */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 4F27E14C033710EC4B42D049 /* Pods-NotificationService.appstore.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=macosx*]\" = \"Apple Distribution\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tINFOPLIST_FILE = NotificationService/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DAPPSTORE\",\n\t\t\t\t\t\"-DEXTENSION\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloud.NotificationService;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"App Store NotificationService\";\n\t\t\t\t\"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]\" = \"Catalyst NotificationService\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSUPPORTS_MACCATALYST = YES;\n\t\t\t};\n\t\t\tname = AppStore;\n\t\t};\n\t\t221D4BA01E23EB4900D403E6 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = BFED8175E3E7FAD3E4906856 /* Pods-NotificationService Enterprise.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = \"NotificationService Enterprise.entitlements\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/NotificationService/Info.plist\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tOTHER_CFLAGS = \"-DEXTENSION\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.enterprise.NotificationService;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"match Development com.irccloud.enterprise.NotificationService\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t221D4BA11E23EB4900D403E6 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = A2393D6BBB8E07F3DE0D5379 /* Pods-NotificationService Enterprise.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = \"NotificationService Enterprise.entitlements\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/NotificationService/Info.plist\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DEXTENSION\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.enterprise.NotificationService;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"Crashlytics NotificationService-Enterprise\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t221D4BA21E23EB4900D403E6 /* AppStore */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 2D34900179BBF7DB46AC6ABF /* Pods-NotificationService Enterprise.appstore.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = \"NotificationService Enterprise.entitlements\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/NotificationService/Info.plist\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DAPPSTORE\",\n\t\t\t\t\t\"-DEXTENSION\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.enterprise.NotificationService;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"App Store Enterprise NotificationService\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = AppStore;\n\t\t};\n\t\t224589CB1DCA19BB00D3110A /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 734B6CF2BBC243289BBDFE3E /* Pods-IRCCloudUnitTests.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tINFOPLIST_FILE = IRCCloudUnitTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@loader_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloudUnitTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/IRCCloud.app/IRCCloud\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t224589CC1DCA19BB00D3110A /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7E8BEE7BE95EE6C639899F19 /* Pods-IRCCloudUnitTests.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tINFOPLIST_FILE = IRCCloudUnitTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@loader_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloudUnitTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/IRCCloud.app/IRCCloud\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t224589CD1DCA19BB00D3110A /* AppStore */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = F4F652185AA9F602056FD25B /* Pods-IRCCloudUnitTests.appstore.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tINFOPLIST_FILE = IRCCloudUnitTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@loader_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloudUnitTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/IRCCloud.app/IRCCloud\";\n\t\t\t};\n\t\t\tname = AppStore;\n\t\t};\n\t\t225D979D18AA995900065087 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 096184601771D02417AC2EA7 /* Pods-IRCCloud Enterprise.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = IRCEnterprise.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tINFOPLIST_FILE = \"IRCCloud/IRCCloud-Enterprise-Info.plist\";\n\t\t\t\tINFOPLIST_PREPROCESSOR_DEFINITIONS = \"\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(PROJECT_DIR)/IRCCloud\\\"\",\n\t\t\t\t);\n\t\t\t\tOTHER_CFLAGS = \"-DENTERPRISE\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.enterprise;\n\t\t\t\tPRODUCT_NAME = IRCEnterprise;\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"match Development com.irccloud.enterprise\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t225D979E18AA995900065087 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = F7E442A5DB675C1935189274 /* Pods-IRCCloud Enterprise.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = IRCEnterprise.entitlements;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tINFOPLIST_FILE = \"IRCCloud/IRCCloud-Enterprise-Info.plist\";\n\t\t\t\tINFOPLIST_PREPROCESSOR_DEFINITIONS = \"\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(PROJECT_DIR)/IRCCloud\\\"\",\n\t\t\t\t);\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DENTERPRISE\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.enterprise;\n\t\t\t\tPRODUCT_NAME = IRCEnterprise;\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"Crashlytics-Enterprise\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t228A05A516D3DABB0029769C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = NO;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\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_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tINFOPLIST_PREFIX_HEADER = IRCCloud/InfoPlist.h;\n\t\t\t\tINFOPLIST_PREPROCESS = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 12.0;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\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\t228A05A616D3DABB0029769C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = NO;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Distribution\";\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tINFOPLIST_PREFIX_HEADER = IRCCloud/InfoPlist.h;\n\t\t\t\tINFOPLIST_PREPROCESS = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 12.0;\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_CFLAGS = \"-DNS_BLOCK_ASSERTIONS=1\";\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\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\t228A05A816D3DABB0029769C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = BB5BF7CE5566B5B9E80ACC95 /* Pods-IRCCloud.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = IRCCloud/IRCCloud.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=macosx*]\" = \"Apple Development\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\t\"DEVELOPMENT_TEAM[sdk=macosx*]\" = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tINFOPLIST_FILE = \"IRCCloud/IRCCloud-Info.plist\";\n\t\t\t\tINFOPLIST_KEY_LSApplicationCategoryType = \"public.app-category.business\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(PROJECT_DIR)/IRCCloud\\\"\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.irccloud.${PRODUCT_NAME:rfc1034identifier}${BUNDLE_SUFFIX}\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"match Development com.irccloud.IRCCloud\";\n\t\t\t\t\"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]\" = \"Catalyst Development\";\n\t\t\t\tSUPPORTS_MACCATALYST = YES;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t228A05A916D3DABB0029769C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 8B18E14B6DD31D7CDE986D5B /* Pods-IRCCloud.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = IRCCloud/IRCCloud.entitlements;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tINFOPLIST_FILE = \"IRCCloud/IRCCloud-Info.plist\";\n\t\t\t\tINFOPLIST_KEY_LSApplicationCategoryType = \"public.app-category.business\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(PROJECT_DIR)/IRCCloud\\\"\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.irccloud.${PRODUCT_NAME:rfc1034identifier}${BUNDLE_SUFFIX}\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = Crashlytics;\n\t\t\t\tSUPPORTS_MACCATALYST = YES;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t22CE2AE31D2AA663001397C0 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tINFOPLIST_FILE = UITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@loader_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.UITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"UITests/UITests-Bridging-Header.h\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 4.2;\n\t\t\t\tTEST_TARGET_NAME = IRCCloud;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t22CE2AE41D2AA663001397C0 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tINFOPLIST_FILE = UITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@loader_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.UITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"UITests/UITests-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 4.2;\n\t\t\t\tTEST_TARGET_NAME = IRCCloud;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t22CE2AE51D2AA663001397C0 /* AppStore */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tINFOPLIST_FILE = UITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@loader_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.UITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"UITests/UITests-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 4.2;\n\t\t\t\tTEST_TARGET_NAME = IRCCloud;\n\t\t\t};\n\t\t\tname = AppStore;\n\t\t};\n\t\t22D97898215BC910005C2713 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 747834BB92EAB6AFAEC360EA /* Pods-IRCCloud FLEX.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = IRCCloud/IRCCloud.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"FLEX=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/IRCCloud/IRCCloud-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(PROJECT_DIR)/IRCCloud\\\"\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloud;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"match Development com.irccloud.IRCCloud\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t22D97899215BC910005C2713 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 1C7FC0255C6F93D841E44603 /* Pods-IRCCloud FLEX.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = IRCCloud/IRCCloud.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/IRCCloud/IRCCloud-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(PROJECT_DIR)/IRCCloud\\\"\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloud;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = Crashlytics;\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t22D9789A215BC910005C2713 /* AppStore */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 501E461E42461CCDCA1FEA73 /* Pods-IRCCloud FLEX.appstore.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = IRCCloud/IRCCloud.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/IRCCloud/IRCCloud-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(PROJECT_DIR)/IRCCloud\\\"\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.IRCCloud;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"App Store\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = AppStore;\n\t\t};\n\t\t22DB25341982DF2B0008728E /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 312A65F8D9286A2A8D9E9C43 /* Pods-ShareExtension Enterprise.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = \"ShareExtension Enterprise.entitlements\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\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_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tINFOPLIST_FILE = \"ShareExtension/Info-Enterprise.plist\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DEXTENSION\",\n\t\t\t\t\t\"-DENTERPRISE\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.enterprise.ShareExtension;\n\t\t\t\tPRODUCT_NAME = \"ShareExtension Enterprise\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"match Development com.irccloud.enterprise.ShareExtension\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t22DB25351982DF2B0008728E /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 42EA3F8746F7A000AFEB8A4F /* Pods-ShareExtension Enterprise.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = \"ShareExtension Enterprise.entitlements\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tINFOPLIST_FILE = \"ShareExtension/Info-Enterprise.plist\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DEXTENSION\",\n\t\t\t\t\t\"-DENTERPRISE\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.enterprise.ShareExtension;\n\t\t\t\tPRODUCT_NAME = \"ShareExtension Enterprise\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"Crashlytics ShareExtension-Enterprise\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t22DB25361982DF2B0008728E /* AppStore */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = EB28B506CCB1E9844E1A26E4 /* Pods-ShareExtension Enterprise.appstore.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = \"ShareExtension Enterprise.entitlements\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tINFOPLIST_FILE = \"ShareExtension/Info-Enterprise.plist\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@executable_path/../../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DAPPSTORE\",\n\t\t\t\t\t\"-DEXTENSION\",\n\t\t\t\t\t\"-DENTERPRISE\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.enterprise.ShareExtension;\n\t\t\t\tPRODUCT_NAME = \"ShareExtension Enterprise\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"App Store Enterprise ShareExtension\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = AppStore;\n\t\t};\n\t\t22DE05B318D8CA0800590FC3 /* 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\t22DE05B418D8CA0800590FC3 /* 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\t\t22DE05C218DB52D700590FC3 /* AppStore */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = NO;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Distribution\";\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tINFOPLIST_PREFIX_HEADER = IRCCloud/InfoPlist.h;\n\t\t\t\tINFOPLIST_PREPROCESS = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 12.0;\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DAPPSTORE\",\n\t\t\t\t);\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 = AppStore;\n\t\t};\n\t\t22DE05C318DB52D700590FC3 /* AppStore */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 26CA7871B88FD75900DEEA57 /* Pods-IRCCloud.appstore.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = IRCCloud/IRCCloud.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=macosx*]\" = \"Apple Distribution\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tINFOPLIST_FILE = \"IRCCloud/IRCCloud-Info.plist\";\n\t\t\t\tINFOPLIST_KEY_LSApplicationCategoryType = \"public.app-category.business\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(PROJECT_DIR)/IRCCloud\\\"\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.irccloud.${PRODUCT_NAME:rfc1034identifier}${BUNDLE_SUFFIX}\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"App Store\";\n\t\t\t\t\"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]\" = \"Catalyst IRCCloud\";\n\t\t\t\tSUPPORTS_MACCATALYST = YES;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = AppStore;\n\t\t};\n\t\t22DE05C518DB52D700590FC3 /* AppStore */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 1BBDF60D720CF290BFDB54FA /* Pods-IRCCloud Enterprise.appstore.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = IRCEnterprise.entitlements;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Distribution\";\n\t\t\t\tDEVELOPMENT_TEAM = GED45EQAGA;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREFIX_HEADER = \"IRCCloud/IRCCloud-Prefix.pch\";\n\t\t\t\tINFOPLIST_FILE = \"IRCCloud/IRCCloud-Enterprise-Info.plist\";\n\t\t\t\tINFOPLIST_PREPROCESSOR_DEFINITIONS = \"\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(PROJECT_DIR)/IRCCloud\\\"\",\n\t\t\t\t);\n\t\t\t\tOTHER_CFLAGS = (\n\t\t\t\t\t\"-DNS_BLOCK_ASSERTIONS=1\",\n\t\t\t\t\t\"-DAPPSTORE\",\n\t\t\t\t\t\"-DENTERPRISE\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-lstdc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.irccloud.enterprise;\n\t\t\t\tPRODUCT_NAME = IRCEnterprise;\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"App Store Enterprise\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = AppStore;\n\t\t};\n\t\t22DE05C618DB52D700590FC3 /* AppStore */ = {\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 = AppStore;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t221034F5197EFBAF00AB414F /* Build configuration list for PBXNativeTarget \"ShareExtension\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t221034F6197EFBAF00AB414F /* Debug */,\n\t\t\t\t221034F7197EFBAF00AB414F /* Release */,\n\t\t\t\t221034F8197EFBAF00AB414F /* AppStore */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t221D4B961E23EAD700D403E6 /* Build configuration list for PBXNativeTarget \"NotificationService\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t221D4B971E23EAD700D403E6 /* Debug */,\n\t\t\t\t221D4B981E23EAD700D403E6 /* Release */,\n\t\t\t\t221D4B991E23EAD700D403E6 /* AppStore */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t221D4B9F1E23EB4900D403E6 /* Build configuration list for PBXNativeTarget \"NotificationService Enterprise\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t221D4BA01E23EB4900D403E6 /* Debug */,\n\t\t\t\t221D4BA11E23EB4900D403E6 /* Release */,\n\t\t\t\t221D4BA21E23EB4900D403E6 /* AppStore */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t224589CE1DCA19BB00D3110A /* Build configuration list for PBXNativeTarget \"IRCCloudUnitTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t224589CB1DCA19BB00D3110A /* Debug */,\n\t\t\t\t224589CC1DCA19BB00D3110A /* Release */,\n\t\t\t\t224589CD1DCA19BB00D3110A /* AppStore */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t225D979C18AA995900065087 /* Build configuration list for PBXNativeTarget \"IRCCloud Enterprise\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t225D979D18AA995900065087 /* Debug */,\n\t\t\t\t225D979E18AA995900065087 /* Release */,\n\t\t\t\t22DE05C518DB52D700590FC3 /* AppStore */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t228A056716D3DABA0029769C /* Build configuration list for PBXProject \"IRCCloud\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t228A05A516D3DABB0029769C /* Debug */,\n\t\t\t\t228A05A616D3DABB0029769C /* Release */,\n\t\t\t\t22DE05C218DB52D700590FC3 /* AppStore */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t228A05A716D3DABB0029769C /* Build configuration list for PBXNativeTarget \"IRCCloud\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t228A05A816D3DABB0029769C /* Debug */,\n\t\t\t\t228A05A916D3DABB0029769C /* Release */,\n\t\t\t\t22DE05C318DB52D700590FC3 /* AppStore */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t22CE2AE61D2AA663001397C0 /* Build configuration list for PBXNativeTarget \"UITests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t22CE2AE31D2AA663001397C0 /* Debug */,\n\t\t\t\t22CE2AE41D2AA663001397C0 /* Release */,\n\t\t\t\t22CE2AE51D2AA663001397C0 /* AppStore */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t22D97897215BC910005C2713 /* Build configuration list for PBXNativeTarget \"IRCCloud FLEX\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t22D97898215BC910005C2713 /* Debug */,\n\t\t\t\t22D97899215BC910005C2713 /* Release */,\n\t\t\t\t22D9789A215BC910005C2713 /* AppStore */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t22DB25331982DF2B0008728E /* Build configuration list for PBXNativeTarget \"ShareExtension Enterprise\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t22DB25341982DF2B0008728E /* Debug */,\n\t\t\t\t22DB25351982DF2B0008728E /* Release */,\n\t\t\t\t22DB25361982DF2B0008728E /* AppStore */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t22DE05B218D8CA0800590FC3 /* Build configuration list for PBXAggregateTarget \"GitRevision\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t22DE05B318D8CA0800590FC3 /* Debug */,\n\t\t\t\t22DE05B418D8CA0800590FC3 /* Release */,\n\t\t\t\t22DE05C618DB52D700590FC3 /* AppStore */,\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 = 228A056416D3DABA0029769C /* Project object */;\n}\n"
  },
  {
    "path": "IRCCloud.xcodeproj/xcshareddata/xcschemes/IRCCloud Enterprise.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1400\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"225D973618AA995900065087\"\n               BuildableName = \"IRCEnterprise.app\"\n               BlueprintName = \"IRCCloud Enterprise\"\n               ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"225D973618AA995900065087\"\n            BuildableName = \"IRCEnterprise.app\"\n            BlueprintName = \"IRCCloud Enterprise\"\n            ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <Testables>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"225D973618AA995900065087\"\n            BuildableName = \"IRCEnterprise.app\"\n            BlueprintName = \"IRCCloud Enterprise\"\n            ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"225D973618AA995900065087\"\n            BuildableName = \"IRCEnterprise.app\"\n            BlueprintName = \"IRCCloud Enterprise\"\n            ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"AppStore\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "IRCCloud.xcodeproj/xcshareddata/xcschemes/IRCCloud Mock Data.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1400\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"228A056B16D3DABA0029769C\"\n               BuildableName = \"IRCCloud.app\"\n               BlueprintName = \"IRCCloud\"\n               ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"228A056B16D3DABA0029769C\"\n            BuildableName = \"IRCCloud.app\"\n            BlueprintName = \"IRCCloud\"\n            ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"22CE2ADB1D2AA659001397C0\"\n               BuildableName = \"UITests.xctest\"\n               BlueprintName = \"UITests\"\n               ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n         <TestableReference\n            skipped = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"224589C31DCA19BB00D3110A\"\n               BuildableName = \"IRCCloudUnitTests.xctest\"\n               BlueprintName = \"IRCCloudUnitTests\"\n               ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"228A056B16D3DABA0029769C\"\n            BuildableName = \"IRCCloud.app\"\n            BlueprintName = \"IRCCloud\"\n            ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <CommandLineArguments>\n         <CommandLineArgument\n            argument = \"-ui_testing\"\n            isEnabled = \"YES\">\n         </CommandLineArgument>\n         <CommandLineArgument\n            argument = \"-memberlist\"\n            isEnabled = \"NO\">\n         </CommandLineArgument>\n         <CommandLineArgument\n            argument = \"-theme ash\"\n            isEnabled = \"NO\">\n         </CommandLineArgument>\n         <CommandLineArgument\n            argument = \"-theme dusk\"\n            isEnabled = \"YES\">\n         </CommandLineArgument>\n         <CommandLineArgument\n            argument = \"-mono\"\n            isEnabled = \"NO\">\n         </CommandLineArgument>\n      </CommandLineArguments>\n      <EnvironmentVariables>\n         <EnvironmentVariable\n            key = \"CA_DEBUG_TRANSACTIONS\"\n            value = \"1\"\n            isEnabled = \"YES\">\n         </EnvironmentVariable>\n      </EnvironmentVariables>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Debug\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"/Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/Resources/templates/Time Profiler.tracetemplate\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"228A056B16D3DABA0029769C\"\n            BuildableName = \"IRCCloud.app\"\n            BlueprintName = \"IRCCloud\"\n            ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"NO\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "IRCCloud.xcodeproj/xcshareddata/xcschemes/IRCCloud.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1400\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"228A056B16D3DABA0029769C\"\n               BuildableName = \"IRCCloud.app\"\n               BlueprintName = \"IRCCloud\"\n               ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"22CE2ADB1D2AA659001397C0\"\n               BuildableName = \"UITests.xctest\"\n               BlueprintName = \"UITests\"\n               ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"224589C31DCA19BB00D3110A\"\n               BuildableName = \"IRCCloudUnitTests.xctest\"\n               BlueprintName = \"IRCCloudUnitTests\"\n               ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"228A056B16D3DABA0029769C\"\n            BuildableName = \"IRCCloud.app\"\n            BlueprintName = \"IRCCloud\"\n            ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <CommandLineArguments>\n         <CommandLineArgument\n            argument = \"-FIRDebugEnabled\"\n            isEnabled = \"YES\">\n         </CommandLineArgument>\n      </CommandLineArguments>\n      <EnvironmentVariables>\n         <EnvironmentVariable\n            key = \"CA_DEBUG_TRANSACTIONS\"\n            value = \"1\"\n            isEnabled = \"YES\">\n         </EnvironmentVariable>\n      </EnvironmentVariables>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Debug\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"/Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/Resources/templates/Time Profiler.tracetemplate\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"228A056B16D3DABA0029769C\"\n            BuildableName = \"IRCCloud.app\"\n            BlueprintName = \"IRCCloud\"\n            ReferencedContainer = \"container:IRCCloud.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"AppStore\"\n      revealArchiveInOrganizer = \"NO\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "IRCCloudUnitTests/CollapsedEventsTests.m",
    "content": "//\n//  CollapsedEventsTests.m\n//  IRCCloudUnitTests\n//\n//  Created by Sam Steele on 11/2/16.\n//  Copyright © 2016 IRCCloud, Ltd. All rights reserved.\n//\n\n#import <XCTest/XCTest.h>\n#import \"ServersDataSource.h\"\n#import \"EventsDataSource.h\"\n#import \"CollapsedEvents.h\"\n#import \"ColorFormatter.h\"\n\n#define AssertEvents(expectedResult) XCTAssert([[_events.collapse stripIRCFormatting] isEqualToString:expectedResult], \"Unexpected result: %@\", [_events.collapse stripIRCFormatting]);\n\n@interface CollapsedEventsTests : XCTestCase {\n    CollapsedEvents *_events;\n    NSTimeInterval _eid;\n}\n\n@end\n\n@implementation CollapsedEventsTests\n\n- (void)setUp {\n    [super setUp];\n    _events = [CollapsedEvents new];\n    [_events setServer:nil];\n    _events.showChan = NO;\n    self.continueAfterFailure = YES;\n}\n\n- (void)tearDown {\n    [_events clear];\n    [super tearDown];\n}\n\n- (void)addMode:(NSString *)mode nick:(NSString *)nick from:(NSString *)from channel:(NSString *)channel {\n    Event *e = [Event new];\n    e.eid = _eid++;\n    e.type = @\"user_channel_mode\";\n    e.from = from;\n    e.fromMode = @\"q\";\n    e.nick = nick;\n    e.targetMode = mode;\n    e.server = @\"irc.example.net\";\n    e.chan = channel;\n    e.ops = @{@\"add\":@[@{@\"param\":nick, @\"mode\": mode}], @\"remove\":@[]};\n    \n    [_events addEvent:e];\n}\n\n- (void)removeMode:(NSString *)mode nick:(NSString *)nick from:(NSString *)from channel:(NSString *)channel {\n    Event *e = [Event new];\n    e.eid = _eid++;\n    e.type = @\"user_channel_mode\";\n    e.from = from;\n    e.fromMode = @\"q\";\n    e.nick = nick;\n    e.targetMode = mode;\n    e.server = @\"irc.example.net\";\n    e.chan = channel;\n    e.ops = @{@\"remove\":@[@{@\"param\":nick, @\"mode\": mode}], @\"add\":@[]};\n    \n    [_events addEvent:e];\n}\n\n- (void)join:(NSString *)channel nick:(NSString *)nick hostmask:(NSString *)hostmask {\n    Event *e = [Event new];\n    e.eid = _eid++;\n    e.type = @\"joined_channel\";\n    e.nick = nick;\n    e.hostmask = hostmask;\n    e.server = @\"irc.example.net\";\n    e.chan = channel;\n    \n    [_events addEvent:e];\n}\n\n- (void)part:(NSString *)channel nick:(NSString *)nick hostmask:(NSString *)hostmask {\n    Event *e = [Event new];\n    e.eid = _eid++;\n    e.type = @\"parted_channel\";\n    e.nick = nick;\n    e.hostmask = hostmask;\n    e.server = @\"irc.example.net\";\n    e.chan = channel;\n    \n    [_events addEvent:e];\n}\n\n- (void)quit:(NSString *)message nick:(NSString *)nick hostmask:(NSString *)hostmask {\n    Event *e = [Event new];\n    e.eid = _eid++;\n    e.type = @\"quit\";\n    e.nick = nick;\n    e.hostmask = hostmask;\n    e.server = @\"irc.example.net\";\n    e.msg = message;\n    \n    [_events addEvent:e];\n}\n\n- (void)nickChange:(NSString *)nick oldNick:(NSString *)oldNick hostmask:(NSString *)hostmask {\n    Event *e = [Event new];\n    e.eid = _eid++;\n    e.type = @\"nickchange\";\n    e.nick = nick;\n    e.oldNick = oldNick;\n    e.hostmask = hostmask;\n    e.server = @\"irc.example.net\";\n    \n    [_events addEvent:e];\n}\n\n- (void)testOper1 {\n    [self addMode:@\"Y\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"• sam was promoted to oper (+Y) by • ChanServ\");\n}\n\n- (void)testOper2 {\n    [self addMode:@\"y\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"• sam was promoted to oper (+y) by • ChanServ\");\n}\n\n- (void)testOwner1 {\n    [self addMode:@\"q\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"• sam was promoted to owner (+q) by • ChanServ\");\n}\n\n- (void)testOwner2 {\n    Server *s = [Server new];\n    s.MODE_OPER = @\"\";\n    s.MODE_OWNER = @\"y\";\n    [_events setServer:s];\n    [self addMode:@\"y\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"• sam was promoted to owner (+y) by • ChanServ\");\n}\n\n- (void)testOp {\n    [self addMode:@\"o\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"• sam was opped (+o) by • ChanServ\");\n}\n\n- (void)testDeop {\n    [self removeMode:@\"o\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"• sam was de-opped (-o) by • ChanServ\");\n}\n\n- (void)testVoice {\n    [self addMode:@\"v\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"• sam was voiced (+v) by • ChanServ\");\n}\n\n- (void)testDevoice {\n    [self removeMode:@\"v\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"• sam was de-voiced (-v) by • ChanServ\");\n}\n\n- (void)testOpByServer {\n    [self addMode:@\"o\" nick:@\"sam\" from:nil channel:@\"#test\"];\n    AssertEvents(@\"• sam was opped (+o) by the server irc.example.net\");\n}\n\n- (void)testOpDeop {\n    [self addMode:@\"o\" nick:@\"sam\" from:@\"james\" channel:@\"#test\"];\n    [self removeMode:@\"o\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"• sam was de-opped (-o) by • ChanServ\");\n}\n\n- (void)testJoin {\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"→︎ sam joined (sam@example.net)\");\n}\n\n- (void)testPart {\n    [self part:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"←︎ sam left (sam@example.net)\");\n}\n\n- (void)testQuit {\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"⇐︎ sam quit (sam@example.net): Leaving\");\n}\n\n- (void)testQuit2 {\n    [self quit:@\"*.net *.split\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"⇐︎ sam quit (sam@example.net): *.net *.split\");\n}\n\n- (void)testNickChange {\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"sam_ →︎ sam\");\n}\n\n- (void)testNickChangeQuit {\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"⇐︎ sam (was sam_) quit (sam@example.net): Leaving\");\n}\n\n- (void)testJoinQuit {\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam popped in\");\n}\n\n- (void)testJoinQuitJoin {\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"→︎ sam joined (sam@example.net)\");\n}\n\n- (void)testJoinJoin {\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"james\" hostmask:@\"james@example.net\"];\n    AssertEvents(@\"→︎ sam and james joined\");\n}\n\n- (void)testJoinQuit2 {\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"james\" hostmask:@\"james@example.net\"];\n    AssertEvents(@\"→︎ sam joined ⇐︎ james quit\");\n}\n\n- (void)testJoinPart {\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self part:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam popped in\");\n}\n\n- (void)testJoinPart2 {\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self part:@\"#test\" nick:@\"james\" hostmask:@\"james@example.net\"];\n    AssertEvents(@\"→︎ sam joined ←︎ james left\");\n}\n\n- (void)testQuitJoin {\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam nipped out\");\n}\n\n- (void)testPartJoin {\n    [self part:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam nipped out\");\n}\n\n- (void)testJoinNickchange {\n    [self join:@\"#test\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"→︎ sam (was sam_) joined (sam@example.net)\");\n}\n\n- (void)testQuitJoinNickchange {\n    [self quit:@\"Leaving\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam (was sam_) nipped out\");\n}\n\n- (void)testQuitJoinNickchange2 {\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam nipped out\");\n}\n\n- (void)testQuitJoinMode {\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self addMode:@\"o\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"↔︎ • sam (opped) nipped out\");\n}\n\n- (void)testQuitJoinModeNickPart {\n    [self quit:@\"Leaving\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self addMode:@\"o\" nick:@\"sam_\" from:@\"ChanServ\" channel:@\"#test\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self part:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"←︎ • sam (was sam_; opped) left\");\n}\n\n- (void)testNickchangeNickchange {\n    [self nickChange:@\"james\" oldNick:@\"james_old\" hostmask:@\"james@example.net\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"james_old →︎ james, sam_ →︎ sam\");\n}\n\n- (void)testJoinQuitNickchange {\n    [self join:@\"#test\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam (was sam_) nipped out\");\n}\n\n- (void)testJoinQuitNickchange2 {\n    [self join:@\"#test\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test\" nick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam (was sam_) nipped out\");\n}\n\n- (void)testModeMode {\n    [self addMode:@\"v\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    [self addMode:@\"o\" nick:@\"james\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"mode: • sam (voiced) and • james (opped)\");\n}\n\n- (void)testModeMode2 {\n    [self addMode:@\"o\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    [self addMode:@\"v\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"mode: • sam (opped, voiced)\");\n}\n\n- (void)testModeNickchange {\n    [self addMode:@\"o\" nick:@\"james\" from:@\"ChanServ\" channel:@\"#test\"];\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"mode: • james (opped) • sam_ →︎ sam\");\n}\n\n- (void)testJoinMode {\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self addMode:@\"o\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"→︎ • sam (opped) joined\");\n}\n\n- (void)testJoinModeMode {\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self addMode:@\"o\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    [self addMode:@\"q\" nick:@\"sam\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"→︎ • sam (promoted to owner, opped) joined\");\n}\n\n- (void)testModeJoinPart {\n    [self addMode:@\"o\" nick:@\"james\" from:@\"ChanServ\" channel:@\"#test\"];\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self part:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"mode: • james (opped) ↔︎ sam popped in\");\n}\n\n- (void)testJoinNickchangeModeModeMode {\n    [self join:@\"#test\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self nickChange:@\"james\" oldNick:@\"james_old\" hostmask:@\"james@example.net\"];\n    [self removeMode:@\"o\" nick:@\"james\" from:@\"ChanServ\" channel:@\"#test\"];\n    [self addMode:@\"v\" nick:@\"RJ\" from:@\"ChanServ\" channel:@\"#test\"];\n    [self addMode:@\"v\" nick:@\"james\" from:@\"ChanServ\" channel:@\"#test\"];\n    AssertEvents(@\"→︎ sam joined • mode: • RJ (voiced) • james_old →︎ • james (voiced, de-opped)\");\n}\n\n- (void)testMultiChannelJoin {\n    _events.showChan = YES;\n    [self join:@\"#test1\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test2\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test3\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"→︎ sam joined #test1, #test2, and #test3\");\n}\n\n- (void)testMultiChannelNickChangeQuitJoin {\n    _events.showChan = YES;\n    [self nickChange:@\"sam\" oldNick:@\"sam_\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test1\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test2\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test1\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test2\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test1\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test2\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam (was sam_) nipped out #test1 and #test2\");\n}\n\n- (void)testMultiChannelPopIn1 {\n    _events.showChan = YES;\n    [self join:@\"#test1\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test2\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test3\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self part:@\"#test1\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self part:@\"#test2\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"→︎ sam joined #test3 ↔︎ sam popped in #test1 and #test2\");\n}\n\n- (void)testMultiChannelPopIn2 {\n    _events.showChan = YES;\n    [self join:@\"#test1\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test2\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test3\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam popped in #test1, #test2, and #test3\");\n}\n\n- (void)testMultiChannelQuit {\n    _events.showChan = YES;\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test1\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"⇐︎ sam quit (sam@example.net): Leaving\");\n}\n\n- (void)testMultiChannelQuitJoin {\n    _events.showChan = YES;\n    [self quit:@\"Leaving\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test1\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self join:@\"#test2\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"↔︎ sam nipped out #test1 and #test2\");\n}\n\n- (void)testNetSplit {\n    [self quit:@\"irc.example.net irc2.example.net\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    [self quit:@\"irc.example.net irc2.example.net\" nick:@\"james\" hostmask:@\"james@example.net\"];\n    [self quit:@\"irc3.example.net irc2.example.net\" nick:@\"RJ\" hostmask:@\"RJ@example.net\"];\n    [self quit:@\"fake.net fake.net\" nick:@\"russ\" hostmask:@\"russ@example.net\"];\n    [self join:@\"#test1\" nick:@\"sam\" hostmask:@\"sam@example.net\"];\n    AssertEvents(@\"irc.example.net ↮︎ irc2.example.net and irc3.example.net ↮︎ irc2.example.net ⇐︎ james, RJ, and russ quit ↔︎ sam nipped out\");\n}\n\n- (void)testChanServJoin {\n    [self join:@\"#test\" nick:@\"ChanServ\" hostmask:@\"ChanServ@services.\"];\n    [self addMode:@\"o\" nick:@\"ChanServ\" from:nil channel:@\"#test\"];\n    AssertEvents(@\"→︎ • ChanServ (opped) joined\");\n}\n\n@end\n"
  },
  {
    "path": "IRCCloudUnitTests/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>$(PRODUCT_BUNDLE_IDENTIFIER)</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>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>VERSION_STRING</string>\n\t<key>CFBundleVersion</key>\n\t<string>GIT_VERSION</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "IRCCloudUnitTests/MessageTypeTests.m",
    "content": "//\n//  MessageTypeTests.m\n//  IRCCloudUnitTests\n//\n//  Created by Sam Steele on 8/16/17.\n//  Copyright © 2017 IRCCloud, Ltd. All rights reserved.\n//\n\n#import <XCTest/XCTest.h>\n#import \"NetworkConnection.h\"\n\n@interface MessageTypeTests : XCTestCase\n\n@end\n\n@implementation MessageTypeTests\n\n- (void)checkTypes:(NSArray *)types {\n    NSDictionary *map = [NetworkConnection sharedInstance].parserMap;\n    \n    for(NSString *type in types) {\n        XCTAssertTrue([map objectForKey:type], @\"Missing handler for message type: %@\", type);\n    }\n}\n\n- (void)testTypes1 {\n    //JSON.stringify(Object.keys(cbv().scroll.log.lineRenderer.messageHandlers))\n    NSArray *types = @[@\"channel_topic\",@\"buffer_msg\",@\"newsflash\",@\"invited\",@\"channel_invite\",@\"callerid\",@\"buffer_me_msg\",@\"twitch_hosttarget_start\",@\"twitch_hosttarget_stop\",@\"twitch_usernotice\",@\"your_unique_id\",@\"server_welcome\",@\"server_yourhost\",@\"server_created\",@\"myinfo\",@\"version\",@\"server_luserclient\",@\"server_luserop\",@\"server_luserunknown\",@\"server_luserchannels\",@\"server_luserconns\",@\"server_luserme\",@\"server_n_global\",@\"server_n_local\",@\"server_snomask\",@\"self_details\",@\"hidden_host_set\",@\"codepage\",@\"logged_in_as\",@\"logged_out\",@\"nick_locked\",@\"server_motdstart\",@\"server_motd\",@\"server_endofmotd\",@\"server_nomotd\",@\"motd_response\",@\"info_response\",@\"generic_server_info\",@\"error\",@\"unknown_umode\",@\"notice\",@\"wallops\",@\"too_fast\",@\"no_bots\",@\"bad_ping\",@\"nickname_in_use\",@\"invalid_nick_change\",@\"save_nick\",@\"nick_collision\",@\"bad_channel_mask\",@\"you_are_operator\",@\"sasl_success\",@\"sasl_fail\",@\"sasl_too_long\",@\"sasl_aborted\",@\"sasl_already\",@\"cap_ls\",@\"cap_list\",@\"cap_new\",@\"cap_del\",@\"cap_req\",@\"cap_ack\",@\"cap_nak\",@\"cap_raw\",@\"cap_invalid\",@\"rehashed_config\",@\"inviting_to_channel\",@\"invite_notify\",@\"user_chghost\",@\"channel_name_change\",@\"knock\",@\"kill_deny\",@\"chan_own_priv_needed\",@\"not_for_halfops\",@\"link_channel\",@\"chan_forbidden\",@\"joined_channel\",@\"you_joined_channel\",@\"parted_channel\",@\"you_parted_channel\",@\"kicked_channel\",@\"you_kicked_channel\",@\"quit\",@\"quit_server\",@\"kill\",@\"banned\",@\"socket_closed\",@\"connecting_failed\",@\"connecting_cancelled\",@\"wait\",@\"starircd_welcome\",@\"nickchange\",@\"you_nickchange\",@\"channel_mode_list_change\",@\"user_channel_mode\",@\"user_mode\",@\"channel_mode\",@\"channel_mode_is\",@\"channel_url\",@\"zurna_motd\",@\"loaded_module\",@\"unloaded_module\",@\"unhandled_line\",@\"unparsed_line\",@\"msg_services\",@\"ambiguous_error_message\",@\"list_usage\",@\"list_syntax\",@\"who_syntax\",@\"services_down\",@\"help_topics_start\",@\"help_topics\",@\"help_topics_end\",@\"helphdr\",@\"helpop\",@\"helptlr\",@\"helphlp\",@\"helpfwd\",@\"helpign\",@\"stats\",@\"statslinkinfo\",@\"statscommands\",@\"statscline\",@\"statsnline\",@\"statsiline\",@\"statskline\",@\"statsqline\",@\"statsyline\",@\"endofstats\",@\"statsbline\",@\"statsgline\",@\"statstline\",@\"statseline\",@\"statsvline\",@\"statslline\",@\"statsuptime\",@\"statsoline\",@\"statshline\",@\"statssline\",@\"statsuline\",@\"statsdebug\",@\"spamfilter\",@\"text\",@\"target_callerid\",@\"target_notified\",@\"time\",@\"admin_info\",@\"watch_status\",@\"sqline_nick\"];\n    \n    [self checkTypes:types];\n}\n\n- (void)testTypes2 {\n    //BufferOverlayHandler.js\n    NSArray *types = @[@\"who_response\",@\"who_special_response\",@\"whowas_response\",@\"whois_response\",@\"ignore_list\",@\"monitor_list\",@\"a_list\",@\"quiet_list\",@\"invited_list\",@\"invite_list\",@\"q_list\",@\"ircops\",@\"ban_list\",@\"modules_list\",@\"ban_exception_list\",@\"accept_list\",@\"map_list\",@\"silence_list\",@\"links_response\",@\"query_too_long\",@\"input_too_long\",@\"try_again\",@\"list_response_fetching\",@\"list_response_toomany\",@\"list_response\",@\"remote_isupport_params\",@\"names_reply\",@\"notice\",@\"services_down\",@\"time\",@\"ison\",@\"trace_response\",@\"monitor_offline\",@\"monitor_online\",@\"watch_status\",@\"channel_query\",@\"userhost\",@\"channel_invite\"];\n\n    [self checkTypes:types];\n}\n\n- (void)testTypes3 {\n    //ConnectionPromptHandler.js\n    NSArray *types = @[@\"invalid_nick\",@\"no_such_channel\",@\"no_such_nick\",@\"bad_channel_key\",@\"bad_channel_name\",@\"need_registered_nick\",@\"blocked_channel\",@\"invite_only_chan\",@\"channel_full\",@\"channel_key_set\",@\"banned_from_channel\",@\"oper_only\",@\"invalid_nick_change\",@\"nickname_in_use\",@\"no_nick_change\",@\"no_messages_from_non_registered\",@\"not_registered\",@\"already_registered\",@\"too_many_channels\",@\"too_many_targets\",@\"no_such_server\",@\"unknown_command\",@\"unknown_error\",@\"help_not_found\",@\"accept_full\",@\"accept_exists\",@\"accept_not\",@\"nick_collision\",@\"nick_too_fast\",@\"save_nick\",@\"unknown_mode\",@\"user_not_in_channel\",@\"need_more_params\",@\"users_dont_match\",@\"chan_privs_needed\",@\"channame_in_use\",@\"users_disabled\",@\"invalid_operator_password\",@\"flood_warning\",@\"privs_needed\",@\"operator_fail\",@\"not_on_channel\",@\"ban_on_chan\",@\"cannot_send_to_chan\",@\"user_on_channel\",@\"pong\",@\"no_nick_given\",@\"no_text_to_send\",@\"no_origin\",@\"only_servers_can_change_mode\",@\"not_for_halfops\",@\"silence\",@\"monitor_full\",@\"no_channel_topic\",@\"channel_topic_is\",@\"mlock_restricted\",@\"cannot_do_cmd\",@\"secure_only_chan\",@\"cannot_change_chan_mode\",@\"knock_delivered\",@\"too_many_knocks\",@\"chan_open\",@\"knock_on_chan\",@\"knock_disabled\",@\"cannotknock\",@\"ownmode\",@\"nossl\",@\"link_channel\",@\"redirect_error\",@\"invalid_flood\",@\"join_flood\",@\"metadata_limit\",@\"metadata_targetinvalid\",@\"metadata_nomatchingkey\",@\"metadata_keyinvalid\",@\"metadata_keynotset\",@\"metadata_keynopermission\",@\"metadata_toomanysubs\"];\n\n    [self checkTypes:types];\n}\n@end\n"
  },
  {
    "path": "IRCCloudUnitTests/URLtoBIDTests.m",
    "content": "//\n//  URLtoBIDTests.m\n//  IRCCloud\n//\n//  Created by Sam Steele on 4/27/17.\n//  Copyright © 2017 IRCCloud, Ltd. All rights reserved.\n//\n\n#import <XCTest/XCTest.h>\n#import \"ServersDataSource.h\"\n#import \"BuffersDataSource.h\"\n#import \"URLHandler.h\"\n\n@interface URLtoBIDTests : XCTestCase\n\n@end\n\n@implementation URLtoBIDTests\n\n- (void)setUp {\n    [super setUp];\n    \n    Server *s = [[Server alloc] init];\n    s.hostname = @\"irc.irccloud.com\";\n    s.port = 6667;\n    s.name = @\"IRCCloud\";\n    s.cid = 1;\n    s.isupport = @{\n                   @\"AWAYLEN\": @(200),\n                   @\"CALLERID\": @(1),\n                   @\"CASEMAPPING\": @\"ascii\",\n                   @\"CHANMODES\": @\"IZbegw,k,FJLdfjl,ACKMNORSTcimnprstz\",\n                   @\"CHANNELLEN\": @(64),\n                   @\"CHANTYPES\": @\"#\",\n                   @\"CHARSET\": @\"ascii\",\n                   @\"ELIST\": @\"MU\",\n                   @\"ESILENCE\": @(1),\n                   @\"EXCEPTS\": @\"e\",\n                   @\"FNC\": @(1),\n                   @\"INVEX\": @\"I\",\n                   @\"KICKLEN\": @(255),\n                   @\"MAP\": @(1),\n                   @\"MAXBANS\": @(60),\n                   @\"MAXCHANNELS\": @(20),\n                   @\"MAXPARA\": @(32),\n                   @\"MAXTARGETS\": @(20),\n                   @\"MODES\": @(20),\n                   @\"NAMESX\": @(1),\n                   @\"NETWORK\": @\"IRCCloud\",\n                   @\"NICKLEN\": @(32),\n                   @\"OVERRIDE\": @(1),\n                   @\"PREFIX\": @{@\"Y\": @\"!\", @\"h\": @\"%\", @\"o\": @\"@\", @\"v\": @\"+\"},\n                   @\"REMOVE\": @(1),\n                   @\"SILENCE\": @(32),\n                   @\"SSL\": @\"[::]:6697\",\n                   @\"STATUSMSG\": @\"!@%+\",\n                   @\"TOPICLEN\": @(307),\n                   @\"UHNAMES\": @(1),\n                   @\"USERIP\": @(1),\n                   @\"VBANLIST\": @(1),\n                   @\"WALLCHOPS\": @(1),\n                   @\"WALLVOICES\": @(1),\n                   @\"WATCH\": @(32),\n                   }.mutableCopy;\n    \n    [[ServersDataSource sharedInstance] addServer:s];\n    \n    Buffer *b = [[Buffer alloc] init];\n    b.cid = 1;\n    b.bid = 1;\n    b.type = @\"channel\";\n    b.name = @\"#feedback\";\n    \n    [[BuffersDataSource sharedInstance] addBuffer:b];\n\n    b = [[Buffer alloc] init];\n    b.cid = 1;\n    b.bid = 2;\n    b.type = @\"conversation\";\n    b.name = @\"sam\";\n    \n    [[BuffersDataSource sharedInstance] addBuffer:b];\n\n    b = [[Buffer alloc] init];\n    b.cid = 1;\n    b.bid = 3;\n    b.type = @\"channel\";\n    b.name = @\"##test\";\n    \n    [[BuffersDataSource sharedInstance] addBuffer:b];\n}\n\n- (void)tearDown {\n    [super tearDown];\n    [[ServersDataSource sharedInstance] clear];\n    [[BuffersDataSource sharedInstance] clear];\n}\n\n- (void)testURLs {\n    XCTAssertEqual(-1, [URLHandler URLtoBID:[NSURL URLWithString:@\"https://www.irccloud.com/irc/irccloud.com/channel/vip\"]]);\n    XCTAssertEqual(-1, [URLHandler URLtoBID:[NSURL URLWithString:@\"https://www.irccloud.com/irc/irccloud.com/channel/test\"]]);\n    XCTAssertEqual(1, [URLHandler URLtoBID:[NSURL URLWithString:@\"https://www.irccloud.com/irc/irccloud.com/channel/feedback\"]]);\n    XCTAssertEqual(2, [URLHandler URLtoBID:[NSURL URLWithString:@\"https://www.irccloud.com/irc/irccloud.com/messages/sam\"]]);\n    XCTAssertEqual(3, [URLHandler URLtoBID:[NSURL URLWithString:@\"https://www.irccloud.com/irc/irccloud.com/channel/%23%23test\"]]);\n}\n\n@end\n"
  },
  {
    "path": "IRCEnterprise.entitlements",
    "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>aps-environment</key>\n\t<string>production</string>\n\t<key>com.apple.developer.icloud-container-identifiers</key>\n\t<array>\n\t\t<string>iCloud.com.irccloud.enterprise.public</string>\n\t</array>\n\t<key>com.apple.developer.icloud-services</key>\n\t<array>\n\t\t<string>CloudDocuments</string>\n\t\t<string>CloudKit</string>\n\t</array>\n\t<key>com.apple.developer.ubiquity-container-identifiers</key>\n\t<array>\n\t\t<string>iCloud.com.irccloud.enterprise.public</string>\n\t</array>\n\t<key>com.apple.developer.ubiquity-kvstore-identifier</key>\n\t<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>\n\t<key>com.apple.security.application-groups</key>\n\t<array>\n\t\t<string>group.com.irccloud.enterprise.share</string>\n\t</array>\n\t<key>keychain-access-groups</key>\n\t<array>\n\t\t<string>$(AppIdentifierPrefix)com.irccloud.enterprise</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\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"
  },
  {
    "path": "NSURL+IDN/NSURL+IDN.h",
    "content": "//\n// NSURL+IDN.h\n//\n// Created by Jorge Bernal on 4/8/11.\n// Adapted from OmniNetworking framework\n//\n// Copyright 1997-2005 Omni Development, Inc.  All rights reserved.\n//\n// This software may only be used and reproduced according to the\n// terms in the file OmniSourceLicense.html, which should be\n// distributed with this project and can also be found at\n// <http://www.omnigroup.com/developer/sourcecode/sourcelicense/>.\n\n#import <Foundation/Foundation.h>\n\n@interface NSURL (IDN)\n+ (NSString *)IDNEncodedHostname:(NSString *)aHostname;\n+ (NSString *)IDNDecodedHostname:(NSString *)anIDNHostname;\n+ (NSString *)IDNEncodedURL:(NSString *)aURL;\n+ (NSString *)IDNDecodedURL:(NSString *)anIDNURL;\n@end\n"
  },
  {
    "path": "NSURL+IDN/NSURL+IDN.m",
    "content": "//\n// NSURL+IDN.m\n//\n// Created by Jorge Bernal on 4/8/11.\n// Adapted from OmniNetworking framework\n//\n// Copyright 1997-2005 Omni Development, Inc.  All rights reserved.\n//\n// This software may only be used and reproduced according to the\n// terms in the file OmniSourceLicense.html, which should be\n// distributed with this project and can also be found at\n// <http://www.omnigroup.com/developer/sourcecode/sourcelicense/>.\n\n#import \"NSURL+IDN.h\"\n\n#ifndef MAX_HOSTNAME_LEN\n#ifdef NI_MAXHOST\n#define MAX_HOSTNAME_LEN NI_MAXHOST\n#else\n#define MAX_HOSTNAME_LEN 1024\n#endif\n#endif\n\n@implementation NSURL (IDN)\n\n// Punycode is defined in RFC 3492\n\n#define ACEPrefix @\"xn--\"   // Prefix for encoded labels, defined in RFC3490 [5]\n\n#define encode_character(c) (c) < 26 ? (c) + 'a' : (c) - 26 + '0'\n\nstatic const short punycodeDigitValue[0x7B] = {\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00 - 0x0F\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10 - 0x1F\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x20 - 0x2F\n    26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, // 0x30 - 0x3F\n    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, // 0x40 - 0x4F\n    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 0x50 - 0x5F\n    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, // 0x60 - 0x6F\n    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25                      // 0x70 - 0x7A\n};\n\n\nstatic int adaptPunycodeDelta(int delta, int number, BOOL firstTime)\n{\n    int power;\n    \n    delta = firstTime ? delta / 700 : delta / 2;\n    delta += delta / number;\n    \n    for (power = 0; delta > (35 * 26) / 2; power += 36)\n        delta /= 35;\n    return power + (35 + 1) * delta / (delta + 38);\n}\n\n/* Minimal validity checking. This should be elaborated to include the full IDN stringprep profile. */\nstatic BOOL validIDNCodeValue(unsigned codepoint)\n{\n    /* Valid Unicode, non-basic codepoint? (implied by rfc3492) */\n    if (codepoint < 0x9F || codepoint > 0x10FFFF)\n        return NO;\n    \n    /* Some prohibited values from rfc3454 referenced by rfc3491[5] */\n    if (codepoint == 0x00A0 ||\n        (codepoint >= 0x2000 && codepoint <= 0x200D) ||\n        codepoint == 0x202F || codepoint == 0xFEFF ||\n        ( codepoint >= 0xFFF9 && codepoint <= 0xFFFF ))\n        return NO; /* Miscellaneous whitespace & non-printing characters */\n    \n    int plane = ( codepoint & ~(0xFFFF) );\n    \n    if (plane == 0x0F0000 || plane == 0x100000 ||\n        (codepoint >= 0xE000 && codepoint <= 0xF8FF))\n        return NO;  /* Private use areas */\n    \n    if ((codepoint & 0xFFFE) == 0xFFFE ||\n        (codepoint >= 0xD800 && codepoint <= 0xDFFF) ||\n        (codepoint >= 0xFDD0 && codepoint <= 0xFDEF))\n        return NO; /* Various non-character code points */\n    \n    /* end of gauntlet */\n    return YES;\n}\n\n+ (NSString *)_punycodeEncode:(NSString *)aString;\n{\n    // setup buffers\n    char outputBuffer[MAX_HOSTNAME_LEN]; \n    size_t stringLength = [aString length];\n    unichar *inputBuffer = alloca(stringLength * sizeof(unichar));\n    unichar *inputPtr, *inputEnd = inputBuffer + stringLength;\n    char *outputEnd = outputBuffer + MAX_HOSTNAME_LEN;\n    char *outputPtr = outputBuffer;\n    \n    // check once for hostname too long here and just refuse to encode if it is (this handles it if all ASCII)\n    // there are additional checks for running over the buffer during the encoding loop\n    if (stringLength > MAX_HOSTNAME_LEN)\n        return aString;\n    \n    [aString getCharacters:inputBuffer];\n    \n    // handle ASCII characters\n    for (inputPtr = inputBuffer; inputPtr < inputEnd; inputPtr++) {\n        if (*inputPtr < 0x80) \n            *outputPtr++ = *inputPtr;            \n    }\n    unsigned int handled = (unsigned int)(outputPtr - outputBuffer);\n    \n    if (handled == stringLength)\n        return aString;\n    \n    // add dash separator\n    if (handled > 0 && outputPtr < outputEnd)\n        *outputPtr++ = '-';\n    \n    // encode the rest\n    int n = 0x80;\n    int delta = 0;\n    int bias = 72;\n    BOOL firstTime = YES;\n    \n    while (handled < stringLength) {\n        unichar max = (unichar)-1;\n        for (inputPtr = inputBuffer; inputPtr < inputEnd; inputPtr++) {\n            if (*inputPtr >= n && *inputPtr < max)\n                max = *inputPtr;\n        }\n        \n        delta += (max - n) * (handled + 1);\n        n = max;\n        \n        for (inputPtr = inputBuffer; inputPtr < inputEnd; inputPtr++) {\n            if (*inputPtr < n) \n                delta++;\n            else if (*inputPtr == n) {\n                int oldDelta = delta;\n                int power = 36;\n                \n                // NSLog(@\"encode: delta=%d pos=%d bias=%d codepoint=%05x\", delta, inputPtr-inputBuffer, bias, *inputPtr);\n                \n                while (1) {\n                    int t;\n                    if (power <= bias)\n                        t = 1;\n                    else if (power >= bias + 26)\n                        t = 26;\n                    else\n                        t = power - bias;\n                    if (delta < t)\n                        break;\n                    if (outputPtr >= outputEnd)\n                        return aString;\n                    *outputPtr++ = encode_character(t + (delta - t) % (36 - t));\n                    delta = (delta - t) / (36 - t);\n                    power += 36;\n                }\n                \n                if (outputPtr >= outputEnd)\n                    return aString;\n                *outputPtr++ = encode_character(delta);\n                bias = adaptPunycodeDelta(oldDelta, ++handled, firstTime);\n                firstTime = NO;\n                delta = 0;\n            }\n        }\n        delta++;\n        n++;\n    }\n    if (outputPtr >= outputEnd)\n        return aString;\n    *outputPtr = '\\0';\n#ifdef DEBUG_toon    \n    NSLog(@\"Punycode encoded \\\"%@\\\" into \\\"%s\\\"\", aString, outputBuffer);\n#endif    \n    return [ACEPrefix stringByAppendingString:[NSString stringWithUTF8String:outputBuffer]];\n}\n\n+ (NSString *)_punycodeDecode:(NSString *)aString;\n{\n    unsigned int *delta;\n    {\n        NSMutableString *decoded;\n        NSRange deltas;\n        unsigned deltaCount, deltaIndex;\n        NSUInteger labelLength;\n        const unsigned acePrefixLength = 4;\n        \n        /* Check that the string has the IDNA ACE prefix. Most strings won't. */\n        labelLength = [aString length];\n        if (labelLength < acePrefixLength ||\n            ([aString compare:ACEPrefix options:NSCaseInsensitiveSearch range:(NSRange){0,acePrefixLength}] != NSOrderedSame))\n            return aString;\n        \n        /* Also, any valid encoded string will be all-ASCII */\n        if (![aString canBeConvertedToEncoding:NSASCIIStringEncoding])\n            return aString;\n        \n        /* Find the delimiter that marks the end of the basic-code-points section. */\n        NSRange delimiter = [aString rangeOfString:@\"-\"\n                                           options:NSBackwardsSearch\n                                             range:(NSRange){acePrefixLength, labelLength-acePrefixLength}];\n        if (delimiter.length > 0) {\n            decoded = [[aString substringWithRange:(NSRange){acePrefixLength, delimiter.location - acePrefixLength}] mutableCopy];\n            deltas = (NSRange){NSMaxRange(delimiter), labelLength - NSMaxRange(delimiter)};\n        } else {\n            /* No delimiter means no basic code point section: it's all encoded deltas (RFC3492 [3.1]) */\n            decoded = [[NSMutableString alloc] init];\n            deltas = (NSRange){acePrefixLength, labelLength - acePrefixLength};\n        }\n        \n        /* If there aren't any deltas, it's not a valid IDN label, because you're not supposed to encode something that didn't need to be encoded. */\n        if (deltas.length == 0) {\n            return aString;\n        }\n        \n        unsigned int decodedLabelLength = (unsigned)[decoded length];\n        \n        /* Convert the variable-length-integers in the deltas section into machine representation */\n        {\n            unichar *enc;\n            unsigned i, bias, value, weight, position;\n            BOOL reset;\n            const int base = 36, tmin = 1, tmax = 26;\n            \n            enc = malloc(sizeof(*enc) * deltas.length);  // code points from encoded string\n            delta = malloc(sizeof(*delta) * deltas.length); // upper bound on number of decoded integers\n            deltaCount = 0;\n            bias = 72;\n            reset = YES;\n            value = weight = position = 0;\n            \n            [aString getCharacters:enc range:deltas];\n            for(i = 0; i < deltas.length; i++) {\n                int digit, threshold;\n                \n                if (reset) {\n                    value = 0;\n                    weight = 1;\n                    position = 0;\n                    reset = NO;\n                }\n                \n                if (enc[i] <= 0x7A)\n                    digit = punycodeDigitValue[enc[i]];\n                else {\n                    free(enc);\n                    goto fail;\n                }\n                if (digit < 0) { // unassigned value\n                    free(enc);\n                    goto fail;\n                }\n                \n                value += weight * digit;\n                threshold = base * (position+1) - bias;\n                \n                // clamp to tmin=1 tmax=26 (rfc3492 [5])\n                threshold = MIN(threshold, tmax);\n                threshold = MAX(threshold, tmin);\n                \n                if (digit < threshold) {\n                    delta[deltaCount++] = value;\n                    // NSLog(@\"decode: delta[%d]=%d bias=%d from=%@\", deltaCount-1, value, bias, [aString substringWithRange:(NSRange){deltas.location + i - position, position+1}]);\n                    bias = adaptPunycodeDelta(value, deltaCount + decodedLabelLength, (deltaCount==1) ? YES : NO);\n                    reset = YES;\n                } else {\n                    weight *= (base - threshold);\n                    position ++;\n                }\n            }\n            \n            free(enc);\n            \n            if (!reset) {\n                /* The deltas section ended in the middle of an integer: something's wrong */\n                goto fail;\n            }\n            \n            /* deltas[] now holds deltaCount integers */\n        }\n        \n        /* now use the decoded integers to insert characters into the decoded string */\n        {\n            unsigned position, codeValue;\n            unichar ch[1];\n            \n            position = 0;\n            codeValue = 0x80;\n            \n            for (deltaIndex = 0; deltaIndex < deltaCount; deltaIndex ++) {\n                position += delta[deltaIndex];\n                \n                codeValue += ( position / (decodedLabelLength + 1) );\n                position = ( position % (decodedLabelLength + 1) );\n                \n                if (!validIDNCodeValue(codeValue))\n                    goto fail;\n                \n                /* TODO: This will misbehave for code points greater than 0x0FFFF, because NSString uses a 16-bit encoding internally; the position values will be off by one afterwards [actually, we'll just get bad results because I'm using initWithCharacters:length: (BMP-only) instead of initWithCharacter: (all planes but only exists in OmniFoundation)] */\n                ch[0] = codeValue;\n                NSString *insertion = [[NSString alloc] initWithCharacters:ch length:1];\n                [decoded replaceCharactersInRange:(NSRange){position, 0} withString:insertion];\n                \n                position ++;\n                decodedLabelLength ++;\n            }\n        }\n        \n        if ([decoded length] != decodedLabelLength)\n            goto fail;\n        \n        free(delta);\n        \n        NSString *normalized = [decoded precomposedStringWithCompatibilityMapping];  // Applies normalization KC\n        if ([normalized compare:decoded options:NSLiteralSearch] != NSOrderedSame) {\n            // Decoded string was not normalized, therefore could not have been the result of decoding a correctly encoded IDN.\n            return aString;\n        } else {\n            return normalized;\n        }\n    }\nfail:\n    free(delta);\n    return aString;\n}\n\n+ (NSString *)IDNEncodedHostname:(NSString *)aHostname;\n{\n    if ([aHostname canBeConvertedToEncoding:NSASCIIStringEncoding])\n        return aHostname;\n    \n    NSArray *parts = [aHostname componentsSeparatedByString:@\".\"];\n    NSMutableArray *encodedParts = [NSMutableArray array];\n    NSUInteger partIndex, partCount = [parts count];\n    \n    for (partIndex = 0; partIndex < partCount; partIndex++)\n        [encodedParts addObject:[self _punycodeEncode:[[parts objectAtIndex:partIndex] precomposedStringWithCompatibilityMapping]]];\n    return [encodedParts componentsJoinedByString:@\".\"];\n}\n\n+ (NSString *)IDNDecodedHostname:(NSString *)anIDNHostname;\n{\n    NSArray *labels = [anIDNHostname componentsSeparatedByString:@\".\"];\n    NSMutableArray *decodedLabels;\n    NSUInteger labelIndex, labelCount;\n    BOOL wasEncoded;\n    \n    labelCount = [labels count];\n    decodedLabels = [[NSMutableArray alloc] initWithCapacity:labelCount];\n    wasEncoded = NO;\n    \n    for (labelIndex = 0; labelIndex < labelCount; labelIndex++) {\n        NSString *label, *decodedLabel;\n        \n        label = [labels objectAtIndex:labelIndex];\n        decodedLabel = [self _punycodeDecode:label];\n        if (!wasEncoded && ![label isEqualToString:decodedLabel])\n            wasEncoded = YES;\n        [decodedLabels addObject:decodedLabel];\n    }\n    \n    if (wasEncoded) {\n        NSString *result = [decodedLabels componentsJoinedByString:@\".\"];\n        return result;\n    } else {\n        /* This is by far the most common case. */\n        return anIDNHostname;\n    }\n}\n\n+ (NSString *)IDNEncodedURL:(NSString *)aURL {\n    NSString *hostname = aURL;\n    NSMutableArray *components = [[aURL componentsSeparatedByString:@\"://\"] mutableCopy];\n    if ([components count] > 1) {\n        hostname = [components objectAtIndex:1];\n    }\n    hostname = [NSURL IDNEncodedHostname:hostname];\n    if ([components count] > 1) {\n        [components replaceObjectAtIndex:1 withObject:hostname];\n        return [components componentsJoinedByString:@\"://\"];\n    } else {\n        return hostname;\n    }\n}\n\n+ (NSString *)IDNDecodedURL:(NSString *)anIDNURL {\n    NSString *hostname = anIDNURL;\n    NSMutableArray *components = [[anIDNURL componentsSeparatedByString:@\"://\"] mutableCopy];\n    if ([components count] > 1) {\n        hostname = [components objectAtIndex:1];\n    }\n    hostname = [NSURL IDNDecodedHostname:hostname];\n    if ([components count] > 1) {\n        [components replaceObjectAtIndex:1 withObject:hostname];\n        return [components componentsJoinedByString:@\"://\"];\n    } else {\n        return hostname;\n    }    \n}\n\n\n@end\n"
  },
  {
    "path": "NotificationService/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>NotificationService</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</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>XPC!</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>VERSION_STRING</string>\n\t<key>CFBundleVersion</key>\n\t<string>GIT_VERSION</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string></string>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSExceptionDomains</key>\n\t\t<dict>\n\t\t\t<key>irccloud.com</key>\n\t\t\t<dict>\n\t\t\t\t<key>NSIncludesSubdomains</key>\n\t\t\t\t<true/>\n\t\t\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t\t\t<false/>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>NSExtension</key>\n\t<dict>\n\t\t<key>NSExtensionPointIdentifier</key>\n\t\t<string>com.apple.usernotifications.service</string>\n\t\t<key>NSExtensionPrincipalClass</key>\n\t\t<string>NotificationService</string>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "NotificationService/NotificationService.entitlements",
    "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>com.apple.security.app-sandbox</key>\n\t<true/>\n\t<key>com.apple.security.application-groups</key>\n\t<array>\n\t\t<string>group.com.irccloud.share</string>\n\t</array>\n\t<key>com.apple.security.network.client</key>\n\t<true/>\n\t<key>keychain-access-groups</key>\n\t<array>\n\t\t<string>$(AppIdentifierPrefix)com.irccloud.IRCCloud</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "NotificationService/NotificationService.h",
    "content": "//\n//  NotificationService.h\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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#import <UserNotifications/UserNotifications.h>\n\n@interface NotificationService : UNNotificationServiceExtension\n\n@end\n"
  },
  {
    "path": "NotificationService/NotificationService.m",
    "content": "//\n//  NotificationService.h\n//\n//  Copyright (C) 2017 IRCCloud, Ltd.\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#import <MobileCoreServices/MobileCoreServices.h>\n#import \"NetworkConnection.h\"\n#import \"NotificationService.h\"\n#import \"ColorFormatter.h\"\n#import \"ImageCache.h\"\n\n@interface NotificationService ()\n@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);\n@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;\n\n@end\n\n@implementation NotificationService\n\n- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {\n    NSURL *attachment = nil;\n    NSString *typeHint = (NSString *)kUTTypeJPEG;\n    self.contentHandler = contentHandler;\n    self.bestAttemptContent = [request.content mutableCopy];\n    \n#ifdef ENTERPRISE\n    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n    IRCCLOUD_HOST = [d objectForKey:@\"host\"];\n    IRCCLOUD_PATH = [d objectForKey:@\"path\"];\n\n    if([d boolForKey:@\"defaultSound\"])\n        self.bestAttemptContent.sound = [UNNotificationSound defaultSound];\n    \n    if([self.bestAttemptContent.categoryIdentifier isEqualToString:@\"buffer_me_msg\"])\n        self.bestAttemptContent.categoryIdentifier = @\"buffer_msg\";\n    \n    self.bestAttemptContent.threadIdentifier = [NSString stringWithFormat:@\"%@-%@\", [[request.content.userInfo objectForKey:@\"d\"] objectAtIndex:0], [[request.content.userInfo objectForKey:@\"d\"] objectAtIndex:1]];\n\n    self.bestAttemptContent.summaryArgumentCount = 1;\n\n    if(![d boolForKey:@\"disableNotificationPreviews\"]) {\n        [NetworkConnection sync];\n        \n        if([request.content.userInfo objectForKey:@\"f\"]) {\n            NSString *fileID = [[request.content.userInfo objectForKey:@\"f\"] objectAtIndex:0];\n            \n            if(![NetworkConnection sharedInstance].config) {\n                [[NetworkConnection sharedInstance] requestConfigurationWithHandler:^(IRCCloudJSONObject *result) {\n                    if(result)\n                        [self didReceiveNotificationRequest:request withContentHandler:contentHandler];\n                    else\n                        self.contentHandler(self.bestAttemptContent);\n                }];\n                return;\n            }\n            \n            [[NetworkConnection sharedInstance] propertiesForFile:fileID handler:^(IRCCloudJSONObject *o) {\n                NSURL *attachment = nil;\n                NSString *typeHint = nil;\n                if(o) {\n                    NSString *type = [o objectForKey:@\"mime_type\"];\n                    typeHint = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef _Nonnull)(type), NULL);\n                    \n                    if([type hasPrefix:@\"image/\"]) {\n                        attachment = [NSURL URLWithString:[[NetworkConnection sharedInstance].fileURITemplate relativeStringWithVariables:@{@\"id\":[o objectForKey:@\"id\"], @\"modifiers\":[NSString stringWithFormat:@\"w%.f\", ([UIScreen mainScreen].bounds.size.width/2) * [UIScreen mainScreen].scale]} error:nil]];\n                    } else {\n                        attachment = [NSURL URLWithString:[o objectForKey:@\"url\"]];\n                    }\n                }\n                [self attach:attachment typeHint:typeHint];\n            }];\n            return;\n        } else if([d boolForKey:@\"thirdPartyNotificationPreviews\"]) {\n            NSDictionary *extensions = @{@\"png\":(NSString *)kUTTypePNG,\n                                         @\"jpg\":(NSString *)kUTTypeJPEG,\n                                         @\"jpeg\":(NSString *)kUTTypeJPEG,\n                                         @\"gif\":(NSString *)kUTTypeGIF,\n                                         @\"m4v\":(NSString *)kUTTypeMPEG4,\n                                         @\"mp4\":(NSString *)kUTTypeMPEG4,\n                                         @\"mov\":(NSString *)kUTTypeMPEG4,\n                                         @\"m4a\":(NSString *)kUTTypeMPEG4Audio,\n                                         @\"mp3\":(NSString *)kUTTypeMP3,\n                                         @\"wav\":(NSString *)kUTTypeWaveformAudio,\n                                         @\"avi\":(NSString *)kUTTypeAVIMovie,\n                                         @\"aif\":(NSString *)kUTTypeAudioInterchangeFileFormat,\n                                         @\"aiff\":(NSString *)kUTTypeAudioInterchangeFileFormat\n                                         };\n            NSArray *links;\n            [ColorFormatter format:request.content.body defaultColor:[UIColor blackColor] mono:NO linkify:YES server:nil links:&links];\n\n            for(NSTextCheckingResult *r in links) {\n                if(r.resultType == NSTextCheckingTypeLink) {\n                    NSString *type = [r.URL.pathExtension lowercaseString];\n                    if([extensions objectForKey:type]) {\n                        attachment = r.URL;\n                        typeHint = [extensions objectForKey:type];\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    [self attach:attachment typeHint:typeHint];\n}\n\n- (void)attach:(NSURL *)attachment typeHint:(NSString *)typeHint {\n    if(attachment) {\n        if([[NSFileManager defaultManager] fileExistsAtPath:[[ImageCache sharedInstance] pathForURL:attachment].path]) {\n            [self downloadComplete:attachment typeHint:typeHint];\n        } else {\n            [[ImageCache sharedInstance] fetchURL:attachment completionHandler:^(BOOL success) {\n                [self downloadComplete:attachment typeHint:typeHint];\n            }];\n        }\n    } else {\n        self.contentHandler(self.bestAttemptContent);\n    }\n}\n\n- (void)downloadComplete:(NSURL *)url typeHint:(NSString *)typeHint {\n    NSError *error;\n    UNNotificationAttachment *a = [UNNotificationAttachment attachmentWithIdentifier:url.lastPathComponent URL:[[ImageCache sharedInstance] pathForURL:url] options:@{UNNotificationAttachmentOptionsTypeHintKey:typeHint} error:&error];\n    if(error) {\n        NSLog(@\"Attachment error: %@\", error);\n    } else {\n        self.bestAttemptContent.attachments = @[a];\n    }\n    self.contentHandler(self.bestAttemptContent);\n}\n\n- (void)serviceExtensionTimeWillExpire {\n    self.contentHandler(self.bestAttemptContent);\n}\n\n@end\n"
  },
  {
    "path": "NotificationService Enterprise.entitlements",
    "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>com.apple.security.application-groups</key>\n\t<array>\n\t\t<string>group.com.irccloud.enterprise.share</string>\n\t</array>\n\t<key>keychain-access-groups</key>\n\t<array>\n\t\t<string>$(AppIdentifierPrefix)com.irccloud.enterprise</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "OpenInChrome/OpenInChromeController.h",
    "content": "// Copyright 2012-2014, Google Inc.\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//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER 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#import <Foundation/Foundation.h>\n\n// This class is used to check if Google Chrome is installed in the system and\n// to open a URL in Google Chrome either with or without a callback URL.\n@interface OpenInChromeController : NSObject\n\n// Returns a shared instance of the OpenInChromeController.\n+ (OpenInChromeController *)sharedInstance;\n\n// Returns YES if Google Chrome is installed in the user's system.\n- (BOOL)isChromeInstalled;\n\n// Opens a URL in Google Chrome.\n- (BOOL)openInChrome:(NSURL *)url;\n\n// Open a URL in Google Chrome providing a |callbackURL| to return to the app.\n// URLs from the same app will be opened in the same tab unless |createNewTab|\n// is set to YES.\n// |callbackURL| can be nil.\n// The return value of this method is YES if the URL is successfully opened.\n- (BOOL)openInChrome:(NSURL *)url\n     withCallbackURL:(NSURL *)callbackURL\n        createNewTab:(BOOL)createNewTab;\n\n@end\n"
  },
  {
    "path": "OpenInChrome/OpenInChromeController.m",
    "content": "#if !defined(__has_feature) || !__has_feature(objc_arc)\n#error \"This file requires ARC support.\"\n#endif\n\n// Copyright 2012-2014, Google Inc.\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//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER 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#import <UIKit/UIKit.h>\n\n#import \"OpenInChromeController.h\"\n\nstatic NSString * const kGoogleChromeHTTPScheme = @\"googlechrome:\";\nstatic NSString * const kGoogleChromeHTTPSScheme = @\"googlechromes:\";\nstatic NSString * const kGoogleChromeCallbackScheme = @\"googlechrome-x-callback:\";\n\nstatic NSString *encodeByAddingPercentEscapes(NSString *input) {\n    return [input stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@\"!*'();:@&=+$,/?#[] \"].invertedSet];\n}\n\n@implementation OpenInChromeController\n\n+ (OpenInChromeController *)sharedInstance {\n  static OpenInChromeController *sharedInstance;\n  static dispatch_once_t onceToken;\n  dispatch_once(&onceToken, ^{\n    sharedInstance = [[self alloc] init];\n  });\n  return sharedInstance;\n}\n\n- (BOOL)isChromeInstalled {\n  NSURL *simpleURL = [NSURL URLWithString:kGoogleChromeHTTPScheme];\n  NSURL *callbackURL = [NSURL URLWithString:kGoogleChromeCallbackScheme];\n  return  [[UIApplication sharedApplication] canOpenURL:simpleURL] ||\n      [[UIApplication sharedApplication] canOpenURL:callbackURL];\n}\n\n- (BOOL)openInChrome:(NSURL *)url {\n  return [self openInChrome:url withCallbackURL:nil createNewTab:NO];\n}\n\n- (BOOL)openInChrome:(NSURL *)url\n     withCallbackURL:(NSURL *)callbackURL\n        createNewTab:(BOOL)createNewTab {\n  NSURL *chromeSimpleURL = [NSURL URLWithString:kGoogleChromeHTTPScheme];\n  NSURL *chromeCallbackURL = [NSURL URLWithString:kGoogleChromeCallbackScheme];\n  if ([[UIApplication sharedApplication] canOpenURL:chromeCallbackURL]) {\n    NSString *appName =\n        [[NSBundle mainBundle]\n            objectForInfoDictionaryKey:@\"CFBundleDisplayName\"];\n\n    NSString *scheme = [url.scheme lowercaseString];\n\n    // Proceed only if scheme is http or https.\n    if ([scheme isEqualToString:@\"http\"] ||\n        [scheme isEqualToString:@\"https\"]) {\n\n      NSMutableString *chromeURLString = [NSMutableString string];\n      [chromeURLString appendFormat:\n          @\"%@//x-callback-url/open/?x-source=%@&url=%@\",\n          kGoogleChromeCallbackScheme,\n          encodeByAddingPercentEscapes(appName),\n          encodeByAddingPercentEscapes([url absoluteString])];\n      if (callbackURL) {\n        [chromeURLString appendFormat:@\"&x-success=%@\",\n            encodeByAddingPercentEscapes([callbackURL absoluteString])];\n      }\n      if (createNewTab) {\n        [chromeURLString appendString:@\"&create-new-tab\"];\n      }\n\n      NSURL *chromeURL = [NSURL URLWithString:chromeURLString];\n\n      // Open the URL with Google Chrome.\n        if([[UIApplication sharedApplication] canOpenURL:chromeURL]) {\n            [[UIApplication sharedApplication] openURL:chromeURL options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n            return YES;\n        } else {\n            return NO;\n        }\n    }\n  } else if ([[UIApplication sharedApplication] canOpenURL:chromeSimpleURL]) {\n    NSString *scheme = [url.scheme lowercaseString];\n\n    // Replace the URL Scheme with the Chrome equivalent.\n    NSString *chromeScheme = nil;\n    if ([scheme isEqualToString:@\"http\"]) {\n      chromeScheme = kGoogleChromeHTTPScheme;\n    } else if ([scheme isEqualToString:@\"https\"]) {\n      chromeScheme = kGoogleChromeHTTPSScheme;\n    }\n\n    // Proceed only if a valid Google Chrome URI Scheme is available.\n    if (chromeScheme) {\n      NSString *absoluteString = [url absoluteString];\n      NSRange rangeForScheme = [absoluteString rangeOfString:@\":\"];\n      NSString *urlNoScheme =\n          [absoluteString substringFromIndex:rangeForScheme.location + 1];\n      NSString *chromeURLString =\n          [chromeScheme stringByAppendingString:urlNoScheme];\n      NSURL *chromeURL = [NSURL URLWithString:chromeURLString];\n\n      // Open the URL with Google Chrome.\n        if([[UIApplication sharedApplication] canOpenURL:chromeURL]) {\n            [[UIApplication sharedApplication] openURL:chromeURL options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n            return YES;\n        } else {\n            return NO;\n        }\n    }\n  }\n  return NO;\n}\n\n@end\n"
  },
  {
    "path": "OpenInFirefoxClient/LICENSE",
    "content": "Mozilla Public License, version 2.0\n\n1. Definitions\n\n1.1. \"Contributor\"\n\n     means each individual or legal entity that creates, contributes to the\n     creation of, or owns Covered Software.\n\n1.2. \"Contributor Version\"\n\n     means the combination of the Contributions of others (if any) used by a\n     Contributor and that particular Contributor's Contribution.\n\n1.3. \"Contribution\"\n\n     means Covered Software of a particular Contributor.\n\n1.4. \"Covered Software\"\n\n     means Source Code Form to which the initial Contributor has attached the\n     notice in Exhibit A, the Executable Form of such Source Code Form, and\n     Modifications of such Source Code Form, in each case including portions\n     thereof.\n\n1.5. \"Incompatible With Secondary Licenses\"\n     means\n\n     a. that the initial Contributor has attached the notice described in\n        Exhibit B to the Covered Software; or\n\n     b. that the Covered Software was made available under the terms of\n        version 1.1 or earlier of the License, but not also under the terms of\n        a Secondary License.\n\n1.6. \"Executable Form\"\n\n     means any form of the work other than Source Code Form.\n\n1.7. \"Larger Work\"\n\n     means a work that combines Covered Software with other material, in a\n     separate file or files, that is not Covered Software.\n\n1.8. \"License\"\n\n     means this document.\n\n1.9. \"Licensable\"\n\n     means having the right to grant, to the maximum extent possible, whether\n     at the time of the initial grant or subsequently, any and all of the\n     rights conveyed by this License.\n\n1.10. \"Modifications\"\n\n     means any of the following:\n\n     a. any file in Source Code Form that results from an addition to,\n        deletion from, or modification of the contents of Covered Software; or\n\n     b. any new file in Source Code Form that contains any Covered Software.\n\n1.11. \"Patent Claims\" of a Contributor\n\n      means any patent claim(s), including without limitation, method,\n      process, and apparatus claims, in any patent Licensable by such\n      Contributor that would be infringed, but for the grant of the License,\n      by the making, using, selling, offering for sale, having made, import,\n      or transfer of either its Contributions or its Contributor Version.\n\n1.12. \"Secondary License\"\n\n      means either the GNU General Public License, Version 2.0, the GNU Lesser\n      General Public License, Version 2.1, the GNU Affero General Public\n      License, Version 3.0, or any later versions of those licenses.\n\n1.13. \"Source Code Form\"\n\n      means the form of the work preferred for making modifications.\n\n1.14. \"You\" (or \"Your\")\n\n      means an individual or a legal entity exercising rights under this\n      License. For legal entities, \"You\" includes any entity that controls, is\n      controlled by, or is under common control with You. For purposes of this\n      definition, \"control\" means (a) the power, direct or indirect, to cause\n      the direction or management of such entity, whether by contract or\n      otherwise, or (b) ownership of more than fifty percent (50%) of the\n      outstanding shares or beneficial ownership of such entity.\n\n\n2. License Grants and Conditions\n\n2.1. Grants\n\n     Each Contributor hereby grants You a world-wide, royalty-free,\n     non-exclusive license:\n\n     a. under intellectual property rights (other than patent or trademark)\n        Licensable by such Contributor to use, reproduce, make available,\n        modify, display, perform, distribute, and otherwise exploit its\n        Contributions, either on an unmodified basis, with Modifications, or\n        as part of a Larger Work; and\n\n     b. under Patent Claims of such Contributor to make, use, sell, offer for\n        sale, have made, import, and otherwise transfer either its\n        Contributions or its Contributor Version.\n\n2.2. Effective Date\n\n     The licenses granted in Section 2.1 with respect to any Contribution\n     become effective for each Contribution on the date the Contributor first\n     distributes such Contribution.\n\n2.3. Limitations on Grant Scope\n\n     The licenses granted in this Section 2 are the only rights granted under\n     this License. No additional rights or licenses will be implied from the\n     distribution or licensing of Covered Software under this License.\n     Notwithstanding Section 2.1(b) above, no patent license is granted by a\n     Contributor:\n\n     a. for any code that a Contributor has removed from Covered Software; or\n\n     b. for infringements caused by: (i) Your and any other third party's\n        modifications of Covered Software, or (ii) the combination of its\n        Contributions with other software (except as part of its Contributor\n        Version); or\n\n     c. under Patent Claims infringed by Covered Software in the absence of\n        its Contributions.\n\n     This License does not grant any rights in the trademarks, service marks,\n     or logos of any Contributor (except as may be necessary to comply with\n     the notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\n     No Contributor makes additional grants as a result of Your choice to\n     distribute the Covered Software under a subsequent version of this\n     License (see Section 10.2) or under the terms of a Secondary License (if\n     permitted under the terms of Section 3.3).\n\n2.5. Representation\n\n     Each Contributor represents that the Contributor believes its\n     Contributions are its original creation(s) or it has sufficient rights to\n     grant the rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\n     This License is not intended to limit any rights You have under\n     applicable copyright doctrines of fair use, fair dealing, or other\n     equivalents.\n\n2.7. Conditions\n\n     Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in\n     Section 2.1.\n\n\n3. Responsibilities\n\n3.1. Distribution of Source Form\n\n     All distribution of Covered Software in Source Code Form, including any\n     Modifications that You create or to which You contribute, must be under\n     the terms of this License. You must inform recipients that the Source\n     Code Form of the Covered Software is governed by the terms of this\n     License, and how they can obtain a copy of this License. You may not\n     attempt to alter or restrict the recipients' rights in the Source Code\n     Form.\n\n3.2. Distribution of Executable Form\n\n     If You distribute Covered Software in Executable Form then:\n\n     a. such Covered Software must also be made available in Source Code Form,\n        as described in Section 3.1, and You must inform recipients of the\n        Executable Form how they can obtain a copy of such Source Code Form by\n        reasonable means in a timely manner, at a charge no more than the cost\n        of distribution to the recipient; and\n\n     b. You may distribute such Executable Form under the terms of this\n        License, or sublicense it under different terms, provided that the\n        license for the Executable Form does not attempt to limit or alter the\n        recipients' rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\n     You may create and distribute a Larger Work under terms of Your choice,\n     provided that You also comply with the requirements of this License for\n     the Covered Software. If the Larger Work is a combination of Covered\n     Software with a work governed by one or more Secondary Licenses, and the\n     Covered Software is not Incompatible With Secondary Licenses, this\n     License permits You to additionally distribute such Covered Software\n     under the terms of such Secondary License(s), so that the recipient of\n     the Larger Work may, at their option, further distribute the Covered\n     Software under the terms of either this License or such Secondary\n     License(s).\n\n3.4. Notices\n\n     You may not remove or alter the substance of any license notices\n     (including copyright notices, patent notices, disclaimers of warranty, or\n     limitations of liability) contained within the Source Code Form of the\n     Covered Software, except that You may alter any license notices to the\n     extent required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\n     You may choose to offer, and to charge a fee for, warranty, support,\n     indemnity or liability obligations to one or more recipients of Covered\n     Software. However, You may do so only on Your own behalf, and not on\n     behalf of any Contributor. You must make it absolutely clear that any\n     such warranty, support, indemnity, or liability obligation is offered by\n     You alone, and You hereby agree to indemnify every Contributor for any\n     liability incurred by such Contributor as a result of warranty, support,\n     indemnity or liability terms You offer. You may include additional\n     disclaimers of warranty and limitations of liability specific to any\n     jurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n\n   If it is impossible for You to comply with any of the terms of this License\n   with respect to some or all of the Covered Software due to statute,\n   judicial order, or regulation then You must: (a) comply with the terms of\n   this License to the maximum extent possible; and (b) describe the\n   limitations and the code they affect. Such description must be placed in a\n   text file included with all distributions of the Covered Software under\n   this License. Except to the extent prohibited by statute or regulation,\n   such description must be sufficiently detailed for a recipient of ordinary\n   skill to be able to understand it.\n\n5. Termination\n\n5.1. The rights granted under this License will terminate automatically if You\n     fail to comply with any of its terms. However, if You become compliant,\n     then the rights granted under this License from a particular Contributor\n     are reinstated (a) provisionally, unless and until such Contributor\n     explicitly and finally terminates Your grants, and (b) on an ongoing\n     basis, if such Contributor fails to notify You of the non-compliance by\n     some reasonable means prior to 60 days after You have come back into\n     compliance. Moreover, Your grants from a particular Contributor are\n     reinstated on an ongoing basis if such Contributor notifies You of the\n     non-compliance by some reasonable means, this is the first time You have\n     received notice of non-compliance with this License from such\n     Contributor, and You become compliant prior to 30 days after Your receipt\n     of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\n     infringement claim (excluding declaratory judgment actions,\n     counter-claims, and cross-claims) alleging that a Contributor Version\n     directly or indirectly infringes any patent, then the rights granted to\n     You by any and all Contributors for the Covered Software under Section\n     2.1 of this License shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user\n     license agreements (excluding distributors and resellers) which have been\n     validly granted by You or Your distributors under this License prior to\n     termination shall survive termination.\n\n6. Disclaimer of Warranty\n\n   Covered Software is provided under this License on an \"as is\" basis,\n   without warranty of any kind, either expressed, implied, or statutory,\n   including, without limitation, warranties that the Covered Software is free\n   of defects, merchantable, fit for a particular purpose or non-infringing.\n   The entire risk as to the quality and performance of the Covered Software\n   is with You. Should any Covered Software prove defective in any respect,\n   You (not any Contributor) assume the cost of any necessary servicing,\n   repair, or correction. This disclaimer of warranty constitutes an essential\n   part of this License. No use of  any Covered Software is authorized under\n   this License except under this disclaimer.\n\n7. Limitation of Liability\n\n   Under no circumstances and under no legal theory, whether tort (including\n   negligence), contract, or otherwise, shall any Contributor, or anyone who\n   distributes Covered Software as permitted above, be liable to You for any\n   direct, indirect, special, incidental, or consequential damages of any\n   character including, without limitation, damages for lost profits, loss of\n   goodwill, work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses, even if such party shall have been\n   informed of the possibility of such damages. This limitation of liability\n   shall not apply to liability for death or personal injury resulting from\n   such party's negligence to the extent applicable law prohibits such\n   limitation. Some jurisdictions do not allow the exclusion or limitation of\n   incidental or consequential damages, so this exclusion and limitation may\n   not apply to You.\n\n8. Litigation\n\n   Any litigation relating to this License may be brought only in the courts\n   of a jurisdiction where the defendant maintains its principal place of\n   business and such litigation shall be governed by laws of that\n   jurisdiction, without reference to its conflict-of-law provisions. Nothing\n   in this Section shall prevent a party's ability to bring cross-claims or\n   counter-claims.\n\n9. Miscellaneous\n\n   This License represents the complete agreement concerning the subject\n   matter hereof. If any provision of this License is held to be\n   unenforceable, such provision shall be reformed only to the extent\n   necessary to make it enforceable. Any law or regulation which provides that\n   the language of a contract shall be construed against the drafter shall not\n   be used to construe this License against a Contributor.\n\n\n10. Versions of the License\n\n10.1. New Versions\n\n      Mozilla Foundation is the license steward. Except as provided in Section\n      10.3, no one other than the license steward has the right to modify or\n      publish new versions of this License. Each version will be given a\n      distinguishing version number.\n\n10.2. Effect of New Versions\n\n      You may distribute the Covered Software under the terms of the version\n      of the License under which You originally received the Covered Software,\n      or under the terms of any subsequent version published by the license\n      steward.\n\n10.3. Modified Versions\n\n      If you create software not governed by this License, and you want to\n      create a new license for such software, you may create and use a\n      modified version of this License if you rename the license and remove\n      any references to the name of the license steward (except to note that\n      such modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary\n      Licenses If You choose to distribute Source Code Form that is\n      Incompatible With Secondary Licenses under the terms of this version of\n      the License, the notice described in Exhibit B of this License must be\n      attached.\n\nExhibit A - Source Code Form License Notice\n\n      This Source Code Form is subject to the\n      terms of the Mozilla Public License, v.\n      2.0. If a copy of the MPL was not\n      distributed with this file, You can\n      obtain one at\n      http://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular file,\nthen You may include the notice in a location (such as a LICENSE file in a\nrelevant directory) where a recipient would be likely to look for such a\nnotice.\n\nYou may add additional accurate notices of copyright ownership.\n\nExhibit B - \"Incompatible With Secondary Licenses\" Notice\n\n      This Source Code Form is \"Incompatible\n      With Secondary Licenses\", as defined by\n      the Mozilla Public License, v. 2.0.\n\n"
  },
  {
    "path": "OpenInFirefoxClient/OpenInFirefoxControllerObjC.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#import <Foundation/Foundation.h>\n\n// This class is used to check if Firefox is installed in the system and\n// to open a URL in Firefox either with or without a callback URL.\n@interface OpenInFirefoxControllerObjC : NSObject\n\n// Returns a shared instance of the OpenInFirefoxControllerObjC.\n+ (OpenInFirefoxControllerObjC *)sharedInstance;\n\n// Returns YES if Firefox is installed in the user's system.\n- (BOOL)isFirefoxInstalled;\n\n// Opens a URL in Firefox.\n- (BOOL)openInFirefox:(NSURL *)url;\n\n@end\n"
  },
  {
    "path": "OpenInFirefoxClient/OpenInFirefoxControllerObjC.m",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#import <UIKit/UIKit.h>\n#import \"OpenInFirefoxControllerObjC.h\"\n\nstatic NSString *const firefoxScheme = @\"firefox:\";\n\n@implementation OpenInFirefoxControllerObjC\n\n// Creates a shared instance of the controller.\n+ (OpenInFirefoxControllerObjC *)sharedInstance {\n    static OpenInFirefoxControllerObjC *sharedInstance;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        sharedInstance = [[self alloc] init];\n    });\n    return sharedInstance;\n}\n\n// Custom function that does complete percent escape for constructing the URL.\nstatic NSString *encodeByAddingPercentEscapes(NSString *string) {\n    return [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@\"!*'();:@&=+$,/?#[] \"].invertedSet];\n}\n\n// Checks if Firefox is installed.\n- (BOOL)isFirefoxInstalled {\n    NSURL *url = [NSURL URLWithString:firefoxScheme];\n    return [[UIApplication sharedApplication] canOpenURL:url];\n}\n\n// Opens the URL in Firefox.\n- (BOOL)openInFirefox:(NSURL *)url {\n    if (![self isFirefoxInstalled]) {\n        return NO;\n    }\n\n    NSString *scheme = [url.scheme lowercaseString];\n    if (![scheme isEqualToString:@\"http\"] && ![scheme isEqualToString:@\"https\"]) {\n        return NO;\n    }\n\n    NSString *urlString = [url absoluteString];\n    NSMutableString *firefoxURLString = [NSMutableString string];\n    [firefoxURLString appendFormat:@\"%@//open-url?url=%@\", firefoxScheme, encodeByAddingPercentEscapes(urlString)];\n    NSURL *firefoxURL = [NSURL URLWithString: firefoxURLString];\n\n    // Open the URL with Firefox.\n    if([[UIApplication sharedApplication] canOpenURL:firefoxURL]) {\n        [[UIApplication sharedApplication] openURL:firefoxURL options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n        return YES;\n    } else {\n        return NO;\n    }\n}\n\n@end\n"
  },
  {
    "path": "Podfile",
    "content": "# Uncomment the next line to define a global platform for your project\nplatform :ios, '12.0'\nuse_modular_headers!\n\npod 'GoogleUtilities/AppDelegateSwizzler'\npod 'GoogleUtilities/Environment'\npod 'GoogleUtilities/ISASwizzler'\npod 'GoogleUtilities/Logger'\npod 'GoogleUtilities/MethodSwizzler'\npod 'GoogleUtilities/NSData+zlib'\npod 'GoogleUtilities/Network'\npod 'GoogleUtilities/Reachability'\npod 'GoogleUtilities/UserDefaults'\npod 'Firebase/Crashlytics'\npod 'SSZipArchive'\n\ntarget 'IRCCloud' do\n  # Comment the next line if you don't want to use dynamic frameworks\n  use_frameworks!\n\n  # Pods for IRCCloud\n  pod 'youtube-ios-player-helper'\n  pod 'Firebase/Messaging'\n\n  target 'IRCCloudUnitTests' do\n    inherit! :search_paths\n    # Pods for testing\n  end\n\nend\n\ntarget 'IRCCloud Enterprise' do\n  # Comment the next line if you don't want to use dynamic frameworks\n  use_frameworks!\n\n  # Pods for IRCCloud Enterprise\n  pod 'youtube-ios-player-helper'\n  pod 'Firebase/Messaging'\n\nend\n\ntarget 'IRCCloud FLEX' do\n  # Comment the next line if you don't want to use dynamic frameworks\n  use_frameworks!\n\n  # Pods for IRCCloud FLEX\n  pod 'youtube-ios-player-helper'\n  pod 'Firebase/Messaging'\n\nend\n\ntarget 'NotificationService' do\n  # Comment the next line if you don't want to use dynamic frameworks\n  use_frameworks!\n\n  # Pods for NotificationService\n\nend\n\ntarget 'NotificationService Enterprise' do\n  # Comment the next line if you don't want to use dynamic frameworks\n  use_frameworks!\n\n  # Pods for NotificationService Enterprise\n\nend\n\ntarget 'ShareExtension' do\n  # Comment the next line if you don't want to use dynamic frameworks\n  use_frameworks!\n\n  # Pods for ShareExtension\n\nend\n\ntarget 'ShareExtension Enterprise' do\n  # Comment the next line if you don't want to use dynamic frameworks\n  use_frameworks!\n\n  # Pods for ShareExtension Enterprise\n\nend\n\npost_install do |installer|\n  installer.pods_project.targets.each do |t|\n      t.build_configurations.each do |config|\n          config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'\n      end\n  end\n  installer.aggregate_targets.each do |target|\n    target.xcconfigs.each do |variant, xcconfig|\n      xcconfig_path = target.client_root + target.xcconfig_relative_path(variant)\n      IO.write(xcconfig_path, IO.read(xcconfig_path).gsub(\"DT_TOOLCHAIN_DIR\", \"TOOLCHAIN_DIR\"))\n    end\n  end\n  installer.pods_project.targets.each do |target|\n    target.build_configurations.each do |config|\n      if config.base_configuration_reference.is_a? Xcodeproj::Project::Object::PBXFileReference\n        xcconfig_path = config.base_configuration_reference.real_path\n        IO.write(xcconfig_path, IO.read(xcconfig_path).gsub(\"DT_TOOLCHAIN_DIR\", \"TOOLCHAIN_DIR\"))\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "README.md",
    "content": "The official iOS app for IRCCloud.com\n=======\n\nChat on IRC from anywhere, and never miss a message.\n\n* All your chats and logs are stored in the cloud. Access them on the go\n* Push notifications on highlights and PMs\n* Fully syncs with IRCCloud.com on the web\n* Works on iPhone and iPad\n\nJoin our #ios channel on irc.irccloud.com for feedback and suggestions so we can improve the app.\nYou can also email us on team@irccloud.com or find us on Twitter [@irccloud](https://twitter.com/irccloud).\n\nIRCCloud for iOS is available in the [App Store](https://itunes.apple.com/us/app/irccloud/id672699103).\n\nScreenshots\n------\n<img src=\"https://blog.irccloud.com/static/ios-announce/iphone-sidebar-case.png\" height=\"640\">\n&nbsp;\n<img src=\"https://blog.irccloud.com/static/ios-announce/iphone-chat-case.png\" height=\"640\">\n\nRequirements\n------\n_A code signing key from Apple is required to deploy apps to a device.\nWithout a developer key, the app can only be installed on the iPhone/iPad Simulator._\n\n* CocoaPods\n* Xcode 11.3\n* iOS 13 SDK\n* An iPhone, iPad, or iPod Touch running iOS 8.0 or newer\n\nRun the following command from the Terminal to install the required libraries, and then open the generated IRCCloud.xcworkspace file to build and run the app.\n```\n$ pod install\n```\n\nLicense\n------\nCopyright (C) 2020 IRCCloud, Ltd.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "SBJson/SBJson5.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#import \"SBJson5Writer.h\"\n#import \"SBJson5StreamParser.h\"\n#import \"SBJson5Parser.h\"\n#import \"SBJson5StreamWriter.h\"\n#import \"SBJson5StreamTokeniser.h\"\n\n"
  },
  {
    "path": "SBJson/SBJson5Parser.h",
    "content": "/*\n Copyright (c) 2010-2013, 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 \"SBJson5StreamParser.h\"\n\n/**\n Block called when the parser has parsed an item. This could be once\n for each root document parsed, or once for each unwrapped root array element.\n\n @param item contains the parsed item.\n @param stop set to YES if you want the parser to stop\n */\ntypedef void (^SBJson5ValueBlock)(id item, BOOL* stop);\n\n/**\n Block called if an error occurs.\n @param error the error.\n */\ntypedef void (^SBJson5ErrorBlock)(NSError* error);\n\n\n/**\n Parse one or more chunks 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 ## How JSON is mapped\n\n JSON is mapped to Objective-C types in the following way:\n\n - null    -> NSNull\n - string  -> NSString\n - array   -> NSMutableArray\n - object  -> NSMutableDictionary\n - true    -> NSNumber's -numberWithBool:YES\n - false   -> NSNumber's -numberWithBool:NO\n - number -> NSNumber\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 Integers are parsed into either a `long long` or `unsigned long long`\n type if they fit, else a `double` is used. All real & exponential numbers\n are represented using a `double`. Previous versions of this library used\n an NSDecimalNumber in some cases, but this is no longer the case.\n\n ## A word of warning\n\n Stream based parsing does mean that you lose some of the correctness\n verification you would have with a parser that considered the entire input\n before returning an answer. It is technically possible to have some parts\n of a document returned *as if they were correct* but then encounter an error\n in a later part of the document. You should keep this in mind when\n considering whether it would suit your application.\n\n*/\n@interface SBJson5Parser : NSObject\n\n/**\n Create a JSON Parser\n\n This can be used to create a parser that accepts only one document, or one\n that parses many documents, or both! You can also use this if you need to\n parse documents with nesting depth deeper than 32.\n\n @param block Called for each element. Set *stop to `YES` if you have seen\n enough and would like to skip the rest of the elements.\n\n @param allowMultiRoot Indicate that you are expecting multiple whitespace-separated\n JSON documents, similar to what Twitter uses.\n\n @param unwrapRootArray If set the parser will pretend an root array does not exist\n and the enumerator block will be called once for each item in it. This option\n does nothing if the the JSON has an object at its root.\n\n @param maxDepth The max recursion depth.\n\n @param eh Called if the parser encounters an error.\n\n */\n+ (id)parserWithBlock:(SBJson5ValueBlock)block\n       allowMultiRoot:(BOOL)allowMultiRoot\n      unwrapRootArray:(BOOL)unwrapRootArray\n             maxDepth:(NSUInteger)maxDepth\n         errorHandler:(SBJson5ErrorBlock)eh;\n\n/**\n Create a JSON Parser to parse a single document\n\n @param block Called for each element. Set *stop to `YES` if you have seen\n enough and would like to skip the rest of the elements.\n\n @param eh Called if the parser encounters an error.\n\n */\n+ (id)parserWithBlock:(SBJson5ValueBlock)block\n         errorHandler:(SBJson5ErrorBlock)eh;\n\n\n/**\n  Create a JSON Parser that parses multiple consequtive documents\n\n This is useful for something like Twitter's feed, which gives you one JSON\n document per line. Here is an example of parsing many consequtive JSON\n documents, where your block will be called once for each document:\n\n    SBJson5ValueBlock block = ^(id v, BOOL *stop) {\n        BOOL isArray = [v isKindOfClass:[NSArray class]];\n        NSLog(@\"Found: %@\", isArray ? @\"Array\" : @\"Object\");\n    };\n\n    SBJson5ErrorBlock eh = ^(NSError* err) {\n        NSLog(@\"OOPS: %@\", err);\n    };\n\n    id parser = [SBJson5Parser multiRootParserWithBlock:block\n                                           errorHandler:eh];\n\n    // Note that this input contains multiple top-level JSON documents\n    id data = [@\"[]{}\" dataWithEncoding:NSUTF8StringEncoding];\n    [parser parse:data];\n    [parser parse:data];\n\n The above example will print:\n\n - Found: Array\n - Found: Object\n - Found: Array\n - Found: Object\n\n @param block Called for each element. Set *stop to `YES` if you have seen\n enough and would like to skip the rest of the elements.\n\n @param eh Called if the parser encounters an error.\n\n @see +unwrapRootArrayParserWithBlock:errorHandler:\n @see +parserWithBlock:allowMultiRoot:unwrapRootArray:maxDepth:errorHandler:\n */\n+ (id)multiRootParserWithBlock:(SBJson5ValueBlock)block\n                  errorHandler:(SBJson5ErrorBlock)eh;\n\n/**\n Create a parser that \"unwraps\" a top-level array.\n\n Often you won't have control over the input, so can't use a multi-root\n parser. But, all is not lost: if you are parsing a long array you can get the\n same effect by unwrapping the root array. Here is an example:\n\n    SBJson5ValueBlock block = ^(id v, BOOL *stop) {\n        BOOL isArray = [v isKindOfClass:[NSArray class]];\n        NSLog(@\"Found: %@\", isArray ? @\"Array\" : @\"Object\");\n    };\n\n    SBJson5ErrorBlock eh = ^(NSError* err) {\n        NSLog(@\"OOPS: %@\", err);\n    };\n\n    id parser = [SBJson5Parser unwrapRootArrayParserWithBlock:block\n                                                 errorHandler:eh];\n\n    // Note that this input contains A SINGLE top-level document\n    id data = [@\"[[],{},[],{}]\" dataWithEncoding:NSUTF8StringEncoding];\n    [parser parse:data];\n\n The above example will print:\n\n - Found: Array\n - Found: Object\n - Found: Array\n - Found: Object\n\n @param block Called for each element. Set *stop to `YES` if you have seen\n enough and would like to skip the rest of the elements.\n\n @param eh Called if the parser encounters an error.\n\n @see +multiRootParserWithBlock:errorHandler:\n @see +parserWithBlock:allowMultiRoot:unwrapRootArray:maxDepth:errorHandler:\n */\n+ (id)unwrapRootArrayParserWithBlock:(SBJson5ValueBlock)block\n                        errorHandler:(SBJson5ErrorBlock)eh;\n\n/**\n Feed data to parser\n\n The JSON is assumed to be UTF8 encoded. This can be a full JSON document, or\n a part of one.\n\n @param data An NSData object containing the next chunk of JSON\n\n @return\n - SBJson5ParserComplete if a full document was found\n - SBJson5ParserWaitingForData if a partial document was found and more data is required to complete it\n - SBJson5ParserError if an error occurred.\n\n */\n- (SBJson5ParserStatus)parse:(NSData*)data;\n\n@end\n"
  },
  {
    "path": "SBJson/SBJson5Parser.m",
    "content": "/*\n Copyright (c) 2010-2013, 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#if !__has_feature(objc_arc)\n#error \"This source file must be compiled with ARC enabled!\"\n#endif\n\n#import \"SBJson5Parser.h\"\n\n@interface SBJson5Parser () <SBJson5StreamParserDelegate>\n\n- (void)pop;\n\n@end\n\ntypedef enum {\n    SBJson5ChunkNone,\n    SBJson5ChunkArray,\n    SBJson5ChunkObject,\n} SBJson5ChunkType;\n\n@implementation SBJson5Parser {\n    SBJson5StreamParser *_parser;\n    NSUInteger depth;\n    NSMutableArray *array;\n    NSMutableDictionary *dict;\n    NSMutableArray *keyStack;\n    NSMutableArray *stack;\n    SBJson5ErrorBlock errorHandler;\n    SBJson5ValueBlock valueBlock;\n    SBJson5ChunkType currentType;\n    BOOL supportManyDocuments;\n    BOOL supportPartialDocuments;\n    NSUInteger _maxDepth;\n}\n\n#pragma mark Housekeeping\n\n- (id)init {\n    @throw @\"Not Implemented\";\n}\n\n+ (id)parserWithBlock:(SBJson5ValueBlock)block\n         errorHandler:(SBJson5ErrorBlock)eh {\n    return [self parserWithBlock:block\n                  allowMultiRoot:NO\n                 unwrapRootArray:NO\n                        maxDepth:32\n                    errorHandler:eh];\n}\n\n+ (id)multiRootParserWithBlock:(SBJson5ValueBlock)block\n                  errorHandler:(SBJson5ErrorBlock)eh {\n    return [self parserWithBlock:block\n                  allowMultiRoot:YES\n                 unwrapRootArray:NO\n                        maxDepth:32\n                    errorHandler:eh];\n}\n\n+ (id)unwrapRootArrayParserWithBlock:(SBJson5ValueBlock)block\n                        errorHandler:(SBJson5ErrorBlock)eh {\n    return [self parserWithBlock:block\n                  allowMultiRoot:NO\n                 unwrapRootArray:YES\n                        maxDepth:32\n                    errorHandler:eh];\n}\n\n+ (id)parserWithBlock:(SBJson5ValueBlock)block\n       allowMultiRoot:(BOOL)allowMultiRoot\n      unwrapRootArray:(BOOL)unwrapRootArray\n             maxDepth:(NSUInteger)maxDepth\n         errorHandler:(SBJson5ErrorBlock)eh {\n    return [[self alloc] initWithBlock:block\n                        allowMultiRoot:allowMultiRoot\n                       unwrapRootArray:unwrapRootArray\n                              maxDepth:maxDepth\n                          errorHandler:eh];\n}\n\n- (id)initWithBlock:(SBJson5ValueBlock)block\n     allowMultiRoot:(BOOL)multiRoot\n    unwrapRootArray:(BOOL)unwrapRootArray\n           maxDepth:(NSUInteger)maxDepth\n       errorHandler:(SBJson5ErrorBlock)eh {\n\n\tself = [super init];\n\tif (self) {\n        _parser = [SBJson5StreamParser parserWithDelegate:self];\n\n        supportManyDocuments = multiRoot;\n        supportPartialDocuments = unwrapRootArray;\n\n        valueBlock = block;\n\t\tkeyStack = [[NSMutableArray alloc] initWithCapacity:32];\n\t\tstack = [[NSMutableArray alloc] initWithCapacity:32];\n        errorHandler = eh ? eh : ^(NSError*err) { NSLog(@\"%@\", err); };\n\t\tcurrentType = SBJson5ChunkNone;\n        _maxDepth = maxDepth;\n\t}\n\treturn self;\n}\n\n\n#pragma mark Private methods\n\n- (void)pop {\n\t[stack removeLastObject];\n\tarray = nil;\n\tdict = nil;\n\tcurrentType = SBJson5ChunkNone;\n\n\tid value = [stack lastObject];\n\n\tif ([value isKindOfClass:[NSArray class]]) {\n\t\tarray = value;\n\t\tcurrentType = SBJson5ChunkArray;\n\t} else if ([value isKindOfClass:[NSDictionary class]]) {\n\t\tdict = value;\n\t\tcurrentType = SBJson5ChunkObject;\n\t}\n}\n\n- (void)parserFound:(id)obj isValue:(BOOL)isValue {\n    NSParameterAssert(obj);\n\n    switch (currentType) {\n    case SBJson5ChunkArray:\n        [array addObject:obj];\n        break;\n\n    case SBJson5ChunkObject:\n        NSParameterAssert(keyStack.count);\n        [dict setObject:obj forKey:[keyStack lastObject]];\n        [keyStack removeLastObject];\n        break;\n\n    case SBJson5ChunkNone: {\n        __block BOOL stop = NO;\n        valueBlock(obj, &stop);\n        if (stop) [_parser stop];\n    }\n        break;\n\n    default:\n        break;\n    }\n}\n\n\n#pragma mark Delegate methods\n\n- (void)parserFoundObjectStart {\n    ++depth;\n    if (depth > _maxDepth)\n        [self maxDepthError];\n\n    dict = [NSMutableDictionary new];\n\t[stack addObject:dict];\n    currentType = SBJson5ChunkObject;\n}\n\n- (void)parserFoundObjectKey:(NSString *)key_ {\n    [keyStack addObject:key_];\n}\n\n- (void)parserFoundObjectEnd {\n    depth--;\n\tid value = dict;\n\t[self pop];\n    [self parserFound:value isValue:NO ];\n}\n\n- (void)parserFoundArrayStart {\n    depth++;\n    if (depth > _maxDepth)\n        [self maxDepthError];\n\n    if (depth > 1 || !supportPartialDocuments) {\n\t\tarray = [NSMutableArray new];\n\t\t[stack addObject:array];\n\t\tcurrentType = SBJson5ChunkArray;\n    }\n}\n\n- (void)parserFoundArrayEnd {\n    depth--;\n    if (depth > 0 || !supportPartialDocuments) {\n\t\tid value = array;\n\t\t[self pop];\n        [self parserFound:value isValue:NO ];\n    }\n}\n\n- (void)maxDepthError {\n    id ui = @{ NSLocalizedDescriptionKey: [NSString stringWithFormat:@\"Input depth exceeds max depth of %lu\", (unsigned long)_maxDepth]};\n    errorHandler([NSError errorWithDomain:@\"org.sbjson.parser\" code:3 userInfo:ui]);\n    [_parser stop];\n}\n\n- (void)parserFoundBoolean:(BOOL)x {\n\t[self parserFound:[NSNumber numberWithBool:x] isValue:YES ];\n}\n\n- (void)parserFoundNull {\n    [self parserFound:[NSNull null] isValue:YES ];\n}\n\n- (void)parserFoundNumber:(NSNumber *)num {\n    [self parserFound:num isValue:YES ];\n}\n\n- (void)parserFoundString:(NSString *)string {\n    [self parserFound:string isValue:YES ];\n}\n\n- (void)parserFoundError:(NSError *)err {\n    errorHandler(err);\n}\n\n- (BOOL)parserShouldSupportManyDocuments {\n    return supportManyDocuments;\n}\n\n- (SBJson5ParserStatus)parse:(NSData *)data {\n    return [_parser parse:data];\n}\n\n@end\n"
  },
  {
    "path": "SBJson/SBJson5StreamParser.h",
    "content": "/*\n Copyright (c) 2010-2013, 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 SBJson5StreamParser;\n@class SBJson5StreamParserState;\n\ntypedef enum {\n    SBJson5ParserComplete,\n    SBJson5ParserStopped,\n    SBJson5ParserWaitingForData,\n    SBJson5ParserError,\n} SBJson5ParserStatus;\n\n\n/**\n Delegate for interacting directly with the low-level parser\n\n You will most likely find it much more convenient to use the SBJson5Parser instead.\n */\n@protocol SBJson5StreamParserDelegate < NSObject >\n\n/// Called when object start is found\n- (void)parserFoundObjectStart;\n\n/// Called when object key is found\n- (void)parserFoundObjectKey:(NSString *)key;\n\n/// Called when object end is found\n- (void)parserFoundObjectEnd;\n\n/// Called when array start is found\n- (void)parserFoundArrayStart;\n\n/// Called when array end is found\n- (void)parserFoundArrayEnd;\n\n/// Called when a boolean value is found\n- (void)parserFoundBoolean:(BOOL)x;\n\n/// Called when a null value is found\n- (void)parserFoundNull;\n\n/// Called when a number is found\n- (void)parserFoundNumber:(NSNumber *)num;\n\n/// Called when a string is found\n- (void)parserFoundString:(NSString *)string;\n\n/// Called when an error occurs\n- (void)parserFoundError:(NSError *)err;\n\n@optional\n\n/// Called to determine whether to allow multiple whitespace-separated documents\n- (BOOL)parserShouldSupportManyDocuments;\n\n@end\n\n/**\n Low-level Stream parser\n\n You most likely want to use the SBJson5Parser instead, but if you\n really need low-level access to tokens one-by-one you can use this class.\n */\n@interface SBJson5StreamParser : NSObject\n\n@property (nonatomic, weak) SBJson5StreamParserState *state; // Private\n@property (readonly) id<SBJson5StreamParserDelegate> delegate; // Private\n\n/**\n Create a streaming parser.\n\n @param delegate Receives a series of messages as the parser breaks down\n the JSON stream into valid tokens. Usually this would be an instance of\n SBJson5Parser, but you can substitute your own implementation of the\n SBJson5StreamParserDelegate protocol if you need to.\n*/\n+ (id)parserWithDelegate:(id<SBJson5StreamParserDelegate>)delegate;\n\n/**\n 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 - SBJson5ParserComplete if a full document was found\n - SBJson5ParserWaitingForData if a partial document was found and more data is required to complete it\n - SBJson5ParserError if an error occurred.\n\n */\n- (SBJson5ParserStatus)parse:(NSData*)data;\n\n/**\n Call this to cause parsing to stop.\n */\n- (void)stop;\n\n@end\n"
  },
  {
    "path": "SBJson/SBJson5StreamParser.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#if !__has_feature(objc_arc)\n#error \"This source file must be compiled with ARC enabled!\"\n#endif\n\n#import \"SBJson5StreamParser.h\"\n#import \"SBJson5StreamTokeniser.h\"\n#import \"SBJson5StreamParserState.h\"\n\n#define SBStringIsSurrogateHighCharacter(character) ((character >= 0xD800UL) && (character <= 0xDBFFUL))\n\n@implementation SBJson5StreamParser {\n    SBJson5StreamTokeniser *tokeniser;\n    BOOL stopped;\n    NSMutableArray *_stateStack;\n    __weak id<SBJson5StreamParserDelegate> _delegate;\n}\n\n#pragma mark Housekeeping\n\n- (id)init {\n    return [self initWithDelegate:nil];\n}\n\n+ (id)parserWithDelegate:(id<SBJson5StreamParserDelegate>)delegate {\n    return [[self alloc] initWithDelegate:delegate];\n}\n\n- (id)initWithDelegate:(id<SBJson5StreamParserDelegate>)delegate {\n    self = [super init];\n    if (self) {\n        _delegate = delegate;\n        _stateStack = [[NSMutableArray alloc] initWithCapacity:32];\n        _state = [SBJson5StreamParserStateStart sharedInstance];\n        tokeniser = [[SBJson5StreamTokeniser alloc] init];\n    }\n    return self;\n}\n\n\n#pragma mark Methods\n\n- (NSString*)tokenName:(sbjson5_token_t)token {\n\tswitch (token) {\n    case sbjson5_token_array_open:\n        return @\"start of array\";\n\n    case sbjson5_token_array_close:\n        return @\"end of array\";\n\n    case sbjson5_token_integer:\n    case sbjson5_token_real:\n        return @\"number\";\n\n    case sbjson5_token_string:\n    case sbjson5_token_encoded:\n        return @\"string\";\n\n    case sbjson5_token_bool:\n        return @\"boolean\";\n\n    case sbjson5_token_null:\n        return @\"null\";\n\n    case sbjson5_token_entry_sep:\n        return @\"key-value separator\";\n\n    case sbjson5_token_value_sep:\n        return @\"value separator\";\n\n    case sbjson5_token_object_open:\n        return @\"start of object\";\n\n    case sbjson5_token_object_close:\n        return @\"end of object\";\n\n    case sbjson5_token_eof:\n    case sbjson5_token_error:\n        break;\n\t}\n\tNSAssert(NO, @\"Should not get here\");\n\treturn @\"<aaiiie!>\";\n}\n\n- (void)handleObjectStart {\n    [_delegate parserFoundObjectStart];\n    [_stateStack addObject:_state];\n    _state = [SBJson5StreamParserStateObjectStart sharedInstance];\n}\n\n- (void)handleObjectEnd: (sbjson5_token_t) tok  {\n    _state = [_stateStack lastObject];\n    [_stateStack removeLastObject];\n    [_state parser:self shouldTransitionTo:tok];\n    [_delegate parserFoundObjectEnd];\n}\n\n- (void)handleArrayStart {\n    [_delegate parserFoundArrayStart];\n    [_stateStack addObject:_state];\n    _state = [SBJson5StreamParserStateArrayStart sharedInstance];\n}\n\n- (void)handleArrayEnd: (sbjson5_token_t) tok  {\n    _state = [_stateStack lastObject];\n    [_stateStack removeLastObject];\n    [_state parser:self shouldTransitionTo:tok];\n    [_delegate parserFoundArrayEnd];\n}\n\n- (void) handleTokenNotExpectedHere: (sbjson5_token_t) tok  {\n    NSString *tokenName = [self tokenName:tok];\n    NSString *stateName = [_state name];\n\n    _state = [SBJson5StreamParserStateError sharedInstance];\n    id ui = @{ NSLocalizedDescriptionKey : [NSString stringWithFormat:@\"Token '%@' not expected %@\", tokenName, stateName]};\n    [_delegate parserFoundError:[NSError errorWithDomain:@\"org.sbjson.parser\" code:2 userInfo:ui]];\n}\n\n- (SBJson5ParserStatus)parse:(NSData *)data_ {\n    @autoreleasepool {\n        [tokeniser appendData:data_];\n        \n        for (;;) {\n\n            if (stopped)\n                return SBJson5ParserStopped;\n            \n            if ([_state isError])\n                return SBJson5ParserError;\n\n            char *token;\n            NSUInteger token_len;\n            sbjson5_token_t tok = [tokeniser getToken:&token length:&token_len];\n            \n            switch (tok) {\n            case sbjson5_token_eof:\n                return [_state parserShouldReturn:self];\n\n            case sbjson5_token_error:\n                _state = [SBJson5StreamParserStateError sharedInstance];\n                [_delegate parserFoundError:[NSError errorWithDomain:@\"org.sbjson.parser\" code:3\n                                                            userInfo:@{NSLocalizedDescriptionKey : tokeniser.error}]];\n                return SBJson5ParserError;\n\n            default:\n                    \n                if (![_state parser:self shouldAcceptToken:tok]) {\n                    [self handleTokenNotExpectedHere: tok];\n                    return SBJson5ParserError;\n                }\n                    \n                switch (tok) {\n                case sbjson5_token_object_open:\n                    [self handleObjectStart];\n                    break;\n                            \n                case sbjson5_token_object_close:\n                    [self handleObjectEnd: tok];\n                    break;\n                            \n                case sbjson5_token_array_open:\n                    [self handleArrayStart];\n                    break;\n                            \n                case sbjson5_token_array_close:\n                    [self handleArrayEnd: tok];\n                    break;\n                            \n                case sbjson5_token_value_sep:\n                case sbjson5_token_entry_sep:\n                    [_state parser:self shouldTransitionTo:tok];\n                    break;\n                            \n                case sbjson5_token_bool:\n                    [_delegate parserFoundBoolean:token[0] == 't'];\n                    [_state parser:self shouldTransitionTo:tok];\n                    break;\n                            \n\n                case sbjson5_token_null:\n                    [_delegate parserFoundNull];\n                    [_state parser:self shouldTransitionTo:tok];\n                    break;\n\n                case sbjson5_token_integer: {\n                    const int UNSIGNED_LONG_LONG_MAX_DIGITS = 20;\n                    if (token_len <= UNSIGNED_LONG_LONG_MAX_DIGITS) {\n                        if (*token == '-')\n                            [_delegate parserFoundNumber:@(strtoll(token, NULL, 10))];\n                        else\n                            [_delegate parserFoundNumber:@(strtoull(token, NULL, 10))];\n                                \n                        [_state parser:self shouldTransitionTo:tok];\n                        break;\n                    }\n                }\n                    // FALL THROUGH\n\n                case sbjson5_token_real:\n                    [_delegate parserFoundNumber:@(strtod(token, NULL))];\n                    [_state parser:self shouldTransitionTo:tok];\n                    break;\n\n                case sbjson5_token_string:\n                    [self parserFoundString:[[NSString alloc] initWithBytes:token length:token_len encoding:NSUTF8StringEncoding]\n                                   forToken:tok];\n                    break;\n\n                case sbjson5_token_encoded:\n                    [self parserFoundString:[self decodeStringToken:token length:token_len]\n                                   forToken:tok];\n                    break;\n\n                default:\n                    break;\n                }\n                break;\n            }\n        }\n        return SBJson5ParserComplete;\n    }\n}\n\n- (void)parserFoundString:(NSString*)string forToken:(sbjson5_token_t)tok {\n    if ([_state needKey])\n        [_delegate parserFoundObjectKey:string];\n    else\n        [_delegate parserFoundString:string];\n    [_state parser:self shouldTransitionTo:tok];\n}\n\n- (unichar)decodeHexQuad:(char *)quad {\n    unichar ch = 0;\n    for (NSUInteger i = 0; i < 4; i++) {\n        int c = quad[i];\n        ch *= 16;\n        switch (c) {\n        case '0' ... '9': ch += c - '0'; break;\n        case 'a' ... 'f': ch += 10 + c - 'a'; break;\n        case 'A' ... 'F': ch += 10 + c - 'A'; break;\n        default: @throw @\"FUT FUT FUT\";\n        }\n    }\n    return ch;\n}\n\n- (NSString*)decodeStringToken:(char*)bytes length:(NSUInteger)len {\n    NSMutableData *buf = [NSMutableData dataWithCapacity:len];\n    for (NSUInteger i = 0; i < len;) {\n        switch ((unsigned char)bytes[i]) {\n        case '\\\\': {\n            switch ((unsigned char)bytes[++i]) {\n            case '\"': [buf appendBytes:\"\\\"\" length:1]; i++; break;\n            case '/': [buf appendBytes:\"/\" length:1]; i++; break;\n            case '\\\\': [buf appendBytes:\"\\\\\" length:1]; i++; break;\n            case 'b': [buf appendBytes:\"\\b\" length:1]; i++; break;\n            case 'f': [buf appendBytes:\"\\f\" length:1]; i++; break;\n            case 'n': [buf appendBytes:\"\\n\" length:1]; i++; break;\n            case 'r': [buf appendBytes:\"\\r\" length:1]; i++; break;\n            case 't': [buf appendBytes:\"\\t\" length:1]; i++; break;\n            case 'u': {\n                unichar hi = [self decodeHexQuad:bytes + i + 1];\n                i += 5;\n                if (SBStringIsSurrogateHighCharacter(hi)) {\n                    // Skip past \\u that we know is there..\n                    unichar lo = [self decodeHexQuad:bytes + i + 2];\n                    i += 6;\n                    [buf appendData:[[NSString stringWithFormat:@\"%C%C\", hi, lo] dataUsingEncoding:NSUTF8StringEncoding]];\n                } else {\n                    [buf appendData:[[NSString stringWithFormat:@\"%C\", hi] dataUsingEncoding:NSUTF8StringEncoding]];\n                }\n                break;\n            }\n            default: @throw @\"FUT FUT FUT\";\n            }\n            break;\n        }\n        default:\n            [buf appendBytes:bytes + i length:1];\n            i++;\n            break;\n        }\n    }\n    return [[NSString alloc] initWithData:buf encoding:NSUTF8StringEncoding];\n}\n\n- (void)stop {\n    stopped = YES;\n}\n\n@end\n"
  },
  {
    "path": "SBJson/SBJson5StreamParserState.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 \"SBJson5StreamTokeniser.h\"\n#import \"SBJson5StreamParser.h\"\n\n@interface SBJson5StreamParserState : NSObject\n+ (id)sharedInstance;\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token;\n- (SBJson5ParserStatus)parserShouldReturn:(SBJson5StreamParser *)parser;\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok;\n- (BOOL)needKey;\n- (BOOL)isError;\n\n- (NSString*)name;\n\n@end\n\n@interface SBJson5StreamParserStateStart : SBJson5StreamParserState\n@end\n\n@interface SBJson5StreamParserStateComplete : SBJson5StreamParserState\n@end\n\n@interface SBJson5StreamParserStateError : SBJson5StreamParserState\n@end\n\n@interface SBJson5StreamParserStateObjectStart : SBJson5StreamParserState\n@end\n\n@interface SBJson5StreamParserStateObjectGotKey : SBJson5StreamParserState\n@end\n\n@interface SBJson5StreamParserStateObjectSeparator : SBJson5StreamParserState\n@end\n\n@interface SBJson5StreamParserStateObjectGotValue : SBJson5StreamParserState\n@end\n\n@interface SBJson5StreamParserStateObjectNeedKey : SBJson5StreamParserState\n@end\n\n@interface SBJson5StreamParserStateArrayStart : SBJson5StreamParserState\n@end\n\n@interface SBJson5StreamParserStateArrayGotValue : SBJson5StreamParserState\n@end\n\n@interface SBJson5StreamParserStateArrayNeedValue : SBJson5StreamParserState\n@end\n"
  },
  {
    "path": "SBJson/SBJson5StreamParserState.m",
    "content": "/*\n Copyright (c) 2010-2013, 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#if !__has_feature(objc_arc)\n#error \"This source file must be compiled with ARC enabled!\"\n#endif\n\n#import \"SBJson5StreamParserState.h\"\n\n#define SINGLETON                                           \\\n    + (id)sharedInstance {                                  \\\n        static id state = nil;                              \\\n        if (!state) {                                       \\\n            @synchronized(self) {                           \\\n                if (!state) state = [[self alloc] init];    \\\n            }                                               \\\n        }                                                   \\\n        return state;                                       \\\n    }\n\n@implementation SBJson5StreamParserState\n\n+ (id)sharedInstance { return nil; }\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token {\n    return NO;\n}\n\n- (SBJson5ParserStatus)parserShouldReturn:(SBJson5StreamParser *)parser {\n    return SBJson5ParserWaitingForData;\n}\n\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok {}\n\n- (BOOL)needKey {\n    return NO;\n}\n\n- (NSString*)name {\n    return @\"<aaiie!>\";\n}\n\n- (BOOL)isError {\n    return NO;\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateStart\n\nSINGLETON\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token {\n    switch (token) {\n    case sbjson5_token_object_open:\n    case sbjson5_token_array_open:\n    case sbjson5_token_bool:\n    case sbjson5_token_null:\n    case sbjson5_token_integer:\n    case sbjson5_token_real:\n    case sbjson5_token_string:\n    case sbjson5_token_encoded:\n        return YES;\n\n    default:\n        return NO;\n\t}\n}\n\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok {\n\n    SBJson5StreamParserState *state = nil;\n    switch (tok) {\n    case sbjson5_token_array_open:\n        state = [SBJson5StreamParserStateArrayStart sharedInstance];\n        break;\n\n    case sbjson5_token_object_open:\n        state = [SBJson5StreamParserStateObjectStart sharedInstance];\n        break;\n\n    case sbjson5_token_array_close:\n    case sbjson5_token_object_close:\n        if ([parser.delegate respondsToSelector:@selector(parserShouldSupportManyDocuments)] && [parser.delegate parserShouldSupportManyDocuments])\n            state = parser.state;\n        else\n            state = [SBJson5StreamParserStateComplete sharedInstance];\n        break;\n\n    case sbjson5_token_eof:\n        return;\n\n    default:\n        break;\n    }\n\n\tparser.state = state;\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateComplete\n\nSINGLETON\n\n- (NSString*)name { return @\"after complete json\"; }\n\n- (SBJson5ParserStatus)parserShouldReturn:(SBJson5StreamParser *)parser {\n\treturn SBJson5ParserComplete;\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateError\n\nSINGLETON\n\n- (NSString*)name { return @\"in error\"; }\n\n- (SBJson5ParserStatus)parserShouldReturn:(SBJson5StreamParser *)parser {\n\treturn SBJson5ParserError;\n}\n\n- (BOOL)isError {\n    return YES;\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateObjectStart\n\nSINGLETON\n\n- (NSString*)name { return @\"at beginning of object\"; }\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson5_token_object_close:\n\t\tcase sbjson5_token_string:\n        case sbjson5_token_encoded:\n\t\t\treturn YES;\n\t\tdefault:\n\t\t\treturn NO;\n\t}\n}\n\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok {\n\tparser.state = [SBJson5StreamParserStateObjectGotKey sharedInstance];\n}\n\n- (BOOL)needKey {\n\treturn YES;\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateObjectGotKey\n\nSINGLETON\n\n- (NSString*)name { return @\"after object key\"; }\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token {\n\treturn token == sbjson5_token_entry_sep;\n}\n\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok {\n\tparser.state = [SBJson5StreamParserStateObjectSeparator sharedInstance];\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateObjectSeparator\n\nSINGLETON\n\n- (NSString*)name { return @\"as object value\"; }\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson5_token_object_open:\n\t\tcase sbjson5_token_array_open:\n\t\tcase sbjson5_token_bool:\n\t\tcase sbjson5_token_null:\n        case sbjson5_token_integer:\n        case sbjson5_token_real:\n        case sbjson5_token_string:\n        case sbjson5_token_encoded:\n\t\t\treturn YES;\n\n\t\tdefault:\n\t\t\treturn NO;\n\t}\n}\n\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok {\n\tparser.state = [SBJson5StreamParserStateObjectGotValue sharedInstance];\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateObjectGotValue\n\nSINGLETON\n\n- (NSString*)name { return @\"after object value\"; }\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson5_token_object_close:\n        case sbjson5_token_value_sep:\n\t\t\treturn YES;\n\n\t\tdefault:\n\t\t\treturn NO;\n\t}\n}\n\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok {\n\tparser.state = [SBJson5StreamParserStateObjectNeedKey sharedInstance];\n}\n\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateObjectNeedKey\n\nSINGLETON\n\n- (NSString*)name { return @\"in place of object key\"; }\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token {\n    return sbjson5_token_string == token || sbjson5_token_encoded == token;\n}\n\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok {\n\tparser.state = [SBJson5StreamParserStateObjectGotKey sharedInstance];\n}\n\n- (BOOL)needKey {\n\treturn YES;\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateArrayStart\n\nSINGLETON\n\n- (NSString*)name { return @\"at array start\"; }\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson5_token_object_close:\n        case sbjson5_token_entry_sep:\n        case sbjson5_token_value_sep:\n\t\t\treturn NO;\n\n\t\tdefault:\n\t\t\treturn YES;\n\t}\n}\n\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok {\n\tparser.state = [SBJson5StreamParserStateArrayGotValue sharedInstance];\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateArrayGotValue\n\nSINGLETON\n\n- (NSString*)name { return @\"after array value\"; }\n\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token {\n\treturn token == sbjson5_token_array_close || token == sbjson5_token_value_sep;\n}\n\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok {\n\tif (tok == sbjson5_token_value_sep)\n\t\tparser.state = [SBJson5StreamParserStateArrayNeedValue sharedInstance];\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJson5StreamParserStateArrayNeedValue\n\nSINGLETON\n\n- (NSString*)name { return @\"as array value\"; }\n\n\n- (BOOL)parser:(SBJson5StreamParser *)parser shouldAcceptToken:(sbjson5_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson5_token_array_close:\n        case sbjson5_token_entry_sep:\n\t\tcase sbjson5_token_object_close:\n\t\tcase sbjson5_token_value_sep:\n\t\t\treturn NO;\n\n\t\tdefault:\n\t\t\treturn YES;\n\t}\n}\n\n- (void)parser:(SBJson5StreamParser *)parser shouldTransitionTo:(sbjson5_token_t)tok {\n\tparser.state = [SBJson5StreamParserStateArrayGotValue sharedInstance];\n}\n\n@end\n\n"
  },
  {
    "path": "SBJson/SBJson5StreamTokeniser.h",
    "content": "//\n// Created by SuperPappi on 09/01/2013.\n//\n// To change the template use AppCode | Preferences | File Templates.\n//\n\n#import <Foundation/Foundation.h>\n\ntypedef enum {\n    sbjson5_token_error = -1,\n    sbjson5_token_eof,\n\n    sbjson5_token_array_open,\n    sbjson5_token_array_close,\n    sbjson5_token_value_sep,\n\n    sbjson5_token_object_open,\n    sbjson5_token_object_close,\n    sbjson5_token_entry_sep,\n\n    sbjson5_token_bool,\n    sbjson5_token_null,\n\n    sbjson5_token_integer,\n    sbjson5_token_real,\n\n    sbjson5_token_string,\n    sbjson5_token_encoded,\n} sbjson5_token_t;\n\n\n@interface SBJson5StreamTokeniser : NSObject\n\n@property (nonatomic, readonly, copy) NSString *error;\n\n- (void)appendData:(NSData*)data_;\n- (sbjson5_token_t)getToken:(char**)tok length:(NSUInteger*)len;\n\n@end\n\n"
  },
  {
    "path": "SBJson/SBJson5StreamTokeniser.m",
    "content": "//\n// Created by SuperPappi on 09/01/2013.\n//\n// To change the template use AppCode | Preferences | File Templates.\n//\n\n\n#import \"SBJson5StreamTokeniser.h\"\n\n#define SBStringIsIllegalSurrogateHighCharacter(character) (((character) >= 0xD800UL) && ((character) <= 0xDFFFUL))\n#define SBStringIsSurrogateLowCharacter(character) ((character >= 0xDC00UL) && (character <= 0xDFFFUL))\n#define SBStringIsSurrogateHighCharacter(character) ((character >= 0xD800UL) && (character <= 0xDBFFUL))\n\n@implementation SBJson5StreamTokeniser {\n    NSMutableData *data;\n    const char *bytes;\n    NSUInteger index;\n    NSUInteger offset;\n}\n\n- (void)setError:(NSString *)error {\n    _error = [NSString stringWithFormat:@\"%@ at index %lu\", error, (unsigned long)(offset + index)];\n}\n\n- (void)appendData:(NSData *)data_ {\n    if (!data) {\n        data = [data_ mutableCopy];\n\n    } else if (index) {\n        // Discard data we've already parsed\n        [data replaceBytesInRange:NSMakeRange(0, index) withBytes:\"\" length:0];\n        [data appendData:data_];\n\n        // Add to the offset for reporting\n        offset += index;\n\n        // Reset index to point to current position\n        index = 0u;\n\n    }\n    else {\n       [data appendData:data_];\n    }\n\n    bytes = [data bytes];\n}\n\n- (void)skipWhitespace {\n    while (index < data.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        }\n    }\n}\n\n- (BOOL)getUnichar:(unichar *)ch {\n    if ([self haveRemainingBytes:1]) {\n        *ch = (unichar) bytes[index];\n        return YES;\n    }\n    return NO;\n}\n\n- (BOOL)haveOneMoreByte {\n    return [self haveRemainingBytes:1];\n}\n\n- (BOOL)haveRemainingBytes:(NSUInteger)length {\n    return data.length - index >= length;\n}\n\n- (sbjson5_token_t)match:(char *)str retval:(sbjson5_token_t)tok token:(char **)token length:(NSUInteger *)length {\n    NSUInteger len = strlen(str);\n    if ([self haveRemainingBytes:len]) {\n        if (!memcmp(bytes + index, str, len)) {\n            *token = str;\n            *length = len;\n            index += len;\n            return tok;\n        }\n        [self setError: [NSString stringWithFormat:@\"Expected '%s' after initial '%.1s'\", str, str]];\n        return sbjson5_token_error;\n    }\n\n    return sbjson5_token_eof;\n}\n\n- (BOOL)decodeHexQuad:(unichar*)quad {\n    unichar tmp = 0;\n\n    for (int i = 0; i < 4; i++, index++) {\n        unichar c = (unichar)bytes[index];\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- (sbjson5_token_t)getStringToken:(char **)token length:(NSUInteger *)length {\n\n    // Skip initial \"\n    index++;\n\n    NSUInteger string_start = index;\n    sbjson5_token_t tok = sbjson5_token_string;\n\n    for (;;) {\n        if (![self haveOneMoreByte])\n            return sbjson5_token_eof;\n\n        switch ((uint8_t)bytes[index]) {\n            case 0 ... 0x1F:\n                [self setError:[NSString stringWithFormat:@\"Unescaped control character [0x%0.2hhX] in string\", bytes[index]]];\n                return sbjson5_token_error;\n\n            case '\"':\n                *token = (char *)(bytes + string_start);\n                *length = index - string_start;\n                index++;\n                return tok;\n\n            case '\\\\':\n                tok = sbjson5_token_encoded;\n                index++;\n                if (![self haveOneMoreByte])\n                    return sbjson5_token_eof;\n\n                if (bytes[index] == 'u') {\n                    index++;\n                    if (![self haveRemainingBytes:4])\n                        return sbjson5_token_eof;\n\n                    unichar hi;\n                    if (![self decodeHexQuad:&hi]) {\n                        [self setError:@\"Invalid hex quad\"];\n                        return sbjson5_token_error;\n                    }\n\n                    if (SBStringIsSurrogateHighCharacter(hi)) {\n                        if (![self haveRemainingBytes:6])\n                            return sbjson5_token_eof;\n\n                        unichar lo;\n                        if (bytes[index++] != '\\\\' || bytes[index++] != 'u' || ![self decodeHexQuad:&lo]) {\n                            [self setError:@\"Missing low character in surrogate pair\"];\n                            return sbjson5_token_error;\n                        }\n\n                        if (!SBStringIsSurrogateLowCharacter(lo)) {\n                            [self setError:@\"Invalid low character in surrogate pair\"];\n                            return sbjson5_token_error;\n                        }\n\n                    } else if (SBStringIsIllegalSurrogateHighCharacter(hi)) {\n                        [self setError:@\"Invalid high character in surrogate pair\"];\n                        return sbjson5_token_error;\n\n                    }\n\n\n                } else {\n                    switch (bytes[index]) {\n                        case '\\\\':\n                        case '/':\n                        case '\"':\n                        case 'b':\n                        case 'n':\n                        case 'r':\n                        case 't':\n                        case 'f':\n                            index++;\n                            break;\n\n                        default:\n                            [self setError:[NSString stringWithFormat:@\"Illegal escape character [0x%0.2hhX]\", bytes[index]]];\n                            return sbjson5_token_error;\n                    }\n                }\n\n                break;\n\n            case 0x80 ... 0xBF:\n                [self setError:[NSString stringWithFormat: @\"Unexpected UTF-8 continuation byte [0x%0.2hhX]\", bytes[index]]];\n                return sbjson5_token_error;\n\n            case 0xC0 ... 0xC1:\n            case 0xF5 ... 0xFF:\n                // Flat out illegal UTF-8 bytes, see\n                // https://en.wikipedia.org/wiki/UTF-8#Codepage_layout\n                [self setError:[NSString stringWithFormat: @\"Illegal UTF-8 byte [0x%0.2hhX]\", bytes[index]]];\n                return sbjson5_token_error;\n                break;\n\n            case 0xC2 ... 0xDF:\n                // Expecting 1 continuation byte\n                index++;\n                if (![self haveOneMoreByte]) return sbjson5_token_eof;\n                if (![self isContinuationByte]) return sbjson5_token_error;\n                index++;\n                break;\n\n            case 0xE0 ... 0xEF: {\n                // Expecting 2 continuation bytes\n                long cp = bytes[index] & 0x0F;\n                index++;\n                for (NSUInteger i = 0; i < 2; i++) {\n                    if (![self haveOneMoreByte]) return sbjson5_token_eof;\n                    if (![self isContinuationByte]) return sbjson5_token_error;\n                    cp = cp << 6 | (bytes[index] & 0x3F);\n                    index++;\n                }\n\n                if (!(cp & 0b1111100000000000)) {\n                    [self setError:[NSString stringWithFormat:@\"Illegal overlong encoding [0x%0.2hhX %0.2hhX %0.2hhX]\",\n                                    bytes[index-3], bytes[index-2], bytes[index-1]]];\n                    return sbjson5_token_error;\n                }\n\n                if ([self isInvalidCodePoint:cp])\n                    return sbjson5_token_error;\n\n                break;\n            }\n\n            case 0xF0 ... 0xF4: {\n                // Expecting 3 continuation bytes\n                long cp = bytes[index] & 0x07;\n                index++;\n                for (NSUInteger i = 0; i < 3; i++) {\n                    if (![self haveOneMoreByte]) return sbjson5_token_eof;\n                    if (![self isContinuationByte]) return sbjson5_token_error;\n                    cp = cp << 6 | (bytes[index] & 0x3F);\n                    index++;\n                }\n\n                if (!(cp & 0b111110000000000000000)) {\n                    [self setError:[NSString stringWithFormat:@\"Illegal overlong encoding [0x%0.2hhX %0.2hhX %0.2hhX %0.2hhX]\",\n                                    bytes[index-4], bytes[index-3], bytes[index-2], bytes[index-1]]];\n                    return sbjson5_token_error;\n                }\n\n                if ([self isInvalidCodePoint:cp])\n                    return sbjson5_token_error;\n\n                break;\n            }\n\n            default:\n                index++;\n                break;\n        }\n    }\n}\n\n- (BOOL)isInvalidCodePoint:(long)cp {\n    if (cp > 0x10FFFF || SBStringIsSurrogateLowCharacter(cp) || SBStringIsSurrogateHighCharacter(cp)) {\n        [self setError:[NSString stringWithFormat:@\"Illegal Unicode code point [0x%lX]\", cp]];\n        return YES;\n    }\n    return NO;\n}\n\n- (BOOL)isContinuationByte {\n    if ((bytes[index] & 0b11000000) != 0b10000000) {\n        [self setError:[NSString stringWithFormat:@\"Missing UTF-8 continuation byte; found [0x%0.2hhX]\", bytes[index]]];\n        return NO;\n    }\n    return YES;\n}\n\n- (sbjson5_token_t)getNumberToken:(char **)token length:(NSUInteger *)length {\n    NSUInteger num_start = index;\n    if (bytes[index] == '-') {\n        index++;\n\n        if (![self haveOneMoreByte])\n            return sbjson5_token_eof;\n    }\n\n    sbjson5_token_t tok = sbjson5_token_integer;\n    if (bytes[index] == '0') {\n        index++;\n\n        if (![self haveOneMoreByte])\n            return sbjson5_token_eof;\n\n        if (isdigit(bytes[index])) {\n            [self setError:@\"Leading zero is illegal in number\"];\n            return sbjson5_token_error;\n        }\n    }\n\n    while (isdigit(bytes[index])) {\n        index++;\n        if (![self haveOneMoreByte])\n            return sbjson5_token_eof;\n    }\n\n    if (![self haveOneMoreByte])\n        return sbjson5_token_eof;\n\n\n    if (bytes[index] == '.') {\n        index++;\n        tok = sbjson5_token_real;\n\n        if (![self haveOneMoreByte])\n            return sbjson5_token_eof;\n\n        NSUInteger fraction_start = index;\n        while (isdigit(bytes[index])) {\n            index++;\n            if (![self haveOneMoreByte])\n                return sbjson5_token_eof;\n        }\n\n        if (fraction_start == index) {\n            [self setError:@\"No digits after decimal point\"];\n            return sbjson5_token_error;\n        }\n    }\n\n    if (bytes[index] == 'e' || bytes[index] == 'E') {\n        index++;\n        tok = sbjson5_token_real;\n\n        if (![self haveOneMoreByte])\n            return sbjson5_token_eof;\n\n        if (bytes[index] == '-' || bytes[index] == '+') {\n            index++;\n            if (![self haveOneMoreByte])\n                return sbjson5_token_eof;\n        }\n\n        NSUInteger exp_start = index;\n        while (isdigit(bytes[index])) {\n            index++;\n            if (![self haveOneMoreByte])\n                return sbjson5_token_eof;\n        }\n\n        if (exp_start == index) {\n            [self setError:@\"No digits in exponent\"];\n            return sbjson5_token_error;\n        }\n\n    }\n\n    if (num_start + 1 == index && bytes[num_start] == '-') {\n        [self setError:@\"No digits after initial minus\"];\n        return sbjson5_token_error;\n    }\n\n    *token = (char *)(bytes + num_start);\n    *length = index - num_start;\n    return tok;\n}\n\n\n- (sbjson5_token_t)getToken:(char **)token length:(NSUInteger *)length {\n    [self skipWhitespace];\n    NSUInteger copyOfIndex = index;\n\n    unichar ch;\n    if (![self getUnichar:&ch])\n        return sbjson5_token_eof;\n\n    sbjson5_token_t tok;\n    switch (ch) {\n        case '{': {\n            index++;\n            tok = sbjson5_token_object_open;\n            break;\n        }\n        case '}': {\n            index++;\n            tok = sbjson5_token_object_close;\n            break;\n\n        }\n        case '[': {\n            index++;\n            tok = sbjson5_token_array_open;\n            break;\n\n        }\n        case ']': {\n            index++;\n            tok = sbjson5_token_array_close;\n            break;\n\n        }\n        case 't': {\n            tok = [self match:\"true\" retval:sbjson5_token_bool token:token length:length];\n            break;\n\n        }\n        case 'f': {\n            tok = [self match:\"false\" retval:sbjson5_token_bool token:token length:length];\n            break;\n\n        }\n        case 'n': {\n            tok = [self match:\"null\" retval:sbjson5_token_null token:token length:length];\n            break;\n\n        }\n        case ',': {\n            index++;\n            tok = sbjson5_token_value_sep;\n            break;\n\n        }\n        case ':': {\n            index++;\n            tok = sbjson5_token_entry_sep;\n            break;\n\n        }\n        case '\"': {\n            tok = [self getStringToken:token length:length];\n            break;\n\n        }\n        case '-':\n        case '0' ... '9': {\n            tok = [self getNumberToken:token length:length];\n            break;\n\n        }\n        case '+': {\n            self.error = @\"Leading + is illegal in number\";\n            tok = sbjson5_token_error;\n            break;\n\n        }\n        default: {\n            self.error = [NSString stringWithFormat:@\"Illegal start of token [%c]\", ch];\n            tok = sbjson5_token_error;\n            break;\n        }\n    }\n\n    if (tok == sbjson5_token_eof) {\n        // We ran out of bytes before we could finish parsing the current token.\n        // Back up to the start & wait for more data.\n        index = copyOfIndex;\n    }\n\n    return tok;\n}\n\n@end\n"
  },
  {
    "path": "SBJson/SBJson5StreamWriter.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 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     - (id)proxyForJson {\n        return [NSDictionary dictionaryWithObjectsAndKeys:\n        name, @\"name\",\n        phone, @\"phone\",\n        email, @\"email\",\n        nil];\n     }\n\n */\n- (id)proxyForJson;\n\n@end\n\n@class SBJson5StreamWriter;\n\n@protocol SBJson5StreamWriterDelegate\n\n- (void)writer:(SBJson5StreamWriter *)writer appendBytes:(const void *)bytes length:(NSUInteger)length;\n\n@end\n\n@class SBJson5StreamWriterState;\n\n/**\n 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 Objective-C types are mapped to JSON types in the following way:\n\n - NSNull        -> null\n - NSString      -> string\n - NSArray       -> array\n - NSDictionary  -> object\n - NSNumber's -initWithBool:YES -> true\n - NSNumber's -initWithBool:NO  -> false\n - NSNumber      -> number\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 @warning: 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 */\n\n@interface SBJson5StreamWriter : NSObject {\n    NSMutableDictionary *cache;\n}\n\n@property (nonatomic, weak) SBJson5StreamWriterState *state; // Internal\n@property (nonatomic, readonly, strong) NSMutableArray *stateStack; // Internal\n\n/**\n Create a JSON stream writer\n\n @param delegate Delegate that will receive messages with output.\n\n @param maxDepth If the input is nested deeper than this the input will be\n deemed to be malicious and the parser returns nil, signalling an error.\n (\"Nested too deep\".) You can turn off this security feature by setting the\n maxDepth to 0.\n\n @param humanReadable If YES, produces human-readable output with linebreaks\n and indentation.\n\n @param sortKeys Whether or not to sort the dictionary keys in the output.\n (Useful if you need to compare two structures.)\n\n @param sortKeysComparator A custom comparator to sort dictionary keys when @p\n sortKeys is YES. If nil, @selector(compare:) is used for sorting.\n\n */\n\n+ (id)writerWithDelegate:(id<SBJson5StreamWriterDelegate>)delegate\n                maxDepth:(NSUInteger)maxDepth\n           humanReadable:(BOOL)humanReadable\n                sortKeys:(BOOL)sortKeys\n      sortKeysComparator:(NSComparator)sortKeysComparator;\n\n/// Contains the error description after an error has occurred.\n@property (nonatomic, 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 SBJson5StreamWriter (Private)\n- (BOOL)writeValue:(id)v;\n- (void)appendBytes:(const void *)bytes length:(NSUInteger)length;\n@end\n\n"
  },
  {
    "path": "SBJson/SBJson5StreamWriter.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#if !__has_feature(objc_arc)\n#error \"This source file must be compiled with ARC enabled!\"\n#endif\n\n#import \"SBJson5StreamWriter.h\"\n#import \"SBJson5StreamWriterState.h\"\n\nstatic NSNumber *kTrue;\nstatic NSNumber *kFalse;\nstatic NSNumber *kPositiveInfinity;\nstatic NSNumber *kNegativeInfinity;\n\n\n@implementation SBJson5StreamWriter {\n    BOOL _sortKeys, _humanReadable;\n    NSUInteger _maxDepth;\n    __weak id<SBJson5StreamWriterDelegate> _delegate;\n    NSComparator _sortKeysComparator;\n}\n\n+ (void)initialize {\n    kPositiveInfinity = [NSNumber numberWithDouble:+HUGE_VAL];\n    kNegativeInfinity = [NSNumber numberWithDouble:-HUGE_VAL];\n    kTrue = [NSNumber numberWithBool:YES];\n    kFalse = [NSNumber numberWithBool:NO];\n}\n\n#pragma mark Housekeeping\n\n- (id)init {\n    @throw @\"Not Implemented\";\n}\n\n+ (id)writerWithDelegate:(id<SBJson5StreamWriterDelegate>)delegate\n                maxDepth:(NSUInteger)maxDepth\n           humanReadable:(BOOL)humanReadable\n                sortKeys:(BOOL)sortKeys\n      sortKeysComparator:(NSComparator)sortKeysComparator {\n    return [[self alloc] initWithDelegate:delegate\n                                 maxDepth:maxDepth\n                            humanReadable:humanReadable\n                                 sortKeys:sortKeys\n                       sortKeysComparator:sortKeysComparator];\n}\n\n- (id)initWithDelegate:(id<SBJson5StreamWriterDelegate>)delegate\n              maxDepth:(NSUInteger)maxDepth\n         humanReadable:(BOOL)humanReadable\n              sortKeys:(BOOL)sortKeys\n    sortKeysComparator:(NSComparator)sortKeysComparator {\n\tself = [super init];\n\tif (self) {\n        _delegate = delegate;\n\t\t_maxDepth = maxDepth;\n        _sortKeys = sortKeys;\n        _humanReadable = humanReadable;\n        _sortKeysComparator = sortKeysComparator;\n        _stateStack = [[NSMutableArray alloc] initWithCapacity:maxDepth];\n        _state = [SBJson5StreamWriterStateStart sharedInstance];\n        cache = [[NSMutableDictionary alloc] initWithCapacity:32];\n    }\n\treturn self;\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\n\tif (_sortKeys) {\n\t\tif (_sortKeysComparator) {\n\t\t\tkeys = [keys sortedArrayWithOptions:NSSortStable usingComparator:_sortKeysComparator];\n\t\t}\n\t\telse{\n\t\t\tkeys = [keys sortedArrayUsingSelector:@selector(compare:)];\n\t\t}\n\t}\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 = [SBJson5StreamWriterStateObjectStart 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    SBJson5StreamWriterState *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 = [SBJson5StreamWriterStateArrayStart 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    SBJson5StreamWriterState *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\treturn [self writeString:o];\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\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\";\n\t\tcase 1: return \"\\\\u0001\";\n\t\tcase 2: return \"\\\\u0002\";\n\t\tcase 3: return \"\\\\u0003\";\n\t\tcase 4: return \"\\\\u0004\";\n\t\tcase 5: return \"\\\\u0005\";\n\t\tcase 6: return \"\\\\u0006\";\n\t\tcase 7: return \"\\\\u0007\";\n\t\tcase 8: return \"\\\\b\";\n\t\tcase 9: return \"\\\\t\";\n\t\tcase 10: return \"\\\\n\";\n\t\tcase 11: return \"\\\\u000b\";\n\t\tcase 12: return \"\\\\f\";\n\t\tcase 13: return \"\\\\r\";\n\t\tcase 14: return \"\\\\u000e\";\n\t\tcase 15: return \"\\\\u000f\";\n\t\tcase 16: return \"\\\\u0010\";\n\t\tcase 17: return \"\\\\u0011\";\n\t\tcase 18: return \"\\\\u0012\";\n\t\tcase 19: return \"\\\\u0013\";\n\t\tcase 20: return \"\\\\u0014\";\n\t\tcase 21: return \"\\\\u0015\";\n\t\tcase 22: return \"\\\\u0016\";\n\t\tcase 23: return \"\\\\u0017\";\n\t\tcase 24: return \"\\\\u0018\";\n\t\tcase 25: return \"\\\\u0019\";\n\t\tcase 26: return \"\\\\u001a\";\n\t\tcase 27: return \"\\\\u001b\";\n\t\tcase 28: return \"\\\\u001c\";\n\t\tcase 29: return \"\\\\u001d\";\n\t\tcase 30: return \"\\\\u001e\";\n\t\tcase 31: return \"\\\\u001f\";\n\t\tcase 34: return \"\\\\\\\"\";\n\t\tcase 92: return \"\\\\\\\\\";\n\t\tdefault:\n\t\t\t[NSException raise:@\"Illegal escape char\" format:@\"-->%c<-- is not a legal escape character\", c];\n\t\t\treturn NULL;\n\t}\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 = [cache 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:(NSUInteger)(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        [cache 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 (number == kTrue || number == kFalse)\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 ([kPositiveInfinity isEqualToNumber:number]) {\n\t\tself.error = @\"+Infinity is not a valid number in JSON\";\n\t\treturn NO;\n\n\t} else if ([kNegativeInfinity isEqualToNumber:number]) {\n\t\tself.error = @\"-Infinity is not a valid number in JSON\";\n\t\treturn NO;\n\n\t} else if (isnan([number doubleValue])) {\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            len = snprintf(num, sizeof num, \"%.17g\", [number doubleValue]);\n\t\t\tbreak;\n        }\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": "SBJson/SBJson5StreamWriterState.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 SBJson5StreamWriter;\n\n@interface SBJson5StreamWriterState : NSObject\n+ (id)sharedInstance;\n- (BOOL)isInvalidState:(SBJson5StreamWriter *)writer;\n- (void)appendSeparator:(SBJson5StreamWriter *)writer;\n- (BOOL)expectingKey:(SBJson5StreamWriter *)writer;\n- (void)transitionState:(SBJson5StreamWriter *)writer;\n- (void)appendWhitespace:(SBJson5StreamWriter *)writer;\n@end\n\n@interface SBJson5StreamWriterStateObjectStart : SBJson5StreamWriterState\n@end\n\n@interface SBJson5StreamWriterStateObjectKey : SBJson5StreamWriterStateObjectStart\n@end\n\n@interface SBJson5StreamWriterStateObjectValue : SBJson5StreamWriterState\n@end\n\n@interface SBJson5StreamWriterStateArrayStart : SBJson5StreamWriterState\n@end\n\n@interface SBJson5StreamWriterStateArrayValue : SBJson5StreamWriterState\n@end\n\n@interface SBJson5StreamWriterStateStart : SBJson5StreamWriterState\n@end\n\n@interface SBJson5StreamWriterStateComplete : SBJson5StreamWriterState\n@end\n\n@interface SBJson5StreamWriterStateError : SBJson5StreamWriterState\n@end\n\n"
  },
  {
    "path": "SBJson/SBJson5StreamWriterState.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#if !__has_feature(objc_arc)\n#error \"This source file must be compiled with ARC enabled!\"\n#endif\n\n#import \"SBJson5StreamWriterState.h\"\n#import \"SBJson5StreamWriter.h\"\n\n#define SINGLETON                                           \\\n    + (id)sharedInstance {                                  \\\n        static id state = nil;                              \\\n        if (!state) {                                       \\\n            @synchronized(self) {                           \\\n                if (!state) state = [[self alloc] init];    \\\n            }                                               \\\n        }                                                   \\\n        return state;                                       \\\n    }\n\n\n@implementation SBJson5StreamWriterState\n+ (id)sharedInstance { return nil; }\n- (BOOL)isInvalidState:(SBJson5StreamWriter *)writer { return NO; }\n- (void)appendSeparator:(SBJson5StreamWriter *)writer {}\n- (BOOL)expectingKey:(SBJson5StreamWriter *)writer { return NO; }\n- (void)transitionState:(SBJson5StreamWriter *)writer {}\n- (void)appendWhitespace:(SBJson5StreamWriter *)writer {\n    [writer appendBytes:\"\\n\" length:1];\n    for (NSUInteger i = 0; i < writer.stateStack.count; i++)\n        [writer appendBytes:\"  \" length:2];\n}\n@end\n\n@implementation SBJson5StreamWriterStateObjectStart\n\nSINGLETON\n\n- (void)transitionState:(SBJson5StreamWriter *)writer {\n    writer.state = [SBJson5StreamWriterStateObjectValue sharedInstance];\n}\n- (BOOL)expectingKey:(SBJson5StreamWriter *)writer {\n    writer.error = @\"JSON object key must be string\";\n    return YES;\n}\n@end\n\n@implementation SBJson5StreamWriterStateObjectKey\n\nSINGLETON\n\n- (void)appendSeparator:(SBJson5StreamWriter *)writer {\n    [writer appendBytes:\",\" length:1];\n}\n@end\n\n@implementation SBJson5StreamWriterStateObjectValue\n\nSINGLETON\n\n- (void)appendSeparator:(SBJson5StreamWriter *)writer {\n    [writer appendBytes:\":\" length:1];\n}\n- (void)transitionState:(SBJson5StreamWriter *)writer {\n    writer.state = [SBJson5StreamWriterStateObjectKey sharedInstance];\n}\n- (void)appendWhitespace:(SBJson5StreamWriter *)writer {\n    [writer appendBytes:\" \" length:1];\n}\n@end\n\n@implementation SBJson5StreamWriterStateArrayStart\n\nSINGLETON\n\n- (void)transitionState:(SBJson5StreamWriter *)writer {\n    writer.state = [SBJson5StreamWriterStateArrayValue sharedInstance];\n}\n@end\n\n@implementation SBJson5StreamWriterStateArrayValue\n\nSINGLETON\n\n- (void)appendSeparator:(SBJson5StreamWriter *)writer {\n    [writer appendBytes:\",\" length:1];\n}\n@end\n\n@implementation SBJson5StreamWriterStateStart\n\nSINGLETON\n\n\n- (void)transitionState:(SBJson5StreamWriter *)writer {\n    writer.state = [SBJson5StreamWriterStateComplete sharedInstance];\n}\n- (void)appendSeparator:(SBJson5StreamWriter *)writer {\n}\n@end\n\n@implementation SBJson5StreamWriterStateComplete\n\nSINGLETON\n\n- (BOOL)isInvalidState:(SBJson5StreamWriter *)writer {\n\twriter.error = @\"Stream is closed\";\n\treturn YES;\n}\n@end\n\n@implementation SBJson5StreamWriterStateError\n\nSINGLETON\n\n@end\n\n"
  },
  {
    "path": "SBJson/SBJson5Writer.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 The JSON writer class.\n\n This uses SBJson5StreamWriter internally.\n\n */\n\n@interface SBJson5Writer : NSObject\n\n/**\n Create a JSON Writer instance.\n\n @param maxDepth If the input is nested deeper than this the input will be\n deemed to be malicious and the parser returns nil, signalling an error.\n (\"Nested too deep\".) You can turn off this security feature by setting the\n maxDepth value to 0. Defaults to 32.\n\n @param humanReadable Whether we are generating human-readable (multi line)\n JSON. If set to YES, generates human-readable JSON with line breaks after\n each array value and dictionary key/value pair, indented two spaces per\n nesting level. The default is NO, which produces JSON without any whitespace.\n (Except inside strings.)\n\n @param sortKeys Whether to sort the dictionary keys in the output.\n The default is to not sort the keys.\n\n @see -writerWithMaxDepth:humanReadable:customSortKeysComparator:\n */\n+ (id)writerWithMaxDepth:(NSUInteger)maxDepth\n           humanReadable:(BOOL)humanReadable\n                sortKeys:(BOOL)sortKeys;\n\n\n/**\n Create a JSON Writer instance.\n\n @param maxDepth If the input is nested deeper than this the input will be\n deemed to be malicious and the parser returns nil, signalling an error.\n (\"Nested too deep\".) You can turn off this security feature by setting the\n maxDepth value to 0. Defaults to 32.\n\n @param humanReadable Whether we are generating human-readable (multi line)\n JSON. If set to YES, generates human-readable JSON with line breaks after\n each array value and dictionary key/value pair, indented two spaces per\n nesting level. The default is NO, which produces JSON without any whitespace.\n (Except inside strings.)\n\n @param sortKeysComparator Use this if you want a custom sort order for your\n dictionary keys.\n\n @see -writerWithMaxDepth:humanReadable:sortKeys: if you just care about sort\n order being stable.\n\n */\n+ (id)writerWithMaxDepth:(NSUInteger)maxDepth\n           humanReadable:(BOOL)humanReadable\n      sortKeysComparator:(NSComparator)sortKeysComparator;\n\n/**\n 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 (nonatomic, readonly, copy) NSString *error;\n\n/**\n Generates string with 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 error is not NULL, *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 Generates 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@end\n"
  },
  {
    "path": "SBJson/SBJson5Writer.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#if !__has_feature(objc_arc)\n#error \"This source file must be compiled with ARC enabled!\"\n#endif\n\n#import \"SBJson5Writer.h\"\n#import \"SBJson5StreamWriter.h\"\n\n\n@interface SBJson5Writer () < SBJson5StreamWriterDelegate >\n@property (nonatomic, copy) NSString *error;\n@property (nonatomic, strong) NSMutableData *acc;\n@end\n\n@implementation SBJson5Writer {\n    NSUInteger _maxDepth;\n    BOOL _sortKeys;\n    NSComparator _sortKeysComparator;\n    BOOL _humanReadable;\n}\n\n- (id)init {\n    return [self initWithMaxDepth:32\n                    humanReadable:NO\n                         sortKeys:NO\n               sortKeysComparator:nil];\n}\n\n- (id)initWithMaxDepth:(NSUInteger)maxDepth\n         humanReadable:(BOOL)humanReadable\n              sortKeys:(BOOL)sortKeys\n    sortKeysComparator:(NSComparator)sortKeysComparator {\n    self = [super init];\n    if (self) {\n        _maxDepth = maxDepth;\n        _humanReadable = humanReadable;\n        _sortKeys = sortKeys;\n        _sortKeysComparator = sortKeysComparator;\n    }\n    return self;\n}\n\n+ (id)writerWithMaxDepth:(NSUInteger)maxDepth\n           humanReadable:(BOOL)humanReadable\n                sortKeys:(BOOL)sortKeys {\n    return [[self alloc] initWithMaxDepth:maxDepth\n                            humanReadable:humanReadable\n                                 sortKeys:sortKeys\n                       sortKeysComparator:nil];\n}\n\n+ (id)writerWithMaxDepth:(NSUInteger)maxDepth\n           humanReadable:(BOOL)humanReadable\n      sortKeysComparator:(NSComparator)keyComparator {\n    return [[self alloc] initWithMaxDepth:maxDepth\n                            humanReadable:humanReadable\n                                 sortKeys:YES\n                       sortKeysComparator:keyComparator];\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];\n\treturn nil;\n}\n\n- (NSData*)dataWithObject:(id)object {\n    self.error = nil;\n\n    self.acc = [[NSMutableData alloc] initWithCapacity:8096u];\n\n    SBJson5StreamWriter *streamWriter = [SBJson5StreamWriter writerWithDelegate:self\n                                                                       maxDepth:_maxDepth\n                                                                  humanReadable:_humanReadable\n                                                                       sortKeys:_sortKeys\n                                                             sortKeysComparator:_sortKeysComparator];\n\n\tif ([streamWriter writeValue:object])\n\t\treturn self.acc;\n\n\tself.error = streamWriter.error;\n\treturn nil;\n}\n\n#pragma mark SBJson5StreamWriterDelegate\n\n- (void)writer:(SBJson5StreamWriter *)writer appendBytes:(const void *)bytes length:(NSUInteger)length {\n    [self.acc appendBytes:bytes length:length];\n}\n\n\n\n@end\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Reporting a Vulnerability\n\nPlease report security vulnerabilities here: https://hackerone.com/irccloud\n"
  },
  {
    "path": "ShareExtension/Info-Enterprise.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>IRCEnterprise</string>\n\t<key>CFBundleExecutable</key>\n\t<string>${EXECUTABLE_NAME}</string>\n\t<key>CFBundleIcons</key>\n\t<dict/>\n\t<key>CFBundleIcons~ipad</key>\n\t<dict/>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</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>XPC!</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>VERSION_STRING</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>GIT_VERSION</string>\n\t<key>NSExtension</key>\n\t<dict>\n\t\t<key>NSExtensionAttributes</key>\n\t\t<dict>\n\t\t\t<key>NSExtensionActivationRule</key>\n\t\t\t<string>(SUBQUERY (\n    extensionItems,\n    $extensionItem,\n    SUBQUERY (\n        $extensionItem.attachments,\n        $attachment,\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.image\" ||\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.movie\" ||\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.plain-text\" ||\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.url\"\n    ).@count == $extensionItem.attachments.@count).@count == 1 AND\nSUBQUERY (\n    extensionItems,\n    $extensionItem,\n    SUBQUERY (\n        $extensionItem.attachments,\n        $attachment,\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.image\" ||\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.movie\"\n    ).@count &lt;= 1).@count == 1 AND\nSUBQUERY (\n    extensionItems,\n    $extensionItem,\n    SUBQUERY (\n        $extensionItem.attachments,\n        $attachment,\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.file-url\"\n    ).@count &lt;= 1).@count == 1\n) OR (\nSUBQUERY(extensionItems, $extensionItem, \nSUBQUERY($extensionItem.attachments, $attachment, SUBQUERY($attachment.registeredTypeIdentifiers, $uti, $uti UTI-CONFORMS-TO \"public.url\" AND NOT $uti UTI-CONFORMS-TO \"public.file-url\").@count == 1).@count == 1).@count == 1\n)</string>\n\t\t</dict>\n\t\t<key>NSExtensionPointIdentifier</key>\n\t\t<string>com.apple.share-services</string>\n\t\t<key>NSExtensionPrincipalClass</key>\n\t\t<string>ShareViewController</string>\n\t</dict>\n\t<key>UIAppFonts</key>\n\t<array>\n\t\t<string>FontAwesome.otf</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "ShareExtension/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>UIDesignRequiresCompatibility</key>\n\t<true/>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>IRCCloud</string>\n\t<key>CFBundleExecutable</key>\n\t<string>${EXECUTABLE_NAME}</string>\n\t<key>CFBundleIcons</key>\n\t<dict/>\n\t<key>CFBundleIcons~ipad</key>\n\t<dict/>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</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>XPC!</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>VERSION_STRING</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>GIT_VERSION</string>\n\t<key>NSExtension</key>\n\t<dict>\n\t\t<key>NSExtensionAttributes</key>\n\t\t<dict>\n\t\t\t<key>IntentsSupported</key>\n\t\t\t<array>\n\t\t\t\t<string>INSendMessageIntent</string>\n\t\t\t</array>\n\t\t\t<key>NSExtensionActivationRule</key>\n\t\t\t<string>(SUBQUERY (\n    extensionItems,\n    $extensionItem,\n    SUBQUERY (\n        $extensionItem.attachments,\n        $attachment,\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO &quot;public.image&quot; ||\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO &quot;public.movie&quot; ||\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO &quot;public.plain-text&quot; ||\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO &quot;public.url&quot;\n    ).@count == $extensionItem.attachments.@count).@count == 1 AND\nSUBQUERY (\n    extensionItems,\n    $extensionItem,\n    SUBQUERY (\n        $extensionItem.attachments,\n        $attachment,\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO &quot;public.image&quot; ||\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO &quot;public.movie&quot;\n    ).@count &lt;= 1).@count == 1 AND\nSUBQUERY (\n    extensionItems,\n    $extensionItem,\n    SUBQUERY (\n        $extensionItem.attachments,\n        $attachment,\n        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO &quot;public.file-url&quot;\n    ).@count &lt;= 1).@count == 1\n) OR (\nSUBQUERY(extensionItems, $extensionItem, \nSUBQUERY($extensionItem.attachments, $attachment, SUBQUERY($attachment.registeredTypeIdentifiers, $uti, $uti UTI-CONFORMS-TO &quot;public.url&quot; AND NOT $uti UTI-CONFORMS-TO &quot;public.file-url&quot;).@count == 1).@count == 1).@count == 1\n)</string>\n\t\t</dict>\n\t\t<key>NSExtensionPointIdentifier</key>\n\t\t<string>com.apple.share-services</string>\n\t\t<key>NSExtensionPrincipalClass</key>\n\t\t<string>ShareViewController</string>\n\t</dict>\n\t<key>UIAppFonts</key>\n\t<array>\n\t\t<string>FontAwesome.otf</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "ShareExtension/ShareExtension.entitlements",
    "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>com.apple.security.app-sandbox</key>\n\t<true/>\n\t<key>com.apple.security.application-groups</key>\n\t<array>\n\t\t<string>group.com.irccloud.share</string>\n\t</array>\n\t<key>com.apple.security.network.client</key>\n\t<true/>\n\t<key>keychain-access-groups</key>\n\t<array>\n\t\t<string>$(AppIdentifierPrefix)com.irccloud.IRCCloud</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "ShareExtension/ShareViewController.h",
    "content": "//\n//  ShareViewController.h\n//  ShareExtension\n//\n//  Created by Sam Steele on 7/22/14.\n//  Copyright (c) 2014 IRCCloud, Ltd. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import <Social/Social.h>\n#import \"BuffersTableView.h\"\n#import \"NetworkConnection.h\"\n#import \"FileUploader.h\"\n\n@interface ShareViewController : SLComposeServiceViewController<BuffersTableViewDelegate,FileUploaderDelegate,UITextFieldDelegate,UITextViewDelegate> {\n    NetworkConnection *_conn;\n    BuffersTableView *_buffersView;\n    UIViewController *_splash;\n    Buffer *_buffer;\n    FileUploader *_fileUploader;\n    SystemSoundID _sound;\n    NSString *_filename;\n    UIImage *_item;\n    BOOL _uploadStarted;\n    IRCCloudAPIResultHandler _resultHandler;\n}\n@property SystemSoundID sound;\n@end\n"
  },
  {
    "path": "ShareExtension/ShareViewController.m",
    "content": "//\n//  ShareViewController.m\n//  ShareExtension\n//\n//  Created by Sam Steele on 7/22/14.\n//  Copyright (c) 2014 IRCCloud, Ltd. All rights reserved.\n//\n\n#import <AudioToolbox/AudioToolbox.h>\n#import <Intents/Intents.h>\n#import \"ShareViewController.h\"\n#import \"BuffersTableView.h\"\n#import \"UIColor+IRCCloud.h\"\n@import Firebase;\n\n@implementation ShareViewController\n\n- (void)presentationAnimationDidFinish {\n    if(self->_conn.session.length) {\n#ifdef ENTERPRISE\n        NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n        NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n        if([d boolForKey:@\"uploadsAvailable\"]) {\n            NSExtensionItem *input = self.extensionContext.inputItems.firstObject;\n            NSExtensionItem *output = [input copy];\n            output.attributedContentText = [[NSAttributedString alloc] initWithString:self.contentText attributes:nil];\n            \n            if(output.attachments.count) {\n                NSItemProvider *i = nil;\n                for(NSItemProvider *p in output.attachments) {\n                    if([p hasItemConformingToTypeIdentifier:@\"public.url\"] && ![p hasItemConformingToTypeIdentifier:@\"public.file-url\"]) {\n                        NSLog(@\"Attachment has a public URL\");\n                        i = p;\n                        break;\n                    }\n                }\n                if(!i) {\n                    for(NSItemProvider *p in output.attachments) {\n                        if(([p hasItemConformingToTypeIdentifier:@\"public.file-url\"] && ![p hasItemConformingToTypeIdentifier:@\"public.image\"]) || [p hasItemConformingToTypeIdentifier:@\"public.movie\"]) {\n                            NSLog(@\"Attachment is file URL\");\n                            i = p;\n                            break;\n                        }\n                    }\n                }\n                if(!i) {\n                    for(NSItemProvider *p in output.attachments) {\n                        if([p hasItemConformingToTypeIdentifier:@\"public.image\"]) {\n                            NSLog(@\"Attachment is image\");\n                            i = p;\n                            break;\n                        }\n                    }\n                }\n                if(!i)\n                    i = output.attachments.firstObject;\n                \n                NSItemProviderCompletionHandler imageHandler = ^(UIImage *item, NSError *error) {\n                    NSLog(@\"Uploading image to IRCCloud\");\n                    self->_item = item;\n                    if([i hasItemConformingToTypeIdentifier:@\"public.png\"])\n                        [self->_fileUploader uploadPNG:item];\n                    else\n                        [self->_fileUploader uploadImage:item];\n                    if(!self->_filename)\n                        self->_filename = self->_fileUploader.originalFilename;\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        [self reloadConfigurationItems];\n                        [self validateContent];\n                    }];\n                };\n                \n                NSItemProviderCompletionHandler urlHandler = ^(NSURL *item, NSError *error) {\n                    if([i hasItemConformingToTypeIdentifier:@\"public.image\"] && ![item.pathExtension.lowercaseString isEqualToString:@\"gif\"] && ![item.pathExtension.lowercaseString isEqualToString:@\"png\"]) {\n                            self->_fileUploader.originalFilename = [[item pathComponents] lastObject];\n                        [i loadItemForTypeIdentifier:@\"public.image\" options:nil completionHandler:imageHandler];\n                    } else {\n                        NSLog(@\"Uploading file to IRCCloud\");\n                        [i hasItemConformingToTypeIdentifier:@\"public.movie\"]?[self->_fileUploader uploadVideo:item]:[self->_fileUploader uploadFile:item];\n                        if(!self->_filename)\n                            self->_filename = self->_fileUploader.originalFilename;\n                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                            [self reloadConfigurationItems];\n                            [self validateContent];\n                        }];\n                    }\n                };\n                \n                if([i hasItemConformingToTypeIdentifier:@\"public.file-url\"]) {\n                    [i loadItemForTypeIdentifier:@\"public.file-url\" options:nil completionHandler:urlHandler];\n                } else if([i hasItemConformingToTypeIdentifier:@\"public.url\"]) {\n                    self->_fileUploader = nil;\n                    [self reloadConfigurationItems];\n                    [self validateContent];\n                } else if([i hasItemConformingToTypeIdentifier:@\"public.movie\"]) {\n                    [i loadItemForTypeIdentifier:@\"public.movie\" options:nil completionHandler:urlHandler];\n                } else if([i hasItemConformingToTypeIdentifier:@\"public.image\"]) {\n                    [i loadItemForTypeIdentifier:@\"public.image\" options:nil completionHandler:imageHandler];\n                } else {\n                    self->_uploadStarted = YES;\n                }\n            }\n        } else {\n            self->_uploadStarted = YES;\n        }\n    } else {\n        UIAlertController *c = [UIAlertController alertControllerWithTitle:@\"Not Logged in\" message:@\"Please login to the IRCCloud app before sharing.\" preferredStyle:UIAlertControllerStyleAlert];\n        [c addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {\n            [self cancel];\n        }]];\n        [self presentViewController:c animated:YES completion:nil];\n    }\n}\n\n- (void)viewDidLoad {\n    if([FIROptions defaultOptions]) {\n        [FIRApp configure];\n    }\n    __weak ShareViewController *weakSelf = self;\n    self->_resultHandler = ^(IRCCloudJSONObject *result) {\n        NSLog(@\"Say result: %@\", result);\n        [weakSelf.extensionContext completeRequestReturningItems:nil completionHandler:nil];\n        AudioServicesPlaySystemSound(weakSelf.sound);\n    };\n    [UIColor setTheme:@\"dawn\"];\n    if (@available(iOS 13, *)) {\n        NSString *theme = [UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark?@\"midnight\":@\"dawn\";\n        [UIColor setTheme:theme];\n        self.view.window.overrideUserInterfaceStyle = self.view.overrideUserInterfaceStyle = [theme isEqualToString:@\"dawn\"]?UIUserInterfaceStyleLight:UIUserInterfaceStyleDark;\n    } else {\n        [UIColor setTheme:@\"dawn\"];\n    }\n    [super viewDidLoad];\n    self.textView.superview.superview.superview.superview.backgroundColor = [UIColor contentBackgroundColor];\n    [[NSNotificationCenter defaultCenter] addObserver:self\n                                             selector:@selector(backlogComplete:)\n                                                 name:kIRCCloudBacklogCompletedNotification object:nil];\n#ifdef ENTERPRISE\n    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n    NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n    IRCCLOUD_HOST = [d objectForKey:@\"host\"];\n    IRCCLOUD_PATH = [d objectForKey:@\"path\"];\n    self->_fileUploader = [[FileUploader alloc] init];\n    self->_fileUploader.delegate = self;\n    [[NSUserDefaults standardUserDefaults] setObject:[d objectForKey:@\"cacheVersion\"] forKey:@\"cacheVersion\"];\n    [[NSUserDefaults standardUserDefaults] registerDefaults:@{@\"fontSize\":@([UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody].pointSize * 0.8)}];\n    if([d objectForKey:@\"fontSize\"])\n        [[NSUserDefaults standardUserDefaults] setObject:[d objectForKey:@\"fontSize\"] forKey:@\"fontSize\"];\n    [NetworkConnection sync];\n    self->_conn = [NetworkConnection sharedInstance];\n    self->_buffer = nil;\n    if(self->_conn.session.length) {\n        if([BuffersDataSource sharedInstance].count && _conn.userInfo) {\n            [self backlogComplete:nil];\n        }\n        [self->_conn connect:YES];\n    }\n    if (@available(iOS 15.0, *)) {\n        [self.navigationController.navigationBar setStandardAppearance:[UINavigationBar appearance].standardAppearance];\n        [self.navigationController.navigationBar setScrollEdgeAppearance:[UINavigationBar appearance].scrollEdgeAppearance];\n        [self.navigationController.navigationBar setCompactAppearance:[UINavigationBar appearance].compactAppearance];\n        [self.navigationController.navigationBar setCompactScrollEdgeAppearance:[UINavigationBar appearance].compactScrollEdgeAppearance];\n    } else {\n        [self.navigationController.navigationBar setBackgroundImage:[UIColor navBarBackgroundImage] forBarMetrics:UIBarMetricsDefault];\n    }\n    self.title = @\"IRCCloud\";\n    self->_sound = 1001;\n    self.textView.returnKeyType = UIReturnKeySend;\n    self.textView.delegate = self;\n}\n\n-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {\n    if([text isEqualToString:@\"\\n\"]) {\n        [self didSelectPost];\n        return NO;\n    }\n    return YES;\n}\n\n- (void)backlogComplete:(NSNotification *)n {\n    if (@available(iOS 13.0, *)) {\n        if(self.extensionContext && [self.extensionContext.intent isKindOfClass:INSendMessageIntent.class]) {\n            INSendMessageIntent *intent = (INSendMessageIntent *)self.extensionContext.intent;\n            INPerson *person = intent.recipients.firstObject;\n            if(person && [person.customIdentifier hasPrefix:@\"irccloud://\"]) {\n                NSString *ident = [person.customIdentifier substringFromIndex:11];\n                NSUInteger sep = [ident rangeOfString:@\"/\"].location;\n                int cid = [ident substringToIndex:sep].intValue;\n                NSString *to = [ident substringFromIndex:sep + 1];\n                Buffer *b = [[Buffer alloc] init];\n                b.bid = -1;\n                b.cid = cid;\n                b.name = to;\n                self->_buffer = b;\n            }\n        }\n    } else {\n    }\n    if(!self->_buffer)\n        self->_buffer = [[BuffersDataSource sharedInstance] getBuffer:[[self->_conn.userInfo objectForKey:@\"last_selected_bid\"] intValue]];\n    if(!self->_buffer)\n        self->_buffer = [[BuffersDataSource sharedInstance] getBuffer:[BuffersDataSource sharedInstance].mostRecentBid];\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        [self reloadConfigurationItems];\n        [self validateContent];\n    }];\n}\n\n- (BOOL)isContentValid {\n    if(self->_fileUploader && !self->_uploadStarted)\n        return NO;\n    return _conn.session.length && _buffer != nil && ![self->_buffer.type isEqualToString:@\"console\"];\n}\n\n- (void)didSelectPost {\n    NSExtensionItem *input = self.extensionContext.inputItems.firstObject;\n    NSExtensionItem *output = [input copy];\n    output.attributedContentText = [[NSAttributedString alloc] initWithString:self.contentText attributes:nil];\n\n    if(self->_buffer == nil || self->_buffer.name == nil) {\n        return;\n    }\n    \n    if(output.attachments.count) {\n        if(self->_fileUploader.originalFilename) {\n            NSLog(@\"Setting filename, bid, and message for IRCCloud upload\");\n            self->_fileUploader.to = @[@{@\"cid\":@(self->_buffer.cid), @\"to\":self->_buffer.name}];\n            [self->_fileUploader setFilename:self->_filename message:self.contentText];\n            if(!self->_fileUploader.finished) {\n                [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                    [self.extensionContext completeRequestReturningItems:@[output] completionHandler:nil];\n                }];\n            }\n        } else {\n            NSItemProvider *i = nil;\n            for(NSItemProvider *p in output.attachments) {\n                if([p hasItemConformingToTypeIdentifier:@\"public.url\"] && ![p hasItemConformingToTypeIdentifier:@\"public.file-url\"]) {\n                    i = p;\n                    break;\n                }\n            }\n            if(!i) {\n                for(NSItemProvider *p in output.attachments) {\n                    if([p hasItemConformingToTypeIdentifier:@\"public.image\"]) {\n                        i = p;\n                        break;\n                    }\n                }\n            }\n            if(!i)\n                i = output.attachments.firstObject;\n\n            NSItemProviderCompletionHandler imageHandler = ^(UIImage *item, NSError *error) {\n                self->_fileUploader.to = @[@{@\"cid\":@(self->_buffer.cid), @\"to\":self->_buffer.name}];\n                [self->_fileUploader setFilename:self->_filename message:self.contentText];\n                [self->_fileUploader uploadImage:item];\n                if(!self->_fileUploader.finished) {\n                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n                        [self.extensionContext completeRequestReturningItems:nil completionHandler:nil];\n                    }];\n                }\n            };\n            \n            NSItemProviderCompletionHandler urlHandler = ^(NSURL *item, NSError *error) {\n                if([item.scheme isEqualToString:@\"file\"] && [i hasItemConformingToTypeIdentifier:@\"public.image\"]) {\n                    [i loadItemForTypeIdentifier:@\"public.image\" options:nil completionHandler:imageHandler];\n                } else {\n                    if(self.contentText.length)\n                        [self->_conn say:[NSString stringWithFormat:@\"%@ %@\",self.contentText,item.absoluteString] to:self->_buffer.name cid:self->_buffer.cid handler:self->_resultHandler];\n                    else\n                        [self->_conn say:item.absoluteString to:self->_buffer.name cid:self->_buffer.cid handler:self->_resultHandler];\n                }\n            };\n            \n            if([i hasItemConformingToTypeIdentifier:@\"public.url\"]) {\n                [i loadItemForTypeIdentifier:@\"public.url\" options:nil completionHandler:urlHandler];\n            } else if([i hasItemConformingToTypeIdentifier:@\"public.movie\"]) {\n                [i loadItemForTypeIdentifier:@\"public.movie\" options:nil completionHandler:urlHandler];\n            } else if([i hasItemConformingToTypeIdentifier:@\"public.image\"]) {\n                [i loadItemForTypeIdentifier:@\"public.image\" options:nil completionHandler:imageHandler];\n            } else if([i hasItemConformingToTypeIdentifier:@\"public.plain-text\"]) {\n                [self->_conn say:self.contentText to:self->_buffer.name cid:self->_buffer.cid handler:self->_resultHandler];\n            } else {\n                NSLog(@\"Unknown attachment type: %@\", output.attachments.firstObject);\n                [self.extensionContext completeRequestReturningItems:nil completionHandler:nil];\n                AudioServicesPlaySystemSound(self->_sound);\n            }\n        }\n    } else {\n        [self->_conn say:self.contentText to:self->_buffer.name cid:self->_buffer.cid handler:self->_resultHandler];\n    }\n}\n\n- (NSArray *)configurationItems {\n    if(self->_conn.session.length) {\n        SLComposeSheetConfigurationItem *bufferConfigItem = [[SLComposeSheetConfigurationItem alloc] init];\n        bufferConfigItem.title = @\"Conversation\";\n        if(self->_buffer) {\n            if(![self->_buffer.type isEqualToString:@\"console\"])\n                bufferConfigItem.value = self->_buffer.displayName;\n            else\n                bufferConfigItem.value = nil;\n        } else {\n            bufferConfigItem.valuePending = YES;\n        }\n        \n        bufferConfigItem.tapHandler = ^() {\n            BuffersTableView *b = [[BuffersTableView alloc] initWithStyle:UITableViewStylePlain];\n            [b setPreferredContentSize:CGSizeMake(self.navigationController.preferredContentSize.width, [BuffersDataSource sharedInstance].count * 42)];\n            b.navigationItem.title = @\"Conversations\";\n            b.delegate = self;\n            [self pushConfigurationViewController:b];\n        };\n\n#ifdef ENTERPRISE\n        NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.enterprise.share\"];\n#else\n        NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:@\"group.com.irccloud.share\"];\n#endif\n        if(self->_fileUploader && [d boolForKey:@\"uploadsAvailable\"]) {\n            NSExtensionItem *input = self.extensionContext.inputItems.firstObject;\n            NSExtensionItem *output = [input copy];\n            output.attributedContentText = [[NSAttributedString alloc] initWithString:self.contentText attributes:nil];\n            \n            if(output.attachments.count && ([output.attachments.firstObject hasItemConformingToTypeIdentifier:@\"public.image\"] || [output.attachments.firstObject hasItemConformingToTypeIdentifier:@\"public.movie\"])) {\n                SLComposeSheetConfigurationItem *filenameConfigItem = [[SLComposeSheetConfigurationItem alloc] init];\n                filenameConfigItem.title = @\"Filename\";\n                if(self->_filename)\n                    filenameConfigItem.value = self->_filename;\n                else\n                    filenameConfigItem.valuePending = YES;\n                \n                filenameConfigItem.tapHandler = ^() {\n                    [self.view.window endEditing:YES];\n                    UIAlertController *c = [UIAlertController alertControllerWithTitle:@\"Enter a Filename\" message:nil preferredStyle:UIAlertControllerStyleAlert];\n                    [c addTextFieldWithConfigurationHandler:^(UITextField *textField) {\n                        textField.text = self->_filename;\n                        textField.delegate = self;\n                        textField.placeholder = @\"Filename\";\n                        textField.tintColor = [UIColor isDarkTheme]?[UIColor whiteColor]:[UIColor blackColor];\n                    }];\n                    [c addAction:[UIAlertAction actionWithTitle:@\"Save\" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {\n                        self->_filename = [[c.textFields objectAtIndex:0] text];\n                        [self reloadConfigurationItems];\n                    }]];\n                    \n                    [self presentViewController:c animated:YES completion:nil];\n                };\n                \n                if(!self->_uploadStarted) {\n                    SLComposeSheetConfigurationItem *exporting = [[SLComposeSheetConfigurationItem alloc] init];\n                    exporting.title = [output.attachments.firstObject hasItemConformingToTypeIdentifier:@\"public.movie\"]?@\"Exporting Video\":@\"Resizing Photo\";\n                    exporting.valuePending = YES;\n\n                    return @[filenameConfigItem, bufferConfigItem, exporting];\n                } else {\n                    return @[filenameConfigItem, bufferConfigItem];\n                }\n            } else {\n                return @[bufferConfigItem];\n            }\n        } else {\n            return @[bufferConfigItem];\n        }\n    } else {\n        return nil;\n    }\n}\n\n-(void)textFieldDidBeginEditing:(UITextField *)textField {\n    if(textField.text.length) {\n        textField.selectedTextRange = [textField textRangeFromPosition:textField.beginningOfDocument\n                                                            toPosition:([textField.text rangeOfString:@\".\"].location != NSNotFound)?[textField positionFromPosition:textField.beginningOfDocument offset:[textField.text rangeOfString:@\".\" options:NSBackwardsSearch].location]:textField.endOfDocument];\n    }\n}\n\n-(void)bufferSelected:(int)bid {\n    Buffer *b = [[BuffersDataSource sharedInstance] getBuffer:bid];\n    if(b && ![b.type isEqualToString:@\"console\"]) {\n        self->_buffer = b;\n        [self reloadConfigurationItems];\n        [self validateContent];\n        [self popConfigurationViewController];\n    }\n}\n\n-(void)bufferLongPressed:(int)bid rect:(CGRect)rect {\n    \n}\n\n-(void)dismissKeyboard {\n    \n}\n\n-(void)fileUploadProgress:(float)progress {\n    if(!self->_uploadStarted) {\n        NSLog(@\"File upload started\");\n        self->_uploadStarted = YES;\n        [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n            [self reloadConfigurationItems];\n            [self validateContent];\n        }];\n    }\n}\n\n-(void)fileUploadDidFail:(NSString *)reason {\n    NSLog(@\"File upload failed: %@\", reason);\n    \n    NSString *msg;\n    if([reason isEqualToString:@\"upload_limit_reached\"]) {\n        msg = @\"Sorry, you can’t upload more than 100 MB of files.  Delete some uploads and try again.\";\n    } else if([reason isEqualToString:@\"upload_already_exists\"]) {\n        msg = @\"You’ve already uploaded this file\";\n    } else if([reason isEqualToString:@\"banned_content\"]) {\n        msg = @\"Banned content\";\n    } else {\n        msg= @\"Failed to upload file. Please try again shortly.\";\n    }\n\n    UIAlertController *c = [UIAlertController alertControllerWithTitle:@\"Upload Failed\" message:msg preferredStyle:UIAlertControllerStyleAlert];\n    [c addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {\n        [self cancel];\n        [self.extensionContext completeRequestReturningItems:nil completionHandler:nil];\n    }]];\n    [self presentViewController:c animated:YES completion:nil];\n}\n\n-(void)fileUploadTooLarge {\n    NSLog(@\"File upload too large\");\n    UIAlertController *c = [UIAlertController alertControllerWithTitle:@\"Upload Failed\" message:@\"Sorry, you can’t upload files larger than 15 MB\" preferredStyle:UIAlertControllerStyleAlert];\n    [c addAction:[UIAlertAction actionWithTitle:@\"Close\" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {\n        [self cancel];\n        [self.extensionContext completeRequestReturningItems:nil completionHandler:nil];\n    }]];\n    [self presentViewController:c animated:YES completion:nil];\n}\n\n-(void)fileUploadDidFinish {\n    NSLog(@\"File upload successful\");\n    [self->_conn disconnect];\n    AudioServicesPlaySystemSound(self->_sound);\n    [[NSOperationQueue mainQueue] addOperationWithBlock:^{\n        [self.extensionContext completeRequestReturningItems:nil completionHandler:nil];\n    }];\n}\n\n-(void)fileUploadWasCancelled {\n}\n\n-(void)spamSelected:(int)cid {\n    \n}\n\n-(void)addNetwork {\n    \n}\n@end\n"
  },
  {
    "path": "ShareExtension Enterprise.entitlements",
    "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>com.apple.security.application-groups</key>\n\t<array>\n\t\t<string>group.com.irccloud.enterprise.share</string>\n\t</array>\n\t<key>keychain-access-groups</key>\n\t<array>\n\t\t<string>$(AppIdentifierPrefix)com.irccloud.enterprise</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "StringScore/NSString+Score.h",
    "content": "//\n//  NSString+Score.h\n//\n//  Created by Nicholas Bruning on 5/12/11.\n//  Copyright (c) 2011 Involved Pty Ltd. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\nenum{\n    NSStringScoreOptionNone                         = 1 << 0,\n    NSStringScoreOptionFavorSmallerWords            = 1 << 1,\n    NSStringScoreOptionReducedLongStringPenalty     = 1 << 2\n};\n\ntypedef NSUInteger NSStringScoreOption;\n\n@interface NSString (Score)\n\n- (CGFloat) scoreAgainst:(NSString *)otherString;\n- (CGFloat) scoreAgainst:(NSString *)otherString fuzziness:(NSNumber *)fuzziness;\n- (CGFloat) scoreAgainst:(NSString *)otherString fuzziness:(NSNumber *)fuzziness options:(NSStringScoreOption)options;\n\n@end\n"
  },
  {
    "path": "StringScore/NSString+Score.m",
    "content": "//\n//  NSString+Score.m\n//\n//  Created by Nicholas Bruning on 5/12/11.\n//  Copyright (c) 2011 Involved Pty Ltd. All rights reserved.\n//\n\n//score reference: http://jsfiddle.net/JrLVD/\n\n#import \"NSString+Score.h\"\n\n@implementation NSString (Score)\n\n- (CGFloat) scoreAgainst:(NSString *)otherString{\n    return [self scoreAgainst:otherString fuzziness:nil];\n}\n\n- (CGFloat) scoreAgainst:(NSString *)otherString fuzziness:(NSNumber *)fuzziness{\n    return [self scoreAgainst:otherString fuzziness:fuzziness options:NSStringScoreOptionNone];\n}\n\n- (CGFloat) scoreAgainst:(NSString *)anotherString fuzziness:(NSNumber *)fuzziness options:(NSStringScoreOption)options{\n    NSCharacterSet *invalidCharacterSet = NSCharacterSet.punctuationCharacterSet;\n    \n    NSString *string = [[[self decomposedStringWithCanonicalMapping] componentsSeparatedByCharactersInSet:invalidCharacterSet] componentsJoinedByString:@\"\"];\n    NSString *otherString = [[[anotherString decomposedStringWithCanonicalMapping] componentsSeparatedByCharactersInSet:invalidCharacterSet] componentsJoinedByString:@\"\"];\n    \n    // If the string is equal to the abbreviation, perfect match.\n    if([string isEqualToString:otherString]) return (CGFloat) 1.0f;\n    \n    //if it's not a perfect match and is empty return 0\n    if([otherString length] == 0) return (CGFloat) 0.0f;\n    \n    CGFloat totalCharacterScore = 0;\n    NSUInteger otherStringLength = [otherString length];\n    NSUInteger stringLength = [string length];\n    BOOL startOfStringBonus = NO;\n    CGFloat otherStringScore;\n    CGFloat fuzzies = 1;\n    CGFloat finalScore;\n        \n    // Walk through abbreviation and add up scores.\n    for(uint index = 0; index < otherStringLength; index++){\n        CGFloat characterScore = 0.1;\n        NSInteger indexInString = NSNotFound;\n        NSString *chr;\n        NSRange rangeChrLowercase;\n        NSRange rangeChrUppercase;\n\n        chr = [otherString substringWithRange:NSMakeRange(index, 1)];\n        \n        //make these next few lines leverage NSNotfound, methinks.\n        rangeChrLowercase = [string rangeOfString:[chr lowercaseString]];\n        rangeChrUppercase = [string rangeOfString:[chr uppercaseString]];\n        \n        if(rangeChrLowercase.location == NSNotFound && rangeChrUppercase.location == NSNotFound){\n            if(fuzziness){\n                fuzzies += 1 - [fuzziness floatValue];\n            } else {\n                return 0; // this is an error!\n            }\n            \n        } else if (rangeChrLowercase.location != NSNotFound && rangeChrUppercase.location != NSNotFound){\n            indexInString = MIN(rangeChrLowercase.location, rangeChrUppercase.location);\n            \n        } else if(rangeChrLowercase.location != NSNotFound || rangeChrUppercase.location != NSNotFound){\n            indexInString = rangeChrLowercase.location != NSNotFound ? rangeChrLowercase.location : rangeChrUppercase.location;\n            \n        } else {\n            indexInString = MIN(rangeChrLowercase.location, rangeChrUppercase.location);\n            \n        }\n        \n        // Set base score for matching chr\n        \n        // Same case bonus.\n        if(indexInString != NSNotFound && [[string substringWithRange:NSMakeRange(indexInString, 1)] isEqualToString:chr]){\n            characterScore += 0.1;\n        }\n        \n        // Consecutive letter & start-of-string bonus\n        if(indexInString == 0){\n            // Increase the score when matching first character of the remainder of the string\n            characterScore += 0.6;\n            if(index == 0){\n                // If match is the first character of the string\n                // & the first character of abbreviation, add a\n                // start-of-string match bonus.\n                startOfStringBonus = YES;\n            }\n        } else if(indexInString != NSNotFound) {\n            // Acronym Bonus\n            // Weighing Logic: Typing the first character of an acronym is as if you\n            // preceded it with two perfect character matches.\n            if( [[string substringWithRange:NSMakeRange(indexInString - 1, 1)] isEqualToString:@\" \"] ){\n                characterScore += 0.8;\n            }\n        }\n        \n        // Left trim the already matched part of the string\n        // (forces sequential matching).\n        if(indexInString != NSNotFound){\n            string = [string substringFromIndex:indexInString + 1];\n        }\n        \n        totalCharacterScore += characterScore;\n    }\n    \n    if(NSStringScoreOptionFavorSmallerWords == (options & NSStringScoreOptionFavorSmallerWords)){\n        // Weigh smaller words higher\n        return totalCharacterScore / stringLength;\n    }\n    \n    otherStringScore = totalCharacterScore / otherStringLength;\n    \n    if(NSStringScoreOptionReducedLongStringPenalty == (options & NSStringScoreOptionReducedLongStringPenalty)){\n        // Reduce the penalty for longer words\n        CGFloat percentageOfMatchedString = otherStringLength / stringLength;\n        CGFloat wordScore = otherStringScore * percentageOfMatchedString;\n        finalScore = (wordScore + otherStringScore) / 2;\n        \n    } else {\n        finalScore = ((otherStringScore * ((CGFloat)(otherStringLength) / (CGFloat)(stringLength))) + otherStringScore) / 2;\n    }\n    \n    finalScore = finalScore / fuzzies;\n    \n    if(startOfStringBonus && finalScore + 0.15 < 1){\n        finalScore += 0.15;\n    }\n    \n    return finalScore;\n}\n\n@end\n"
  },
  {
    "path": "TUSafariActivity/TUSafariActivity.h",
    "content": "//\n//  TUSafariActivity.h\n//\n//  Created by David Beck on 11/30/12.\n//  Copyright (c) 2012 ThinkUltimate. All rights reserved.\n//\n//  http://github.com/davbeck/TUSafariActivity\n//\n//  Redistribution and use in source and binary forms, with or without modification,\n//  are permitted provided that the following conditions are met:\n//\n//  - Redistributions of source code must retain the above copyright notice,\n//    this list of conditions and the following disclaimer.\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//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n//  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n//  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n//  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n//  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n//  OF THE POSSIBILITY OF SUCH DAMAGE.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface TUSafariActivity : UIActivity\n\n@end\n"
  },
  {
    "path": "TUSafariActivity/TUSafariActivity.m",
    "content": "//\n//  TUSafariActivity.h\n//\n//  Created by David Beck on 11/30/12.\n//  Copyright (c) 2012 ThinkUltimate. All rights reserved.\n//\n//  http://github.com/davbeck/TUSafariActivity\n//\n//  Redistribution and use in source and binary forms, with or without modification,\n//  are permitted provided that the following conditions are met:\n//\n//  - Redistributions of source code must retain the above copyright notice,\n//    this list of conditions and the following disclaimer.\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//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n//  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n//  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n//  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n//  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n//  OF THE POSSIBILITY OF SUCH DAMAGE.\n//\n\n#import \"TUSafariActivity.h\"\n\n@implementation TUSafariActivity\n{\n\tNSURL *_URL;\n}\n\n- (NSString *)activityType\n{\n\treturn NSStringFromClass([self class]);\n}\n\n- (NSString *)activityTitle\n{\n\treturn NSLocalizedStringFromTable(@\"Open in Safari\", @\"TUSafariActivity\", nil);\n}\n\n- (UIImage *)activityImage\n{\n\treturn [UIImage imageNamed:@\"Safari\"];\n}\n\n- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems\n{\n\tfor (id activityItem in activityItems) {\n\t\tif ([activityItem isKindOfClass:[NSURL class]] && [[UIApplication sharedApplication] canOpenURL:activityItem]) {\n\t\t\treturn YES;\n\t\t}\n\t}\n\t\n\treturn NO;\n}\n\n- (void)prepareWithActivityItems:(NSArray *)activityItems\n{\n\tfor (id activityItem in activityItems) {\n\t\tif ([activityItem isKindOfClass:[NSURL class]]) {\n\t\t\t_URL = activityItem;\n\t\t}\n\t}\n}\n\n- (void)performActivity\n{\n    BOOL completed = NO;\n    \n    if([[UIApplication sharedApplication] canOpenURL:_URL]) {\n        [[UIApplication sharedApplication] openURL:_URL options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:nil];\n        completed = YES;\n    }\n\t\n\t[self activityDidFinish:completed];\n}\n\n@end\n"
  },
  {
    "path": "TUSafariActivity/en.lproj/TUSafariActivity.strings",
    "content": "\"Open in Safari\" = \"Open in Safari\";"
  },
  {
    "path": "TrustKit/Dependencies/README.md",
    "content": "Dependencies needed for building TrustKit.\n\n* RSSwizzle: https://github.com/rabovik/RSSwizzle\n* domain\\_registry\\_provider: https://github.com/nabla-c0d3/domain-registry-provider/\n"
  },
  {
    "path": "TrustKit/Dependencies/RSSwizzle/RSSwizzle.h",
    "content": "//\n//  RSSwizzle.h\n//  RSSwizzleTests\n//\n//  Created by Yan Rabovik on 05.09.13.\n//\n//\n\n#import <Foundation/Foundation.h>\n\n#pragma mark - Macros Based API\n\n/// A macro for wrapping the return type of the swizzled method.\n#define RSSWReturnType(type) type\n\n/// A macro for wrapping arguments of the swizzled method.\n#define RSSWArguments(arguments...) _RSSWArguments(arguments)\n\n/// A macro for wrapping the replacement code for the swizzled method.\n#define RSSWReplacement(code...) code\n\n/// A macro for casting and calling original implementation.\n/// May be used only in RSSwizzleInstanceMethod or RSSwizzleClassMethod macros.\n#define RSSWCallOriginal(arguments...) _RSSWCallOriginal(arguments)\n\n#pragma mark └ Swizzle Instance Method\n\n/**\n Swizzles the instance method of the class with the new implementation.\n\n Example for swizzling `-(int)calculate:(int)number;` method:\n\n @code\n\n    RSSwizzleInstanceMethod(classToSwizzle,\n                            @selector(calculate:),\n                            RSSWReturnType(int),\n                            RSSWArguments(int number),\n                            RSSWReplacement(\n    {\n        // Calling original implementation.\n        int res = RSSWCallOriginal(number);\n        // Returning modified return value.\n        return res + 1;\n    }), 0, NULL);\n \n @endcode\n \n Swizzling frequently goes along with checking whether this particular class (or one of its superclasses) has been already swizzled. Here the `RSSwizzleMode` and `key` parameters can help. See +[RSSwizzle swizzleInstanceMethod:inClass:newImpFactory:mode:key:] for details.\n\n Swizzling is fully thread-safe.\n\n @param classToSwizzle The class with the method that should be swizzled.\n\n @param selector Selector of the method that should be swizzled.\n \n @param RSSWReturnType The return type of the swizzled method wrapped in the RSSWReturnType macro.\n \n @param RSSWArguments The arguments of the swizzled method wrapped in the RSSWArguments macro.\n \n @param RSSWReplacement The code of the new implementation of the swizzled method wrapped in the RSSWReplacement macro.\n \n @param RSSwizzleMode The mode is used in combination with the key to indicate whether the swizzling should be done for the given class. You can pass 0 for RSSwizzleModeAlways.\n \n @param key The key is used in combination with the mode to indicate whether the swizzling should be done for the given class. May be NULL if the mode is RSSwizzleModeAlways.\n\n @return YES if successfully swizzled and NO if swizzling has been already done for given key and class (or one of superclasses, depends on the mode).\n\n */\n#define RSSwizzleInstanceMethod(classToSwizzle, \\\n                                selector, \\\n                                RSSWReturnType, \\\n                                RSSWArguments, \\\n                                RSSWReplacement, \\\n                                RSSwizzleMode, \\\n                                key) \\\n    _RSSwizzleInstanceMethod(classToSwizzle, \\\n                             selector, \\\n                             RSSWReturnType, \\\n                             _RSSWWrapArg(RSSWArguments), \\\n                             _RSSWWrapArg(RSSWReplacement), \\\n                             RSSwizzleMode, \\\n                             key)\n\n#pragma mark └ Swizzle Class Method\n\n/**\n Swizzles the class method of the class with the new implementation.\n\n Example for swizzling `+(int)calculate:(int)number;` method:\n\n @code\n\n    RSSwizzleClassMethod(classToSwizzle,\n                         @selector(calculate:),\n                         RSSWReturnType(int),\n                         RSSWArguments(int number),\n                         RSSWReplacement(\n    {\n        // Calling original implementation.\n        int res = RSSWCallOriginal(number);\n        // Returning modified return value.\n        return res + 1;\n    }));\n \n @endcode\n\n Swizzling is fully thread-safe.\n\n @param classToSwizzle The class with the method that should be swizzled.\n\n @param selector Selector of the method that should be swizzled.\n \n @param RSSWReturnType The return type of the swizzled method wrapped in the RSSWReturnType macro.\n \n @param RSSWArguments The arguments of the swizzled method wrapped in the RSSWArguments macro.\n \n @param RSSWReplacement The code of the new implementation of the swizzled method wrapped in the RSSWReplacement macro.\n \n */\n#define RSSwizzleClassMethod(classToSwizzle, \\\n                             selector, \\\n                             RSSWReturnType, \\\n                             RSSWArguments, \\\n                             RSSWReplacement) \\\n    _RSSwizzleClassMethod(classToSwizzle, \\\n                          selector, \\\n                          RSSWReturnType, \\\n                          _RSSWWrapArg(RSSWArguments), \\\n                          _RSSWWrapArg(RSSWReplacement))\n\n#pragma mark - Main API\n\n/**\n A function pointer to the original implementation of the swizzled method.\n */\ntypedef void (*RSSwizzleOriginalIMP)(void /* id, SEL, ... */ );\n\n/**\n RSSwizzleInfo is used in the new implementation block to get and call original implementation of the swizzled method.\n */\n@interface RSSwizzleInfo : NSObject\n\n/**\n Returns the original implementation of the swizzled method.\n\n It is actually either an original implementation if the swizzled class implements the method itself; or a super implementation fetched from one of the superclasses.\n \n @note You must always cast returned implementation to the appropriate function pointer when calling.\n \n @return A function pointer to the original implementation of the swizzled method.\n */\n-(RSSwizzleOriginalIMP)getOriginalImplementation;\n\n/// The selector of the swizzled method.\n@property (nonatomic, readonly) SEL selector;\n\n@end\n\n/**\n A factory block returning the block for the new implementation of the swizzled method.\n\n You must always obtain original implementation with swizzleInfo and call it from the new implementation.\n \n @param swizzleInfo An info used to get and call the original implementation of the swizzled method.\n\n @return A block that implements a method.\n    Its signature should be: `method_return_type ^(id self, method_args...)`. \n    The selector is not available as a parameter to this block.\n */\ntypedef id (^RSSwizzleImpFactoryBlock)(RSSwizzleInfo *swizzleInfo);\n\ntypedef NS_ENUM(NSUInteger, RSSwizzleMode) {\n    /// RSSwizzle always does swizzling.\n    RSSwizzleModeAlways = 0,\n    /// RSSwizzle does not do swizzling if the same class has been swizzled earlier with the same key.\n    RSSwizzleModeOncePerClass = 1,\n    /// RSSwizzle does not do swizzling if the same class or one of its superclasses have been swizzled earlier with the same key.\n    /// @note There is no guarantee that your implementation will be called only once per method call. If the order of swizzling is: first inherited class, second superclass, then both swizzlings will be done and the new implementation will be called twice.\n    RSSwizzleModeOncePerClassAndSuperclasses = 2\n};\n\n@interface RSSwizzle : NSObject\n\n#pragma mark └ Swizzle Instance Method\n\n/**\n Swizzles the instance method of the class with the new implementation.\n\n Original implementation must always be called from the new implementation. And because of the the fact that for safe and robust swizzling original implementation must be dynamically fetched at the time of calling and not at the time of swizzling, swizzling API is a little bit complicated.\n\n You should pass a factory block that returns the block for the new implementation of the swizzled method. And use swizzleInfo argument to retrieve and call original implementation.\n\n Example for swizzling `-(int)calculate:(int)number;` method:\n \n @code\n\n    SEL selector = @selector(calculate:);\n    [RSSwizzle\n     swizzleInstanceMethod:selector\n     inClass:classToSwizzle\n     newImpFactory:^id(RSSWizzleInfo *swizzleInfo) {\n         // This block will be used as the new implementation.\n         return ^int(__unsafe_unretained id self, int num){\n             // You MUST always cast implementation to the correct function pointer.\n             int (*originalIMP)(__unsafe_unretained id, SEL, int);\n             originalIMP = (__typeof(originalIMP))[swizzleInfo getOriginalImplementation];\n             // Calling original implementation.\n             int res = originalIMP(self,selector,num);\n             // Returning modified return value.\n             return res + 1;\n         };\n     }\n     mode:RSSwizzleModeAlways\n     key:NULL];\n \n @endcode\n\n Swizzling frequently goes along with checking whether this particular class (or one of its superclasses) has been already swizzled. Here the `mode` and `key` parameters can help.\n\n Here is an example of swizzling `-(void)dealloc;` only in case when neither class and no one of its superclasses has been already swizzled with our key. However \"Deallocating ...\" message still may be logged multiple times per method call if swizzling was called primarily for an inherited class and later for one of its superclasses.\n \n @code\n \n    static const void *key = &key;\n    SEL selector = NSSelectorFromString(@\"dealloc\");\n    [RSSwizzle\n     swizzleInstanceMethod:selector\n     inClass:classToSwizzle\n     newImpFactory:^id(RSSWizzleInfo *swizzleInfo) {\n         return ^void(__unsafe_unretained id self){\n             NSLog(@\"Deallocating %@.\",self);\n             \n             void (*originalIMP)(__unsafe_unretained id, SEL);\n             originalIMP = (__typeof(originalIMP))[swizzleInfo getOriginalImplementation];\n             originalIMP(self,selector);\n         };\n     }\n     mode:RSSwizzleModeOncePerClassAndSuperclasses\n     key:key];\n \n @endcode\n\n Swizzling is fully thread-safe.\n \n @param selector Selector of the method that should be swizzled.\n\n @param classToSwizzle The class with the method that should be swizzled.\n \n @param factoryBlock The factory block returning the block for the new implementation of the swizzled method.\n \n @param mode The mode is used in combination with the key to indicate whether the swizzling should be done for the given class.\n \n @param key The key is used in combination with the mode to indicate whether the swizzling should be done for the given class. May be NULL if the mode is RSSwizzleModeAlways.\n\n @return YES if successfully swizzled and NO if swizzling has been already done for given key and class (or one of superclasses, depends on the mode).\n */\n+(BOOL)swizzleInstanceMethod:(SEL)selector\n                     inClass:(Class)classToSwizzle\n               newImpFactory:(RSSwizzleImpFactoryBlock)factoryBlock\n                        mode:(RSSwizzleMode)mode\n                         key:(const void *)key;\n\n#pragma mark └ Swizzle Class method\n\n/**\n Swizzles the class method of the class with the new implementation.\n\n Original implementation must always be called from the new implementation. And because of the the fact that for safe and robust swizzling original implementation must be dynamically fetched at the time of calling and not at the time of swizzling, swizzling API is a little bit complicated.\n\n You should pass a factory block that returns the block for the new implementation of the swizzled method. And use swizzleInfo argument to retrieve and call original implementation.\n\n Example for swizzling `+(int)calculate:(int)number;` method:\n \n @code\n\n    SEL selector = @selector(calculate:);\n    [RSSwizzle\n     swizzleClassMethod:selector\n     inClass:classToSwizzle\n     newImpFactory:^id(RSSWizzleInfo *swizzleInfo) {\n         // This block will be used as the new implementation.\n         return ^int(__unsafe_unretained id self, int num){\n             // You MUST always cast implementation to the correct function pointer.\n             int (*originalIMP)(__unsafe_unretained id, SEL, int);\n             originalIMP = (__typeof(originalIMP))[swizzleInfo getOriginalImplementation];\n             // Calling original implementation.\n             int res = originalIMP(self,selector,num);\n             // Returning modified return value.\n             return res + 1;\n         };\n     }];\n \n @endcode\n\n Swizzling is fully thread-safe.\n \n @param selector Selector of the method that should be swizzled.\n\n @param classToSwizzle The class with the method that should be swizzled.\n \n @param factoryBlock The factory block returning the block for the new implementation of the swizzled method.\n */\n+(void)swizzleClassMethod:(SEL)selector\n                  inClass:(Class)classToSwizzle\n            newImpFactory:(RSSwizzleImpFactoryBlock)factoryBlock;\n\n@end\n\n#pragma mark - Implementation details\n// Do not write code that depends on anything below this line.\n\n// Wrapping arguments to pass them as a single argument to another macro.\n#define _RSSWWrapArg(args...) args\n\n#define _RSSWDel2Arg(a1, a2, args...) a1, ##args\n#define _RSSWDel3Arg(a1, a2, a3, args...) a1, a2, ##args\n\n// To prevent comma issues if there are no arguments we add one dummy argument\n// and remove it later.\n#define _RSSWArguments(arguments...) DEL, ##arguments\n\n#define _RSSwizzleInstanceMethod(classToSwizzle, \\\n                                 selector, \\\n                                 RSSWReturnType, \\\n                                 RSSWArguments, \\\n                                 RSSWReplacement, \\\n                                 RSSwizzleMode, \\\n                                 KEY) \\\n    [RSSwizzle \\\n     swizzleInstanceMethod:selector \\\n     inClass:[classToSwizzle class] \\\n     newImpFactory:^id(RSSwizzleInfo *swizzleInfo) { \\\n        RSSWReturnType (*originalImplementation_)(_RSSWDel3Arg(__unsafe_unretained id, \\\n                                                               SEL, \\\n                                                               RSSWArguments)); \\\n        SEL selector_ = selector; \\\n        return ^RSSWReturnType (_RSSWDel2Arg(__unsafe_unretained id self, \\\n                                             RSSWArguments)) \\\n        { \\\n            RSSWReplacement \\\n        }; \\\n     } \\\n     mode:RSSwizzleMode \\\n     key:KEY];\n\n#define _RSSwizzleClassMethod(classToSwizzle, \\\n                              selector, \\\n                              RSSWReturnType, \\\n                              RSSWArguments, \\\n                              RSSWReplacement) \\\n    [RSSwizzle \\\n     swizzleClassMethod:selector \\\n     inClass:[classToSwizzle class] \\\n     newImpFactory:^id(RSSwizzleInfo *swizzleInfo) { \\\n        RSSWReturnType (*originalImplementation_)(_RSSWDel3Arg(__unsafe_unretained id, \\\n                                                               SEL, \\\n                                                               RSSWArguments)); \\\n        SEL selector_ = selector; \\\n        return ^RSSWReturnType (_RSSWDel2Arg(__unsafe_unretained id self, \\\n                                             RSSWArguments)) \\\n        { \\\n            RSSWReplacement \\\n        }; \\\n     }];\n\n#define _RSSWCallOriginal(arguments...) \\\n    ((__typeof(originalImplementation_))[swizzleInfo \\\n                                         getOriginalImplementation])(self, \\\n                                                                     selector_, \\\n                                                                     ##arguments)\n"
  },
  {
    "path": "TrustKit/Dependencies/RSSwizzle/RSSwizzle.m",
    "content": "//\n//  RSSwizzle.m\n//  RSSwizzleTests\n//\n//  Created by Yan Rabovik on 05.09.13.\n//\n//\n\n#import \"RSSwizzle.h\"\n#import <objc/runtime.h>\n#include <dlfcn.h>\n\n\n#if !__has_feature(objc_arc)\n#error This code needs ARC. Use compiler option -fobjc-arc\n#endif\n\n\n// Use os_unfair_lock over OSSpinLock when building with the following SDKs: iOS 10, macOS 10.12 and any tvOS and watchOS\n#define DEPLOYMENT_TARGET_HIGHER_THAN_10 TARGET_OS_WATCH || TARGET_OS_TV || (TARGET_OS_IOS &&__IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_ALLOWED >= 101200)\n\n#define BASE_SDK_HIGHER_THAN_10 (TARGET_OS_WATCH || TARGET_OS_TV || (TARGET_OS_IOS &&__IPHONE_OS_VERSION_MAX_ALLOWED >= 100000) || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200))\n\n\n#if BASE_SDK_HIGHER_THAN_10\n#import <os/lock.h>\n#else\n// Below iOS 10, OS_UNFAIR_LOCK_INIT will not exist. Note that this type works with OSSpinLock\n#define OS_UNFAIR_LOCK_INIT ((os_unfair_lock){0})\n\ntypedef struct _os_unfair_lock_s {\n    uint32_t _os_unfair_lock_opaque;\n} os_unfair_lock, *os_unfair_lock_t;\n#endif\n\n\n#if !DEPLOYMENT_TARGET_HIGHER_THAN_10\n#import <libkern/OSAtomic.h>\n#endif\n\n\n// NSDimension was introduced at the same time that os_unfair_lock_lock was made public, ie. iOS 10\n#define DEVICE_HIGHER_THAN_10 objc_getClass(\"NSDimension\")\n\n\n#pragma mark Locking\n\n// This function will lock a lock using os_unfair_lock_lock (on ios10/macos10.12) or OSSpinLockLock (9 and lower).\nstatic void chooseLock(os_unfair_lock *lock)\n{\n#if DEPLOYMENT_TARGET_HIGHER_THAN_10\n    // iOS 10+, os_unfair_lock_lock is available\n    os_unfair_lock_lock(lock);\n#else\n    if (DEVICE_HIGHER_THAN_10)\n    {\n        // Attempt to use os_unfair_lock_lock().\n        void (*os_unfair_lock_lock)(void *lock) = dlsym(dlopen(NULL, RTLD_NOW | RTLD_GLOBAL), \"os_unfair_lock_lock\");\n        if (os_unfair_lock_lock != NULL)\n        {\n            os_unfair_lock_lock(lock);\n            return;\n        }\n    }\n    \n    // Unfair locks are not available on iOS 9 and lower, using deprecated OSSpinLock.\n    OSSpinLockLock((void *)lock);\n#endif\n}\n\n// This function will unlock a lock using os_unfair_lock_unlock (on ios10/macos10.12) or OSSpinLockUnlock (9 and lower).\nstatic void chooseUnlock(os_unfair_lock *lock)\n{\n#if DEPLOYMENT_TARGET_HIGHER_THAN_10\n    // iOS 10+, os_unfair_lock_unlock is available\n    os_unfair_lock_unlock(lock);\n#else\n    if (DEVICE_HIGHER_THAN_10)\n    {\n        // Attempt to use os_unfair_lock_unlock().\n        void (*os_unfair_lock_unlock)(void *lock) = dlsym(dlopen(NULL, RTLD_NOW | RTLD_GLOBAL), \"os_unfair_lock_unlock\");\n        if (os_unfair_lock_unlock != NULL)\n        {\n            os_unfair_lock_unlock(lock);\n            return;\n        }\n    }\n    \n    // Unfair locks are not available on iOS 9 and lower, using deprecated OSSpinUnlock.\n    OSSpinLockUnlock((void *)lock);\n#endif\n}\n\n\n#pragma mark - Block Helpers\n\n#if !defined(NS_BLOCK_ASSERTIONS)\n\n// See http://clang.llvm.org/docs/Block-ABI-Apple.html#high-level\nstruct Block_literal_1 {\n    void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock\n    int flags;\n    int reserved;\n    void (*invoke)(void *, ...);\n    struct Block_descriptor_1 {\n        unsigned long int reserved;         // NULL\n        unsigned long int size;         // sizeof(struct Block_literal_1)\n        // optional helper functions\n        void (*copy_helper)(void *dst, void *src);     // IFF (1<<25)\n        void (*dispose_helper)(void *src);             // IFF (1<<25)\n        // required ABI.2010.3.16\n        const char *signature;                         // IFF (1<<30)\n    } *descriptor;\n    // imported variables\n};\n\nenum {\n    BLOCK_HAS_COPY_DISPOSE =  (1 << 25),\n    BLOCK_HAS_CTOR =          (1 << 26), // helpers have C++ code\n    BLOCK_IS_GLOBAL =         (1 << 28),\n    BLOCK_HAS_STRET =         (1 << 29), // IFF BLOCK_HAS_SIGNATURE\n    BLOCK_HAS_SIGNATURE =     (1 << 30),\n};\ntypedef int BlockFlags;\n\nstatic const char *blockGetType(id block){\n    struct Block_literal_1 *blockRef = (__bridge struct Block_literal_1 *)block;\n    BlockFlags flags = blockRef->flags;\n    \n    if (flags & BLOCK_HAS_SIGNATURE) {\n        void *signatureLocation = blockRef->descriptor;\n        signatureLocation += sizeof(unsigned long int);\n        signatureLocation += sizeof(unsigned long int);\n        \n        if (flags & BLOCK_HAS_COPY_DISPOSE) {\n            signatureLocation += sizeof(void(*)(void *dst, void *src));\n            signatureLocation += sizeof(void (*)(void *src));\n        }\n        \n        const char *signature = (*(const char **)signatureLocation);\n        return signature;\n    }\n    \n    return NULL;\n}\n\nstatic BOOL blockIsCompatibleWithMethodType(id block, const char *methodType){\n    \n    const char *blockType = blockGetType(block);\n    \n    NSMethodSignature *blockSignature;\n    \n    if (0 == strncmp(blockType, (const char *)\"@\\\"\", 2)) {\n        // Block return type includes class name for id types\n        // while methodType does not include.\n        // Stripping out return class name.\n        char *quotePtr = strchr(blockType+2, '\"');\n        if (NULL != quotePtr) {\n            ++quotePtr;\n            char filteredType[strlen(quotePtr) + 2];\n            memset(filteredType, 0, sizeof(filteredType));\n            *filteredType = '@';\n            strncpy(filteredType + 1, quotePtr, sizeof(filteredType) - 2);\n            \n            blockSignature = [NSMethodSignature signatureWithObjCTypes:filteredType];\n        }else{\n            return NO;\n        }\n    }else{\n        blockSignature = [NSMethodSignature signatureWithObjCTypes:blockType];\n    }\n    \n    NSMethodSignature *methodSignature =\n    [NSMethodSignature signatureWithObjCTypes:methodType];\n    \n    if (!blockSignature || !methodSignature) {\n        return NO;\n    }\n    \n    if (blockSignature.numberOfArguments != methodSignature.numberOfArguments){\n        return NO;\n    }\n    \n    if (strcmp(blockSignature.methodReturnType, methodSignature.methodReturnType) != 0) {\n        return NO;\n    }\n    \n    for (int i=0; i<methodSignature.numberOfArguments; ++i){\n        if (i == 0){\n            // self in method, block in block\n            if (strcmp([methodSignature getArgumentTypeAtIndex:i], \"@\") != 0) {\n                return NO;\n            }\n            if (strcmp([blockSignature getArgumentTypeAtIndex:i], \"@?\") != 0) {\n                return NO;\n            }\n        }else if(i == 1){\n            // SEL in method, self in block\n            if (strcmp([methodSignature getArgumentTypeAtIndex:i], \":\") != 0) {\n                return NO;\n            }\n            if (strncmp([blockSignature getArgumentTypeAtIndex:i], \"@\", 1) != 0) {\n                return NO;\n            }\n        }else {\n            const char *blockSignatureArg = [blockSignature getArgumentTypeAtIndex:i];\n            \n            if (strncmp(blockSignatureArg, \"@?\", 2) == 0) {\n                // Handle function pointer / block arguments\n                blockSignatureArg = \"@?\";\n            }\n            else if (strncmp(blockSignatureArg, \"@\", 1) == 0) {\n                blockSignatureArg = \"@\";\n            }\n            \n            if (strcmp(blockSignatureArg,\n                       [methodSignature getArgumentTypeAtIndex:i]) != 0)\n            {\n                return NO;\n            }\n        }\n    }\n    \n    return YES;\n}\n\nstatic BOOL blockIsAnImpFactoryBlock(id block){\n    const char *blockType = blockGetType(block);\n    RSSwizzleImpFactoryBlock dummyFactory = ^id(RSSwizzleInfo *swizzleInfo){\n        return nil;\n    };\n    const char *factoryType = blockGetType(dummyFactory);\n    return 0 == strcmp(factoryType, blockType);\n}\n\n#endif // NS_BLOCK_ASSERTIONS\n\n\n#pragma mark - Swizzling\n\n#pragma mark └ RSSwizzleInfo\ntypedef IMP (^RSSWizzleImpProvider)(void);\n\n@interface RSSwizzleInfo()\n@property (nonatomic,copy) RSSWizzleImpProvider impProviderBlock;\n@property (nonatomic, readwrite) SEL selector;\n@end\n\n@implementation RSSwizzleInfo\n\n-(RSSwizzleOriginalIMP)getOriginalImplementation{\n    NSAssert(_impProviderBlock,nil);\n    // Casting IMP to RSSwizzleOriginalIMP to force user casting.\n    return (RSSwizzleOriginalIMP)_impProviderBlock();\n}\n\n@end\n\n\n#pragma mark └ RSSwizzle\n@implementation RSSwizzle\n\nstatic void swizzle(Class classToSwizzle,\n                    SEL selector,\n                    RSSwizzleImpFactoryBlock factoryBlock)\n{\n    Method method = class_getInstanceMethod(classToSwizzle, selector);\n    \n    NSCAssert(NULL != method,\n              @\"Selector %@ not found in %@ methods of class %@.\",\n              NSStringFromSelector(selector),\n              class_isMetaClass(classToSwizzle) ? @\"class\" : @\"instance\",\n              classToSwizzle);\n    \n    NSCAssert(blockIsAnImpFactoryBlock(factoryBlock),\n              @\"Wrong type of implementation factory block.\");\n    \n    __block os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;\n    \n    // To keep things thread-safe, we fill in the originalIMP later,\n    // with the result of the class_replaceMethod call below.\n    __block IMP originalIMP = NULL;\n    \n    // This block will be called by the client to get original implementation and call it.\n    RSSWizzleImpProvider originalImpProvider = ^IMP{\n        // It's possible that another thread can call the method between the call to\n        // class_replaceMethod and its return value being set.\n        // So to be sure originalIMP has the right value, we need a lock.\n        \n        \n        chooseLock(&lock);\n        \n        IMP imp = originalIMP;\n        \n        chooseUnlock(&lock);\n        \n        if (NULL == imp){\n            // If the class does not implement the method\n            // we need to find an implementation in one of the superclasses.\n            Class superclass = class_getSuperclass(classToSwizzle);\n            imp = method_getImplementation(class_getInstanceMethod(superclass,selector));\n        }\n        return imp;\n    };\n    \n    RSSwizzleInfo *swizzleInfo = [RSSwizzleInfo new];\n    swizzleInfo.selector = selector;\n    swizzleInfo.impProviderBlock = originalImpProvider;\n    \n    // We ask the client for the new implementation block.\n    // We pass swizzleInfo as an argument to factory block, so the client can\n    // call original implementation from the new implementation.\n    id newIMPBlock = factoryBlock(swizzleInfo);\n    \n    const char *methodType = method_getTypeEncoding(method);\n    \n    NSCAssert(blockIsCompatibleWithMethodType(newIMPBlock,methodType),\n              @\"Block returned from factory is not compatible with method type.\");\n    \n    IMP newIMP = imp_implementationWithBlock(newIMPBlock);\n    \n    // Atomically replace the original method with our new implementation.\n    // This will ensure that if someone else's code on another thread is messing\n    // with the class' method list too, we always have a valid method at all times.\n    //\n    // If the class does not implement the method itself then\n    // class_replaceMethod returns NULL and superclasses's implementation will be used.\n    //\n    // We need a lock to be sure that originalIMP has the right value in the\n    // originalImpProvider block above.\n    \n    chooseLock(&lock);\n    \n    originalIMP = class_replaceMethod(classToSwizzle, selector, newIMP, methodType);\n    \n    chooseUnlock(&lock);\n}\n\n\nstatic NSMutableDictionary *swizzledClassesDictionary(){\n    static NSMutableDictionary *swizzledClasses;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        swizzledClasses = [NSMutableDictionary new];\n    });\n    return swizzledClasses;\n}\n\nstatic NSMutableSet *swizzledClassesForKey(const void *key){\n    NSMutableDictionary *classesDictionary = swizzledClassesDictionary();\n    NSValue *keyValue = [NSValue valueWithPointer:key];\n    NSMutableSet *swizzledClasses = [classesDictionary objectForKey:keyValue];\n    if (!swizzledClasses) {\n        swizzledClasses = [NSMutableSet new];\n        [classesDictionary setObject:swizzledClasses forKey:keyValue];\n    }\n    return swizzledClasses;\n}\n\n+(BOOL)swizzleInstanceMethod:(SEL)selector\n                     inClass:(Class)classToSwizzle\n               newImpFactory:(RSSwizzleImpFactoryBlock)factoryBlock\n                        mode:(RSSwizzleMode)mode\n                         key:(const void *)key\n{\n    NSAssert(!(NULL == key && RSSwizzleModeAlways != mode),\n             @\"Key may not be NULL if mode is not RSSwizzleModeAlways.\");\n    \n    @synchronized(swizzledClassesDictionary()){\n        if (key){\n            NSSet *swizzledClasses = swizzledClassesForKey(key);\n            if (mode == RSSwizzleModeOncePerClass) {\n                if ([swizzledClasses containsObject:classToSwizzle]){\n                    return NO;\n                }\n            }else if (mode == RSSwizzleModeOncePerClassAndSuperclasses){\n                for (Class currentClass = classToSwizzle;\n                     nil != currentClass;\n                     currentClass = class_getSuperclass(currentClass))\n                {\n                    if ([swizzledClasses containsObject:currentClass]) {\n                        return NO;\n                    }\n                }\n            }\n        }\n        \n        swizzle(classToSwizzle, selector, factoryBlock);\n        \n        if (key){\n            [swizzledClassesForKey(key) addObject:classToSwizzle];\n        }\n    }\n    \n    return YES;\n}\n\n+(void)swizzleClassMethod:(SEL)selector\n                  inClass:(Class)classToSwizzle\n            newImpFactory:(RSSwizzleImpFactoryBlock)factoryBlock\n{\n    [self swizzleInstanceMethod:selector\n                        inClass:object_getClass(classToSwizzle)\n                  newImpFactory:factoryBlock\n                           mode:RSSwizzleModeAlways\n                            key:NULL];\n}\n\n@end\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/domain_registry.h",
    "content": "/*\n * Copyright 2011 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#ifndef DOMAIN_REGISTRY_DOMAIN_REGISTRY_H_\n#define DOMAIN_REGISTRY_DOMAIN_REGISTRY_H_\n\n#include <stdlib.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Call once at program startup to enable domain registry\n * search. Calls to GetRegistryLength will crash if this is not\n * called.\n */\nvoid InitializeDomainRegistry(void);\n\n/*\n * Finds the length in bytes of the registrar portion of the host in\n * the given hostname.  Returns 0 if the hostname is invalid or has no\n * host (e.g. a file: URL). Returns 0 if the hostname has multiple\n * trailing dots. If no matching rule is found in the effective-TLD\n * data, returns 0. Internationalized domain names (IDNs) must be\n * converted to punycode first. Non-ASCII hostnames or hostnames\n * longer than 127 bytes will return 0. It is an error to pass in an\n * IP address (either IPv4 or IPv6) and the return value in this case\n * is undefined.\n *\n * Examples:\n *   www.google.com       -> 3                 (com)\n *   WWW.gOoGlE.cOm       -> 3                 (com, case insensitive)\n *   ..google.com         -> 3                 (com)\n *   google.com.          -> 4                 (com)\n *   a.b.co.uk            -> 5                 (co.uk)\n *   a.b.co..uk           -> 0                 (multiple dots in registry)\n *   C:                   -> 0                 (no host)\n *   google.com..         -> 0                 (multiple trailing dots)\n *   bar                  -> 0                 (no subcomponents)\n *   co.uk                -> 5                 (co.uk)\n *   foo.bar              -> 0                 (not a valid top-level registry)\n *   foo.臺灣               -> 0                 (not converted to punycode)\n *   foo.xn--nnx388a      -> 11                (punycode representation of 臺灣)\n *   192.168.0.1          -> ?                 (IP address, retval undefined)\n */\nsize_t GetRegistryLength(const char* hostname);\n\n/*\n * Like GetRegistryLength, but allows unknown registries as well. If\n * the hostname is part of a known registry, the return value will be\n * identical to that of GetRegistryLength. If the hostname is not part\n * of a known registry (e.g. foo.bar) then the return value will\n * assume that the rootmost hostname-part is the registry.  It is an\n * error to pass in an IP address (either IPv4 or IPv6) and the return\n * value in this case is undefined.\n *\n * Examples:\n *   foo.bar              -> 3                 (bar)\n *   bar                  -> 0                 (host is a registry)\n *   www.google.com       -> 3                 (com)\n *   com                  -> 0                 (host is a registry)\n *   co.uk                -> 0                 (host is a registry)\n *   foo.臺灣               -> 0                 (not converted to punycode)\n *   foo.xn--nnx388a      -> 11                (punycode representation of 臺灣)\n *   192.168.0.1          -> ?                 (IP address, retval undefined)\n */\nsize_t GetRegistryLengthAllowUnknownRegistries(const char* hostname);\n\n/*\n * Override the assertion handler by providing a custom assert handler\n * implementation. The assertion handler will be invoked when an\n * internal assertion fails. This is usually indicative of a fatal\n * error and execution should not be allowed to continue. The default\n * implementation logs the assertion information to stderr and invokes\n * abort(). The parameter \"file\" is the filename where the assertion\n * was triggered. \"line_number\" is the line number in that\n * file. \"cond_str\" is the string representation of the assertion that\n * failed.\n */\ntypedef void (*DomainRegistryAssertHandler)(\n    const char* file, int line_number, const char* cond_str);\nvoid SetDomainRegistryAssertHandler(DomainRegistryAssertHandler handler);\n\n#ifdef __cplusplus\n}   /* extern \"C\" */\n#endif\n\n#endif  /* DOMAIN_REGISTRY_DOMAIN_REGISTRY_H_ */\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/private/assert.c",
    "content": "/*\n * Copyright 2011 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#include \"assert.h\"\n\n#include \"../domain_registry.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nstatic void DefaultAssertHandler(const char* file, int line, const char* cond_str) {\n    fprintf(stderr, \"%s:%d. CHECK failed: %s\\n\", file, line, cond_str);\n    abort();\n}\n\nstatic DomainRegistryAssertHandler g_assert_hander = DefaultAssertHandler;\n\nvoid DoAssert(const char* file,\n              int line,\n              const char* condition_str,\n              int condition) {\n  if (condition == 0) {\n    g_assert_hander(file, line, condition_str);\n  }\n}\n\nvoid SetDomainRegistryAssertHandler(DomainRegistryAssertHandler handler) {\n  g_assert_hander = handler;\n}\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/private/assert.h",
    "content": "/*\n * Copyright 2011 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#ifndef DOMAIN_REGISTRY_PRIVATE_ASSERT_H_\n#define DOMAIN_REGISTRY_PRIVATE_ASSERT_H_\n\nvoid DoAssert(const char* file, int line, const char* cond_str, int cond);\n\n#ifdef NDEBUG\n#define DCHECK(x)\n#else\n#define DCHECK(x) DoAssert(__FILE__, __LINE__, #x, (x))\n#endif\n\n#endif  /* DOMAIN_REGISTRY_PRIVATE_ASSERT_H_ */\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/private/init_registry_tables.c",
    "content": "/*\n * Copyright 2011 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 \"../domain_registry.h\"\n\n#include <stdlib.h>\n\n#include \"registry_types.h\"\n#include \"trie_node.h\"\n#include \"trie_search.h\"\n\n/* Include the generated file that contains the actual registry tables. */\n#include \"../registry_tables_genfiles/registry_tables.h\"\n\nvoid InitializeDomainRegistry(void) {\n  SetRegistryTables(kStringTable,\n                    kNodeTable,\n                    kNumRootChildren,\n                    kLeafNodeTable,\n                    kLeafChildOffset);\n}\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/private/registry_search.c",
    "content": "/*\n * Copyright 2011 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#include \"../domain_registry.h\"\n\n#include <string.h>\n\n#include \"assert.h\"\n#include \"string_util.h\"\n#include \"trie_search.h\"\n\n/* RFCs 1035 and 1123 specify a max hostname length of 255 bytes. */\nstatic const size_t kMaxHostnameLen = 255;\n\n/* strdup() is not part of ANSI C89 so we define our own. */\nstatic char* StrDup(const char* s) {\n  const size_t len = strlen(s);\n  char* s2 = malloc(len + 1);\n  if (s2 == NULL) {\n    return NULL;\n  }\n  memcpy(s2, s, len);\n  s2[len] = 0;\n  return s2;\n}\n\n/* strnlen() is not part of ANSI C89 so we define our own. */\nstatic size_t StrnLen(const char* s, size_t max) {\n  const char* end = s + max;\n  const char* i;\n  for (i = s; i < end; ++i) {\n    if (*i == 0) break;\n  }\n  return (size_t) (i - s);\n}\n\nstatic int IsStringASCII(const char* s) {\n  const char* it = s;\n  for (; *it != 0; ++it) {\n    unsigned const char unsigned_char = (unsigned char)*it;\n    if (unsigned_char > 0x7f) {\n      return 0;\n    }\n  }\n  return 1;\n}\n\nstatic int IsValidHostname(const char* hostname) {\n  /*\n   * http://www.ietf.org/rfc/rfc1035.txt (DNS) and\n   * http://tools.ietf.org/html/rfc1123 (Internet host requirements)\n   * specify a maximum hostname length of 255 characters. To make sure\n   * string comparisons, etc are bounded elsewhere in the codebase, we\n   * enforce the 255 character limit here. There are various other\n   * hostname constraints specified in the RFCs (63 bytes per\n   * hostname-part, etc) but we do not enforce those here since doing\n   * so would not change correctness of the overall implementation,\n   * and it's possible that hostnames used in other contexts\n   * (e.g. outside of DNS) would not be subject to the 63-byte\n   * hostname-part limit. So we let the DNS layer enforce its policy,\n   * and enforce only the maximum hostname length here.\n   */\n  if (StrnLen(hostname, kMaxHostnameLen + 1) > kMaxHostnameLen) {\n    return 0;\n  }\n\n  /*\n   * All hostnames must contain only ASCII characters. If a hostname\n   * is passed in that contains non-ASCII (e.g. an IDN that hasn't been\n   * converted to ASCII via punycode) we want to reject it outright.\n   */\n  if (IsStringASCII(hostname) == 0) {\n    return 0;\n  }\n\n  return 1;\n}\n\n/*\n * Get a pointer to the beginning of the valid registry. If rule_part\n * is an exception component, this will seek past the\n * rule_part. Otherwise this will simply return the component itself.\n */\nstatic const char* GetDomainRegistryStr(const char* rule_part,\n                                        const char* component) {\n  if (IsExceptionComponent(rule_part)) {\n    return component + strlen(component) + 1;\n  } else {\n    return component;\n  }\n}\n\n/*\n * Iterates the hostname-parts between start and end in reverse order,\n * separated by the character specified by sep. For instance if the\n * string between start and end is \"foo\\0bar\\0com\" and sep is the null\n * character, we will return a pointer to \"com\", then \"bar\", then\n * \"foo\".\n */\nstatic const char* GetNextHostnamePartImpl(const char* start,\n                                           const char* end,\n                                           char sep,\n                                           void** ctx) {\n  const char* last;\n  const char* i;\n\n  if (*ctx == NULL) {\n    *ctx = (void*) end;\n\n    /*\n     * Special case: a single trailing dot indicates a fully-qualified\n     * domain name. Skip over it.\n     */\n    if (end > start && *(end - 1) == sep) {\n      *ctx = (void*) (end - 1);\n    }\n  }\n  last = *ctx;\n  if (start > last) return NULL;\n  for (i = last - 1; i >= start; --i) {\n    if (*i == sep) {\n      *ctx = (void*) i;\n      return i + 1;\n    }\n  }\n  if (last != start && *start != 0) {\n    /*\n     * Special case: If we didn't find a match, but the context\n     * indicates that we haven't visited the first component yet, and\n     * there is a non-NULL first component, then visit the first\n     * component.\n     */\n    *ctx = (void*) start;\n    return start;\n  }\n  return NULL;\n}\n\nstatic const char* GetNextHostnamePart(const char* start,\n                                       const char* end,\n                                       char sep,\n                                       void** ctx) {\n  const char* hostname_part = GetNextHostnamePartImpl(start, end, sep, ctx);\n  if (IsInvalidComponent(hostname_part)) {\n    return NULL;\n  }\n  return hostname_part;\n}\n\n/*\n * Iterate over all hostname-parts between value and value_end, where\n * the hostname-parts are separated by character sep.\n */\nstatic const char* GetRegistryForHostname(const char* value,\n                                          const char* value_end,\n                                          const char sep) {\n  void *ctx = NULL;\n  const struct TrieNode* current = NULL;\n  const char* component = NULL;\n  const char* last_valid = NULL;\n\n  /*\n   * Iterate over the hostname components one at a time, e.g. if value\n   * is foo.com, we will first visit component com, then component foo.\n   */\n  while ((component =\n          GetNextHostnamePart(value, value_end, sep, &ctx)) != NULL) {\n    const char* leaf_node;\n\n    current = FindRegistryNode(component, current);\n    if (current == NULL) {\n      break;\n    }\n    if (current->is_terminal == 1) {\n      last_valid = GetDomainRegistryStr(\n          GetHostnamePart(current->string_table_offset), component);\n    } else {\n      last_valid = NULL;\n    }\n    if (HasLeafChildren(current)) {\n      /*\n       * The child nodes are in the leaf node table, so perform a\n       * search in that table.\n       */\n      component = GetNextHostnamePart(value, value_end, sep, &ctx);\n      if (component == NULL) {\n        break;\n      }\n      leaf_node = FindRegistryLeafNode(component, current);\n      if (leaf_node == NULL) {\n        break;\n      }\n      return GetDomainRegistryStr(leaf_node, component);\n    }\n  }\n\n  return last_valid;\n}\n\nstatic size_t GetRegistryLengthImpl(\n    const char* value,\n    const char* value_end,\n    const char sep,\n    int allow_unknown_registries) {\n  const char* registry;\n  size_t match_len;\n\n  while (*value == sep && value < value_end) {\n    /* Skip over leading separators. */\n    ++value;\n  }\n  registry = GetRegistryForHostname(value, value_end, sep);\n  if (registry == NULL) {\n    /*\n     * Didn't find a match. If unknown registries are allowed, see if\n     * the root hostname part is not in the table. If so, consider it to be a\n     * valid registry, and return its length.\n     */\n    if (allow_unknown_registries != 0) {\n      void* ctx = NULL;\n      const char* root_hostname_part =\n          GetNextHostnamePart(value, value_end, sep, &ctx);\n      /*\n       * See if the root hostname-part is in the table. If it's not in\n       * the table, then consider the unknown registry to be a valid\n       * registry.\n       */\n      if (root_hostname_part != NULL &&\n          FindRegistryNode(root_hostname_part, NULL) == NULL) {\n        registry = root_hostname_part;\n      }\n    }\n    if (registry == NULL) {\n      return 0;\n    }\n  }\n  if (registry < value || registry >= value_end) {\n    /* Error cases. */\n    DCHECK(registry >= value);\n    DCHECK(registry < value_end);\n    return 0;\n  }\n  match_len = (size_t) (value_end - registry);\n  return match_len;\n}\n\nsize_t GetRegistryLength(const char* hostname) {\n  const char* buf_end;\n  char* buf;\n  size_t registry_length;\n\n  if (hostname == NULL) {\n    return 0;\n  }\n  if (IsValidHostname(hostname) == 0) {\n    return 0;\n  }\n\n  /*\n   * Replace dots between hostname parts with the null byte. This\n   * allows us to index directly into the string and refer to each\n   * hostname-part as if it were its own null-terminated string.\n   */\n  buf = StrDup(hostname);\n  if (buf == NULL) {\n    return 0;\n  }\n  ReplaceChar(buf, '.', '\\0');\n\n  buf_end = buf + strlen(hostname);\n  DCHECK(*buf_end == 0);\n\n  /* Normalize the input by converting all characters to lowercase. */\n  ToLowerASCII(buf, buf_end);\n  registry_length = GetRegistryLengthImpl(buf, buf_end, '\\0', 0);\n  free(buf);\n  return registry_length;\n}\n\nsize_t GetRegistryLengthAllowUnknownRegistries(const char* hostname) {\n  const char* buf_end;\n  char* buf;\n  size_t registry_length;\n\n  if (hostname == NULL) {\n    return 0;\n  }\n  if (IsValidHostname(hostname) == 0) {\n    return 0;\n  }\n\n  /*\n   * Replace dots between hostname parts with the null byte. This\n   * allows us to index directly into the string and refer to each\n   * hostname-part as if it were its own null-terminated string.\n   */\n  buf = StrDup(hostname);\n  if (buf == NULL) {\n    return 0;\n  }\n  ReplaceChar(buf, '.', '\\0');\n\n  buf_end = buf + strlen(hostname);\n  DCHECK(*buf_end == 0);\n\n  /* Normalize the input by converting all characters to lowercase. */\n  ToLowerASCII(buf, buf_end);\n  registry_length = GetRegistryLengthImpl(buf, buf_end, '\\0', 1);\n  free(buf);\n  return registry_length;\n}\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/private/registry_types.h",
    "content": "/*\n * Copyright 2011 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#ifndef DOMAIN_REGISTRY_PRIVATE_REGISTRY_TYPES_H_\n#define DOMAIN_REGISTRY_PRIVATE_REGISTRY_TYPES_H_\n\ntypedef unsigned short REGISTRY_U16;\n\n#endif  /* DOMAIN_REGISTRY_PRIVATE_REGISTRY_TYPES_H_ */\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/private/string_util.h",
    "content": "/*\n * Copyright 2011 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#ifndef DOMAIN_REGISTRY_PRIVATE_STRING_UTIL_H_\n#define DOMAIN_REGISTRY_PRIVATE_STRING_UTIL_H_\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"assert.h\"\n\nstatic const char kUpperLowerDistance = 'A' - 'a';\n\n#if _WINDOWS\n#define __inline__ __inline\n#endif\n\nstatic __inline__ int IsWildcardComponent(const char* component) {\n  if (component[0] == '*') {\n    return 1;\n  }\n  return 0;\n}\n\nstatic __inline__ int IsExceptionComponent(const char* component) {\n  if (component[0] == '!') {\n    return 1;\n  }\n  return 0;\n}\n\nstatic __inline__ int IsInvalidComponent(const char* component) {\n  if (component == NULL ||\n      component[0] == 0 ||\n      IsExceptionComponent(component) ||\n      IsWildcardComponent(component)) {\n    return 1;\n  }\n  return 0;\n}\n\nstatic __inline__ void ReplaceChar(char* value, char old, char newval) {\n  while ((value = strchr(value, old)) != NULL) {\n    *value = newval;\n    ++value;\n  }\n}\n\nstatic __inline__ void ToLowerASCII(char* buf, const char* end) {\n  for (; buf < end; ++buf) {\n    char c = *buf;\n    if (c >= 'A' && c <= 'Z') {\n      *buf = c - kUpperLowerDistance;\n    }\n  }\n}\n\nstatic __inline__ int HostnamePartCmp(const char *a, const char *b) {\n  /*\n   * Optimization: do not invoke strcmp() unless the first characters\n   * in each string match. Since we are performing a binary search, we\n   * expect most invocations to strcmp to not have matching arguments,\n   * and thus not invoke strcmp. This reduces overall runtime by 5-10%\n   * on a Linux laptop running a -O2 optimized build.\n   */\n  int ret = *(unsigned char *)a - *(unsigned char *)b;\n  /*\n   * NOTE: we could invoke strcmp on a+1,b+1 if we are\n   * certain that neither a nor b are the empty string. For now we\n   * take the more conservative approach.\n   */\n  if (ret == 0) return strcmp(a, b);\n  return ret;\n}\n\n#endif  /* DOMAIN_REGISTRY_PRIVATE_STRING_UTIL_H_ */\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/private/trie_node.h",
    "content": "/*\n * Copyright 2011 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#ifndef DOMAIN_REGISTRY_PRIVATE_TRIE_NODE_H_\n#define DOMAIN_REGISTRY_PRIVATE_TRIE_NODE_H_\n\n#pragma pack(push)\n#pragma pack(1)\n\n/*\n * TrieNode represents a single node in a Trie. It uses 6 bytes of\n * storage.\n */\nstruct TrieNode {\n  /*\n   * Index in the string table for the hostname-part associated with\n   * this node.\n   */\n  unsigned int string_table_offset  : 21;\n\n  /*\n   * Offset of the first child of this node in the node table. All\n   * children are stored adjacent to each other, sorted\n   * lexicographically by their hostname parts.\n   */\n  unsigned int first_child_offset   : 14;\n\n  /*\n   * Number of children of this node.\n   */\n  unsigned int num_children         : 12;\n\n  /*\n   * Whether this node is a \"terminal\" node. A terminal node is one\n   * that represents the end of a sequence of nodes in the trie. For\n   * instance if the sequences \"com.foo.bar\" and \"com.foo\" are added\n   * to the trie, \"bar\" and \"foo\" are terminal nodes, since they are\n   * both at the end of their sequences.\n   */\n  unsigned int is_terminal          :  1;\n};\n\n#pragma pack(pop)\n\n#endif  /* DOMAIN_REGISTRY_PRIVATE_TRIE_NODE_H_ */\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/private/trie_search.c",
    "content": "/*\n * Copyright 2011 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#include \"assert.h\"\n#include \"string_util.h\"\n#include \"trie_search.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n/*\n * Helper macro that chooses the node half-way between the start and\n * end nodes. Used for binary search.\n */\n#define MIDDLE(start, end) ((start) + ((((end) - (start)) + 1) / 2));\n\n/*\n * Global data structures used to perform the search. Should be\n * populated once at startup by a call to SetRegistryTables.\n */\nstatic const char* g_string_table = NULL;\nstatic const struct TrieNode* g_node_table = NULL;\nstatic size_t g_num_root_children = 0;\nstatic const REGISTRY_U16* g_leaf_node_table = NULL;\nstatic size_t g_leaf_node_table_offset = 0;\n\n/*\n * Create an \"exception\" version of the given component. For instance\n * if component is \"foo\", will return \"!foo\". The caller is\n * responsible for freeing the returned memory.\n */\nstatic char* StrDupExceptionComponent(const char* component) {\n  /*\n   * TODO(bmcquade): could use thread-local storage of sufficient size\n   * to avoid this allocation. This should be invoked infrequently\n   * enough that it's probably fine for us to perform the allocation.\n   */\n  const size_t component_len = strlen(component);\n  char* exception_component = malloc(component_len + 2);\n  if (exception_component == NULL) {\n    return NULL;\n  }\n  memcpy(exception_component + 1, component, component_len);\n  exception_component[0] = '!';\n  exception_component[component_len + 1] = 0;\n  return exception_component;\n}\n\n/*\n * Performs a binary search looking for value, between the nodes start\n * and end, inclusive. Would normally have static linkage but is made\n * public for testing.\n */\nstatic const struct TrieNode* FindNodeInRange(\n    const char* value,\n    const struct TrieNode* start,\n    const struct TrieNode* end) {\n  DCHECK(value != NULL);\n  DCHECK(start != NULL);\n  DCHECK(end != NULL);\n  if (start > end) return NULL;\n  while (1) {\n    const struct TrieNode* candidate;\n    const char* candidate_str;\n    int result;\n\n    DCHECK(start <= end);\n    candidate = MIDDLE(start, end);\n    candidate_str = g_string_table + candidate->string_table_offset;\n    result = HostnamePartCmp(value, candidate_str);\n    if (result == 0) return candidate;\n    if (result > 0) {\n      if (end == candidate) return NULL;\n      start = candidate + 1;\n    } else {\n      if (start == candidate) return NULL;\n      end = candidate - 1;\n    }\n  }\n}\n\n/*\n * Performs a binary search looking for value, between the nodes start\n * and end, inclusive. Would normally have static linkage but is made\n * public for testing.\n */\nstatic const char* FindLeafNodeInRange(\n    const char* value,\n    const REGISTRY_U16* start,\n    const REGISTRY_U16* end) {\n  DCHECK(value != NULL);\n  DCHECK(start != NULL);\n  DCHECK(end != NULL);\n  if (start > end) return NULL;\n  while (1) {\n    const REGISTRY_U16* candidate;\n    const char* candidate_str;\n    int result;\n    DCHECK(start <= end);\n    candidate = MIDDLE(start, end);\n    candidate_str = g_string_table + *candidate;\n    result = HostnamePartCmp(value, candidate_str);\n    if (result == 0) return candidate_str;\n    if (result > 0) {\n      if (end == candidate) return NULL;\n      start = candidate + 1;\n    } else {\n      if (start == candidate) return NULL;\n      end = candidate - 1;\n    }\n  }\n}\n\n/*\n * Searches to find a registry node with the given component\n * identifier and the given parent node. If parent is null, searches\n * starting from the root node.\n */\nconst struct TrieNode* FindRegistryNode(const char* component,\n                                        const struct TrieNode* parent) {\n  const struct TrieNode* start;\n  const struct TrieNode* end;\n  const struct TrieNode* current;\n  const struct TrieNode* exception;\n\n  DCHECK(g_string_table != NULL);\n  DCHECK(g_node_table != NULL);\n  DCHECK(g_leaf_node_table != NULL);\n  DCHECK(component != NULL);\n\n  if (IsInvalidComponent(component)) {\n    return NULL;\n  }\n  if (parent == NULL) {\n    /* If parent is NULL, start the search at the root node. */\n    start = g_node_table;\n    end = start + (g_num_root_children - 1);\n  } else {\n    if (HasLeafChildren(parent) != 0) {\n      /*\n       * If the parent has leaf children, FindRegistryLeafNode should\n       * have been called instead.\n       */\n      DCHECK(0);\n      return NULL;\n    }\n\n    /* We'll be searching the specified parent node's children. */\n    start = g_node_table + parent->first_child_offset;\n    end = start + ((int) parent->num_children - 1);\n  }\n  current = FindNodeInRange(component, start, end);\n  if (current != NULL) {\n    /* Found a match. Return it. */\n    return current;\n  }\n\n  /*\n   * We didn't find an exact match, so see if there's a wildcard\n   * match. From http://publicsuffix.org/format/: \"The wildcard\n   * character * (asterisk) matches any valid sequence of characters\n   * in a hostname part. (Note: the list uses Unicode, not Punycode\n   * forms, and is encoded using UTF-8.) Wildcards may only be used to\n   * wildcard an entire level. That is, they must be surrounded by\n   * dots (or implicit dots, at the beginning of a line).\"\n   */\n  current = FindNodeInRange(\"*\", start, end);\n  if (current != NULL) {\n    /*\n     * If there was a wildcard match, see if there is a wildcard\n     * exception match, and prefer it if so. From\n     * http://publicsuffix.org/format/: \"An exclamation mark (!) at\n     * the start of a rule marks an exception to a previous wildcard\n     * rule. An exception rule takes priority over any other matching\n     * rule.\".\n     */\n    char* exception_component = StrDupExceptionComponent(component);\n    if (exception_component == NULL) {\n      return NULL;\n    }\n    exception = FindNodeInRange(exception_component,\n                                start,\n                                end);\n    free(exception_component);\n    if (exception != NULL) {\n      current = exception;\n    }\n  }\n  return current;\n}\n\nconst char* FindRegistryLeafNode(const char* component,\n                                 const struct TrieNode* parent) {\n  size_t offset;\n  const REGISTRY_U16* leaf_start;\n  const REGISTRY_U16* leaf_end;\n  const char* match;\n  const char* exception;\n\n  DCHECK(g_string_table != NULL);\n  DCHECK(g_node_table != NULL);\n  DCHECK(g_leaf_node_table != NULL);\n  DCHECK(component != NULL);\n  DCHECK(parent != NULL);\n  DCHECK(HasLeafChildren(parent) != 0);\n\n  if (parent == NULL) {\n    return NULL;\n  }\n  if (HasLeafChildren(parent) == 0) {\n    return NULL;\n  }\n  if (IsInvalidComponent(component)) {\n    return NULL;\n  }\n\n  offset = parent->first_child_offset - g_leaf_node_table_offset;\n  leaf_start = g_leaf_node_table + offset;\n  leaf_end = leaf_start + ((int) parent->num_children - 1);\n  match = FindLeafNodeInRange(component,\n                              leaf_start,\n                              leaf_end);\n  if (match != NULL) {\n    return match;\n  }\n\n  /*\n   * We didn't find an exact match, so see if there's a wildcard\n   * match. From http://publicsuffix.org/format/: \"The wildcard\n   * character * (asterisk) matches any valid sequence of characters\n   * in a hostname part. (Note: the list uses Unicode, not Punycode\n   * forms, and is encoded using UTF-8.) Wildcards may only be used to\n   * wildcard an entire level. That is, they must be surrounded by\n   * dots (or implicit dots, at the beginning of a line).\"\n   */\n  match = FindLeafNodeInRange(\"*\", leaf_start, leaf_end);\n  if (match != NULL) {\n    /*\n     * There was a wildcard match, so see if there is a wildcard\n     * exception match, and prefer it if so. From\n     * http://publicsuffix.org/format/: \"An exclamation mark (!) at\n     * the start of a rule marks an exception to a previous wildcard\n     * rule. An exception rule takes priority over any other matching\n     * rule.\".\n     */\n    char* exception_component = StrDupExceptionComponent(component);\n    if (exception_component == NULL) {\n      return NULL;\n    }\n    exception = FindLeafNodeInRange(exception_component,\n                                    leaf_start,\n                                    leaf_end);\n    free(exception_component);\n    if (exception != NULL) {\n      match = exception;\n    }\n  }\n  return match;\n}\n\nconst char* GetHostnamePart(size_t offset) {\n  DCHECK(g_string_table != NULL);\n  return g_string_table + offset;\n}\n\nint HasLeafChildren(const struct TrieNode* node) {\n  if (node && node->first_child_offset < g_leaf_node_table_offset) return 0;\n  return 1;\n}\n\nvoid SetRegistryTables(const char* string_table,\n                       const struct TrieNode* node_table,\n                       size_t num_root_children,\n                       const REGISTRY_U16* leaf_node_table,\n                       size_t leaf_node_table_offset) {\n  g_string_table = string_table;\n  g_node_table = node_table;\n  g_num_root_children = num_root_children;\n  g_leaf_node_table = leaf_node_table;\n  g_leaf_node_table_offset = leaf_node_table_offset;\n}\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/private/trie_search.h",
    "content": "/*\n * Copyright 2011 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 * Functions to search the registry tables. These should not\n * need to be invoked directly.\n */\n\n#ifndef DOMAIN_REGISTRY_PRIVATE_TRIE_SEARCH_H_\n#define DOMAIN_REGISTRY_PRIVATE_TRIE_SEARCH_H_\n\n#include <stdlib.h>\n\n#include \"registry_types.h\"\n#include \"trie_node.h\"\n\n/*\n * Find a TrieNode under the given parent node with the specified\n * name. If parent is NULL then the search is performed at the root\n * TrieNode.\n */\nconst struct TrieNode* FindRegistryNode(const char* component,\n                                        const struct TrieNode* parent);\n\n/*\n * Find a leaf TrieNode under the given parent node with the specified\n * name. If parent does not have all leaf children (i.e. if\n * HasLeafChildren(parent) returns zero), will assert and return\n * NULL. If parent is NULL then the search is performed at the root\n * TrieNode.\n */\nconst char* FindRegistryLeafNode(const char* component,\n                                 const struct TrieNode* parent);\n\n/* Get the hostname part for the given string table offset. */\nconst char* GetHostnamePart(size_t offset);\n\n/* Does the given node have all leaf children? */\nint HasLeafChildren(const struct TrieNode* node);\n\n/*\n * Initialize the registry tables. Called at system startup by\n * InitializeDomainRegistry().\n */\nvoid SetRegistryTables(const char* string_table,\n                       const struct TrieNode* node_table,\n                       size_t num_root_children,\n                       const REGISTRY_U16* leaf_node_table,\n                       size_t leaf_node_table_offset);\n\n#endif  /* DOMAIN_REGISTRY_PRIVATE_TRIE_SEARCH_H_ */\n"
  },
  {
    "path": "TrustKit/Dependencies/domain_registry/registry_tables_genfiles/registry_tables.h",
    "content": "/* Size of kStringTable 43554 */\n/* Size of kNodeTable 3549 */\n/* Size of kLeafNodeTable 4215 */\n/* Total size 73278 bytes */\n\nstatic const char kStringTable[] =\n\"aaa\\0\" \"aarp\\0\" \"abarth\\0\" \"abb\\0\" \"abbott\\0\" \"abbvie\\0\" \"abc\\0\"\n\"able\\0\" \"abogado\\0\" \"abudhabi\\0\" \"adac\\0\" \"academy\\0\" \"accenture\\0\"\n\"is-an-accountant\\0\" \"accountants\\0\" \"aco\\0\" \"interactive\\0\" \"is-an-actor\\0\"\n\"mad\\0\" \"ads\\0\" \"adult\\0\" \"sakae\\0\" \"aeg\\0\" \"aero\\0\" \"aetna\\0\" \"xn--rhkkervju-01af\\0\"\n\"afamilycompany\\0\" \"afl\\0\" \"eastafrica\\0\" \"dvag\\0\" \"agakhan\\0\" \"agency\\0\"\n\"aisai\\0\" \"aig\\0\" \"daigo\\0\" \"airbus\\0\" \"airforce\\0\" \"airtel\\0\" \"akdn\\0\"\n\"coal\\0\" \"alfaromeo\\0\" \"alibaba\\0\" \"alipay\\0\" \"allfinanz\\0\" \"allstate\\0\"\n\"ally\\0\" \"alsace\\0\" \"alstom\\0\" \"kvam\\0\" \"americanexpress\\0\" \"americanfamily\\0\"\n\"banamex\\0\" \"amfam\\0\" \"amica\\0\" \"amsterdam\\0\" \"analytics\\0\" \"android\\0\"\n\"anquan\\0\" \"vao\\0\" \"aol\\0\" \"apartments\\0\" \"fhapp\\0\" \"apple\\0\" \"iraq\\0\"\n\"aquarelle\\0\" \"far\\0\" \"arab\\0\" \"aramco\\0\" \"archi\\0\" \"army\\0\" \"arpa\\0\"\n\"smart\\0\" \"arte\\0\" \"tas\\0\" \"asda\\0\" \"asia\\0\" \"associates\\0\" \"nat\\0\"\n\"athleta\\0\" \"attorney\\0\" \"itau\\0\" \"auction\\0\" \"audi\\0\" \"audible\\0\"\n\"audio\\0\" \"auspost\\0\" \"author\\0\" \"auto\\0\" \"autos\\0\" \"avianca\\0\"\n\"waw\\0\" \"amazonaws\\0\" \"tax\\0\" \"axa\\0\" \"laz\\0\" \"xenapponazure\\0\"\n\"nba\\0\" \"baby\\0\" \"baidu\\0\" \"bananarepublic\\0\" \"in-the-band\\0\" \"ubank\\0\"\n\"bar\\0\" \"barcelona\\0\" \"barclaycard\\0\" \"barclays\\0\" \"barefoot\\0\"\n\"bargains\\0\" \"baseball\\0\" \"basketball\\0\" \"bauhaus\\0\" \"bayern\\0\"\n\"bbc\\0\" \"bbt\\0\" \"bbva\\0\" \"bcg\\0\" \"bcn\\0\" \"xn--mgbab2bd\\0\" \"kobe\\0\"\n\"beats\\0\" \"beauty\\0\" \"servebeer\\0\" \"bentley\\0\" \"berlin\\0\" \"best\\0\"\n\"bestbuy\\0\" \"bet\\0\" \"xn--mgb9awbf\\0\" \"bg\\0\" \"gmbh\\0\" \"bharti\\0\"\n\"sbi\\0\" \"bible\\0\" \"bid\\0\" \"bike\\0\" \"plumbing\\0\" \"bingo\\0\" \"bio\\0\"\n\"ebiz\\0\" \"bj\\0\" \"black\\0\" \"blackfriday\\0\" \"blanco\\0\" \"blockbuster\\0\"\n\"serveblog\\0\" \"bloomberg\\0\" \"blue\\0\" \"ibm\\0\" \"bms\\0\" \"bmw\\0\" \"cbn\\0\"\n\"bnl\\0\" \"bnpparibas\\0\" \"abo\\0\" \"boats\\0\" \"boehringer\\0\" \"bofa\\0\"\n\"bom\\0\" \"bond\\0\" \"boo\\0\" \"book\\0\" \"booking\\0\" \"boots\\0\" \"bosch\\0\"\n\"bostik\\0\" \"boston\\0\" \"bot\\0\" \"boutique\\0\" \"xbox\\0\" \"abr\\0\" \"bradesco\\0\"\n\"bridgestone\\0\" \"broadway\\0\" \"broker\\0\" \"brother\\0\" \"brussels\\0\"\n\"cbs\\0\" \"budapest\\0\" \"bugatti\\0\" \"build\\0\" \"builders\\0\" \"business\\0\"\n\"buzz\\0\" \"bv\\0\" \"bw\\0\" \"bz\\0\" \"bzh\\0\" \"aca\\0\" \"cab\\0\" \"cafe\\0\" \"medical\\0\"\n\"call\\0\" \"calvinklein\\0\" \"webcam\\0\" \"mysecuritycamera\\0\" \"at-band-camp\\0\"\n\"cancerresearch\\0\" \"canon\\0\" \"capetown\\0\" \"capital\\0\" \"capitalone\\0\"\n\"car\\0\" \"caravan\\0\" \"cards\\0\" \"healthcare\\0\" \"career\\0\" \"careers\\0\"\n\"is-into-cars\\0\" \"cartier\\0\" \"casa\\0\" \"case\\0\" \"caseih\\0\" \"cash\\0\"\n\"casino\\0\" \"avocat\\0\" \"catering\\0\" \"catholic\\0\" \"xn--nmesjevuemie-tcba\\0\"\n\"cbre\\0\" \"xn--l1acc\\0\" \"mcd\\0\" \"ceb\\0\" \"artcenter\\0\" \"ceo\\0\" \"cern\\0\"\n\"sncf\\0\" \"cfa\\0\" \"cfd\\0\" \"tech\\0\" \"chanel\\0\" \"travelchannel\\0\" \"chase\\0\"\n\"chat\\0\" \"cheap\\0\" \"chintai\\0\" \"chloe\\0\" \"christmas\\0\" \"chrome\\0\"\n\"chrysler\\0\" \"church\\0\" \"tci\\0\" \"cipriani\\0\" \"circle\\0\" \"sanfrancisco\\0\"\n\"citadel\\0\" \"citi\\0\" \"citic\\0\" \"!city\\0\" \"cityeats\\0\" \"duck\\0\" \"wlocl\\0\"\n\"claims\\0\" \"cleaning\\0\" \"click\\0\" \"clinic\\0\" \"clinique\\0\" \"clothing\\0\"\n\"rhcloud\\0\" \"aeroclub\\0\" \"clubmed\\0\" \"tcm\\0\" \"ecn\\0\" \"coach\\0\" \"codes\\0\"\n\"coffee\\0\" \"ilovecollege\\0\" \"cologne\\0\" \"mincom\\0\" \"comcast\\0\" \"commbank\\0\"\n\"community\\0\" \"compare\\0\" \"computer\\0\" \"comsec\\0\" \"condos\\0\" \"construction\\0\"\n\"consulting\\0\" \"contact\\0\" \"contractors\\0\" \"cooking\\0\" \"cookingchannel\\0\"\n\"cool\\0\" \"coop\\0\" \"corsica\\0\" \"country\\0\" \"coupon\\0\" \"coupons\\0\"\n\"courses\\0\" \"cr\\0\" \"credit\\0\" \"creditcard\\0\" \"creditunion\\0\" \"cricket\\0\"\n\"crown\\0\" \"crs\\0\" \"cruise\\0\" \"cruises\\0\" \"csc\\0\" \"icu\\0\" \"cuisinella\\0\"\n\"cv\\0\" \"pccw\\0\" \"cx\\0\" \"cymru\\0\" \"cyou\\0\" \"lowicz\\0\" \"dabur\\0\" \"baghdad\\0\"\n\"dance\\0\" \"alwaysdata\\0\" \"hakodate\\0\" \"dating\\0\" \"datsun\\0\" \"today\\0\"\n\"dclk\\0\" \"dds\\0\" \"iide\\0\" \"deal\\0\" \"dealer\\0\" \"deals\\0\" \"degree\\0\"\n\"delivery\\0\" \"dell\\0\" \"deloitte\\0\" \"delta\\0\" \"is-a-democrat\\0\" \"dental\\0\"\n\"dentist\\0\" \"desi\\0\" \"artanddesign\\0\" \"dev\\0\" \"dhl\\0\" \"diamonds\\0\"\n\"diet\\0\" \"digital\\0\" \"nextdirect\\0\" \"myactivedirectory\\0\" \"discount\\0\"\n\"discover\\0\" \"dish\\0\" \"diy\\0\" \"dj\\0\" \"tdk\\0\" \"adm\\0\" \"dnp\\0\" \"godo\\0\"\n\"docs\\0\" \"is-a-doctor\\0\" \"dodge\\0\" \"dog\\0\" \"doha\\0\" \"domains\\0\"\n\"dot\\0\" \"download\\0\" \"drive\\0\" \"dtv\\0\" \"dubai\\0\" \"dunlop\\0\" \"duns\\0\"\n\"dupont\\0\" \"durban\\0\" \"dvr\\0\" \"dwg\\0\" \"czeladz\\0\" \"earth\\0\" \"seat\\0\"\n\"rec\\0\" \"iveco\\0\" \"edeka\\0\" \"edu\\0\" \"arteducation\\0\" \"tree\\0\" \"leg\\0\"\n\"email\\0\" \"emerck\\0\" \"energy\\0\" \"is-an-engineer\\0\" \"engineering\\0\"\n\"enterprises\\0\" \"epost\\0\" \"epson\\0\" \"farmequipment\\0\" \"lier\\0\" \"ericsson\\0\"\n\"terni\\0\" \"neues\\0\" \"esq\\0\" \"realestate\\0\" \"esurance\\0\" \"fet\\0\"\n\"etisalat\\0\" \"eu\\0\" \"eurovision\\0\" \"eus\\0\" \"events\\0\" \"everbank\\0\"\n\"serveexchange\\0\" \"geometre-expert\\0\" \"exposed\\0\" \"orientexpress\\0\"\n\"extraspace\\0\" \"fage\\0\" \"fail\\0\" \"fairwinds\\0\" \"faith\\0\" \"tuxfamily\\0\"\n\"mlbfan\\0\" \"fans\\0\" \"statefarm\\0\" \"farmers\\0\" \"fashion\\0\" \"fast\\0\"\n\"fedex\\0\" \"feedback\\0\" \"ferrari\\0\" \"ferrero\\0\" \"sanofi\\0\" \"fiat\\0\"\n\"fidelity\\0\" \"fido\\0\" \"film\\0\" \"final\\0\" \"finance\\0\" \"lplfinancial\\0\"\n\"fire\\0\" \"firestone\\0\" \"firmdale\\0\" \"fish\\0\" \"fishing\\0\" \"fit\\0\"\n\"fitness\\0\" \"fj\\0\" \"jfk\\0\" \"flickr\\0\" \"flights\\0\" \"flir\\0\" \"florist\\0\"\n\"flowers\\0\" \"fly\\0\" \"ifm\\0\" \"ortsinfo\\0\" \"foo\\0\" \"food\\0\" \"foodnetwork\\0\"\n\"football\\0\" \"oxford\\0\" \"forex\\0\" \"forsale\\0\" \"forum\\0\" \"foundation\\0\"\n\"fox\\0\" \"sfr\\0\" \"dyndns-free\\0\" \"fresenius\\0\" \"frl\\0\" \"frogans\\0\"\n\"frontdoor\\0\" \"frontier\\0\" \"ftr\\0\" \"fujitsu\\0\" \"fujixerox\\0\" \"fun\\0\"\n\"fund\\0\" \"furniture\\0\" \"futbol\\0\" \"fyi\\0\" \"saga\\0\" \"legal\\0\" \"artgallery\\0\"\n\"gallo\\0\" \"gallup\\0\" \"marugame\\0\" \"is-into-games\\0\" \"gap\\0\" \"usgarden\\0\"\n\"xn--sandnessjen-ogb\\0\" \"gbiz\\0\" \"gd\\0\" \"gdn\\0\" \"koge\\0\" \"gea\\0\"\n\"gent\\0\" \"genting\\0\" \"george\\0\" \"ggf\\0\" \"gg\\0\" \"ggee\\0\" \"pittsburgh\\0\"\n\"nogi\\0\" \"gift\\0\" \"gifts\\0\" \"gives\\0\" \"giving\\0\" \"gl\\0\" \"glade\\0\"\n\"glass\\0\" \"withgoogle\\0\" \"global\\0\" \"globo\\0\" \"xn--fzys8d69uvgm\\0\"\n\"gmail\\0\" \"gmo\\0\" \"gmx\\0\" \"bjugn\\0\" \"godaddy\\0\" \"gold\\0\" \"goldpoint\\0\"\n\"golf\\0\" \"goo\\0\" \"goodhands\\0\" \"goodyear\\0\" \"goog\\0\" \"gop\\0\" \"forgot\\0\"\n\"chernigov\\0\" \"gp\\0\" \"gq\\0\" \"agr\\0\" \"grainger\\0\" \"graphics\\0\" \"gratis\\0\"\n\"is-a-green\\0\" \"gripe\\0\" \"grocery\\0\" \"stcgroup\\0\" \"vgs\\0\" \"gt\\0\"\n\"ivgu\\0\" \"theguardian\\0\" \"gucci\\0\" \"guge\\0\" \"guide\\0\" \"guitars\\0\"\n\"is-a-guru\\0\" \"rzgw\\0\" \"hair\\0\" \"hamburg\\0\" \"hangout\\0\" \"hbo\\0\"\n\"hdfc\\0\" \"hdfcbank\\0\" \"health\\0\" \"help\\0\" \"helsinki\\0\" \"thruhere\\0\"\n\"hermes\\0\" \"hgtv\\0\" \"hiphop\\0\" \"hisamitsu\\0\" \"hitachi\\0\" \"chernihiv\\0\"\n\"nhk\\0\" \"hkt\\0\" \"hm\\0\" \"stjohn\\0\" \"hockey\\0\" \"holdings\\0\" \"holiday\\0\"\n\"homedepot\\0\" \"homegoods\\0\" \"homes\\0\" \"homesense\\0\" \"honda\\0\" \"honeywell\\0\"\n\"horse\\0\" \"hospital\\0\" \"nfshost\\0\" \"futurehosting\\0\" \"hot\\0\" \"hoteles\\0\"\n\"kerryhotels\\0\" \"hotmail\\0\" \"mulhouse\\0\" \"show\\0\" \"ruhr\\0\" \"hsbc\\0\"\n\"recht\\0\" \"htc\\0\" \"sohu\\0\" \"hughes\\0\" \"hyatt\\0\" \"hyundai\\0\" \"icbc\\0\"\n\"venice\\0\" \"fie\\0\" \"ieee\\0\" \"iinet\\0\" \"ikano\\0\" \"mil\\0\" \"cim\\0\"\n\"imamat\\0\" \"imdb\\0\" \"immo\\0\" \"immobilien\\0\" \"fin\\0\" \"industries\\0\"\n\"infiniti\\0\" \"sling\\0\" \"pink\\0\" \"institute\\0\" \"lifeinsurance\\0\"\n\"insure\\0\" \"mint\\0\" \"intel\\0\" \"international\\0\" \"intuit\\0\" \"investments\\0\"\n\"ipiranga\\0\" \"iq\\0\" \"irish\\0\" \"iris\\0\" \"iselect\\0\" \"ismaili\\0\" \"gist\\0\"\n\"istanbul\\0\" \"itv\\0\" \"iwc\\0\" \"jaguar\\0\" \"java\\0\" \"jcb\\0\" \"jcp\\0\"\n\"fedje\\0\" \"jeep\\0\" \"jetzt\\0\" \"jewelry\\0\" \"jio\\0\" \"jlc\\0\" \"jll\\0\"\n\"jm\\0\" \"jmp\\0\" \"jnj\\0\" \"gujo\\0\" \"jobs\\0\" \"joburg\\0\" \"jot\\0\" \"joy\\0\"\n\"jp\\0\" \"jpmorgan\\0\" \"jprs\\0\" \"juegos\\0\" \"juniper\\0\" \"kaufen\\0\" \"kddi\\0\"\n\"wake\\0\" \"kerrylogistics\\0\" \"kerryproperties\\0\" \"kfh\\0\" \"kg\\0\" \"kh\\0\"\n\"ski\\0\" \"nokia\\0\" \"askim\\0\" \"kinder\\0\" \"kindle\\0\" \"kitchen\\0\" \"kiwi\\0\"\n\"km\\0\" \"bokn\\0\" \"koeln\\0\" \"komatsu\\0\" \"kosher\\0\" \"ostrowwlkp\\0\"\n\"kpmg\\0\" \"kpn\\0\" \"wskr\\0\" \"krd\\0\" \"kred\\0\" \"kuokgroup\\0\" \"kw\\0\"\n\"sky\\0\" \"kyoto\\0\" \"kz\\0\" \"fla\\0\" \"lacaixa\\0\" \"ladbrokes\\0\" \"lamborghini\\0\"\n\"lamer\\0\" \"lancaster\\0\" \"lancia\\0\" \"lancome\\0\" \"orland\\0\" \"landrover\\0\"\n\"lanxess\\0\" \"lasalle\\0\" \"balat\\0\" \"latino\\0\" \"latrobe\\0\" \"wroclaw\\0\"\n\"is-a-lawyer\\0\" \"mlb\\0\" \"plc\\0\" \"mcdonalds\\0\" \"lease\\0\" \"leclerc\\0\"\n\"lefrak\\0\" \"lego\\0\" \"lexus\\0\" \"lgbt\\0\" \"suli\\0\" \"liaison\\0\" \"lidl\\0\"\n\"metlife\\0\" \"lifestyle\\0\" \"lighting\\0\" \"like\\0\" \"lilly\\0\" \"limited\\0\"\n\"limo\\0\" \"lincoln\\0\" \"linde\\0\" \"homelink\\0\" \"lipsy\\0\" \"live\\0\" \"living\\0\"\n\"lixil\\0\" \"elk\\0\" \"loan\\0\" \"loans\\0\" \"locker\\0\" \"locus\\0\" \"loft\\0\"\n\"lol\\0\" \"london\\0\" \"lotte\\0\" \"lotto\\0\" \"love\\0\" \"lpl\\0\" \"lr\\0\" \"mls\\0\"\n\"alt\\0\" \"ltd\\0\" \"ltda\\0\" \"lu\\0\" \"lundbeck\\0\" \"lupin\\0\" \"luxe\\0\"\n\"luxury\\0\" \"malselv\\0\" \"mma\\0\" \"macys\\0\" \"madrid\\0\" \"maif\\0\" \"est-a-la-maison\\0\"\n\"makeup\\0\" \"itoman\\0\" \"management\\0\" \"mango\\0\" \"map\\0\" \"indianmarket\\0\"\n\"marketing\\0\" \"markets\\0\" \"marriott\\0\" \"marshalls\\0\" \"maserati\\0\"\n\"mattel\\0\" \"gotemba\\0\" \"xn--qcka1pmc\\0\" \"mckinsey\\0\" \"bmd\\0\" \"wme\\0\"\n\"media\\0\" \"meet\\0\" \"melbourne\\0\" \"meme\\0\" \"memorial\\0\" \"drammen\\0\"\n\"menu\\0\" \"merckmsd\\0\" \"xn--j1amh\\0\" \"miami\\0\" \"microsoft\\0\" \"rimini\\0\"\n\"rmit\\0\" \"mitsubishi\\0\" \"mk\\0\" \"ml\\0\" \"0emm\\0\" \"pmn\\0\" \"mobi\\0\"\n\"azure-mobile\\0\" \"mobily\\0\" \"shimoda\\0\" \"moe\\0\" \"moi\\0\" \"mom\\0\"\n\"monash\\0\" \"money\\0\" \"monster\\0\" \"montblanc\\0\" \"mopar\\0\" \"mormon\\0\"\n\"mortgage\\0\" \"moscow\\0\" \"kumamoto\\0\" \"motorcycles\\0\" \"mov\\0\" \"movie\\0\"\n\"movistar\\0\" \"emp\\0\" \"mq\\0\" \"emr\\0\" \"from-mt\\0\" \"mtn\\0\" \"mtpc\\0\"\n\"mtr\\0\" \"oumu\\0\" \"naturalhistorymuseum\\0\" \"northwesternmutual\\0\"\n\"mutuelle\\0\" \"mv\\0\" \"sumy\\0\" \"mz\\0\" \"arna\\0\" \"xn--rdy-0nab\\0\" \"nadex\\0\"\n\"nagoya\\0\" \"tokoname\\0\" \"nationwide\\0\" \"natura\\0\" \"oldnavy\\0\" \"pnc\\0\"\n\"etne\\0\" \"nec\\0\" \"netbank\\0\" \"netflix\\0\" \"neustar\\0\" \"new\\0\" \"newholland\\0\"\n\"news\\0\" \"next\\0\" \"nexus\\0\" \"inf\\0\" \"nfl\\0\" \"cng\\0\" \"nango\\0\" \"dni\\0\"\n\"nico\\0\" \"nike\\0\" \"nikon\\0\" \"ninja\\0\" \"nissan\\0\" \"nissay\\0\" \"ueno\\0\"\n\"norton\\0\" \"now\\0\" \"nowruz\\0\" \"nowtv\\0\" \"bnr\\0\" \"kanra\\0\" \"nrw\\0\"\n\"ntt\\0\" \"rnu\\0\" \"nyc\\0\" \"linz\\0\" \"observer\\0\" \"off\\0\" \"homeoffice\\0\"\n\"okinawa\\0\" \"olayan\\0\" \"olayangroup\\0\" \"ollo\\0\" \"nom\\0\" \"omega\\0\"\n\"phone\\0\" \"song\\0\" \"onl\\0\" \"online\\0\" \"onyourside\\0\" \"ooo\\0\" \"open\\0\"\n\"oracle\\0\" \"orange\\0\" \"sarpsborg\\0\" \"eating-organic\\0\" \"origins\\0\"\n\"kosaka\\0\" \"morotsuka\\0\" \"ovh\\0\" \"page\\0\" \"pamperedchef\\0\" \"panasonic\\0\"\n\"panerai\\0\" \"paris\\0\" \"pars\\0\" \"partners\\0\" \"parts\\0\" \"party\\0\"\n\"passagens\\0\" \"pet\\0\" \"pf\\0\" \"pfizer\\0\" \"ppg\\0\" \"ph\\0\" \"pharmacy\\0\"\n\"phd\\0\" \"philips\\0\" \"photo\\0\" \"photography\\0\" \"myphotos\\0\" \"physio\\0\"\n\"piaget\\0\" \"servepics\\0\" \"pictet\\0\" \"pictures\\0\" \"pid\\0\" \"shopping\\0\"\n\"pioneer\\0\" \"pizza\\0\" \"pk\\0\" \"birthplace\\0\" \"play\\0\" \"playstation\\0\"\n\"ptplus\\0\" \"pm\\0\" \"pohl\\0\" \"poker\\0\" \"politie\\0\" \"porn\\0\" \"from-pr\\0\"\n\"pramerica\\0\" \"praxi\\0\" \"prime\\0\" \"pro\\0\" \"prod\\0\" \"productions\\0\"\n\"prof\\0\" \"progressive\\0\" \"promo\\0\" \"property\\0\" \"protection\\0\" \"pru\\0\"\n\"prudential\\0\" \"ups\\0\" \"pt\\0\" \"pub\\0\" \"pw\\0\" \"pwc\\0\" \"spy\\0\" \"xn--bievt-0qa\\0\"\n\"qpon\\0\" \"quebec\\0\" \"quest\\0\" \"qvc\\0\" \"racing\\0\" \"radio\\0\" \"raid\\0\"\n\"kure\\0\" \"stufftoread\\0\" \"realtor\\0\" \"realty\\0\" \"recipes\\0\" \"redstone\\0\"\n\"redumbrella\\0\" \"rehab\\0\" \"reise\\0\" \"reisen\\0\" \"reit\\0\" \"reliance\\0\"\n\"turen\\0\" \"space-to-rent\\0\" \"rentals\\0\" \"repair\\0\" \"report\\0\" \"is-a-republican\\0\"\n\"rest\\0\" \"restaurant\\0\" \"review\\0\" \"reviews\\0\" \"rexroth\\0\" \"zuerich\\0\"\n\"richardli\\0\" \"ricoh\\0\" \"rightathome\\0\" \"ril\\0\" \"sondrio\\0\" \"ditchyourip\\0\"\n\"rocher\\0\" \"rocks\\0\" \"rodeo\\0\" \"rogers\\0\" \"room\\0\" \"rsvp\\0\" \"run\\0\"\n\"rwe\\0\" \"ryukyu\\0\" \"wsa\\0\" \"saarland\\0\" \"safe\\0\" \"safety\\0\" \"sakura\\0\"\n\"salon\\0\" \"samsclub\\0\" \"samsung\\0\" \"sandvik\\0\" \"sandvikcoromant\\0\"\n\"sap\\0\" \"sapo\\0\" \"sarl\\0\" \"sas\\0\" \"save\\0\" \"saxo\\0\" \"sb\\0\" \"sbs\\0\"\n\"psc\\0\" \"sca\\0\" \"scb\\0\" \"schaeffler\\0\" \"schmidt\\0\" \"scholarships\\0\"\n\"school\\0\" \"schule\\0\" \"schwarz\\0\" \"historyofscience\\0\" \"scjohnson\\0\"\n\"scor\\0\" \"scot\\0\" \"from-sd\\0\" \"nose\\0\" \"cdn77-secure\\0\" \"security\\0\"\n\"seek\\0\" \"sener\\0\" \"services\\0\" \"seven\\0\" \"sew\\0\" \"essex\\0\" \"sexy\\0\"\n\"xn--5su34j936bgsg\\0\" \"shangrila\\0\" \"sharp\\0\" \"shaw\\0\" \"shell\\0\"\n\"shia\\0\" \"shiksha\\0\" \"shoes\\0\" \"workshop\\0\" \"shouji\\0\" \"showtime\\0\"\n\"shriram\\0\" \"psi\\0\" \"silk\\0\" \"messina\\0\" \"singles\\0\" \"blogsite\\0\"\n\"sj\\0\" \"msk\\0\" \"skin\\0\" \"skype\\0\" \"qsl\\0\" \"gsm\\0\" \"smile\\0\" \"asn\\0\"\n\"aso\\0\" \"soccer\\0\" \"social\\0\" \"softbank\\0\" \"software\\0\" \"solar\\0\"\n\"solutions\\0\" \"sony\\0\" \"masoy\\0\" \"spiegel\\0\" \"appspot\\0\" \"spreadbetting\\0\"\n\"sr\\0\" \"srl\\0\" \"srt\\0\" \"fst\\0\" \"stada\\0\" \"staples\\0\" \"starhub\\0\"\n\"statebank\\0\" \"statoil\\0\" \"stc\\0\" \"stockholm\\0\" \"storage\\0\" \"store\\0\"\n\"stream\\0\" \"studio\\0\" \"study\\0\" \"kusu\\0\" \"sucks\\0\" \"supplies\\0\"\n\"supply\\0\" \"support\\0\" \"surf\\0\" \"surgery\\0\" \"suzuki\\0\" \"sv\\0\" \"swatch\\0\"\n\"swiftcover\\0\" \"swiss\\0\" \"mypsx\\0\" \"sydney\\0\" \"symantec\\0\" \"systems\\0\"\n\"pisz\\0\" \"tab\\0\" \"taipei\\0\" \"elasticbeanstalk\\0\" \"taobao\\0\" \"target\\0\"\n\"tatamotors\\0\" \"tatar\\0\" \"tattoo\\0\" \"taxi\\0\" \"etc\\0\" \"steam\\0\" \"technology\\0\"\n\"hotel\\0\" \"telecity\\0\" \"telefonica\\0\" \"temasek\\0\" \"tennis\\0\" \"teva\\0\"\n\"wtf\\0\" \"tg\\0\" \"ath\\0\" \"thd\\0\" \"theater\\0\" \"theatre\\0\" \"tiaa\\0\"\n\"tickets\\0\" \"tienda\\0\" \"tiffany\\0\" \"tips\\0\" \"tires\\0\" \"trentinostirol\\0\"\n\"tj\\0\" \"tjmaxx\\0\" \"tjx\\0\" \"tk\\0\" \"tkmaxx\\0\" \"intl\\0\" \"atm\\0\" \"tmall\\0\"\n\"mito\\0\" \"tokyo\\0\" \"tools\\0\" \"top\\0\" \"toray\\0\" \"toshiba\\0\" \"total\\0\"\n\"tours\\0\" \"toyota\\0\" \"toys\\0\" \"ntr\\0\" \"trade\\0\" \"trading\\0\" \"training\\0\"\n\"travel\\0\" \"travelers\\0\" \"travelersinsurance\\0\" \"trust\\0\" \"trv\\0\"\n\"withyoutube\\0\" \"tui\\0\" \"tunes\\0\" \"tushu\\0\" \"tvs\\0\" \"tw\\0\" \"myfritz\\0\"\n\"padua\\0\" \"ubs\\0\" \"uconnect\\0\" \"pug\\0\" \"jeonbuk\\0\" \"unicom\\0\" \"university\\0\"\n\"kazuno\\0\" \"uol\\0\" \"jus\\0\" \"tuva\\0\" \"vacations\\0\" \"vana\\0\" \"vanguard\\0\"\n\"vegas\\0\" \"ventures\\0\" \"verisign\\0\" \"versicherung\\0\" \"skiptvet\\0\"\n\"fvg\\0\" \"vi\\0\" \"viajes\\0\" \"video\\0\" \"vig\\0\" \"viking\\0\" \"villas\\0\"\n\"granvin\\0\" \"vip\\0\" \"virgin\\0\" \"visa\\0\" \"television\\0\" \"vista\\0\"\n\"vistaprint\\0\" \"viva\\0\" \"vivo\\0\" \"vlaanderen\\0\" \"koebenhavn\\0\" \"vodka\\0\"\n\"volkswagen\\0\" \"volvo\\0\" \"vote\\0\" \"voting\\0\" \"voto\\0\" \"voyage\\0\"\n\"vu\\0\" \"vuelos\\0\" \"wales\\0\" \"walmart\\0\" \"walter\\0\" \"wang\\0\" \"wanggou\\0\"\n\"warman\\0\" \"watches\\0\" \"weather\\0\" \"weatherchannel\\0\" \"weber\\0\"\n\"s3-website\\0\" \"wed\\0\" \"wedding\\0\" \"weibo\\0\" \"weir\\0\" \"wf\\0\" \"whoswho\\0\"\n\"wien\\0\" \"dyndns-wiki\\0\" \"williamhill\\0\" \"win\\0\" \"windows\\0\" \"wine\\0\"\n\"winners\\0\" \"wolterskluwer\\0\" \"woodside\\0\" \"works\\0\" \"world\\0\" \"wow\\0\"\n\"wtc\\0\" \"xfinity\\0\" \"xihuan\\0\" \"xin\\0\" \"xn--11b4c3d\\0\" \"xn--1ck2e1b\\0\"\n\"xn--1qqw23a\\0\" \"xn--30rr7y\\0\" \"xn--3bst00m\\0\" \"xn--3ds443g\\0\" \"xn--3e0b707e\\0\"\n\"xn--3oq18vl8pn36a\\0\" \"xn--3pxu8k\\0\" \"xn--42c2d9a\\0\" \"xn--45brj9c\\0\"\n\"xn--45q11c\\0\" \"xn--4gbrim\\0\" \"xn--4gq48lf9j\\0\" \"xn--54b7fta0cc\\0\"\n\"xn--55qw42g\\0\" \"xn--55qx5d\\0\" \"xn--5tzm5g\\0\" \"xn--6frz82g\\0\" \"xn--6qq986b3xl\\0\"\n\"xn--80adxhks\\0\" \"xn--80ao21a\\0\" \"xn--80aqecdr1a\\0\" \"xn--80asehdb\\0\"\n\"xn--80aswg\\0\" \"xn--8y0a063a\\0\" \"xn--90a3ac\\0\" \"xn--90ais\\0\" \"xn--9dbq2a\\0\"\n\"xn--9et52u\\0\" \"xn--9krt00a\\0\" \"xn--b4w605ferd\\0\" \"xn--bck1b9a5dre4c\\0\"\n\"xn--c1avg\\0\" \"xn--c2br7g\\0\" \"xn--cck2b3b\\0\" \"xn--cg4bki\\0\" \"xn--clchc0ea0b2g2a9gcd\\0\"\n\"xn--czr694b\\0\" \"xn--czrs0t\\0\" \"xn--czru2d\\0\" \"xn--d1acj3b\\0\" \"xn--d1alf\\0\"\n\"xn--e1a4c\\0\" \"xn--eckvdtc9d\\0\" \"xn--efvy88h\\0\" \"xn--estv75g\\0\"\n\"xn--fct429k\\0\" \"xn--fhbei\\0\" \"xn--fiq228c5hs\\0\" \"xn--fiq64b\\0\"\n\"xn--fiqs8s\\0\" \"xn--fiqz9s\\0\" \"xn--fjq720a\\0\" \"xn--flw351e\\0\" \"xn--fpcrj9c3d\\0\"\n\"xn--fzc2c9e2c\\0\" \"xn--g2xx48c\\0\" \"xn--gckr3f0f\\0\" \"xn--gecrj9c\\0\"\n\"xn--gk3at1e\\0\" \"xn--h2brj9c\\0\" \"xn--hxt814e\\0\" \"xn--i1b6b1a6a2e\\0\"\n\"xn--imr513n\\0\" \"xn--io0a7i\\0\" \"xn--j1aef\\0\" \"xn--j6w193g\\0\" \"xn--jlq61u9w7b\\0\"\n\"xn--jvr189m\\0\" \"xn--kcrx77d1x4a\\0\" \"xn--kprw13d\\0\" \"xn--kpry57d\\0\"\n\"xn--kpu716f\\0\" \"xn--kput3i\\0\" \"xn--lgbbat1ad8j\\0\" \"xn--mgb2ddes\\0\"\n\"xn--mgba3a3ejt\\0\" \"xn--mgba3a4f16a\\0\" \"xn--mgba3a4fra\\0\" \"xn--mgba7c0bbn0a\\0\"\n\"xn--mgbaakc7dvf\\0\" \"xn--mgbaam7a8h\\0\" \"xn--mgbai9a5eva00b\\0\" \"xn--mgbai9azgqp6j\\0\"\n\"xn--mgbayh7gpa\\0\" \"xn--mgbb9fbpob\\0\" \"xn--mgbbh1a71e\\0\" \"xn--mgbc0a9azcg\\0\"\n\"xn--mgbca7dzdo\\0\" \"xn--mgberp4a5d4a87g\\0\" \"xn--mgberp4a5d4ar\\0\"\n\"xn--mgbi4ecexp\\0\" \"xn--mgbpl2fh\\0\" \"xn--mgbqly7c0a67fbc\\0\" \"xn--mgbqly7cvafr\\0\"\n\"xn--mgbt3dhd\\0\" \"xn--mgbtf8fl\\0\" \"xn--mgbtx2b\\0\" \"xn--mgbx4cd0ab\\0\"\n\"xn--mix082f\\0\" \"xn--mix891f\\0\" \"xn--mk1bu44c\\0\" \"xn--mxtq1m\\0\"\n\"xn--ngbc5azd\\0\" \"xn--ngbe9e0a\\0\" \"xn--ngbrx\\0\" \"xn--nnx388a\\0\"\n\"xn--node\\0\" \"xn--nqv7f\\0\" \"xn--nqv7fs00ema\\0\" \"xn--nyqy26a\\0\" \"xn--o3cw4h\\0\"\n\"xn--ogbpf8fl\\0\" \"xn--p1acf\\0\" \"xn--p1ai\\0\" \"xn--pbt977c\\0\" \"xn--pgbs0dh\\0\"\n\"xn--pssy2u\\0\" \"xn--q9jyb4c\\0\" \"xn--qxam\\0\" \"xn--rhqv96g\\0\" \"xn--rovu88b\\0\"\n\"xn--s9brj9c\\0\" \"xn--ses554g\\0\" \"xn--t60b56a\\0\" \"xn--tckwe\\0\" \"xn--tiq49xqyj\\0\"\n\"xn--unup4y\\0\" \"xn--vermgensberater-ctb\\0\" \"xn--vermgensberatung-pwb\\0\"\n\"xn--vhquv\\0\" \"xn--vuq861b\\0\" \"xn--w4r85el8fhu5dnra\\0\" \"xn--w4rs40l\\0\"\n\"xn--wgbh1c\\0\" \"xn--wgbl6a\\0\" \"xn--xhq521b\\0\" \"xn--xkc2al3hye2a\\0\"\n\"xn--xkc2dl3a5ee0h\\0\" \"xn--y9a3aq\\0\" \"xn--yfro4i67o\\0\" \"xn--ygbi2ammx\\0\"\n\"xn--zfr164b\\0\" \"xperia\\0\" \"xxx\\0\" \"xyz\\0\" \"yachts\\0\" \"yahoo\\0\"\n\"yamaxun\\0\" \"yandex\\0\" \"ye\\0\" \"yodobashi\\0\" \"teaches-yoga\\0\" \"yokohama\\0\"\n\"yt\\0\" \"yun\\0\" \"koza\\0\" \"zappos\\0\" \"zara\\0\" \"zero\\0\" \"zip\\0\" \"zippo\\0\"\n\"zm\\0\" \"podzone\\0\" \"zw\\0\" \"blogspot\\0\" \"accident-investigation\\0\"\n\"accident-prevention\\0\" \"aerobatic\\0\" \"aerodrome\\0\" \"agents\\0\" \"air-surveillance\\0\"\n\"air-traffic-control\\0\" \"aircraft\\0\" \"airline\\0\" \"airport\\0\" \"airtraffic\\0\"\n\"ambulance\\0\" \"amusement\\0\" \"passenger-association\\0\" \"ballooning\\0\"\n\"caa\\0\" \"cargo\\0\" \"certification\\0\" \"championship\\0\" \"charter\\0\"\n\"civilaviation\\0\" \"conference\\0\" \"consultant\\0\" \"council\\0\" \"crew\\0\"\n\"dgca\\0\" \"educator\\0\" \"emergency\\0\" \"engine\\0\" \"entertainment\\0\"\n\"federation\\0\" \"flight\\0\" \"freight\\0\" \"fuel\\0\" \"hanggliding\\0\" \"government\\0\"\n\"groundhandling\\0\" \"homebuilt\\0\" \"journal\\0\" \"journalist\\0\" \"leasing\\0\"\n\"magazine\\0\" \"maintenance\\0\" \"microlight\\0\" \"modelling\\0\" \"navigation\\0\"\n\"parachuting\\0\" \"paragliding\\0\" \"pilot\\0\" \"production\\0\" \"recreation\\0\"\n\"repbody\\0\" \"rotorcraft\\0\" \"scientist\\0\" \"skydiving\\0\" \"is-a-student\\0\"\n\"trader\\0\" \"is-a-personaltrainer\\0\" \"workinggroup\\0\" \"fed\\0\" \"gv\\0\"\n\"spb\\0\" \"gob\\0\" \"karikatur\\0\" \"e164\\0\" \"in-addr\\0\" \"ip6\\0\" \"heguri\\0\"\n\"urn\\0\" \"cloudns\\0\" \"futuremailing\\0\" \"jor\\0\" \"priv\\0\" \"szex\\0\"\n\"kunden\\0\" \"*\\0\" \"conf\\0\" \"nsw\\0\" \"cnt\\0\" \"wuoz\\0\" \"qld\\0\" \"uvic\\0\"\n\"sowa\\0\" \"klepp\\0\" \"transurl\\0\" \"2000\\0\" \"eu-1\\0\" \"g12\\0\" \"s3\\0\"\n\"e4\\0\" \"5\\0\" \"cdn77\\0\" \"8\\0\" \"9\\0\" \"hb\\0\" \"qc\\0\" \"sf\\0\" \"qh\\0\" \"yk\\0\"\n\"jl\\0\" \"cq\\0\" \"js\\0\" \"gx\\0\" \"dscloud\\0\" \"dyndns\\0\" \"for-better\\0\"\n\"here-for-more\\0\" \"for-some\\0\" \"for-the\\0\" \"mmafan\\0\" \"myftp\\0\"\n\"no-ip\\0\" \"selfip\\0\" \"webhop\\0\" \"campobasso\\0\" \"barreau\\0\" \"gouv\\0\"\n\"adv\\0\" \"arq\\0\" \"bato\\0\" \"eng\\0\" \"esp\\0\" \"rieti\\0\" \"flog\\0\" \"fnd\\0\"\n\"fot\\0\" \"imb\\0\" \"ind\\0\" \"lel\\0\" \"mus\\0\" \"not\\0\" \"slg\\0\" \"srv\\0\"\n\"teo\\0\" \"tmp\\0\" \"trd\\0\" \"vlog\\0\" \"zlg\\0\" \"lecce\\0\" \"idf\\0\" \"togo\\0\"\n\"api\\0\" \"rj\\0\" \"rr\\0\" \"gc\\0\" \"winb\\0\" \"rns\\0\" \"toon\\0\" \"fantasyleague\\0\"\n\"ftpaccess\\0\" \"game-server\\0\" \"scrapping\\0\" \"gotdns\\0\" \"presse\\0\"\n\"xn--aroport-bya\\0\" \"!www\\0\" \"magentosite\\0\" \"myfusion\\0\" \"statics\\0\"\n\"utah\\0\" \"gz\\0\" \"naha\\0\" \"marche\\0\" \"ohi\\0\" \"from-nm\\0\" \"manx\\0\"\n\"xj\\0\" \"xn--od0alg\\0\" \"xz\\0\" \"stryn\\0\" \"zj\\0\" \"cn-north-1\\0\" \"compute\\0\"\n\"elb\\0\" \"firm\\0\" \"on-web\\0\" \"1kapp\\0\" \"3utilities\\0\" \"xn--8pvr4u\\0\"\n\"alpha-myqnapcloud\\0\" \"appchizi\\0\" \"applinzi\\0\" \"betainabox\\0\" \"blogdns\\0\"\n\"blogsyte\\0\" \"bloxcms\\0\" \"bounty-full\\0\" \"cechire\\0\" \"ciscofreak\\0\"\n\"cloudcontrolapp\\0\" \"cloudcontrolled\\0\" \"codespot\\0\" \"damnserver\\0\"\n\"ddnsking\\0\" \"dev-myqnapcloud\\0\" \"dnsalias\\0\" \"dnsdojo\\0\" \"dnsiskinky\\0\"\n\"doesntexist\\0\" \"dontexist\\0\" \"doomdns\\0\" \"dreamhosters\\0\" \"dsmynas\\0\"\n\"dyn-o-saur\\0\" \"dynalias\\0\" \"dyndns-at-home\\0\" \"dyndns-at-work\\0\"\n\"dyndns-blog\\0\" \"dyndns-home\\0\" \"dyndns-ip\\0\" \"dyndns-mail\\0\" \"dyndns-office\\0\"\n\"dyndns-pics\\0\" \"dyndns-remote\\0\" \"dyndns-server\\0\" \"dyndns-web\\0\"\n\"dyndns-work\\0\" \"dynns\\0\" \"est-a-la-masion\\0\" \"est-le-patron\\0\"\n\"est-mon-blogueur\\0\" \"evennode\\0\" \"familyds\\0\" \"fbsbx\\0\" \"firebaseapp\\0\"\n\"firewall-gateway\\0\" \"flynnhub\\0\" \"freebox-os\\0\" \"freeboxos\\0\" \"from-ak\\0\"\n\"from-al\\0\" \"from-ar\\0\" \"from-ca\\0\" \"from-ct\\0\" \"from-dc\\0\" \"from-de\\0\"\n\"from-fl\\0\" \"from-ga\\0\" \"from-hi\\0\" \"from-ia\\0\" \"from-id\\0\" \"from-il\\0\"\n\"from-in\\0\" \"from-ks\\0\" \"from-ky\\0\" \"from-ma\\0\" \"from-md\\0\" \"from-mi\\0\"\n\"from-mn\\0\" \"from-mo\\0\" \"from-ms\\0\" \"from-nc\\0\" \"from-nd\\0\" \"from-ne\\0\"\n\"from-nh\\0\" \"from-nj\\0\" \"from-nv\\0\" \"from-oh\\0\" \"from-ok\\0\" \"from-or\\0\"\n\"from-pa\\0\" \"from-ri\\0\" \"from-sc\\0\" \"from-tn\\0\" \"from-tx\\0\" \"from-ut\\0\"\n\"from-va\\0\" \"from-vt\\0\" \"from-wa\\0\" \"from-wi\\0\" \"from-wv\\0\" \"from-wy\\0\"\n\"geekgalaxy\\0\" \"getmyip\\0\" \"githubcloud\\0\" \"githubcloudusercontent\\0\"\n\"githubusercontent\\0\" \"googleapis\\0\" \"googlecode\\0\" \"gotpantheon\\0\"\n\"health-carereform\\0\" \"herokuapp\\0\" \"herokussl\\0\" \"hobby-site\\0\"\n\"homelinux\\0\" \"homesecuritymac\\0\" \"homesecuritypc\\0\" \"homeunix\\0\"\n\"iamallama\\0\" \"is-a-anarchist\\0\" \"is-a-blogger\\0\" \"is-a-bookkeeper\\0\"\n\"is-a-bulls-fan\\0\" \"is-a-caterer\\0\" \"is-a-chef\\0\" \"is-a-conservative\\0\"\n\"is-a-cpa\\0\" \"is-a-cubicle-slave\\0\" \"is-a-designer\\0\" \"is-a-financialadvisor\\0\"\n\"is-a-geek\\0\" \"is-a-hard-worker\\0\" \"is-a-hunter\\0\" \"is-a-landscaper\\0\"\n\"is-a-liberal\\0\" \"is-a-libertarian\\0\" \"is-a-llama\\0\" \"is-a-musician\\0\"\n\"is-a-nascarfan\\0\" \"is-a-nurse\\0\" \"is-a-painter\\0\" \"is-a-photographer\\0\"\n\"is-a-player\\0\" \"is-a-rockstar\\0\" \"is-a-socialist\\0\" \"is-a-teacher\\0\"\n\"is-a-techie\\0\" \"is-a-therapist\\0\" \"is-an-actress\\0\" \"is-an-anarchist\\0\"\n\"is-an-artist\\0\" \"is-an-entertainer\\0\" \"is-certified\\0\" \"is-gone\\0\"\n\"is-into-anime\\0\" \"is-into-cartoons\\0\" \"is-leet\\0\" \"is-not-certified\\0\"\n\"is-slick\\0\" \"is-uberleet\\0\" \"is-with-theband\\0\" \"isa-geek\\0\" \"isa-hockeynut\\0\"\n\"issmarterthanyou\\0\" \"joyent\\0\" \"jpn\\0\" \"likes-pie\\0\" \"likescandy\\0\"\n\"logoip\\0\" \"meteorapp\\0\" \"myasustor\\0\" \"mydrobo\\0\" \"myshopblocks\\0\"\n\"myvnc\\0\" \"neat-url\\0\" \"net-freaks\\0\" \"on-aptible\\0\" \"onthewifi\\0\"\n\"operaunite\\0\" \"outsystemscloud\\0\" \"ownprovider\\0\" \"pagefrontapp\\0\"\n\"pagespeedmobilizer\\0\" \"pgfog\\0\" \"point2this\\0\" \"prgmr\\0\" \"publishproxy\\0\"\n\"qa2\\0\" \"quicksytes\\0\" \"rackmaze\\0\" \"remotewd\\0\" \"saves-the-whales\\0\"\n\"securitytactics\\0\" \"sells-for-less\\0\" \"sells-for-u\\0\" \"servebbs\\0\"\n\"servecounterstrike\\0\" \"serveftp\\0\" \"servegame\\0\" \"servehalflife\\0\"\n\"servehttp\\0\" \"servehumour\\0\" \"serveirc\\0\" \"servemp3\\0\" \"servep2p\\0\"\n\"servequake\\0\" \"servesarcasm\\0\" \"simple-url\\0\" \"vipsinaapp\\0\" \"townnews-staging\\0\"\n\"unusualperson\\0\" \"workisboring\\0\" \"writesthisblog\\0\" \"yolasite\\0\"\n\"s3-ap-northeast-1\\0\" \"s3-ap-northeast-2\\0\" \"s3-ap-south-1\\0\" \"s3-ap-southeast-1\\0\"\n\"s3-ap-southeast-2\\0\" \"s3-ca-central-1\\0\" \"compute-1\\0\" \"s3-eu-central-1\\0\"\n\"s3-eu-west-1\\0\" \"s3-external-1\\0\" \"s3-fips-us-gov-west-1\\0\" \"s3-sa-east-1\\0\"\n\"s3-us-east-2\\0\" \"s3-us-gov-west-1\\0\" \"s3-us-west-1\\0\" \"s3-us-west-2\\0\"\n\"s3-website-ap-northeast-1\\0\" \"s3-website-ap-southeast-1\\0\" \"s3-website-ap-southeast-2\\0\"\n\"s3-website-eu-west-1\\0\" \"s3-website-sa-east-1\\0\" \"s3-website-us-east-1\\0\"\n\"s3-website-us-west-1\\0\" \"s3-website-us-west-2\\0\" \"dualstack\\0\"\n\"alpha\\0\" \"beta\\0\" \"eu-2\\0\" \"us-1\\0\" \"us-2\\0\" \"apps\\0\" \"cns\\0\" \"xen\\0\"\n\"ekloges\\0\" \"parliament\\0\" \"realm\\0\" \"cosidns\\0\" \"dd-dns\\0\" \"ddnss\\0\"\n\"dnshome\\0\" \"dnsupdater\\0\" \"dray-dns\\0\" \"draydns\\0\" \"dyn-ip24\\0\"\n\"dyn-vpn\\0\" \"dynamisches-dns\\0\" \"dyndns1\\0\" \"dynvpn\\0\" \"fuettertdasnetz\\0\"\n\"home-webserver\\0\" \"internet-dns\\0\" \"isteingeek\\0\" \"istmein\\0\" \"keymachine\\0\"\n\"l-o-g-i-n\\0\" \"lebtimnetz\\0\" \"leitungsen\\0\" \"mein-vigor\\0\" \"my-gateway\\0\"\n\"my-router\\0\" \"my-vigor\\0\" \"my-wan\\0\" \"myhome-server\\0\" \"spdns\\0\"\n\"syno-ds\\0\" \"synology-diskstation\\0\" \"synology-ds\\0\" \"taifun-dns\\0\"\n\"traeumtgerade\\0\" \"dedyn\\0\" \"reg\\0\" \"sld\\0\" \"nerdpol\\0\" \"k12\\0\"\n\"aip\\0\" \"lib\\0\" \"pri\\0\" \"riik\\0\" \"eun\\0\" \"nieruchomosci\\0\" \"mycd\\0\"\n\"wellbeingzone\\0\" \"is-a-linux-user\\0\" \"ybo\\0\" \"hordaland\\0\" \"cody\\0\"\n\"niki\\0\" \"aeroport\\0\" \"assedic\\0\" \"avoues\\0\" \"chambagri\\0\" \"chirurgiens-dentistes\\0\"\n\"chirurgiens-dentistes-en-france\\0\" \"experts-comptables\\0\" \"fbx-os\\0\"\n\"fbxos\\0\" \"greta\\0\" \"huissier-justice\\0\" \"medecin\\0\" \"notaires\\0\"\n\"pharmacien\\0\" \"prd\\0\" \"veterinaire\\0\" \"pvt\\0\" \"mod\\0\" \"idv\\0\" \"inc\\0\"\n\"xn--ciqpn\\0\" \"xn--gmq050i\\0\" \"xn--gmqw5a\\0\" \"xn--lcvr32d\\0\" \"xn--mk0axi\\0\"\n\"xn--od0aq3b\\0\" \"xn--tn0ag\\0\" \"xn--uc0atv\\0\" \"xn--uc0ay4a\\0\" \"xn--wcvs22d\\0\"\n\"xn--zf0avx\\0\" \"opencraft\\0\" \"from\\0\" \"perso\\0\" \"rel\\0\" \"agrar\\0\"\n\"bolt\\0\" \"erotica\\0\" \"erotika\\0\" \"ingatlan\\0\" \"jogasz\\0\" \"konyvelo\\0\"\n\"lakas\\0\" \"reklam\\0\" \"transport\\0\" \"tozsde\\0\" \"utazas\\0\" \"odesa\\0\"\n\"muni\\0\" \"bergen\\0\" \"barrel-of-knowledge\\0\" \"barrell-of-knowledge\\0\"\n\"dvrcam\\0\" \"dynamic-dns\\0\" \"for-our\\0\" \"groks-the\\0\" \"groks-this\\0\"\n\"knowsitall\\0\" \"nsupdate\\0\" \"backplaneapp\\0\" \"boxfuse\\0\" \"browsersafetymark\\0\"\n\"drud\\0\" \"enonic\\0\" \"github\\0\" \"gitlab\\0\" \"hasura-app\\0\" \"hzc\\0\"\n\"lair\\0\" \"ngrok\\0\" \"nid\\0\" \"pantheonsite\\0\" \"protonet\\0\" \"sandcats\\0\"\n\"shiftedit\\0\" \"spacekit\\0\" \"stolos\\0\" \"customer\\0\" \"cupcake\\0\" \"abruzzo\\0\"\n\"agrigento\\0\" \"alessandria\\0\" \"trentinoalto-adige\\0\" \"trentinoaltoadige\\0\"\n\"esan\\0\" \"ancona\\0\" \"andria-barletta-trani\\0\" \"andria-trani-barletta\\0\"\n\"andriabarlettatrani\\0\" \"andriatranibarletta\\0\" \"valdaosta\\0\" \"aosta-valley\\0\"\n\"aostavalley\\0\" \"valleeaoste\\0\" \"laquila\\0\" \"arezzo\\0\" \"ascoli-piceno\\0\"\n\"ascolipiceno\\0\" \"asti\\0\" \"av\\0\" \"avellino\\0\" \"balsan\\0\" \"nabari\\0\"\n\"barletta-trani-andria\\0\" \"barlettatraniandria\\0\" \"basilicata\\0\"\n\"belluno\\0\" \"benevento\\0\" \"bergamo\\0\" \"biella\\0\" \"publ\\0\" \"bologna\\0\"\n\"bolzano\\0\" \"bozen\\0\" \"brescia\\0\" \"brindisi\\0\" \"cagliari\\0\" \"reggiocalabria\\0\"\n\"caltanissetta\\0\" \"campania\\0\" \"campidano-medio\\0\" \"campidanomedio\\0\"\n\"carbonia-iglesias\\0\" \"carboniaiglesias\\0\" \"carrara-massa\\0\" \"carraramassa\\0\"\n\"caserta\\0\" \"catania\\0\" \"catanzaro\\0\" \"cesena-forli\\0\" \"cesenaforli\\0\"\n\"chieti\\0\" \"como\\0\" \"cosenza\\0\" \"cremona\\0\" \"crotone\\0\" \"acct\\0\"\n\"cuneo\\0\" \"dell-ogliastra\\0\" \"dellogliastra\\0\" \"emilia-romagna\\0\"\n\"emiliaromagna\\0\" \"ravenna\\0\" \"fermo\\0\" \"ferrara\\0\" \"fg\\0\" \"firenze\\0\"\n\"florence\\0\" \"foggia\\0\" \"forli-cesena\\0\" \"forlicesena\\0\" \"friuli-v-giulia\\0\"\n\"friuli-ve-giulia\\0\" \"friuli-vegiulia\\0\" \"friuli-venezia-giulia\\0\"\n\"friuli-veneziagiulia\\0\" \"friuli-vgiulia\\0\" \"friuliv-giulia\\0\" \"friulive-giulia\\0\"\n\"friulivegiulia\\0\" \"friulivenezia-giulia\\0\" \"friuliveneziagiulia\\0\"\n\"friulivgiulia\\0\" \"frosinone\\0\" \"genoa\\0\" \"genova\\0\" \"gorizia\\0\"\n\"grosseto\\0\" \"iglesias-carbonia\\0\" \"iglesiascarbonia\\0\" \"imperia\\0\"\n\"isernia\\0\" \"la-spezia\\0\" \"laspezia\\0\" \"latina\\0\" \"lazio\\0\" \"tele\\0\"\n\"lecco\\0\" \"lig\\0\" \"liguria\\0\" \"livorno\\0\" \"plo\\0\" \"lodi\\0\" \"lom\\0\"\n\"lombardia\\0\" \"lombardy\\0\" \"lucania\\0\" \"lucca\\0\" \"macerata\\0\" \"mantova\\0\"\n\"hamar\\0\" \"massa-carrara\\0\" \"massacarrara\\0\" \"matera\\0\" \"medio-campidano\\0\"\n\"mediocampidano\\0\" \"isumi\\0\" \"milan\\0\" \"milano\\0\" \"modena\\0\" \"mol\\0\"\n\"molise\\0\" \"monza\\0\" \"monza-brianza\\0\" \"monza-e-della-brianza\\0\"\n\"monzabrianza\\0\" \"monzaebrianza\\0\" \"monzaedellabrianza\\0\" \"naples\\0\"\n\"napoli\\0\" \"novara\\0\" \"nuoro\\0\" \"olbia-tempio\\0\" \"olbiatempio\\0\"\n\"oristano\\0\" \"padova\\0\" \"palermo\\0\" \"parma\\0\" \"pavia\\0\" \"pd\\0\" \"perugia\\0\"\n\"pesaro-urbino\\0\" \"pesarourbino\\0\" \"pescara\\0\" \"piacenza\\0\" \"piedmont\\0\"\n\"piemonte\\0\" \"pisa\\0\" \"pistoia\\0\" \"uppo\\0\" \"pordenone\\0\" \"potenza\\0\"\n\"prato\\0\" \"pippu\\0\" \"puglia\\0\" \"pv\\0\" \"pz\\0\" \"nara\\0\" \"ragusa\\0\"\n\"reggio-calabria\\0\" \"reggio-emilia\\0\" \"reggioemilia\\0\" \"elburg\\0\"\n\"saroma\\0\" \"rovigo\\0\" \"salerno\\0\" \"sar\\0\" \"sardegna\\0\" \"sardinia\\0\"\n\"sassari\\0\" \"savona\\0\" \"music\\0\" \"sicilia\\0\" \"sicily\\0\" \"siena\\0\"\n\"siracusa\\0\" \"moss\\0\" \"trentinosuedtirol\\0\" \"kota\\0\" \"vantaa\\0\"\n\"taranto\\0\" \"tempio-olbia\\0\" \"tempioolbia\\0\" \"teramo\\0\" \"torino\\0\"\n\"toscana\\0\" \"trani-andria-barletta\\0\" \"trani-barletta-andria\\0\"\n\"traniandriabarletta\\0\" \"tranibarlettaandria\\0\" \"trapani\\0\" \"trentino\\0\"\n\"trentino-a-adige\\0\" \"trentino-aadige\\0\" \"trentino-alto-adige\\0\"\n\"trentino-altoadige\\0\" \"trentino-s-tirol\\0\" \"trentino-stirol\\0\"\n\"trentino-sud-tirol\\0\" \"trentino-sudtirol\\0\" \"trentino-sued-tirol\\0\"\n\"trentino-suedtirol\\0\" \"trentinoa-adige\\0\" \"trentinoaadige\\0\" \"trentinos-tirol\\0\"\n\"trentinosud-tirol\\0\" \"trentinosudtirol\\0\" \"trentinosued-tirol\\0\"\n\"trento\\0\" \"treviso\\0\" \"trieste\\0\" \"its\\0\" \"turin\\0\" \"tuscany\\0\"\n\"udine\\0\" \"umb\\0\" \"umbria\\0\" \"urbino-pesaro\\0\" \"urbinopesaro\\0\"\n\"val-d-aosta\\0\" \"val-daosta\\0\" \"vald-aosta\\0\" \"valle-aosta\\0\" \"valle-d-aosta\\0\"\n\"valle-daosta\\0\" \"valleaosta\\0\" \"valled-aosta\\0\" \"valledaosta\\0\"\n\"vallee-aoste\\0\" \"varese\\0\" \"vb\\0\" \"vda\\0\" \"veneto\\0\" \"venezia\\0\"\n\"verbania\\0\" \"vercelli\\0\" \"verona\\0\" \"vibo-valentia\\0\" \"vibovalentia\\0\"\n\"vicenza\\0\" \"viterbo\\0\" \"vv\\0\" \"yokkaichi\\0\" \"kawakita\\0\" \"aomori\\0\"\n\"yokaichiba\\0\" \"ehime\\0\" \"fukui\\0\" \"fukuoka\\0\" \"kisofukushima\\0\"\n\"gifu\\0\" \"gunma\\0\" \"kitahiroshima\\0\" \"hokkaido\\0\" \"hyogo\\0\" \"ibaraki\\0\"\n\"nishikawa\\0\" \"iwate\\0\" \"nakagawa\\0\" \"kagoshima\\0\" \"kanagawa\\0\"\n\"kawasaki\\0\" \"kitakyushu\\0\" \"kochi\\0\" \"namie\\0\" \"miyagi\\0\" \"miyazaki\\0\"\n\"kawachinagano\\0\" \"nagasaki\\0\" \"niigata\\0\" \"yoita\\0\" \"okayama\\0\"\n\"saitama\\0\" \"sapporo\\0\" \"satsumasendai\\0\" \"shiga\\0\" \"shimane\\0\"\n\"shizuoka\\0\" \"tochigi\\0\" \"tokushima\\0\" \"tottori\\0\" \"motoyama\\0\"\n\"wakayama\\0\" \"xn--0trq7p7nn\\0\" \"xn--1ctwo\\0\" \"xn--1lqs03n\\0\" \"xn--1lqs71d\\0\"\n\"xn--2m4a15e\\0\" \"xn--32vp30h\\0\" \"xn--4it168d\\0\" \"xn--4it797k\\0\"\n\"xn--4pvxs\\0\" \"xn--5js045d\\0\" \"xn--5rtp49c\\0\" \"xn--5rtq34k\\0\" \"xn--6btw5a\\0\"\n\"xn--6orx2r\\0\" \"xn--7t0a264c\\0\" \"xn--8ltr62k\\0\" \"xn--c3s14m\\0\" \"xn--d5qv7z876c\\0\"\n\"xn--djrs72d6uy\\0\" \"xn--djty4k\\0\" \"xn--efvn9s\\0\" \"xn--ehqz56n\\0\"\n\"xn--elqq16h\\0\" \"xn--f6qx53a\\0\" \"xn--k7yn95e\\0\" \"xn--kbrq7o\\0\" \"xn--klt787d\\0\"\n\"xn--kltp7d\\0\" \"xn--kltx9a\\0\" \"xn--klty5x\\0\" \"xn--mkru45i\\0\" \"xn--nit225k\\0\"\n\"xn--ntso0iqx3a\\0\" \"xn--ntsq17g\\0\" \"xn--pssu33l\\0\" \"xn--qqqt11m\\0\"\n\"xn--rht27z\\0\" \"xn--rht3d\\0\" \"xn--rht61e\\0\" \"xn--rny31h\\0\" \"xn--tor131o\\0\"\n\"xn--uist22h\\0\" \"xn--uisz3g\\0\" \"xn--uuwu58a\\0\" \"xn--vgu402c\\0\" \"xn--zbx025d\\0\"\n\"yamagata\\0\" \"yamaguchi\\0\" \"yamanashi\\0\" \"zama\\0\" \"sanjo\\0\" \"asuke\\0\"\n\"chiryu\\0\" \"chita\\0\" \"fuso\\0\" \"gamagori\\0\" \"handa\\0\" \"hazu\\0\" \"hekinan\\0\"\n\"higashiura\\0\" \"ichinomiya\\0\" \"inazawa\\0\" \"inuyama\\0\" \"isshiki\\0\"\n\"iwakura\\0\" \"kanie\\0\" \"kariya\\0\" \"kasugai\\0\" \"kira\\0\" \"kiyosu\\0\"\n\"komaki\\0\" \"konan\\0\" \"mihama\\0\" \"higashisumiyoshi\\0\" \"nishio\\0\"\n\"nisshin\\0\" \"motobu\\0\" \"oguchi\\0\" \"oharu\\0\" \"okazaki\\0\" \"owariasahi\\0\"\n\"oseto\\0\" \"shikatsu\\0\" \"shinshiro\\0\" \"shitara\\0\" \"tahara\\0\" \"takahama\\0\"\n\"tobishima\\0\" \"toei\\0\" \"tokai\\0\" \"toyoake\\0\" \"toyohashi\\0\" \"toyokawa\\0\"\n\"toyone\\0\" \"komatsushima\\0\" \"yatomi\\0\" \"daisen\\0\" \"fujisato\\0\" \"gojome\\0\"\n\"hachirogata\\0\" \"happou\\0\" \"higashinaruse\\0\" \"yurihonjo\\0\" \"honjyo\\0\"\n\"aikawa\\0\" \"kamikoani\\0\" \"kamioka\\0\" \"katagami\\0\" \"kitaakita\\0\"\n\"kyowa\\0\" \"tomisato\\0\" \"minamitane\\0\" \"moriyoshi\\0\" \"nikaho\\0\" \"noshiro\\0\"\n\"koga\\0\" \"nogata\\0\" \"semboku\\0\" \"yokote\\0\" \"gonohe\\0\" \"hachinohe\\0\"\n\"hashikami\\0\" \"hiranai\\0\" \"hirosaki\\0\" \"itayanagi\\0\" \"kuroishi\\0\"\n\"misawa\\0\" \"mutsu\\0\" \"nakadomari\\0\" \"noheji\\0\" \"oirase\\0\" \"owani\\0\"\n\"rokunohe\\0\" \"sannohe\\0\" \"shichinohe\\0\" \"shingo\\0\" \"takko\\0\" \"towada\\0\"\n\"tsugaru\\0\" \"tsuruta\\0\" \"abiko\\0\" \"chonan\\0\" \"chosei\\0\" \"choshi\\0\"\n\"kibichuo\\0\" \"funabashi\\0\" \"futtsu\\0\" \"hanamigawa\\0\" \"ichihara\\0\"\n\"ichikawa\\0\" \"inzai\\0\" \"kamagaya\\0\" \"kamogawa\\0\" \"kashiwa\\0\" \"takatori\\0\"\n\"nachikatsuura\\0\" \"kimitsu\\0\" \"kisarazu\\0\" \"kozaki\\0\" \"kujukuri\\0\"\n\"kyonan\\0\" \"matsudo\\0\" \"midori\\0\" \"minamiboso\\0\" \"mobara\\0\" \"mutsuzawa\\0\"\n\"nagara\\0\" \"nagareyama\\0\" \"narashino\\0\" \"narita\\0\" \"noda\\0\" \"oamishirasato\\0\"\n\"omigawa\\0\" \"onjuku\\0\" \"kurotaki\\0\" \"shimofusa\\0\" \"shirako\\0\" \"shiroi\\0\"\n\"shisui\\0\" \"sodegaura\\0\" \"sosa\\0\" \"itako\\0\" \"tateyama\\0\" \"togane\\0\"\n\"tohnosho\\0\" \"urayasu\\0\" \"yachimata\\0\" \"yachiyo\\0\" \"yokoshibahikari\\0\"\n\"yotsukaido\\0\" \"kainan\\0\" \"shonai\\0\" \"namikata\\0\" \"imabari\\0\" \"seiyo\\0\"\n\"osakikamijima\\0\" \"kihoku\\0\" \"kumakogen\\0\" \"masaki\\0\" \"matsuno\\0\"\n\"higashimatsuyama\\0\" \"niihama\\0\" \"uozu\\0\" \"saijo\\0\" \"shikokuchuo\\0\"\n\"otobe\\0\" \"fujikawaguchiko\\0\" \"uwajima\\0\" \"yawatahama\\0\" \"minamiechizen\\0\"\n\"eiheiji\\0\" \"ikeda\\0\" \"katsuyama\\0\" \"obama\\0\" \"tono\\0\" \"sabae\\0\"\n\"sakai\\0\" \"tsuruga\\0\" \"wakasa\\0\" \"ashiya\\0\" \"buzen\\0\" \"chikugo\\0\"\n\"chikuho\\0\" \"chikujo\\0\" \"chikushino\\0\" \"chikuzen\\0\" \"dazaifu\\0\"\n\"fukuchi\\0\" \"hakata\\0\" \"higashi\\0\" \"hirokawa\\0\" \"hisayama\\0\" \"iizuka\\0\"\n\"inatsuki\\0\" \"kasuga\\0\" \"kasuya\\0\" \"kawara\\0\" \"keisen\\0\" \"kurate\\0\"\n\"kurogi\\0\" \"higashikurume\\0\" \"asaminami\\0\" \"miyako\\0\" \"kumiyama\\0\"\n\"miyawaka\\0\" \"mizumaki\\0\" \"munakata\\0\" \"nakama\\0\" \"seranishi\\0\"\n\"ogori\\0\" \"okagaki\\0\" \"toki\\0\" \"omuta\\0\" \"onga\\0\" \"miyakonojo\\0\"\n\"koto\\0\" \"saigawa\\0\" \"sasaguri\\0\" \"shingu\\0\" \"shinyoshitomi\\0\" \"soeda\\0\"\n\"matsue\\0\" \"tachiarai\\0\" \"kitagawa\\0\" \"kitakata\\0\" \"toho\\0\" \"toyotsu\\0\"\n\"tsuiki\\0\" \"ukiha\\0\" \"yusui\\0\" \"yamada\\0\" \"yame\\0\" \"yanagawa\\0\"\n\"yukuhashi\\0\" \"aizubange\\0\" \"aizumisato\\0\" \"aizuwakamatsu\\0\" \"asakawa\\0\"\n\"bandai\\0\" \"furudono\\0\" \"futaba\\0\" \"hanawa\\0\" \"hirata\\0\" \"hirono\\0\"\n\"iitate\\0\" \"inawashiro\\0\" \"nishiwaki\\0\" \"izumizaki\\0\" \"kagamiishi\\0\"\n\"kaneyama\\0\" \"kawamata\\0\" \"kitashiobara\\0\" \"koori\\0\" \"yamatokoriyama\\0\"\n\"kunimi\\0\" \"miharu\\0\" \"mishima\\0\" \"nishiaizu\\0\" \"nishigo\\0\" \"okuma\\0\"\n\"omotego\\0\" \"otama\\0\" \"samegawa\\0\" \"shimogo\\0\" \"higashishirakawa\\0\"\n\"showa\\0\" \"soma\\0\" \"sukagawa\\0\" \"taishin\\0\" \"tamakawa\\0\" \"tanagura\\0\"\n\"tenei\\0\" \"yabuki\\0\" \"higashiyamato\\0\" \"yamatsuri\\0\" \"yanaizu\\0\"\n\"yugawa\\0\" \"anpachi\\0\" \"ginan\\0\" \"hashima\\0\" \"hichiso\\0\" \"machida\\0\"\n\"ibigawa\\0\" \"kakamigahara\\0\" \"kani\\0\" \"kasahara\\0\" \"kasamatsu\\0\"\n\"kawaue\\0\" \"kitagata\\0\" \"kimino\\0\" \"minokamo\\0\" \"mitake\\0\" \"mizunami\\0\"\n\"motosu\\0\" \"nakatsugawa\\0\" \"aogaki\\0\" \"sakahogi\\0\" \"ichinoseki\\0\"\n\"sekigahara\\0\" \"tajimi\\0\" \"takayama\\0\" \"tarui\\0\" \"tomika\\0\" \"wanouchi\\0\"\n\"yaotsu\\0\" \"nayoro\\0\" \"annaka\\0\" \"chiyoda\\0\" \"fujioka\\0\" \"higashiagatsuma\\0\"\n\"isesaki\\0\" \"itakura\\0\" \"kanna\\0\" \"katashina\\0\" \"kawaba\\0\" \"kiryu\\0\"\n\"kusatsu\\0\" \"maebashi\\0\" \"meiwa\\0\" \"minakami\\0\" \"naganohara\\0\" \"nakanojo\\0\"\n\"nanmoku\\0\" \"numata\\0\" \"oizumi\\0\" \"ozora\\0\" \"shibukawa\\0\" \"shimonita\\0\"\n\"shinto\\0\" \"takasaki\\0\" \"tamamura\\0\" \"tatebayashi\\0\" \"tomioka\\0\"\n\"tsukiyono\\0\" \"tsumagoi\\0\" \"yoshioka\\0\" \"daiwa\\0\" \"etajima\\0\" \"fuchu\\0\"\n\"fukuyama\\0\" \"hatsukaichi\\0\" \"higashihiroshima\\0\" \"hongo\\0\" \"jinsekikogen\\0\"\n\"kaita\\0\" \"kumano\\0\" \"sagamihara\\0\" \"onomichi\\0\" \"otake\\0\" \"sera\\0\"\n\"shinichi\\0\" \"shobara\\0\" \"takehara\\0\" \"abashiri\\0\" \"akabira\\0\" \"aibetsu\\0\"\n\"akkeshi\\0\" \"asahikawa\\0\" \"ashibetsu\\0\" \"ashoro\\0\" \"assabu\\0\" \"bibai\\0\"\n\"biei\\0\" \"bifuka\\0\" \"bihoro\\0\" \"biratori\\0\" \"chippubetsu\\0\" \"chitose\\0\"\n\"ebetsu\\0\" \"embetsu\\0\" \"eniwa\\0\" \"erimo\\0\" \"esashi\\0\" \"fukagawa\\0\"\n\"kamifurano\\0\" \"furubira\\0\" \"haboro\\0\" \"hamatonbetsu\\0\" \"hidaka\\0\"\n\"higashikagura\\0\" \"higashikawa\\0\" \"hiroo\\0\" \"hokuryu\\0\" \"hokuto\\0\"\n\"honbetsu\\0\" \"horokanai\\0\" \"horonobe\\0\" \"imakane\\0\" \"ishikari\\0\"\n\"iwamizawa\\0\" \"iwanai\\0\" \"kamikawa\\0\" \"kamishihoro\\0\" \"kamisunagawa\\0\"\n\"kamoenai\\0\" \"kayabe\\0\" \"kembuchi\\0\" \"kikonai\\0\" \"kimobetsu\\0\" \"kitami\\0\"\n\"kiyosato\\0\" \"koshimizu\\0\" \"kunneppu\\0\" \"kuriyama\\0\" \"kuromatsunai\\0\"\n\"kushiro\\0\" \"kutchan\\0\" \"mashike\\0\" \"matsumae\\0\" \"mikasa\\0\" \"minamifurano\\0\"\n\"mombetsu\\0\" \"moseushi\\0\" \"samukawa\\0\" \"muroran\\0\" \"naie\\0\" \"nakasatsunai\\0\"\n\"nakatombetsu\\0\" \"nanae\\0\" \"nanporo\\0\" \"nemuro\\0\" \"niikappu\\0\" \"nishiokoppe\\0\"\n\"noboribetsu\\0\" \"obihiro\\0\" \"obira\\0\" \"oketo\\0\" \"otaru\\0\" \"otofuke\\0\"\n\"otoineppu\\0\" \"rankoshi\\0\" \"rebun\\0\" \"rikubetsu\\0\" \"rishiri\\0\" \"rishirifuji\\0\"\n\"sarufutsu\\0\" \"shakotan\\0\" \"shari\\0\" \"shibecha\\0\" \"shikabe\\0\" \"shikaoi\\0\"\n\"shimamaki\\0\" \"shimokawa\\0\" \"shinshinotsu\\0\" \"shintoku\\0\" \"shiranuka\\0\"\n\"shiraoi\\0\" \"shiriuchi\\0\" \"sobetsu\\0\" \"taiki\\0\" \"takasu\\0\" \"takikawa\\0\"\n\"takinoue\\0\" \"teshikaga\\0\" \"tobetsu\\0\" \"tohma\\0\" \"tomakomai\\0\" \"tomari\\0\"\n\"toya\\0\" \"toyako\\0\" \"toyotomi\\0\" \"toyoura\\0\" \"tsubetsu\\0\" \"tsukigata\\0\"\n\"urakawa\\0\" \"urausu\\0\" \"utashinai\\0\" \"wakkanai\\0\" \"wassamu\\0\" \"yakumo\\0\"\n\"yoichi\\0\" \"aioi\\0\" \"akashi\\0\" \"amagasaki\\0\" \"takasago\\0\" \"minamiawaji\\0\"\n\"fukusaki\\0\" \"goshiki\\0\" \"harima\\0\" \"himeji\\0\" \"shinagawa\\0\" \"kakogawa\\0\"\n\"kamigori\\0\" \"kasai\\0\" \"kawanishi\\0\" \"miki\\0\" \"nishinomiya\\0\" \"sanda\\0\"\n\"sannan\\0\" \"sasayama\\0\" \"sayo\\0\" \"shinonsen\\0\" \"shiso\\0\" \"matsumoto\\0\"\n\"taishi\\0\" \"mitaka\\0\" \"takarazuka\\0\" \"takino\\0\" \"kyotamba\\0\" \"tatsuno\\0\"\n\"toyooka\\0\" \"yabu\\0\" \"miyashiro\\0\" \"yoka\\0\" \"atami\\0\" \"bando\\0\"\n\"chikusei\\0\" \"fujishiro\\0\" \"hitachinaka\\0\" \"hitachiomiya\\0\" \"hitachiota\\0\"\n\"ebina\\0\" \"inashiki\\0\" \"iwama\\0\" \"joso\\0\" \"kamisu\\0\" \"kasama\\0\"\n\"takashima\\0\" \"kasumigaura\\0\" \"miho\\0\" \"moriya\\0\" \"namegata\\0\" \"oarai\\0\"\n\"edogawa\\0\" \"omitama\\0\" \"ryugasaki\\0\" \"sakuragawa\\0\" \"shimodate\\0\"\n\"shimotsuma\\0\" \"shirosato\\0\" \"suifu\\0\" \"takahagi\\0\" \"tamatsukuri\\0\"\n\"tomobe\\0\" \"toride\\0\" \"tsuchiura\\0\" \"tsukuba\\0\" \"uchihara\\0\" \"ushiku\\0\"\n\"yawara\\0\" \"yuki\\0\" \"anamizu\\0\" \"hakui\\0\" \"hakusan\\0\" \"ashikaga\\0\"\n\"kahoku\\0\" \"kanazawa\\0\" \"nakanoto\\0\" \"nanao\\0\" \"uchinomi\\0\" \"nonoichi\\0\"\n\"ooshika\\0\" \"suzu\\0\" \"tsubata\\0\" \"tsurugi\\0\" \"uchinada\\0\" \"fudai\\0\"\n\"fujisawa\\0\" \"hanamaki\\0\" \"hiraizumi\\0\" \"iwaizumi\\0\" \"joboji\\0\"\n\"kamaishi\\0\" \"kanegasaki\\0\" \"karumai\\0\" \"kawai\\0\" \"kitakami\\0\" \"kuji\\0\"\n\"kuzumaki\\0\" \"mizusawa\\0\" \"morioka\\0\" \"ninohe\\0\" \"ofunato\\0\" \"koshu\\0\"\n\"otsuchi\\0\" \"rikuzentakata\\0\" \"shizukuishi\\0\" \"sumita\\0\" \"tanohata\\0\"\n\"yahaba\\0\" \"ayagawa\\0\" \"higashikagawa\\0\" \"kanonji\\0\" \"kotohira\\0\"\n\"manno\\0\" \"mitoyo\\0\" \"naoshima\\0\" \"sanuki\\0\" \"tadotsu\\0\" \"takamatsu\\0\"\n\"tonosho\\0\" \"utazu\\0\" \"zentsuji\\0\" \"akune\\0\" \"zamami\\0\" \"hioki\\0\"\n\"kanoya\\0\" \"kawanabe\\0\" \"kinko\\0\" \"kouyama\\0\" \"makurazaki\\0\" \"nakatane\\0\"\n\"nishinoomote\\0\" \"soo\\0\" \"tarumizu\\0\" \"atsugi\\0\" \"ayase\\0\" \"chigasaki\\0\"\n\"hadano\\0\" \"hakone\\0\" \"hiratsuka\\0\" \"isehara\\0\" \"kaisei\\0\" \"kamakura\\0\"\n\"kiyokawa\\0\" \"matsuda\\0\" \"minamiashigara\\0\" \"miura\\0\" \"nakai\\0\"\n\"ninomiya\\0\" \"odawara\\0\" \"kuroiso\\0\" \"tsukui\\0\" \"yamakita\\0\" \"yokosuka\\0\"\n\"yugawara\\0\" \"zushi\\0\" \"geisei\\0\" \"higashitsuno\\0\" \"ebino\\0\" \"kagami\\0\"\n\"ryokami\\0\" \"muroto\\0\" \"nahari\\0\" \"nakamura\\0\" \"nankoku\\0\" \"nishitosa\\0\"\n\"niyodogawa\\0\" \"otoyo\\0\" \"otsuki\\0\" \"sukumo\\0\" \"susaki\\0\" \"tosashimizu\\0\"\n\"umaji\\0\" \"yasuda\\0\" \"yusuhara\\0\" \"kamiamakusa\\0\" \"arao\\0\" \"choyo\\0\"\n\"gyokuto\\0\" \"kikuchi\\0\" \"mashiki\\0\" \"mifune\\0\" \"minamata\\0\" \"minamioguni\\0\"\n\"nagasu\\0\" \"nishihara\\0\" \"takamori\\0\" \"yamaga\\0\" \"yatsushiro\\0\"\n\"fukuchiyama\\0\" \"higashiyama\\0\" \"joyo\\0\" \"kameoka\\0\" \"kizu\\0\" \"kyotanabe\\0\"\n\"kyotango\\0\" \"maizuru\\0\" \"minamiyamashiro\\0\" \"miyazu\\0\" \"muko\\0\"\n\"nagaokakyo\\0\" \"nakagyo\\0\" \"nantan\\0\" \"oyamazaki\\0\" \"sakyo\\0\" \"seika\\0\"\n\"ujitawara\\0\" \"wazuka\\0\" \"yamashina\\0\" \"yawata\\0\" \"inabe\\0\" \"kameyama\\0\"\n\"kawagoe\\0\" \"kiho\\0\" \"kisosaki\\0\" \"kiwa\\0\" \"komono\\0\" \"kuwana\\0\"\n\"matsusaka\\0\" \"minamiise\\0\" \"misugi\\0\" \"suzuka\\0\" \"tado\\0\" \"tamaki\\0\"\n\"toba\\0\" \"ureshino\\0\" \"watarai\\0\" \"furukawa\\0\" \"higashimatsushima\\0\"\n\"ishinomaki\\0\" \"iwanuma\\0\" \"kakuda\\0\" \"marumori\\0\" \"minamisanriku\\0\"\n\"murata\\0\" \"natori\\0\" \"ogawara\\0\" \"onagawa\\0\" \"rifu\\0\" \"semine\\0\"\n\"shibata\\0\" \"shichikashuku\\0\" \"shikama\\0\" \"shiogama\\0\" \"shiroishi\\0\"\n\"tagajo\\0\" \"taiwa\\0\" \"saotome\\0\" \"tomiya\\0\" \"wakuya\\0\" \"watari\\0\"\n\"yamamoto\\0\" \"zao\\0\" \"okaya\\0\" \"gokase\\0\" \"hyuga\\0\" \"kadogawa\\0\"\n\"kawaminami\\0\" \"kijo\\0\" \"kitaura\\0\" \"kobayashi\\0\" \"kunitomi\\0\" \"mimata\\0\"\n\"nichinan\\0\" \"nishimera\\0\" \"nobeoka\\0\" \"saito\\0\" \"shiiba\\0\" \"shintomi\\0\"\n\"takaharu\\0\" \"takanabe\\0\" \"takazaki\\0\" \"adachi\\0\" \"agematsu\\0\" \"kanan\\0\"\n\"aoki\\0\" \"azumino\\0\" \"chikuhoku\\0\" \"chikuma\\0\" \"chino\\0\" \"fujimi\\0\"\n\"hakuba\\0\" \"hiraya\\0\" \"davvesiida\\0\" \"iijima\\0\" \"iiyama\\0\" \"iizuna\\0\"\n\"ikusaka\\0\" \"karuizawa\\0\" \"kawakami\\0\" \"kiso\\0\" \"kitaaiki\\0\" \"komagane\\0\"\n\"komoro\\0\" \"matsukawa\\0\" \"miasa\\0\" \"minamiaiki\\0\" \"minamimaki\\0\"\n\"minamiminowa\\0\" \"miyada\\0\" \"miyota\\0\" \"mochizuki\\0\" \"nagiso\\0\"\n\"nakano\\0\" \"nozawaonsen\\0\" \"obuse\\0\" \"shinanomachi\\0\" \"ookuwa\\0\"\n\"otari\\0\" \"sakaki\\0\" \"saku\\0\" \"sakuho\\0\" \"shimosuwa\\0\" \"shiojiri\\0\"\n\"suzaka\\0\" \"takagi\\0\" \"tateshina\\0\" \"togakushi\\0\" \"togura\\0\" \"ueda\\0\"\n\"yamanouchi\\0\" \"yasaka\\0\" \"yasuoka\\0\" \"chijiwa\\0\" \"shinkamigoto\\0\"\n\"hasami\\0\" \"hirado\\0\" \"isahaya\\0\" \"kawatana\\0\" \"kuchinotsu\\0\" \"matsuura\\0\"\n\"omura\\0\" \"saikai\\0\" \"sasebo\\0\" \"seihi\\0\" \"shimabara\\0\" \"togitsu\\0\"\n\"unzen\\0\" \"ogose\\0\" \"higashiyoshino\\0\" \"ikaruga\\0\" \"ikoma\\0\" \"kamikitayama\\0\"\n\"kanmaki\\0\" \"kashiba\\0\" \"kashihara\\0\" \"katsuragi\\0\" \"koryo\\0\" \"kamitsue\\0\"\n\"miyake\\0\" \"nosegawa\\0\" \"ouda\\0\" \"oyodo\\0\" \"sakurai\\0\" \"sango\\0\"\n\"shimoichi\\0\" \"shimokitayama\\0\" \"shinjo\\0\" \"soni\\0\" \"tawaramoto\\0\"\n\"tenkawa\\0\" \"tenri\\0\" \"yamatotakada\\0\" \"yamazoe\\0\" \"gosen\\0\" \"itoigawa\\0\"\n\"izumozaki\\0\" \"joetsu\\0\" \"kariwa\\0\" \"kashiwazaki\\0\" \"minamiuonuma\\0\"\n\"mitsuke\\0\" \"muika\\0\" \"murakami\\0\" \"myoko\\0\" \"nagaoka\\0\" \"ojiya\\0\"\n\"sado\\0\" \"seiro\\0\" \"seirou\\0\" \"sekikawa\\0\" \"tainai\\0\" \"tochio\\0\"\n\"tokamachi\\0\" \"tsubame\\0\" \"tsunan\\0\" \"yahiko\\0\" \"yuzawa\\0\" \"beppu\\0\"\n\"bungoono\\0\" \"bungotakada\\0\" \"hasama\\0\" \"hiji\\0\" \"himeshima\\0\" \"kokonoe\\0\"\n\"kuju\\0\" \"kunisaki\\0\" \"saiki\\0\" \"taketa\\0\" \"tsukumi\\0\" \"usuki\\0\"\n\"yufu\\0\" \"akaiwa\\0\" \"asakuchi\\0\" \"bizen\\0\" \"hayashima\\0\" \"maibara\\0\"\n\"kagamino\\0\" \"kasaoka\\0\" \"kumenan\\0\" \"kurashiki\\0\" \"maniwa\\0\" \"misaki\\0\"\n\"inagi\\0\" \"niimi\\0\" \"nishiawakura\\0\" \"satosho\\0\" \"setouchi\\0\" \"shoo\\0\"\n\"soja\\0\" \"takahashi\\0\" \"tamano\\0\" \"yakage\\0\" \"yonaguni\\0\" \"ginowan\\0\"\n\"ginoza\\0\" \"gushikami\\0\" \"haebaru\\0\" \"hirara\\0\" \"iheya\\0\" \"ishigaki\\0\"\n\"izena\\0\" \"kadena\\0\" \"kitadaito\\0\" \"kitanakagusuku\\0\" \"kumejima\\0\"\n\"kunigami\\0\" \"minamidaito\\0\" \"yonago\\0\" \"nakijin\\0\" \"nanjo\\0\" \"ogimi\\0\"\n\"donna\\0\" \"shimoji\\0\" \"taketomi\\0\" \"tarama\\0\" \"tokashiki\\0\" \"tomigusuku\\0\"\n\"tonaki\\0\" \"urasoe\\0\" \"uruma\\0\" \"yaese\\0\" \"yomitan\\0\" \"yonabaru\\0\"\n\"abeno\\0\" \"chihayaakasaka\\0\" \"fujiidera\\0\" \"habikino\\0\" \"hannan\\0\"\n\"higashiosaka\\0\" \"higashiyodogawa\\0\" \"hirakata\\0\" \"izumiotsu\\0\"\n\"izumisano\\0\" \"kadoma\\0\" \"kaizuka\\0\" \"kashiwara\\0\" \"katano\\0\" \"kishiwada\\0\"\n\"kumatori\\0\" \"matsubara\\0\" \"sakaiminato\\0\" \"minoh\\0\" \"moriguchi\\0\"\n\"neyagawa\\0\" \"osakasayama\\0\" \"sennan\\0\" \"settsu\\0\" \"shijonawate\\0\"\n\"shimamoto\\0\" \"suita\\0\" \"tadaoka\\0\" \"tajiri\\0\" \"takaishi\\0\" \"takatsuki\\0\"\n\"tondabayashi\\0\" \"toyonaka\\0\" \"toyono\\0\" \"yao\\0\" \"ariake\\0\" \"fukudomi\\0\"\n\"genkai\\0\" \"hamatama\\0\" \"imari\\0\" \"kamimine\\0\" \"kanzaki\\0\" \"karatsu\\0\"\n\"kitahata\\0\" \"kiyama\\0\" \"kouhoku\\0\" \"kyuragi\\0\" \"nishiarita\\0\" \"taku\\0\"\n\"yoshinogari\\0\" \"arakawa\\0\" \"higashichichibu\\0\" \"fujimino\\0\" \"fukaya\\0\"\n\"hanno\\0\" \"hanyu\\0\" \"hasuda\\0\" \"hatogaya\\0\" \"hatoyama\\0\" \"iruma\\0\"\n\"iwatsuki\\0\" \"kamiizumi\\0\" \"kamisato\\0\" \"kasukabe\\0\" \"kawaguchi\\0\"\n\"kawajima\\0\" \"kazo\\0\" \"kitamoto\\0\" \"koshigaya\\0\" \"kounosu\\0\" \"kuki\\0\"\n\"kumagaya\\0\" \"matsubushi\\0\" \"minano\\0\" \"moroyama\\0\" \"nagatoro\\0\"\n\"namegawa\\0\" \"niiza\\0\" \"ogano\\0\" \"okegawa\\0\" \"ranzan\\0\" \"sakado\\0\"\n\"satte\\0\" \"shiraoka\\0\" \"soka\\0\" \"sugito\\0\" \"toda\\0\" \"tokigawa\\0\"\n\"tokorozawa\\0\" \"tsurugashima\\0\" \"urawa\\0\" \"warabi\\0\" \"yashio\\0\"\n\"yokoze\\0\" \"yorii\\0\" \"fujiyoshida\\0\" \"yoshikawa\\0\" \"yoshimi\\0\" \"aisho\\0\"\n\"higashiomi\\0\" \"hikone\\0\" \"koka\\0\" \"kosei\\0\" \"moriyama\\0\" \"nagahama\\0\"\n\"nishiazai\\0\" \"notogawa\\0\" \"omihachiman\\0\" \"gotsu\\0\" \"ritto\\0\" \"ryuoh\\0\"\n\"torahime\\0\" \"toyosato\\0\" \"hamada\\0\" \"higashiizumo\\0\" \"hikimi\\0\"\n\"okuizumo\\0\" \"kakinoki\\0\" \"masuda\\0\" \"nishinoshima\\0\" \"ohda\\0\" \"okinoshima\\0\"\n\"tamayu\\0\" \"tsuwano\\0\" \"unnan\\0\" \"yasugi\\0\" \"yatsuka\\0\" \"fujieda\\0\"\n\"fujikawa\\0\" \"fujinomiya\\0\" \"fukuroi\\0\" \"haibara\\0\" \"hamamatsu\\0\"\n\"higashiizu\\0\" \"iwata\\0\" \"izunokuni\\0\" \"kakegawa\\0\" \"kannami\\0\"\n\"kawanehon\\0\" \"kawazu\\0\" \"kikugawa\\0\" \"kosai\\0\" \"makinohara\\0\" \"matsuzaki\\0\"\n\"minamiizu\\0\" \"morimachi\\0\" \"nishiizu\\0\" \"numazu\\0\" \"omaezaki\\0\"\n\"shimada\\0\" \"susono\\0\" \"yaizu\\0\" \"haga\\0\" \"ichikai\\0\" \"iwafune\\0\"\n\"kaminokawa\\0\" \"kanuma\\0\" \"karasuyama\\0\" \"mashiko\\0\" \"mibu\\0\" \"moka\\0\"\n\"motegi\\0\" \"nasu\\0\" \"nasushiobara\\0\" \"nikko\\0\" \"nishikata\\0\" \"ohtawara\\0\"\n\"shimotsuke\\0\" \"shioya\\0\" \"takanezawa\\0\" \"tsuga\\0\" \"ujiie\\0\" \"utsunomiya\\0\"\n\"yaita\\0\" \"itano\\0\" \"matsushige\\0\" \"mima\\0\" \"mugi\\0\" \"naruto\\0\"\n\"sanagochi\\0\" \"shishikui\\0\" \"wajiki\\0\" \"akiruno\\0\" \"akishima\\0\"\n\"aogashima\\0\" \"bunkyo\\0\" \"chofu\\0\" \"fussa\\0\" \"hachijo\\0\" \"hachioji\\0\"\n\"hamura\\0\" \"higashimurayama\\0\" \"hinode\\0\" \"hinohara\\0\" \"itabashi\\0\"\n\"katsushika\\0\" \"kiyose\\0\" \"kodaira\\0\" \"koganei\\0\" \"kokubunji\\0\"\n\"komae\\0\" \"kouzushima\\0\" \"kunitachi\\0\" \"meguro\\0\" \"mizuho\\0\" \"musashimurayama\\0\"\n\"musashino\\0\" \"nerima\\0\" \"ogasawara\\0\" \"okutama\\0\" \"nome\\0\" \"toshima\\0\"\n\"setagaya\\0\" \"shibuya\\0\" \"shinjuku\\0\" \"suginami\\0\" \"sumida\\0\" \"tachikawa\\0\"\n\"taito\\0\" \"chizu\\0\" \"kawahara\\0\" \"kotoura\\0\" \"misasa\\0\" \"nanbu\\0\"\n\"fukumitsu\\0\" \"funahashi\\0\" \"johana\\0\" \"kamiichi\\0\" \"kurobe\\0\" \"nakaniikawa\\0\"\n\"namerikawa\\0\" \"nanto\\0\" \"nyuzen\\0\" \"oyabe\\0\" \"taira\\0\" \"takaoka\\0\"\n\"toga\\0\" \"tonami\\0\" \"unazuki\\0\" \"arida\\0\" \"aridagawa\\0\" \"gobo\\0\"\n\"hashimoto\\0\" \"hirogawa\\0\" \"iwade\\0\" \"kamitonda\\0\" \"kinokawa\\0\"\n\"koya\\0\" \"kozagawa\\0\" \"kudoyama\\0\" \"kushimoto\\0\" \"shirahama\\0\" \"taiji\\0\"\n\"yuasa\\0\" \"yura\\0\" \"funagata\\0\" \"higashine\\0\" \"kaminoyama\\0\" \"mamurogawa\\0\"\n\"nagai\\0\" \"nakayama\\0\" \"nanyo\\0\" \"obanazawa\\0\" \"ohkura\\0\" \"oishida\\0\"\n\"sagae\\0\" \"sakata\\0\" \"sakegawa\\0\" \"shirataka\\0\" \"takahata\\0\" \"tendo\\0\"\n\"tozawa\\0\" \"tsuruoka\\0\" \"yamanobe\\0\" \"yonezawa\\0\" \"yuza\\0\" \"iwakuni\\0\"\n\"kudamatsu\\0\" \"mitou\\0\" \"nagato\\0\" \"shimonoseki\\0\" \"shunan\\0\" \"tabuse\\0\"\n\"tokuyama\\0\" \"yuu\\0\" \"doshi\\0\" \"fuefuki\\0\" \"hayakawa\\0\" \"ichikawamisato\\0\"\n\"kofu\\0\" \"kosuge\\0\" \"minami-alps\\0\" \"minobu\\0\" \"nakamichi\\0\" \"narusawa\\0\"\n\"nirasaki\\0\" \"nishikatsura\\0\" \"tabayama\\0\" \"tsuru\\0\" \"uenohara\\0\"\n\"yamanakako\\0\" \"pharmaciens\\0\" \"rep\\0\" \"hitra\\0\" \"busan\\0\" \"chungbuk\\0\"\n\"chungnam\\0\" \"daegu\\0\" \"daejeon\\0\" \"gangwon\\0\" \"gwangju\\0\" \"gyeongbuk\\0\"\n\"gyeonggi\\0\" \"gyeongnam\\0\" \"fhs\\0\" \"incheon\\0\" \"jeju\\0\" \"jeonnam\\0\"\n\"seoul\\0\" \"ulsan\\0\" \"static\\0\" \"azurewebsites\\0\" \"cyon\\0\" \"mypep\\0\"\n\"assn\\0\" \"grp\\0\" \"soc\\0\" \"brasilia\\0\" \"daplie\\0\" \"ddns\\0\" \"dnsfor\\0\"\n\"hopto\\0\" \"i234\\0\" \"loginto\\0\" \"myds\\0\" \"noip\\0\" \"synology\\0\" \"yombo\\0\"\n\"agriculture\\0\" \"airguard\\0\" \"alabama\\0\" \"alaska\\0\" \"amber\\0\" \"nativeamerican\\0\"\n\"americana\\0\" \"americanantiques\\0\" \"americanart\\0\" \"brand\\0\" \"annefrank\\0\"\n\"anthro\\0\" \"anthropology\\0\" \"usantiques\\0\" \"aquarium\\0\" \"arboretum\\0\"\n\"archaeological\\0\" \"archaeology\\0\" \"architecture\\0\" \"artdeco\\0\"\n\"artsandcrafts\\0\" \"asmatart\\0\" \"assassination\\0\" \"assisi\\0\" \"astronomy\\0\"\n\"atlanta\\0\" \"austin\\0\" \"australia\\0\" \"automotive\\0\" \"axis\\0\" \"badajoz\\0\"\n\"eisenbahn\\0\" \"bale\\0\" \"baltimore\\0\" \"basel\\0\" \"baths\\0\" \"bauern\\0\"\n\"beauxarts\\0\" \"beeldengeluid\\0\" \"bellevue\\0\" \"bergbau\\0\" \"berkeley\\0\"\n\"bern\\0\" \"bilbao\\0\" \"bill\\0\" \"birdart\\0\" \"bonn\\0\" \"botanical\\0\"\n\"botanicalgarden\\0\" \"botanicgarden\\0\" \"botany\\0\" \"brandywinevalley\\0\"\n\"brasil\\0\" \"bristol\\0\" \"british\\0\" \"britishcolumbia\\0\" \"broadcast\\0\"\n\"brunel\\0\" \"brussel\\0\" \"bruxelles\\0\" \"building\\0\" \"burghof\\0\" \"bushey\\0\"\n\"cadaques\\0\" \"california\\0\" \"cambridge\\0\" \"canada\\0\" \"capebreton\\0\"\n\"carrier\\0\" \"cartoonart\\0\" \"casadelamoneda\\0\" \"castle\\0\" \"castres\\0\"\n\"celtic\\0\" \"chattanooga\\0\" \"cheltenham\\0\" \"chesapeakebay\\0\" \"chicago\\0\"\n\"children\\0\" \"childrens\\0\" \"childrensgarden\\0\" \"chiropractic\\0\"\n\"chocolate\\0\" \"christiansburg\\0\" \"cincinnati\\0\" \"cinema\\0\" \"circus\\0\"\n\"civilisation\\0\" \"civilization\\0\" \"civilwar\\0\" \"clinton\\0\" \"watchandclock\\0\"\n\"coastaldefence\\0\" \"coldwar\\0\" \"collection\\0\" \"colonialwilliamsburg\\0\"\n\"coloradoplateau\\0\" \"columbus\\0\" \"communication\\0\" \"posts-and-telecommunications\\0\"\n\"computerhistory\\0\" \"contemporary\\0\" \"contemporaryart\\0\" \"convent\\0\"\n\"copenhagen\\0\" \"corporation\\0\" \"corvette\\0\" \"costume\\0\" \"uscountryestate\\0\"\n\"county\\0\" \"cranbrook\\0\" \"cultural\\0\" \"culturalcenter\\0\" \"usculture\\0\"\n\"cyber\\0\" \"salvadordali\\0\" \"dallas\\0\" \"database\\0\" \"usdecorativearts\\0\"\n\"stateofdelaware\\0\" \"delmenhorst\\0\" \"denmark\\0\" \"detroit\\0\" \"dinosaur\\0\"\n\"discovery\\0\" \"dolls\\0\" \"donostia\\0\" \"durham\\0\" \"eastcoast\\0\" \"educational\\0\"\n\"egyptian\\0\" \"elvendrell\\0\" \"embroidery\\0\" \"encyclopedic\\0\" \"england\\0\"\n\"entomology\\0\" \"environment\\0\" \"environmentalconservation\\0\" \"epilepsy\\0\"\n\"ethnology\\0\" \"exeter\\0\" \"exhibition\\0\" \"farmstead\\0\" \"field\\0\"\n\"figueres\\0\" \"filatelia\\0\" \"fineart\\0\" \"finearts\\0\" \"finland\\0\"\n\"flanders\\0\" \"florida\\0\" \"fortmissoula\\0\" \"fortworth\\0\" \"francaise\\0\"\n\"frankfurt\\0\" \"franziskaner\\0\" \"freemasonry\\0\" \"freiburg\\0\" \"fribourg\\0\"\n\"frog\\0\" \"fundacio\\0\" \"geelvinck\\0\" \"gemological\\0\" \"geology\\0\"\n\"georgia\\0\" \"giessen\\0\" \"glas\\0\" \"gorge\\0\" \"grandrapids\\0\" \"graz\\0\"\n\"guernsey\\0\" \"halloffame\\0\" \"handson\\0\" \"harvestcelebration\\0\" \"hawaii\\0\"\n\"heimatunduhren\\0\" \"hellas\\0\" \"hembygdsforbund\\0\" \"nationalheritage\\0\"\n\"histoire\\0\" \"historical\\0\" \"historicalsociety\\0\" \"historichouses\\0\"\n\"historisch\\0\" \"naturhistorisches\\0\" \"ushistory\\0\" \"horology\\0\"\n\"humanities\\0\" \"illustration\\0\" \"imageandsound\\0\" \"indian\\0\" \"indiana\\0\"\n\"indianapolis\\0\" \"intelligence\\0\" \"iron\\0\" \"isleofman\\0\" \"jamison\\0\"\n\"jefferson\\0\" \"jerusalem\\0\" \"jewish\\0\" \"jewishart\\0\" \"journalism\\0\"\n\"judaica\\0\" \"judygarland\\0\" \"juedisches\\0\" \"juif\\0\" \"karate\\0\" \"kids\\0\"\n\"kunst\\0\" \"kunstsammlung\\0\" \"kunstunddesign\\0\" \"labor\\0\" \"labour\\0\"\n\"lajolla\\0\" \"lancashire\\0\" \"landes\\0\" \"lans\\0\" \"larsson\\0\" \"lewismiller\\0\"\n\"uslivinghistory\\0\" \"localhistory\\0\" \"losangeles\\0\" \"louvre\\0\" \"loyalist\\0\"\n\"lucerne\\0\" \"luxembourg\\0\" \"luzern\\0\" \"mallorca\\0\" \"manchester\\0\"\n\"mansion\\0\" \"mansions\\0\" \"marburg\\0\" \"maritime\\0\" \"maritimo\\0\" \"maryland\\0\"\n\"marylhurst\\0\" \"medizinhistorisches\\0\" \"meeres\\0\" \"mesaverde\\0\"\n\"michigan\\0\" \"midatlantic\\0\" \"military\\0\" \"windmill\\0\" \"miners\\0\"\n\"mining\\0\" \"minnesota\\0\" \"missile\\0\" \"modern\\0\" \"moma\\0\" \"monmouth\\0\"\n\"monticello\\0\" \"montreal\\0\" \"motorcycle\\0\" \"muenchen\\0\" \"muenster\\0\"\n\"muncie\\0\" \"museet\\0\" \"museumcenter\\0\" \"museumvereniging\\0\" \"nationalfirearms\\0\"\n\"naturalhistory\\0\" \"naturalsciences\\0\" \"nature\\0\" \"natuurwetenschappen\\0\"\n\"naumburg\\0\" \"naval\\0\" \"nebraska\\0\" \"newhampshire\\0\" \"newjersey\\0\"\n\"newmexico\\0\" \"newport\\0\" \"newspaper\\0\" \"newyork\\0\" \"niepce\\0\" \"norfolk\\0\"\n\"north\\0\" \"nuernberg\\0\" \"nuremberg\\0\" \"nyny\\0\" \"oceanographic\\0\"\n\"oceanographique\\0\" \"omaha\\0\" \"ontario\\0\" \"openair\\0\" \"oregon\\0\"\n\"oregontrail\\0\" \"otago\\0\" \"pacific\\0\" \"paderborn\\0\" \"palace\\0\" \"paleo\\0\"\n\"palmsprings\\0\" \"panama\\0\" \"pasadena\\0\" \"philadelphia\\0\" \"philadelphiaarea\\0\"\n\"philately\\0\" \"phoenix\\0\" \"pilots\\0\" \"planetarium\\0\" \"plantation\\0\"\n\"plants\\0\" \"plaza\\0\" \"portal\\0\" \"portland\\0\" \"portlligat\\0\" \"preservation\\0\"\n\"presidio\\0\" \"project\\0\" \"pubol\\0\" \"railroad\\0\" \"railway\\0\" \"resistance\\0\"\n\"riodejaneiro\\0\" \"rochester\\0\" \"rockart\\0\" \"russia\\0\" \"saintlouis\\0\"\n\"salzburg\\0\" \"sandiego\\0\" \"santabarbara\\0\" \"santacruz\\0\" \"santafe\\0\"\n\"saskatchewan\\0\" \"satx\\0\" \"savannahga\\0\" \"schlesisches\\0\" \"schoenbrunn\\0\"\n\"schokoladen\\0\" \"schweiz\\0\" \"science-fiction\\0\" \"scienceandhistory\\0\"\n\"scienceandindustry\\0\" \"sciencecenter\\0\" \"sciencecenters\\0\" \"sciencehistory\\0\"\n\"sciencesnaturelles\\0\" \"scotland\\0\" \"seaport\\0\" \"settlement\\0\" \"settlers\\0\"\n\"sherbrooke\\0\" \"sibenik\\0\" \"skole\\0\" \"sologne\\0\" \"soundandvision\\0\"\n\"southcarolina\\0\" \"southwest\\0\" \"square\\0\" \"stadt\\0\" \"stalbans\\0\"\n\"starnberg\\0\" \"steiermark\\0\" \"stpetersburg\\0\" \"stuttgart\\0\" \"suisse\\0\"\n\"surgeonshall\\0\" \"surrey\\0\" \"svizzera\\0\" \"sweden\\0\" \"tank\\0\" \"telekommunikation\\0\"\n\"texas\\0\" \"textile\\0\" \"timekeeping\\0\" \"topology\\0\" \"touch\\0\" \"trolley\\0\"\n\"trustee\\0\" \"ulm\\0\" \"undersea\\0\" \"usarts\\0\" \"ushuaia\\0\" \"versailles\\0\"\n\"village\\0\" \"virginia\\0\" \"virtual\\0\" \"virtuel\\0\" \"volkenkunde\\0\"\n\"wallonie\\0\" \"washingtondc\\0\" \"watch-and-clock\\0\" \"western\\0\" \"westfalen\\0\"\n\"whaling\\0\" \"wildlife\\0\" \"xn--9dbhblg6di\\0\" \"xn--comunicaes-v6a2o\\0\"\n\"xn--correios-e-telecomunicaes-ghc29a\\0\" \"xn--h1aegh\\0\" \"xn--lns-qla\\0\"\n\"yorkshire\\0\" \"yosemite\\0\" \"youth\\0\" \"zoological\\0\" \"zoology\\0\"\n\"bounceme\\0\" \"broke-it\\0\" \"buyshouses\\0\" \"cdn77-ssl\\0\" \"cloudapp\\0\"\n\"cloudfront\\0\" \"cloudfunctions\\0\" \"cryptonomic\\0\" \"does-it\\0\" \"dynathome\\0\"\n\"dynv6\\0\" \"endofinternet\\0\" \"fastly\\0\" \"feste-ip\\0\" \"from-az\\0\"\n\"from-co\\0\" \"from-la\\0\" \"from-ny\\0\" \"gets-it\\0\" \"ham-radio-op\\0\"\n\"homeftp\\0\" \"homeip\\0\" \"kicks-ass\\0\" \"knx-server\\0\" \"mydissent\\0\"\n\"myeffect\\0\" \"mymediapc\\0\" \"nhlfan\\0\" \"office-on-the\\0\" \"pgafan\\0\"\n\"privatizehealthinsurance\\0\" \"redirectme\\0\" \"scrapper-site\\0\" \"sells-it\\0\"\n\"serveminecraft\\0\" \"static-access\\0\" \"t3l3p0rt\\0\" \"alces\\0\" \"virtueeldomein\\0\"\n\"aarborte\\0\" \"aejrie\\0\" \"kafjord\\0\" \"agdenes\\0\" \"akershus\\0\" \"aknoluokta\\0\"\n\"akrehamn\\0\" \"alaheadju\\0\" \"alesund\\0\" \"algard\\0\" \"alstahaug\\0\"\n\"yalta\\0\" \"alvdal\\0\" \"amli\\0\" \"amot\\0\" \"andasuolo\\0\" \"andebu\\0\"\n\"sandoy\\0\" \"lardal\\0\" \"aremark\\0\" \"arendal\\0\" \"aseral\\0\" \"asker\\0\"\n\"askoy\\0\" \"askvoll\\0\" \"asnes\\0\" \"audnedaln\\0\" \"aukra\\0\" \"aure\\0\"\n\"aurland\\0\" \"aurskog-holand\\0\" \"austevoll\\0\" \"austrheim\\0\" \"averoy\\0\"\n\"badaddja\\0\" \"bahcavuotna\\0\" \"bahccavuotna\\0\" \"baidar\\0\" \"bajddar\\0\"\n\"balestrand\\0\" \"ballangen\\0\" \"balsfjord\\0\" \"bamble\\0\" \"bardu\\0\"\n\"barum\\0\" \"batsfjord\\0\" \"bearalvahki\\0\" \"beardu\\0\" \"beiarn\\0\" \"eidsberg\\0\"\n\"berlevag\\0\" \"bievat\\0\" \"bindal\\0\" \"birkenes\\0\" \"bjarkoy\\0\" \"bjerkreim\\0\"\n\"bodo\\0\" \"bomlo\\0\" \"bremanger\\0\" \"bronnoy\\0\" \"bronnoysund\\0\" \"brumunddal\\0\"\n\"bryne\\0\" \"budejju\\0\" \"buskerud\\0\" \"bygland\\0\" \"bykle\\0\" \"cahcesuolo\\0\"\n\"davvenjarga\\0\" \"deatnu\\0\" \"dep\\0\" \"dielddanuorri\\0\" \"divtasvuodna\\0\"\n\"divttasvuotna\\0\" \"dovre\\0\" \"drangedal\\0\" \"drobak\\0\" \"dyroy\\0\" \"egersund\\0\"\n\"hareid\\0\" \"eidfjord\\0\" \"eidskog\\0\" \"eidsvoll\\0\" \"eigersund\\0\" \"elverum\\0\"\n\"enebakk\\0\" \"engerdal\\0\" \"etnedal\\0\" \"evenassi\\0\" \"evenes\\0\" \"evje-og-hornnes\\0\"\n\"farsund\\0\" \"fauske\\0\" \"fetsund\\0\" \"finnoy\\0\" \"fitjar\\0\" \"fjaler\\0\"\n\"fjell\\0\" \"flakstad\\0\" \"flatanger\\0\" \"flekkefjord\\0\" \"flesberg\\0\"\n\"flora\\0\" \"floro\\0\" \"folkebibl\\0\" \"folldal\\0\" \"forde\\0\" \"forsand\\0\"\n\"fosnes\\0\" \"frana\\0\" \"fredrikstad\\0\" \"frei\\0\" \"frogn\\0\" \"froland\\0\"\n\"frosta\\0\" \"froya\\0\" \"fuoisku\\0\" \"fuossko\\0\" \"fylkesbibl\\0\" \"fyresdal\\0\"\n\"gaivuotna\\0\" \"galsa\\0\" \"gamvik\\0\" \"gangaviika\\0\" \"gaular\\0\" \"gausdal\\0\"\n\"giehtavuoatna\\0\" \"gildeskal\\0\" \"giske\\0\" \"gjemnes\\0\" \"gjerdrum\\0\"\n\"gjerstad\\0\" \"gjesdal\\0\" \"gjovik\\0\" \"gloppen\\0\" \"gol\\0\" \"gran\\0\"\n\"grane\\0\" \"gratangen\\0\" \"grimstad\\0\" \"grong\\0\" \"grue\\0\" \"gulen\\0\"\n\"guovdageaidnu\\0\" \"habmer\\0\" \"hadsel\\0\" \"hagebostad\\0\" \"halden\\0\"\n\"halsa\\0\" \"hamaroy\\0\" \"hammarfeasta\\0\" \"hammerfest\\0\" \"hapmir\\0\"\n\"haram\\0\" \"harstad\\0\" \"hasvik\\0\" \"hattfjelldal\\0\" \"haugesund\\0\"\n\"hedmark\\0\" \"hemne\\0\" \"hemnes\\0\" \"hemsedal\\0\" \"sauherad\\0\" \"hjartdal\\0\"\n\"hjelmeland\\0\" \"hobol\\0\" \"hokksund\\0\" \"hol\\0\" \"hole\\0\" \"holmestrand\\0\"\n\"holtalen\\0\" \"honefoss\\0\" \"hornindal\\0\" \"horten\\0\" \"hoyanger\\0\"\n\"hoylandet\\0\" \"hurdal\\0\" \"hurum\\0\" \"hvaler\\0\" \"hyllestad\\0\" \"ibestad\\0\"\n\"idrett\\0\" \"inderoy\\0\" \"iveland\\0\" \"jan-mayen\\0\" \"jessheim\\0\" \"jevnaker\\0\"\n\"jolster\\0\" \"jondal\\0\" \"jorpeland\\0\" \"karasjohka\\0\" \"karasjok\\0\"\n\"karlsoy\\0\" \"karmoy\\0\" \"kautokeino\\0\" \"kirkenes\\0\" \"klabu\\0\" \"kommune\\0\"\n\"kongsberg\\0\" \"kongsvinger\\0\" \"kopervik\\0\" \"kraanghke\\0\" \"kragero\\0\"\n\"kristiansand\\0\" \"kristiansund\\0\" \"krodsherad\\0\" \"krokstadelva\\0\"\n\"kvafjord\\0\" \"kvalsund\\0\" \"kvanangen\\0\" \"kvinesdal\\0\" \"kvinnherad\\0\"\n\"kviteseid\\0\" \"kvitsoy\\0\" \"laakesvuemie\\0\" \"lahppi\\0\" \"langevag\\0\"\n\"larvik\\0\" \"lavagis\\0\" \"lavangen\\0\" \"leangaviika\\0\" \"lebesby\\0\"\n\"leikanger\\0\" \"leirfjord\\0\" \"leirvik\\0\" \"dlugoleka\\0\" \"leksvik\\0\"\n\"lenvik\\0\" \"lerdal\\0\" \"lesja\\0\" \"levanger\\0\" \"lierne\\0\" \"lillehammer\\0\"\n\"lillesand\\0\" \"lindas\\0\" \"lindesnes\\0\" \"loabat\\0\" \"lodingen\\0\" \"loppa\\0\"\n\"lorenskog\\0\" \"loten\\0\" \"solund\\0\" \"lunner\\0\" \"luroy\\0\" \"luster\\0\"\n\"lyngdal\\0\" \"lyngen\\0\" \"malatvuopmi\\0\" \"malvik\\0\" \"mandal\\0\" \"marker\\0\"\n\"marnardal\\0\" \"masfjorden\\0\" \"matta-varjjat\\0\" \"meldal\\0\" \"melhus\\0\"\n\"meloy\\0\" \"meraker\\0\" \"midsund\\0\" \"midtre-gauldal\\0\" \"mjondalen\\0\"\n\"mo-i-rana\\0\" \"moareke\\0\" \"modalen\\0\" \"modum\\0\" \"molde\\0\" \"more-og-romsdal\\0\"\n\"mosjoen\\0\" \"moskenes\\0\" \"mosvik\\0\" \"muosat\\0\" \"naamesjevuemie\\0\"\n\"namdalseid\\0\" \"namsos\\0\" \"namsskogan\\0\" \"nannestad\\0\" \"naroy\\0\"\n\"narviika\\0\" \"narvik\\0\" \"naustdal\\0\" \"navuotna\\0\" \"nedre-eiker\\0\"\n\"nesna\\0\" \"nesodden\\0\" \"nesoddtangen\\0\" \"nesseby\\0\" \"nesset\\0\" \"nissedal\\0\"\n\"nittedal\\0\" \"nord-aurdal\\0\" \"nord-fron\\0\" \"nord-odal\\0\" \"norddal\\0\"\n\"nordkapp\\0\" \"nordland\\0\" \"nordre-land\\0\" \"nordreisa\\0\" \"nore-og-uvdal\\0\"\n\"notodden\\0\" \"notteroy\\0\" \"odda\\0\" \"oksnes\\0\" \"omasvuotna\\0\" \"oppdal\\0\"\n\"oppegard\\0\" \"orkanger\\0\" \"orkdal\\0\" \"orskog\\0\" \"orsta\\0\" \"oslo\\0\"\n\"osoyro\\0\" \"osteroy\\0\" \"ostfold\\0\" \"ostre-toten\\0\" \"overhalla\\0\"\n\"ovre-eiker\\0\" \"oyer\\0\" \"oygarden\\0\" \"oystre-slidre\\0\" \"porsanger\\0\"\n\"porsangu\\0\" \"porsgrunn\\0\" \"radoy\\0\" \"rahkkeravju\\0\" \"raholt\\0\"\n\"raisa\\0\" \"rakkestad\\0\" \"ralingen\\0\" \"randaberg\\0\" \"rauma\\0\" \"rendalen\\0\"\n\"rennebu\\0\" \"rennesoy\\0\" \"rindal\\0\" \"ringebu\\0\" \"ringerike\\0\" \"ringsaker\\0\"\n\"risor\\0\" \"rissa\\0\" \"roan\\0\" \"rodoy\\0\" \"rollag\\0\" \"tromsa\\0\" \"romskog\\0\"\n\"roros\\0\" \"rost\\0\" \"royken\\0\" \"royrvik\\0\" \"ruovat\\0\" \"rygge\\0\" \"salangen\\0\"\n\"saltdal\\0\" \"samnanger\\0\" \"sandefjord\\0\" \"sandnes\\0\" \"sandnessjoen\\0\"\n\"sauda\\0\" \"selbu\\0\" \"selje\\0\" \"seljord\\0\" \"siellak\\0\" \"sigdal\\0\"\n\"siljan\\0\" \"sirdal\\0\" \"skanit\\0\" \"skanland\\0\" \"skaun\\0\" \"skedsmo\\0\"\n\"skedsmokorset\\0\" \"skien\\0\" \"skierva\\0\" \"skjak\\0\" \"skjervoy\\0\" \"skodje\\0\"\n\"slattum\\0\" \"smola\\0\" \"snaase\\0\" \"snasa\\0\" \"snillfjord\\0\" \"snoasa\\0\"\n\"sogndal\\0\" \"sogne\\0\" \"sokndal\\0\" \"sola\\0\" \"somna\\0\" \"sondre-land\\0\"\n\"songdalen\\0\" \"sor-aurdal\\0\" \"sor-fron\\0\" \"sor-odal\\0\" \"sor-varanger\\0\"\n\"sorfold\\0\" \"sorreisa\\0\" \"sortland\\0\" \"sorum\\0\" \"spjelkavik\\0\" \"spydeberg\\0\"\n\"stange\\0\" \"stat\\0\" \"stathelle\\0\" \"stavanger\\0\" \"stavern\\0\" \"steigen\\0\"\n\"steinkjer\\0\" \"stjordal\\0\" \"stjordalshalsen\\0\" \"stokke\\0\" \"stor-elvdal\\0\"\n\"stord\\0\" \"stordal\\0\" \"storfjord\\0\" \"stranda\\0\" \"sula\\0\" \"suldal\\0\"\n\"sunndal\\0\" \"surnadal\\0\" \"svalbard\\0\" \"sveio\\0\" \"svelvik\\0\" \"sykkylven\\0\"\n\"tananger\\0\" \"telemark\\0\" \"tingvoll\\0\" \"tinn\\0\" \"tjeldsund\\0\" \"tjome\\0\"\n\"tolga\\0\" \"tonsberg\\0\" \"torsken\\0\" \"trana\\0\" \"tranby\\0\" \"tranoy\\0\"\n\"troandin\\0\" \"trogstad\\0\" \"tromso\\0\" \"trondheim\\0\" \"trysil\\0\" \"tvedestrand\\0\"\n\"tydal\\0\" \"tynset\\0\" \"tysfjord\\0\" \"tysnes\\0\" \"tysvar\\0\" \"ullensaker\\0\"\n\"ullensvang\\0\" \"ulvik\\0\" \"unjarga\\0\" \"utsira\\0\" \"vaapste\\0\" \"vadso\\0\"\n\"vaga\\0\" \"vagan\\0\" \"vagsoy\\0\" \"vaksdal\\0\" \"valle\\0\" \"vanylven\\0\"\n\"vardo\\0\" \"varggat\\0\" \"varoy\\0\" \"vefsn\\0\" \"vega\\0\" \"vegarshei\\0\"\n\"vennesla\\0\" \"verdal\\0\" \"verran\\0\" \"vestby\\0\" \"vestfold\\0\" \"vestnes\\0\"\n\"vestre-slidre\\0\" \"vestre-toten\\0\" \"vestvagoy\\0\" \"vevelstad\\0\" \"vikna\\0\"\n\"vindafjord\\0\" \"voagat\\0\" \"volda\\0\" \"voss\\0\" \"vossevangen\\0\" \"xn--andy-ira\\0\"\n\"xn--asky-ira\\0\" \"xn--aurskog-hland-jnb\\0\" \"xn--avery-yua\\0\" \"xn--bdddj-mrabd\\0\"\n\"xn--bearalvhki-y4a\\0\" \"xn--berlevg-jxa\\0\" \"xn--bhcavuotna-s4a\\0\"\n\"xn--bhccavuotna-k7a\\0\" \"xn--bidr-5nac\\0\" \"xn--bjarky-fya\\0\" \"xn--bjddar-pta\\0\"\n\"xn--blt-elab\\0\" \"xn--bmlo-gra\\0\" \"xn--bod-2na\\0\" \"xn--brnny-wuac\\0\"\n\"xn--brnnysund-m8ac\\0\" \"xn--brum-voa\\0\" \"xn--btsfjord-9za\\0\" \"xn--davvenjrga-y4a\\0\"\n\"xn--dnna-gra\\0\" \"xn--drbak-wua\\0\" \"xn--dyry-ira\\0\" \"xn--eveni-0qa01ga\\0\"\n\"xn--finny-yua\\0\" \"xn--fjord-lra\\0\" \"xn--fl-zia\\0\" \"xn--flor-jra\\0\"\n\"xn--frde-gra\\0\" \"xn--frna-woa\\0\" \"xn--frya-hra\\0\" \"xn--ggaviika-8ya47h\\0\"\n\"xn--gildeskl-g0a\\0\" \"xn--givuotna-8ya\\0\" \"xn--gjvik-wua\\0\" \"xn--gls-elac\\0\"\n\"xn--h-2fa\\0\" \"xn--hbmer-xqa\\0\" \"xn--hcesuolo-7ya35b\\0\" \"xn--hgebostad-g3a\\0\"\n\"xn--hmmrfeasta-s4ac\\0\" \"xn--hnefoss-q1a\\0\" \"xn--hobl-ira\\0\" \"xn--holtlen-hxa\\0\"\n\"xn--hpmir-xqa\\0\" \"xn--hyanger-q1a\\0\" \"xn--hylandet-54a\\0\" \"xn--indery-fya\\0\"\n\"xn--jlster-bya\\0\" \"xn--jrpeland-54a\\0\" \"xn--karmy-yua\\0\" \"xn--kfjord-iua\\0\"\n\"xn--klbu-woa\\0\" \"xn--koluokta-7ya57h\\0\" \"xn--krager-gya\\0\" \"xn--kranghke-b0a\\0\"\n\"xn--krdsherad-m8a\\0\" \"xn--krehamn-dxa\\0\" \"xn--krjohka-hwab49j\\0\"\n\"xn--ksnes-uua\\0\" \"xn--kvfjord-nxa\\0\" \"xn--kvitsy-fya\\0\" \"xn--kvnangen-k0a\\0\"\n\"xn--l-1fa\\0\" \"xn--laheadju-7ya\\0\" \"xn--langevg-jxa\\0\" \"xn--ldingen-q1a\\0\"\n\"xn--leagaviika-52b\\0\" \"xn--lesund-hua\\0\" \"xn--lgrd-poac\\0\" \"xn--lhppi-xqa\\0\"\n\"xn--linds-pra\\0\" \"xn--loabt-0qa\\0\" \"xn--lrdal-sra\\0\" \"xn--lrenskog-54a\\0\"\n\"xn--lt-liac\\0\" \"xn--lten-gra\\0\" \"xn--lury-ira\\0\" \"xn--mely-ira\\0\"\n\"xn--merker-kua\\0\" \"xn--mjndalen-64a\\0\" \"xn--mlatvuopmi-s4a\\0\" \"xn--mli-tla\\0\"\n\"xn--mlselv-iua\\0\" \"xn--moreke-jua\\0\" \"xn--mosjen-eya\\0\" \"xn--mot-tla\\0\"\n\"xn--mre-og-romsdal-qqb\\0\" \"xn--msy-ula0h\\0\" \"xn--mtta-vrjjat-k7af\\0\"\n\"xn--muost-0qa\\0\" \"xn--nry-yla5g\\0\" \"xn--nttery-byae\\0\" \"xn--nvuotna-hwa\\0\"\n\"xn--oppegrd-ixa\\0\" \"xn--ostery-fya\\0\" \"xn--osyro-wua\\0\" \"xn--porsgu-sta26f\\0\"\n\"xn--rady-ira\\0\" \"xn--rdal-poa\\0\" \"xn--rde-ula\\0\" \"xn--rennesy-v1a\\0\"\n\"xn--rholt-mra\\0\" \"xn--risa-5na\\0\" \"xn--risr-ira\\0\" \"xn--rland-uua\\0\"\n\"xn--rlingen-mxa\\0\" \"xn--rmskog-bya\\0\" \"xn--rros-gra\\0\" \"xn--rskog-uua\\0\"\n\"xn--rst-0na\\0\" \"xn--rsta-fra\\0\" \"xn--ryken-vua\\0\" \"xn--ryrvik-bya\\0\"\n\"xn--s-1fa\\0\" \"xn--sandy-yua\\0\" \"xn--seral-lra\\0\" \"xn--sgne-gra\\0\"\n\"xn--skierv-uta\\0\" \"xn--skjervy-v1a\\0\" \"xn--skjk-soa\\0\" \"xn--sknit-yqa\\0\"\n\"xn--sknland-fxa\\0\" \"xn--slat-5na\\0\" \"xn--slt-elab\\0\" \"xn--smla-hra\\0\"\n\"xn--smna-gra\\0\" \"xn--snase-nra\\0\" \"xn--sndre-land-0cb\\0\" \"xn--snes-poa\\0\"\n\"xn--snsa-roa\\0\" \"xn--sr-aurdal-l8a\\0\" \"xn--sr-fron-q1a\\0\" \"xn--sr-odal-q1a\\0\"\n\"xn--sr-varanger-ggb\\0\" \"xn--srfold-bya\\0\" \"xn--srreisa-q1a\\0\" \"xn--srum-gra\\0\"\n\"xn--stfold-9xa\\0\" \"xn--stjrdal-s1a\\0\" \"xn--stjrdalshalsen-sqb\\0\"\n\"xn--stre-toten-zcb\\0\" \"xn--tjme-hra\\0\" \"xn--tnsberg-q1a\\0\" \"xn--trany-yua\\0\"\n\"xn--trgstad-r1a\\0\" \"xn--trna-woa\\0\" \"xn--troms-zua\\0\" \"xn--tysvr-vra\\0\"\n\"xn--unjrga-rta\\0\" \"xn--vads-jra\\0\" \"xn--vard-jra\\0\" \"xn--vegrshei-c0a\\0\"\n\"xn--vestvgy-ixa6o\\0\" \"xn--vg-yiab\\0\" \"xn--vgan-qoa\\0\" \"xn--vgsy-qoa0j\\0\"\n\"xn--vre-eiker-k8a\\0\" \"xn--vrggt-xqad\\0\" \"xn--vry-yla5g\\0\" \"xn--yer-zna\\0\"\n\"xn--ygarden-p1a\\0\" \"xn--ystre-slidre-ujb\\0\" \"wios\\0\" \"xn--vler-qoa\\0\"\n\"heroy\\0\" \"sande\\0\" \"xn--b-5ga\\0\" \"xn--hery-ira\\0\" \"merseine\\0\"\n\"shacknet\\0\" \"cri\\0\" \"govt\\0\" \"maori\\0\" \"xn--mori-qsa\\0\" \"amune\\0\"\n\"bmoattachments\\0\" \"boldlygoingnowhere\\0\" \"cable-modem\\0\" \"certmgr\\0\"\n\"collegefan\\0\" \"couchpotatofries\\0\" \"duckdns\\0\" \"dvrdns\\0\" \"endoftheinternet\\0\"\n\"from-me\\0\" \"game-host\\0\" \"hepforge\\0\" \"homedns\\0\" \"is-a-bruinsfan\\0\"\n\"is-a-candidate\\0\" \"is-a-celticsfan\\0\" \"is-a-knight\\0\" \"is-a-patsfan\\0\"\n\"is-a-soxfan\\0\" \"is-found\\0\" \"is-lost\\0\" \"is-saved\\0\" \"is-very-bad\\0\"\n\"is-very-evil\\0\" \"is-very-good\\0\" \"is-very-nice\\0\" \"is-very-sweet\\0\"\n\"misconfused\\0\" \"my-firewall\\0\" \"myfirewall\\0\" \"nflfan\\0\" \"pimienta\\0\"\n\"poivron\\0\" \"potager\\0\" \"read-books\\0\" \"readmyblog\\0\" \"sellsyourhome\\0\"\n\"stuff-4-sale\\0\" \"sweetpepper\\0\" \"tunk\\0\" \"ufcfan\\0\" \"wmflabs\\0\"\n\"zapto\\0\" \"rsc\\0\" \"origin\\0\" \"q-a\\0\" \"gok\\0\" \"agro\\0\" \"augustow\\0\"\n\"babia-gora\\0\" \"bedzin\\0\" \"beep\\0\" \"beskidy\\0\" \"bialowieza\\0\" \"bialystok\\0\"\n\"bielawa\\0\" \"bieszczady\\0\" \"boleslawiec\\0\" \"bydgoszcz\\0\" \"bytom\\0\"\n\"cieszyn\\0\" \"czest\\0\" \"elblag\\0\" \"vologda\\0\" \"gdansk\\0\" \"gdynia\\0\"\n\"gliwice\\0\" \"glogow\\0\" \"gmina\\0\" \"gniezno\\0\" \"gorlice\\0\" \"grajewo\\0\"\n\"ilawa\\0\" \"jaworzno\\0\" \"jelenia-gora\\0\" \"jgora\\0\" \"kalisz\\0\" \"karpacz\\0\"\n\"kartuzy\\0\" \"kaszuby\\0\" \"katowice\\0\" \"kazimierz-dolny\\0\" \"kepno\\0\"\n\"ketrzyn\\0\" \"klodzko\\0\" \"kobierzyce\\0\" \"kolobrzeg\\0\" \"konin\\0\" \"konskowola\\0\"\n\"krakow\\0\" \"kutno\\0\" \"lapy\\0\" \"lebork\\0\" \"legnica\\0\" \"lezajsk\\0\"\n\"limanowa\\0\" \"lomza\\0\" \"lubin\\0\" \"lukow\\0\" \"malbork\\0\" \"malopolska\\0\"\n\"mazowsze\\0\" \"mazury\\0\" \"miasta\\0\" \"mielec\\0\" \"mielno\\0\" \"mragowo\\0\"\n\"naklo\\0\" \"nowaruda\\0\" \"nysa\\0\" \"olawa\\0\" \"olecko\\0\" \"olkusz\\0\"\n\"olsztyn\\0\" \"opoczno\\0\" \"opole\\0\" \"ostroda\\0\" \"ostroleka\\0\" \"ostrowiec\\0\"\n\"pila\\0\" \"podhale\\0\" \"podlasie\\0\" \"polkowice\\0\" \"pomorskie\\0\" \"pomorze\\0\"\n\"powiat\\0\" \"poznan\\0\" \"prochowice\\0\" \"pruszkow\\0\" \"przeworsk\\0\"\n\"pulawy\\0\" \"radom\\0\" \"rawa-maz\\0\" \"rybnik\\0\" \"rzeszow\\0\" \"sanok\\0\"\n\"sejny\\0\" \"sklep\\0\" \"skoczow\\0\" \"slask\\0\" \"slupsk\\0\" \"sopot\\0\" \"sosnowiec\\0\"\n\"stalowa-wola\\0\" \"starachowice\\0\" \"stargard\\0\" \"suwalki\\0\" \"swidnica\\0\"\n\"swiebodzin\\0\" \"swinoujscie\\0\" \"szczecin\\0\" \"szczytno\\0\" \"szkola\\0\"\n\"targi\\0\" \"tarnobrzeg\\0\" \"tgory\\0\" \"tourism\\0\" \"turek\\0\" \"turystyka\\0\"\n\"tychy\\0\" \"ustka\\0\" \"walbrzych\\0\" \"warmia\\0\" \"warszawa\\0\" \"wegrow\\0\"\n\"wielun\\0\" \"wloclawek\\0\" \"wodzislaw\\0\" \"wolomin\\0\" \"wroc\\0\" \"zachpomor\\0\"\n\"zagan\\0\" \"zakopane\\0\" \"zarow\\0\" \"zgora\\0\" \"zgorzelec\\0\" \"griw\\0\"\n\"kmpsp\\0\" \"konsulat\\0\" \"kppsp\\0\" \"kwp\\0\" \"kwpsp\\0\" \"mup\\0\" \"oirm\\0\"\n\"oum\\0\" \"pinb\\0\" \"piw\\0\" \"psse\\0\" \"pup\\0\" \"sdn\\0\" \"starostwo\\0\"\n\"ugim\\0\" \"umig\\0\" \"upow\\0\" \"wzmiuw\\0\" \"uzs\\0\" \"wif\\0\" \"wiih\\0\" \"witd\\0\"\n\"wiw\\0\" \"zp\\0\" \"test\\0\" \"isla\\0\" \"jur\\0\" \"belau\\0\" \"fhsk\\0\" \"fhv\\0\"\n\"komforb\\0\" \"kommunalforbund\\0\" \"komvux\\0\" \"lanbib\\0\" \"naturbruksgymn\\0\"\n\"parti\\0\" \"hashbang\\0\" \"platform\\0\" \"univ\\0\" \"stackspace\\0\" \"consulado\\0\"\n\"embaixada\\0\" \"principe\\0\" \"adygeya\\0\" \"arkhangelsk\\0\" \"balashov\\0\"\n\"bashkiria\\0\" \"bryansk\\0\" \"dagestan\\0\" \"grozny\\0\" \"ivanovo\\0\" \"kalmykia\\0\"\n\"kaluga\\0\" \"karelia\\0\" \"khakassia\\0\" \"krasnodar\\0\" \"kurgan\\0\" \"lenug\\0\"\n\"mordovia\\0\" \"murmansk\\0\" \"nalchik\\0\" \"nov\\0\" \"obninsk\\0\" \"penza\\0\"\n\"pokrovsk\\0\" \"sochi\\0\" \"togliatti\\0\" \"troitsk\\0\" \"tula\\0\" \"vladikavkaz\\0\"\n\"vladimir\\0\" \"knightpoint\\0\" \"agrinet\\0\" \"defense\\0\" \"edunet\\0\"\n\"rnrt\\0\" \"bel\\0\" \"kep\\0\" \"better-than\\0\" \"on-the-web\\0\" \"worse-than\\0\"\n\"xn--czrw28b\\0\" \"xn--zf0ao64a\\0\" \"cherkassy\\0\" \"cherkasy\\0\" \"chernivtsi\\0\"\n\"chernovtsy\\0\" \"crimea\\0\" \"dnepropetrovsk\\0\" \"dnipropetrovsk\\0\"\n\"dominic\\0\" \"donetsk\\0\" \"dp\\0\" \"ivano-frankivsk\\0\" \"kharkiv\\0\" \"kharkov\\0\"\n\"kherson\\0\" \"khmelnitskiy\\0\" \"khmelnytskyi\\0\" \"kiev\\0\" \"kirovograd\\0\"\n\"krym\\0\" \"kv\\0\" \"kyiv\\0\" \"lugansk\\0\" \"lutsk\\0\" \"lviv\\0\" \"mykolaiv\\0\"\n\"nikolaev\\0\" \"odessa\\0\" \"poltava\\0\" \"rivne\\0\" \"rovno\\0\" \"sebastopol\\0\"\n\"sevastopol\\0\" \"ternopil\\0\" \"uzhgorod\\0\" \"vinnica\\0\" \"vinnytsia\\0\"\n\"volyn\\0\" \"zaporizhzhe\\0\" \"zaporizhzhia\\0\" \"zhitomir\\0\" \"zhytomyr\\0\"\n\"nhs\\0\" \"police\\0\" \"service\\0\" \"golffan\\0\" \"is-by\\0\" \"land-4-sale\\0\"\n\"nsn\\0\" \"pointto\\0\" \"chtr\\0\" \"paroch\\0\" \"gub\\0\" \"e12\\0\" \"mypets\\0\"\n\"xn--80au\\0\" \"xn--90azh\\0\" \"xn--d1at\\0\" \"xn--o1ac\\0\" \"xn--o1ach\\0\"\n\"agric\\0\" \"grondar\\0\" \"triton\\0\" \"\";\n\nstatic const struct TrieNode kNodeTable[] = {\n  {     0,     0,     0, 1 },  /* aaa */\n  {     4,     0,     0, 1 },  /* aarp */\n  {     9,     0,     0, 1 },  /* abarth */\n  {    16,     0,     0, 1 },  /* abb */\n  {    20,     0,     0, 1 },  /* abbott */\n  {    27,     0,     0, 1 },  /* abbvie */\n  {    34,     0,     0, 1 },  /* abc */\n  {    38,     0,     0, 1 },  /* able */\n  {    43,     0,     0, 1 },  /* abogado */\n  {    51,     0,     0, 1 },  /* abudhabi */\n  {    62,  3549,     6, 1 },  /* ac */\n  {    65,     0,     0, 1 },  /* academy */\n  {    73,     0,     0, 1 },  /* accenture */\n  {    89,     0,     0, 1 },  /* accountant */\n  {   100,     0,     0, 1 },  /* accountants */\n  {   112,     0,     0, 1 },  /* aco */\n  {   121,     0,     0, 1 },  /* active */\n  {   134,     0,     0, 1 },  /* actor */\n  {   141,  3555,     1, 1 },  /* ad */\n  {    60,     0,     0, 1 },  /* adac */\n  {   144,     0,     0, 1 },  /* ads */\n  {   148,     0,     0, 1 },  /* adult */\n  {   157,  3556,     8, 1 },  /* ae */\n  {   160,     0,     0, 1 },  /* aeg */\n  {   164,  3564,    87, 1 },  /* aero */\n  {   169,     0,     0, 1 },  /* aetna */\n  {   191,  3651,     5, 1 },  /* af */\n  {   194,     0,     0, 1 },  /* afamilycompany */\n  {   209,     0,     0, 1 },  /* afl */\n  {   217,     0,     0, 1 },  /* africa */\n  {   226,  3656,     5, 1 },  /* ag */\n  {   229,     0,     0, 1 },  /* agakhan */\n  {   237,     0,     0, 1 },  /* agency */\n  {   247,  3661,     4, 1 },  /* ai */\n  {   250,     0,     0, 1 },  /* aig */\n  {   255,     0,     0, 1 },  /* aigo */\n  {   260,     0,     0, 1 },  /* airbus */\n  {   267,     0,     0, 1 },  /* airforce */\n  {   276,     0,     0, 1 },  /* airtel */\n  {   283,     0,     0, 1 },  /* akdn */\n  {   290,  3665,     7, 1 },  /* al */\n  {   293,     0,     0, 1 },  /* alfaromeo */\n  {   303,     0,     0, 1 },  /* alibaba */\n  {   311,     0,     0, 1 },  /* alipay */\n  {   318,     0,     0, 1 },  /* allfinanz */\n  {   328,     0,     0, 1 },  /* allstate */\n  {   337,     0,     0, 1 },  /* ally */\n  {   342,     0,     0, 1 },  /* alsace */\n  {   349,     0,     0, 1 },  /* alstom */\n  {   358,  3672,     1, 1 },  /* am */\n  {   361,     0,     0, 1 },  /* americanexpress */\n  {   377,     0,     0, 1 },  /* americanfamily */\n  {   395,     0,     0, 1 },  /* amex */\n  {   400,     0,     0, 1 },  /* amfam */\n  {   406,     0,     0, 1 },  /* amica */\n  {   412,     0,     0, 1 },  /* amsterdam */\n  {   422,     0,     0, 1 },  /* analytics */\n  {   432,     0,     0, 1 },  /* android */\n  {   440,     0,     0, 1 },  /* anquan */\n  {   324,     0,     0, 1 },  /* anz */\n  {   448,  3673,     6, 1 },  /* ao */\n  {   451,     0,     0, 1 },  /* aol */\n  {   455,     0,     0, 1 },  /* apartments */\n  {   468,     0,     0, 1 },  /* app */\n  {   472,     0,     0, 1 },  /* apple */\n  {   480,     0,     0, 1 },  /* aq */\n  {   483,     0,     0, 1 },  /* aquarelle */\n  {   494,  1553,     9, 1 },  /* ar */\n  {   497,     0,     0, 1 },  /* arab */\n  {   502,     0,     0, 1 },  /* aramco */\n  {   509,     0,     0, 1 },  /* archi */\n  {   515,     0,     0, 1 },  /* army */\n  {   520,  3679,     6, 1 },  /* arpa */\n  {   527,     0,     0, 1 },  /* art */\n  {   531,     0,     0, 1 },  /* arte */\n  {   537,  3685,     1, 1 },  /* as */\n  {   540,     0,     0, 1 },  /* asda */\n  {   545,  3686,     1, 1 },  /* asia */\n  {   550,     0,     0, 1 },  /* associates */\n  {   562,  1562,    10, 1 },  /* at */\n  {   565,     0,     0, 1 },  /* athleta */\n  {   573,     0,     0, 1 },  /* attorney */\n  {   584,  1574,    18, 1 },  /* au */\n  {   587,     0,     0, 1 },  /* auction */\n  {   595,     0,     0, 1 },  /* audi */\n  {   600,     0,     0, 1 },  /* audible */\n  {   608,     0,     0, 1 },  /* audio */\n  {   614,     0,     0, 1 },  /* auspost */\n  {   622,     0,     0, 1 },  /* author */\n  {   629,     0,     0, 1 },  /* auto */\n  {   634,     0,     0, 1 },  /* autos */\n  {   640,     0,     0, 1 },  /* avianca */\n  {   649,  3701,     1, 1 },  /* aw */\n  {   658,     0,     0, 1 },  /* aws */\n  {   663,     0,     0, 1 },  /* ax */\n  {   666,     0,     0, 1 },  /* axa */\n  {   671,  3702,    12, 1 },  /* az */\n  {   682,     0,     0, 1 },  /* azure */\n  {   308,  3665,     7, 1 },  /* ba */\n  {   692,     0,     0, 1 },  /* baby */\n  {   697,     0,     0, 1 },  /* baidu */\n  {   392,     0,     0, 1 },  /* banamex */\n  {   703,     0,     0, 1 },  /* bananarepublic */\n  {   725,     0,     0, 1 },  /* band */\n  {   731,     0,     0, 1 },  /* bank */\n  {   736,     0,     0, 1 },  /* bar */\n  {   740,     0,     0, 1 },  /* barcelona */\n  {   750,     0,     0, 1 },  /* barclaycard */\n  {   762,     0,     0, 1 },  /* barclays */\n  {   771,     0,     0, 1 },  /* barefoot */\n  {   780,     0,     0, 1 },  /* bargains */\n  {   789,     0,     0, 1 },  /* baseball */\n  {   798,     0,     0, 1 },  /* basketball */\n  {   809,     0,     0, 1 },  /* bauhaus */\n  {   817,     0,     0, 1 },  /* bayern */\n  {    17,  3714,    10, 1 },  /* bb */\n  {   824,     0,     0, 1 },  /* bbc */\n  {   828,     0,     0, 1 },  /* bbt */\n  {   832,     0,     0, 1 },  /* bbva */\n  {   837,     0,     0, 1 },  /* bcg */\n  {   841,     0,     0, 1 },  /* bcn */\n  {   855,  3687,     1, 0 },  /* bd */\n  {   860,  1592,     3, 1 },  /* be */\n  {   863,     0,     0, 1 },  /* beats */\n  {   869,     0,     0, 1 },  /* beauty */\n  {   881,     0,     0, 1 },  /* beer */\n  {   886,     0,     0, 1 },  /* bentley */\n  {   894,     0,     0, 1 },  /* berlin */\n  {   901,     0,     0, 1 },  /* best */\n  {   906,     0,     0, 1 },  /* bestbuy */\n  {   914,     0,     0, 1 },  /* bet */\n  {   928,  3685,     1, 1 },  /* bf */\n  {   931,  3724,    37, 1 },  /* bg */\n  {   936,  3651,     5, 1 },  /* bh */\n  {   939,     0,     0, 1 },  /* bharti */\n  {    57,  3761,     5, 1 },  /* bi */\n  {   950,     0,     0, 1 },  /* bible */\n  {   956,     0,     0, 1 },  /* bid */\n  {   960,     0,     0, 1 },  /* bike */\n  {   969,     0,     0, 1 },  /* bing */\n  {   974,     0,     0, 1 },  /* bingo */\n  {   980,     0,     0, 1 },  /* bio */\n  {   985,  3766,    12, 1 },  /* biz */\n  {   989,  3778,     4, 1 },  /* bj */\n  {   992,     0,     0, 1 },  /* black */\n  {   998,     0,     0, 1 },  /* blackfriday */\n  {  1010,     0,     0, 1 },  /* blanco */\n  {  1017,     0,     0, 1 },  /* blockbuster */\n  {  1034,     0,     0, 1 },  /* blog */\n  {  1039,     0,     0, 1 },  /* bloomberg */\n  {  1049,     0,     0, 1 },  /* blue */\n  {  1055,  3651,     5, 1 },  /* bm */\n  {  1058,     0,     0, 1 },  /* bms */\n  {  1062,     0,     0, 1 },  /* bmw */\n  {  1067,  3687,     1, 0 },  /* bn */\n  {  1070,     0,     0, 1 },  /* bnl */\n  {  1074,     0,     0, 1 },  /* bnpparibas */\n  {  1086,  3782,     9, 1 },  /* bo */\n  {  1089,     0,     0, 1 },  /* boats */\n  {  1095,     0,     0, 1 },  /* boehringer */\n  {  1106,     0,     0, 1 },  /* bofa */\n  {  1111,     0,     0, 1 },  /* bom */\n  {  1115,     0,     0, 1 },  /* bond */\n  {  1120,     0,     0, 1 },  /* boo */\n  {  1124,     0,     0, 1 },  /* book */\n  {  1129,     0,     0, 1 },  /* booking */\n  {  1137,     0,     0, 1 },  /* boots */\n  {  1143,     0,     0, 1 },  /* bosch */\n  {  1149,     0,     0, 1 },  /* bostik */\n  {  1156,     0,     0, 1 },  /* boston */\n  {  1163,     0,     0, 1 },  /* bot */\n  {  1167,     0,     0, 1 },  /* boutique */\n  {  1177,     0,     0, 1 },  /* box */\n  {  1182,  1595,    70, 1 },  /* br */\n  {  1185,     0,     0, 1 },  /* bradesco */\n  {  1194,     0,     0, 1 },  /* bridgestone */\n  {  1206,     0,     0, 1 },  /* broadway */\n  {  1215,     0,     0, 1 },  /* broker */\n  {  1222,     0,     0, 1 },  /* brother */\n  {  1230,     0,     0, 1 },  /* brussels */\n  {  1240,  3651,     5, 1 },  /* bs */\n  {   829,  3651,     5, 1 },  /* bt */\n  {  1243,     0,     0, 1 },  /* budapest */\n  {  1252,     0,     0, 1 },  /* bugatti */\n  {  1260,     0,     0, 1 },  /* build */\n  {  1266,     0,     0, 1 },  /* builders */\n  {  1275,     0,     0, 1 },  /* business */\n  {   910,     0,     0, 1 },  /* buy */\n  {  1284,     0,     0, 1 },  /* buzz */\n  {  1289,     0,     0, 1 },  /* bv */\n  {  1292,  3818,     2, 1 },  /* bw */\n  {   694,  1665,     4, 1 },  /* by */\n  {  1295,  3820,     6, 1 },  /* bz */\n  {  1298,     0,     0, 1 },  /* bzh */\n  {   221,  3826,    18, 1 },  /* ca */\n  {  1306,     0,     0, 1 },  /* cab */\n  {  1310,     0,     0, 1 },  /* cafe */\n  {  1319,     0,     0, 1 },  /* cal */\n  {  1323,     0,     0, 1 },  /* call */\n  {  1328,     0,     0, 1 },  /* calvinklein */\n  {  1343,     0,     0, 1 },  /* cam */\n  {  1357,     0,     0, 1 },  /* camera */\n  {  1372,     0,     0, 1 },  /* camp */\n  {  1377,     0,     0, 1 },  /* cancerresearch */\n  {  1392,     0,     0, 1 },  /* canon */\n  {  1398,     0,     0, 1 },  /* capetown */\n  {  1407,     0,     0, 1 },  /* capital */\n  {  1415,     0,     0, 1 },  /* capitalone */\n  {  1426,     0,     0, 1 },  /* car */\n  {  1430,     0,     0, 1 },  /* caravan */\n  {  1438,     0,     0, 1 },  /* cards */\n  {  1450,     0,     0, 1 },  /* care */\n  {  1455,     0,     0, 1 },  /* career */\n  {  1462,     0,     0, 1 },  /* careers */\n  {  1478,     0,     0, 1 },  /* cars */\n  {  1483,     0,     0, 1 },  /* cartier */\n  {  1491,     0,     0, 1 },  /* casa */\n  {  1496,     0,     0, 1 },  /* case */\n  {  1501,     0,     0, 1 },  /* caseih */\n  {  1508,     0,     0, 1 },  /* cash */\n  {  1513,     0,     0, 1 },  /* casino */\n  {  1523,     0,     0, 1 },  /* cat */\n  {  1527,     0,     0, 1 },  /* catering */\n  {  1536,     0,     0, 1 },  /* catholic */\n  {  1563,     0,     0, 1 },  /* cba */\n  {  1066,     0,     0, 1 },  /* cbn */\n  {  1567,     0,     0, 1 },  /* cbre */\n  {  1239,     0,     0, 1 },  /* cbs */\n  {  1579,  3844,     6, 1 },  /* cc */\n  {  1583,  3685,     1, 1 },  /* cd */\n  {  1586,     0,     0, 1 },  /* ceb */\n  {  1593,     0,     0, 1 },  /* center */\n  {  1600,     0,     0, 1 },  /* ceo */\n  {  1604,     0,     0, 1 },  /* cern */\n  {  1611,  3672,     1, 1 },  /* cf */\n  {  1614,     0,     0, 1 },  /* cfa */\n  {  1618,     0,     0, 1 },  /* cfd */\n  {   838,     0,     0, 1 },  /* cg */\n  {  1146,  3850,     2, 1 },  /* ch */\n  {  1627,     0,     0, 1 },  /* chanel */\n  {  1640,     0,     0, 1 },  /* channel */\n  {  1648,     0,     0, 1 },  /* chase */\n  {  1654,     0,     0, 1 },  /* chat */\n  {  1659,     0,     0, 1 },  /* cheap */\n  {  1665,     0,     0, 1 },  /* chintai */\n  {  1673,     0,     0, 1 },  /* chloe */\n  {  1679,     0,     0, 1 },  /* christmas */\n  {  1689,     0,     0, 1 },  /* chrome */\n  {  1696,     0,     0, 1 },  /* chrysler */\n  {  1705,     0,     0, 1 },  /* church */\n  {  1713,  3852,    15, 1 },  /* ci */\n  {  1716,     0,     0, 1 },  /* cipriani */\n  {  1725,     0,     0, 1 },  /* circle */\n  {  1739,     0,     0, 1 },  /* cisco */\n  {  1745,     0,     0, 1 },  /* citadel */\n  {  1753,     0,     0, 1 },  /* citi */\n  {  1758,     0,     0, 1 },  /* citic */\n  {  1765,     0,     0, 1 },  /* city */\n  {  1770,     0,     0, 1 },  /* cityeats */\n  {   995,  3867,     2, 0 },  /* ck */\n  {  1787,  3869,     5, 1 },  /* cl */\n  {  1790,     0,     0, 1 },  /* claims */\n  {  1797,     0,     0, 1 },  /* cleaning */\n  {  1806,     0,     0, 1 },  /* click */\n  {  1812,     0,     0, 1 },  /* clinic */\n  {  1819,     0,     0, 1 },  /* clinique */\n  {  1828,     0,     0, 1 },  /* clothing */\n  {  1839,  1669,     3, 1 },  /* cloud */\n  {  1849,  3686,     1, 1 },  /* club */\n  {  1854,     0,     0, 1 },  /* clubmed */\n  {  1863,  3874,     4, 1 },  /* cm */\n  {   842,  1672,    44, 1 },  /* cn */\n  {   113,  1720,    13, 1 },  /* co */\n  {  1870,     0,     0, 1 },  /* coach */\n  {  1876,     0,     0, 1 },  /* codes */\n  {  1882,     0,     0, 1 },  /* coffee */\n  {  1894,     0,     0, 1 },  /* college */\n  {  1902,     0,     0, 1 },  /* cologne */\n  {  1913,  1733,   273, 1 },  /* com */\n  {  1917,     0,     0, 1 },  /* comcast */\n  {  1925,     0,     0, 1 },  /* commbank */\n  {  1934,     0,     0, 1 },  /* community */\n  {   201,     0,     0, 1 },  /* company */\n  {  1944,     0,     0, 1 },  /* compare */\n  {  1952,     0,     0, 1 },  /* computer */\n  {  1961,     0,     0, 1 },  /* comsec */\n  {  1968,     0,     0, 1 },  /* condos */\n  {  1975,     0,     0, 1 },  /* construction */\n  {  1988,     0,     0, 1 },  /* consulting */\n  {  1999,     0,     0, 1 },  /* contact */\n  {  2007,     0,     0, 1 },  /* contractors */\n  {  2019,     0,     0, 1 },  /* cooking */\n  {  2027,     0,     0, 1 },  /* cookingchannel */\n  {  2042,     0,     0, 1 },  /* cool */\n  {  2047,     0,     0, 1 },  /* coop */\n  {  2052,     0,     0, 1 },  /* corsica */\n  {  2060,     0,     0, 1 },  /* country */\n  {  2068,     0,     0, 1 },  /* coupon */\n  {  2075,     0,     0, 1 },  /* coupons */\n  {  2083,     0,     0, 1 },  /* courses */\n  {  2091,  3890,     7, 1 },  /* cr */\n  {  2094,     0,     0, 1 },  /* credit */\n  {  2101,     0,     0, 1 },  /* creditcard */\n  {  2112,     0,     0, 1 },  /* creditunion */\n  {  2124,     0,     0, 1 },  /* cricket */\n  {  2132,     0,     0, 1 },  /* crown */\n  {  2138,     0,     0, 1 },  /* crs */\n  {  2142,     0,     0, 1 },  /* cruise */\n  {  2149,     0,     0, 1 },  /* cruises */\n  {  2157,     0,     0, 1 },  /* csc */\n  {  2162,  3897,     6, 1 },  /* cu */\n  {  2165,     0,     0, 1 },  /* cuisinella */\n  {  2176,  3672,     1, 1 },  /* cv */\n  {  2181,  3903,     4, 1 },  /* cw */\n  {  2184,  3907,     2, 1 },  /* cx */\n  {   241,  2069,    13, 1 },  /* cy */\n  {  2187,     0,     0, 1 },  /* cymru */\n  {  2193,     0,     0, 1 },  /* cyou */\n  {  2202,  3909,     4, 1 },  /* cz */\n  {  2205,     0,     0, 1 },  /* dabur */\n  {  2215,     0,     0, 1 },  /* dad */\n  {  2219,     0,     0, 1 },  /* dance */\n  {  2231,     0,     0, 1 },  /* data */\n  {  2240,     0,     0, 1 },  /* date */\n  {  2245,     0,     0, 1 },  /* dating */\n  {  2252,     0,     0, 1 },  /* datsun */\n  {  1006,     0,     0, 1 },  /* day */\n  {  2265,     0,     0, 1 },  /* dclk */\n  {  2270,     0,     0, 1 },  /* dds */\n  {  2276,  2082,    38, 1 },  /* de */\n  {  2279,     0,     0, 1 },  /* deal */\n  {  2284,     0,     0, 1 },  /* dealer */\n  {  2291,     0,     0, 1 },  /* deals */\n  {  2297,     0,     0, 1 },  /* degree */\n  {  2304,     0,     0, 1 },  /* delivery */\n  {  2313,     0,     0, 1 },  /* dell */\n  {  2318,     0,     0, 1 },  /* deloitte */\n  {  2327,     0,     0, 1 },  /* delta */\n  {  2338,     0,     0, 1 },  /* democrat */\n  {  2347,     0,     0, 1 },  /* dental */\n  {  2354,     0,     0, 1 },  /* dentist */\n  {  2362,     0,     0, 1 },  /* desi */\n  {  2373,     0,     0, 1 },  /* design */\n  {  2380,     0,     0, 1 },  /* dev */\n  {  2384,     0,     0, 1 },  /* dhl */\n  {  2388,     0,     0, 1 },  /* diamonds */\n  {  2397,     0,     0, 1 },  /* diet */\n  {  2402,     0,     0, 1 },  /* digital */\n  {  2414,     0,     0, 1 },  /* direct */\n  {  2429,     0,     0, 1 },  /* directory */\n  {  2439,     0,     0, 1 },  /* discount */\n  {  2448,     0,     0, 1 },  /* discover */\n  {  2457,     0,     0, 1 },  /* dish */\n  {  2462,     0,     0, 1 },  /* diy */\n  {  2466,     0,     0, 1 },  /* dj */\n  {  2470,  3916,     6, 1 },  /* dk */\n  {  2474,  3651,     5, 1 },  /* dm */\n  {  2477,     0,     0, 1 },  /* dnp */\n  {    48,  3922,    10, 1 },  /* do */\n  {  2486,     0,     0, 1 },  /* docs */\n  {  2496,     0,     0, 1 },  /* doctor */\n  {  2503,     0,     0, 1 },  /* dodge */\n  {  2509,     0,     0, 1 },  /* dog */\n  {  2513,     0,     0, 1 },  /* doha */\n  {  2518,     0,     0, 1 },  /* domains */\n  {  2526,     0,     0, 1 },  /* dot */\n  {  2530,     0,     0, 1 },  /* download */\n  {  2539,     0,     0, 1 },  /* drive */\n  {  2545,     0,     0, 1 },  /* dtv */\n  {  2549,     0,     0, 1 },  /* dubai */\n  {  1779,     0,     0, 1 },  /* duck */\n  {  2555,     0,     0, 1 },  /* dunlop */\n  {  2562,     0,     0, 1 },  /* duns */\n  {  2567,     0,     0, 1 },  /* dupont */\n  {  2574,     0,     0, 1 },  /* durban */\n  {   224,     0,     0, 1 },  /* dvag */\n  {  2581,     0,     0, 1 },  /* dvr */\n  {  2585,     0,     0, 1 },  /* dwg */\n  {  2594,  3932,     8, 1 },  /* dz */\n  {  2597,     0,     0, 1 },  /* earth */\n  {  2604,     0,     0, 1 },  /* eat */\n  {  1965,  3940,    12, 1 },  /* ec */\n  {  2614,     0,     0, 1 },  /* eco */\n  {  2618,     0,     0, 1 },  /* edeka */\n  {  2624,     0,     0, 1 },  /* edu */\n  {  2631,     0,     0, 1 },  /* education */\n  {  1886,  2120,    10, 1 },  /* ee */\n  {   161,  2130,     9, 1 },  /* eg */\n  {  2650,     0,     0, 1 },  /* email */\n  {  2656,     0,     0, 1 },  /* emerck */\n  {  2663,     0,     0, 1 },  /* energy */\n  {  2676,     0,     0, 1 },  /* engineer */\n  {  2685,     0,     0, 1 },  /* engineering */\n  {  2697,     0,     0, 1 },  /* enterprises */\n  {  2709,     0,     0, 1 },  /* epost */\n  {  2715,     0,     0, 1 },  /* epson */\n  {  2725,     0,     0, 1 },  /* equipment */\n  {   883,  3687,     1, 0 },  /* er */\n  {  2740,     0,     0, 1 },  /* ericsson */\n  {  2750,     0,     0, 1 },  /* erni */\n  {   558,  2139,     5, 1 },  /* es */\n  {  2761,     0,     0, 1 },  /* esq */\n  {  2769,  2144,     1, 1 },  /* estate */\n  {  2776,     0,     0, 1 },  /* esurance */\n  {   915,  3952,     8, 1 },  /* et */\n  {  2789,     0,     0, 1 },  /* etisalat */\n  {  2798,  2145,     6, 1 },  /* eu */\n  {  2801,     0,     0, 1 },  /* eurovision */\n  {  2812,  2151,     1, 1 },  /* eus */\n  {  2816,     0,     0, 1 },  /* events */\n  {  2823,     0,     0, 1 },  /* everbank */\n  {  2837,     0,     0, 1 },  /* exchange */\n  {  2855,     0,     0, 1 },  /* expert */\n  {  2862,     0,     0, 1 },  /* exposed */\n  {   369,     0,     0, 1 },  /* express */\n  {  2884,     0,     0, 1 },  /* extraspace */\n  {  2895,     0,     0, 1 },  /* fage */\n  {  2900,     0,     0, 1 },  /* fail */\n  {  2905,     0,     0, 1 },  /* fairwinds */\n  {  2915,  3961,     1, 1 },  /* faith */\n  {   385,     0,     0, 1 },  /* family */\n  {  2934,     0,     0, 1 },  /* fan */\n  {  2938,     0,     0, 1 },  /* fans */\n  {  2948,     0,     0, 1 },  /* farm */\n  {  2953,     0,     0, 1 },  /* farmers */\n  {  2961,     0,     0, 1 },  /* fashion */\n  {  2969,     0,     0, 1 },  /* fast */\n  {  2974,     0,     0, 1 },  /* fedex */\n  {  2980,     0,     0, 1 },  /* feedback */\n  {  2989,     0,     0, 1 },  /* ferrari */\n  {  2997,     0,     0, 1 },  /* ferrero */\n  {  3009,  3962,     4, 1 },  /* fi */\n  {  3012,     0,     0, 1 },  /* fiat */\n  {  3017,     0,     0, 1 },  /* fidelity */\n  {  3026,     0,     0, 1 },  /* fido */\n  {  3031,     0,     0, 1 },  /* film */\n  {  3036,     0,     0, 1 },  /* final */\n  {  3042,     0,     0, 1 },  /* finance */\n  {  3053,     0,     0, 1 },  /* financial */\n  {  3063,     0,     0, 1 },  /* fire */\n  {  3068,     0,     0, 1 },  /* firestone */\n  {  3078,     0,     0, 1 },  /* firmdale */\n  {  3087,     0,     0, 1 },  /* fish */\n  {  3092,     0,     0, 1 },  /* fishing */\n  {  3100,  3966,     1, 1 },  /* fit */\n  {  3104,     0,     0, 1 },  /* fitness */\n  {  3112,  3687,     1, 0 },  /* fj */\n  {  3116,  3687,     1, 0 },  /* fk */\n  {  3119,     0,     0, 1 },  /* flickr */\n  {  3126,     0,     0, 1 },  /* flights */\n  {  3134,     0,     0, 1 },  /* flir */\n  {  3139,     0,     0, 1 },  /* florist */\n  {  3147,     0,     0, 1 },  /* flowers */\n  {  3155,     0,     0, 1 },  /* fly */\n  {  3160,     0,     0, 1 },  /* fm */\n  {  3169,     0,     0, 1 },  /* fo */\n  {  3172,     0,     0, 1 },  /* foo */\n  {  3176,     0,     0, 1 },  /* food */\n  {  3181,     0,     0, 1 },  /* foodnetwork */\n  {  3193,     0,     0, 1 },  /* football */\n  {  3204,     0,     0, 1 },  /* ford */\n  {  3209,     0,     0, 1 },  /* forex */\n  {  3215,     0,     0, 1 },  /* forsale */\n  {  3223,     0,     0, 1 },  /* forum */\n  {  3229,     0,     0, 1 },  /* foundation */\n  {  3240,     0,     0, 1 },  /* fox */\n  {  3245,  3967,    30, 1 },  /* fr */\n  {  3255,     0,     0, 1 },  /* free */\n  {  3260,     0,     0, 1 },  /* fresenius */\n  {  3270,     0,     0, 1 },  /* frl */\n  {  3274,     0,     0, 1 },  /* frogans */\n  {  3282,     0,     0, 1 },  /* frontdoor */\n  {  3292,     0,     0, 1 },  /* frontier */\n  {  3301,     0,     0, 1 },  /* ftr */\n  {  3305,     0,     0, 1 },  /* fujitsu */\n  {  3313,     0,     0, 1 },  /* fujixerox */\n  {  3323,     0,     0, 1 },  /* fun */\n  {  3327,     0,     0, 1 },  /* fund */\n  {  3332,     0,     0, 1 },  /* furniture */\n  {  3342,     0,     0, 1 },  /* futbol */\n  {  3349,     0,     0, 1 },  /* fyi */\n  {  3355,     0,     0, 1 },  /* ga */\n  {  3360,     0,     0, 1 },  /* gal */\n  {  3367,     0,     0, 1 },  /* gallery */\n  {  3375,     0,     0, 1 },  /* gallo */\n  {  3381,     0,     0, 1 },  /* gallup */\n  {  3392,     0,     0, 1 },  /* game */\n  {  3405,     0,     0, 1 },  /* games */\n  {  3411,     0,     0, 1 },  /* gap */\n  {  3417,     0,     0, 1 },  /* garden */\n  {  3441,     0,     0, 1 },  /* gb */\n  {  3444,     0,     0, 1 },  /* gbiz */\n  {  3449,     0,     0, 1 },  /* gd */\n  {  3452,     0,     0, 1 },  /* gdn */\n  {  1899,  3997,     7, 1 },  /* ge */\n  {  3461,     0,     0, 1 },  /* gea */\n  {  3465,     0,     0, 1 },  /* gent */\n  {  3470,     0,     0, 1 },  /* genting */\n  {  3478,     0,     0, 1 },  /* george */\n  {  3486,     0,     0, 1 },  /* gf */\n  {  3489,  4004,     3, 1 },  /* gg */\n  {  3492,     0,     0, 1 },  /* ggee */\n  {  3505,  4007,     5, 1 },  /* gh */\n  {  3510,  4012,     6, 1 },  /* gi */\n  {  3513,     0,     0, 1 },  /* gift */\n  {  3518,     0,     0, 1 },  /* gifts */\n  {  3524,     0,     0, 1 },  /* gives */\n  {  3530,     0,     0, 1 },  /* giving */\n  {  3537,  4018,     5, 1 },  /* gl */\n  {  3540,     0,     0, 1 },  /* glade */\n  {  3546,     0,     0, 1 },  /* glass */\n  {  3559,     0,     0, 1 },  /* gle */\n  {  3563,     0,     0, 1 },  /* global */\n  {  3570,     0,     0, 1 },  /* globo */\n  {  3590,     0,     0, 1 },  /* gm */\n  {  3593,     0,     0, 1 },  /* gmail */\n  {   934,     0,     0, 1 },  /* gmbh */\n  {  3599,     0,     0, 1 },  /* gmo */\n  {  3603,     0,     0, 1 },  /* gmx */\n  {  2377,  4023,     6, 1 },  /* gn */\n  {  3613,     0,     0, 1 },  /* godaddy */\n  {  3621,     0,     0, 1 },  /* gold */\n  {  3626,     0,     0, 1 },  /* goldpoint */\n  {  3636,     0,     0, 1 },  /* golf */\n  {  3641,     0,     0, 1 },  /* goo */\n  {  3645,     0,     0, 1 },  /* goodhands */\n  {  3655,     0,     0, 1 },  /* goodyear */\n  {  3664,     0,     0, 1 },  /* goog */\n  {  3556,     0,     0, 1 },  /* google */\n  {  3669,     0,     0, 1 },  /* gop */\n  {  3676,     0,     0, 1 },  /* got */\n  {  3686,     0,     0, 1 },  /* gov */\n  {  3690,  4029,     6, 1 },  /* gp */\n  {  3693,     0,     0, 1 },  /* gq */\n  {  3697,  4035,     6, 1 },  /* gr */\n  {  3700,     0,     0, 1 },  /* grainger */\n  {  3709,     0,     0, 1 },  /* graphics */\n  {  3718,     0,     0, 1 },  /* gratis */\n  {  3730,     0,     0, 1 },  /* green */\n  {  3736,     0,     0, 1 },  /* gripe */\n  {  3742,     0,     0, 1 },  /* grocery */\n  {  3753,     0,     0, 1 },  /* group */\n  {  3760,     0,     0, 1 },  /* gs */\n  {  3763,  4041,     7, 1 },  /* gt */\n  {  3768,  3687,     1, 0 },  /* gu */\n  {  3774,     0,     0, 1 },  /* guardian */\n  {  3783,     0,     0, 1 },  /* gucci */\n  {  3789,     0,     0, 1 },  /* guge */\n  {  3794,     0,     0, 1 },  /* guide */\n  {  3800,     0,     0, 1 },  /* guitars */\n  {  3813,     0,     0, 1 },  /* guru */\n  {  3820,     0,     0, 1 },  /* gw */\n  {  2667,  4048,     6, 1 },  /* gy */\n  {  3823,     0,     0, 1 },  /* hair */\n  {  3828,     0,     0, 1 },  /* hamburg */\n  {  3836,     0,     0, 1 },  /* hangout */\n  {   812,     0,     0, 1 },  /* haus */\n  {  3844,     0,     0, 1 },  /* hbo */\n  {  3848,     0,     0, 1 },  /* hdfc */\n  {  3853,     0,     0, 1 },  /* hdfcbank */\n  {  3862,     0,     0, 1 },  /* health */\n  {  1444,     0,     0, 1 },  /* healthcare */\n  {  3869,     0,     0, 1 },  /* help */\n  {  3874,     0,     0, 1 },  /* helsinki */\n  {  3887,     0,     0, 1 },  /* here */\n  {  3892,     0,     0, 1 },  /* hermes */\n  {  3899,     0,     0, 1 },  /* hgtv */\n  {  3904,     0,     0, 1 },  /* hiphop */\n  {  3911,     0,     0, 1 },  /* hisamitsu */\n  {  3921,     0,     0, 1 },  /* hitachi */\n  {  3935,     0,     0, 1 },  /* hiv */\n  {  3940,  4054,    24, 1 },  /* hk */\n  {  3943,     0,     0, 1 },  /* hkt */\n  {  3947,     0,     0, 1 },  /* hm */\n  {  3954,  4078,     6, 1 },  /* hn */\n  {  3957,     0,     0, 1 },  /* hockey */\n  {  3964,     0,     0, 1 },  /* holdings */\n  {  3973,     0,     0, 1 },  /* holiday */\n  {  3981,     0,     0, 1 },  /* homedepot */\n  {  3991,     0,     0, 1 },  /* homegoods */\n  {  4001,     0,     0, 1 },  /* homes */\n  {  4007,     0,     0, 1 },  /* homesense */\n  {  4017,     0,     0, 1 },  /* honda */\n  {  4023,     0,     0, 1 },  /* honeywell */\n  {  4033,     0,     0, 1 },  /* horse */\n  {  4039,     0,     0, 1 },  /* hospital */\n  {  4051,     0,     0, 1 },  /* host */\n  {  4062,  4084,     1, 1 },  /* hosting */\n  {  4070,     0,     0, 1 },  /* hot */\n  {  4074,     0,     0, 1 },  /* hoteles */\n  {  4087,     0,     0, 1 },  /* hotels */\n  {  4094,     0,     0, 1 },  /* hotmail */\n  {  4105,     0,     0, 1 },  /* house */\n  {  4112,     0,     0, 1 },  /* how */\n  {  4118,  4085,     5, 1 },  /* hr */\n  {  4121,     0,     0, 1 },  /* hsbc */\n  {  4129,  4090,    17, 1 },  /* ht */\n  {  4132,     0,     0, 1 },  /* htc */\n  {  4138,  4107,    32, 1 },  /* hu */\n  {  4141,     0,     0, 1 },  /* hughes */\n  {  4148,     0,     0, 1 },  /* hyatt */\n  {  4154,     0,     0, 1 },  /* hyundai */\n  {  1054,     0,     0, 1 },  /* ibm */\n  {  4162,     0,     0, 1 },  /* icbc */\n  {  4170,     0,     0, 1 },  /* ice */\n  {  2161,     0,     0, 1 },  /* icu */\n  {   437,  2152,    11, 1 },  /* id */\n  {    31,  4139,     2, 1 },  /* ie */\n  {  4178,     0,     0, 1 },  /* ieee */\n  {  3159,     0,     0, 1 },  /* ifm */\n  {  4183,     0,     0, 1 },  /* iinet */\n  {  4189,     0,     0, 1 },  /* ikano */\n  {  2653,  2163,     8, 1 },  /* il */\n  {  4200,  2171,     8, 1 },  /* im */\n  {  4203,     0,     0, 1 },  /* imamat */\n  {  4210,     0,     0, 1 },  /* imdb */\n  {  4215,     0,     0, 1 },  /* immo */\n  {  4220,     0,     0, 1 },  /* immobilien */\n  {   898,  4143,    14, 1 },  /* in */\n  {  4235,     0,     0, 1 },  /* industries */\n  {  4246,     0,     0, 1 },  /* infiniti */\n  {  3167,  4157,    16, 1 },  /* info */\n  {   970,     0,     0, 1 },  /* ing */\n  {  4262,     0,     0, 1 },  /* ink */\n  {  4266,     0,     0, 1 },  /* institute */\n  {  4280,     0,     0, 1 },  /* insurance */\n  {  4290,     0,     0, 1 },  /* insure */\n  {  3632,  3888,     1, 1 },  /* int */\n  {  4302,     0,     0, 1 },  /* intel */\n  {  4308,     0,     0, 1 },  /* international */\n  {  4322,     0,     0, 1 },  /* intuit */\n  {  4329,     0,     0, 1 },  /* investments */\n  {   611,  2179,    20, 1 },  /* io */\n  {  4341,     0,     0, 1 },  /* ipiranga */\n  {  4350,  3549,     6, 1 },  /* iq */\n  {  3136,  4174,     9, 1 },  /* ir */\n  {  4353,     0,     0, 1 },  /* irish */\n  {  3722,  4183,     8, 1 },  /* is */\n  {  4364,     0,     0, 1 },  /* iselect */\n  {  4372,     0,     0, 1 },  /* ismaili */\n  {  2358,     0,     0, 1 },  /* ist */\n  {  4385,     0,     0, 1 },  /* istanbul */\n  {  2098,  4191,   369, 1 },  /* it */\n  {   582,     0,     0, 1 },  /* itau */\n  {  4394,     0,     0, 1 },  /* itv */\n  {  2612,     0,     0, 1 },  /* iveco */\n  {  4398,     0,     0, 1 },  /* iwc */\n  {  4402,     0,     0, 1 },  /* jaguar */\n  {  4409,     0,     0, 1 },  /* java */\n  {  4414,     0,     0, 1 },  /* jcb */\n  {  4418,     0,     0, 1 },  /* jcp */\n  {  4425,  4004,     3, 1 },  /* je */\n  {  4428,     0,     0, 1 },  /* jeep */\n  {  4433,     0,     0, 1 },  /* jetzt */\n  {  4439,     0,     0, 1 },  /* jewelry */\n  {  4447,     0,     0, 1 },  /* jio */\n  {  4451,     0,     0, 1 },  /* jlc */\n  {  4455,     0,     0, 1 },  /* jll */\n  {  4459,  3687,     1, 0 },  /* jm */\n  {  4462,     0,     0, 1 },  /* jmp */\n  {  4466,     0,     0, 1 },  /* jnj */\n  {  4472,  4560,     8, 1 },  /* jo */\n  {  4475,     0,     0, 1 },  /* jobs */\n  {  4480,     0,     0, 1 },  /* joburg */\n  {  4487,     0,     0, 1 },  /* jot */\n  {  4491,     0,     0, 1 },  /* joy */\n  {  4495,  2199,   111, 1 },  /* jp */\n  {  4498,     0,     0, 1 },  /* jpmorgan */\n  {  4507,     0,     0, 1 },  /* jprs */\n  {  4512,     0,     0, 1 },  /* juegos */\n  {  4519,     0,     0, 1 },  /* juniper */\n  {  4527,     0,     0, 1 },  /* kaufen */\n  {  4534,     0,     0, 1 },  /* kddi */\n  {   962,  2310,     2, 0 },  /* ke */\n  {  4082,     0,     0, 1 },  /* kerryhotels */\n  {  4544,     0,     0, 1 },  /* kerrylogistics */\n  {  4559,     0,     0, 1 },  /* kerryproperties */\n  {  4575,     0,     0, 1 },  /* kfh */\n  {  4579,  3549,     6, 1 },  /* kg */\n  {  4582,  3687,     1, 0 },  /* kh */\n  {  3880,  6243,     7, 1 },  /* ki */\n  {  4591,     0,     0, 1 },  /* kia */\n  {  4597,     0,     0, 1 },  /* kim */\n  {  4601,     0,     0, 1 },  /* kinder */\n  {  4608,     0,     0, 1 },  /* kindle */\n  {  4615,     0,     0, 1 },  /* kitchen */\n  {  4623,     0,     0, 1 },  /* kiwi */\n  {  4628,  6250,    17, 1 },  /* km */\n  {  4633,  6267,     4, 1 },  /* kn */\n  {  4636,     0,     0, 1 },  /* koeln */\n  {  4642,     0,     0, 1 },  /* komatsu */\n  {  4650,     0,     0, 1 },  /* kosher */\n  {  4665,  6271,     6, 1 },  /* kp */\n  {  4668,     0,     0, 1 },  /* kpmg */\n  {  4673,     0,     0, 1 },  /* kpn */\n  {  3123,  6277,    30, 1 },  /* kr */\n  {  4682,  6307,     2, 1 },  /* krd */\n  {  4686,     0,     0, 1 },  /* kred */\n  {  4691,     0,     0, 1 },  /* kuokgroup */\n  {  4701,  3687,     1, 0 },  /* kw */\n  {  4705,  3651,     5, 1 },  /* ky */\n  {  4708,     0,     0, 1 },  /* kyoto */\n  {  4714,  3549,     6, 1 },  /* kz */\n  {  2173,  6309,    10, 1 },  /* la */\n  {  4721,     0,     0, 1 },  /* lacaixa */\n  {  4729,     0,     0, 1 },  /* ladbrokes */\n  {  4739,     0,     0, 1 },  /* lamborghini */\n  {  4751,     0,     0, 1 },  /* lamer */\n  {  4757,     0,     0, 1 },  /* lancaster */\n  {  4767,     0,     0, 1 },  /* lancia */\n  {  4774,     0,     0, 1 },  /* lancome */\n  {  4784,  2312,     1, 1 },  /* land */\n  {  4789,     0,     0, 1 },  /* landrover */\n  {  4799,     0,     0, 1 },  /* lanxess */\n  {  4807,     0,     0, 1 },  /* lasalle */\n  {  2794,     0,     0, 1 },  /* lat */\n  {  4821,     0,     0, 1 },  /* latino */\n  {  4828,     0,     0, 1 },  /* latrobe */\n  {  4840,     0,     0, 1 },  /* law */\n  {  4849,     0,     0, 1 },  /* lawyer */\n  {  4857,  3651,     5, 1 },  /* lb */\n  {  4452,  6321,     7, 1 },  /* lc */\n  {  4870,     0,     0, 1 },  /* lds */\n  {  4874,     0,     0, 1 },  /* lease */\n  {  4880,     0,     0, 1 },  /* leclerc */\n  {  4888,     0,     0, 1 },  /* lefrak */\n  {  3358,     0,     0, 1 },  /* legal */\n  {  4895,     0,     0, 1 },  /* lego */\n  {  4900,     0,     0, 1 },  /* lexus */\n  {  4906,     0,     0, 1 },  /* lgbt */\n  {  4377,  3672,     1, 1 },  /* li */\n  {  4916,     0,     0, 1 },  /* liaison */\n  {  4924,     0,     0, 1 },  /* lidl */\n  {  4932,     0,     0, 1 },  /* life */\n  {  4276,     0,     0, 1 },  /* lifeinsurance */\n  {  4937,     0,     0, 1 },  /* lifestyle */\n  {  4947,     0,     0, 1 },  /* lighting */\n  {  4956,     0,     0, 1 },  /* like */\n  {  4961,     0,     0, 1 },  /* lilly */\n  {  4967,     0,     0, 1 },  /* limited */\n  {  4975,     0,     0, 1 },  /* limo */\n  {  4980,     0,     0, 1 },  /* lincoln */\n  {  4988,     0,     0, 1 },  /* linde */\n  {  4998,  6328,     2, 1 },  /* link */\n  {  5003,     0,     0, 1 },  /* lipsy */\n  {  5009,     0,     0, 1 },  /* live */\n  {  5014,     0,     0, 1 },  /* living */\n  {  5021,     0,     0, 1 },  /* lixil */\n  {  2267,  6330,    15, 1 },  /* lk */\n  {  5031,     0,     0, 1 },  /* loan */\n  {  5036,     0,     0, 1 },  /* loans */\n  {  5042,     0,     0, 1 },  /* locker */\n  {  5049,     0,     0, 1 },  /* locus */\n  {  5055,     0,     0, 1 },  /* loft */\n  {  5060,     0,     0, 1 },  /* lol */\n  {  5064,     0,     0, 1 },  /* london */\n  {  5071,     0,     0, 1 },  /* lotte */\n  {  5077,     0,     0, 1 },  /* lotto */\n  {  5083,     0,     0, 1 },  /* love */\n  {  5088,     0,     0, 1 },  /* lpl */\n  {  3050,     0,     0, 1 },  /* lplfinancial */\n  {  5092,  3651,     5, 1 },  /* lr */\n  {  1236,  3818,     2, 1 },  /* ls */\n  {   151,  4139,     2, 1 },  /* lt */\n  {  5103,     0,     0, 1 },  /* ltd */\n  {  5107,     0,     0, 1 },  /* ltda */\n  {  5112,  3672,     1, 1 },  /* lu */\n  {  5115,     0,     0, 1 },  /* lundbeck */\n  {  5124,     0,     0, 1 },  /* lupin */\n  {  5130,     0,     0, 1 },  /* luxe */\n  {  5135,     0,     0, 1 },  /* luxury */\n  {  5147,  6345,     9, 1 },  /* lv */\n  {   339,  6354,     9, 1 },  /* ly */\n  {  5151,  6363,     6, 1 },  /* ma */\n  {  5154,     0,     0, 1 },  /* macys */\n  {  5160,     0,     0, 1 },  /* madrid */\n  {  5167,     0,     0, 1 },  /* maif */\n  {  5181,     0,     0, 1 },  /* maison */\n  {  5188,     0,     0, 1 },  /* makeup */\n  {  5198,     0,     0, 1 },  /* man */\n  {  5202,  6369,     1, 1 },  /* management */\n  {  5213,     0,     0, 1 },  /* mango */\n  {  5219,     0,     0, 1 },  /* map */\n  {  5229,     0,     0, 1 },  /* market */\n  {  5236,     0,     0, 1 },  /* marketing */\n  {  5246,     0,     0, 1 },  /* markets */\n  {  5254,     0,     0, 1 },  /* marriott */\n  {  5263,     0,     0, 1 },  /* marshalls */\n  {  5273,     0,     0, 1 },  /* maserati */\n  {  5282,     0,     0, 1 },  /* mattel */\n  {  5293,     0,     0, 1 },  /* mba */\n  {  5307,  6370,     2, 1 },  /* mc */\n  {  1582,     0,     0, 1 },  /* mcd */\n  {  4864,     0,     0, 1 },  /* mcdonalds */\n  {  5310,     0,     0, 1 },  /* mckinsey */\n  {  5320,  3672,     1, 1 },  /* md */\n  {  1693,  6372,    22, 1 },  /* me */\n  {  1858,     0,     0, 1 },  /* med */\n  {  5327,     0,     0, 1 },  /* media */\n  {  5333,     0,     0, 1 },  /* meet */\n  {  5338,     0,     0, 1 },  /* melbourne */\n  {  5348,     0,     0, 1 },  /* meme */\n  {  5353,     0,     0, 1 },  /* memorial */\n  {  5366,     0,     0, 1 },  /* men */\n  {  5370,     0,     0, 1 },  /* menu */\n  {   299,     0,     0, 1 },  /* meo */\n  {  5375,     0,     0, 1 },  /* merckmsd */\n  {  4929,     0,     0, 1 },  /* metlife */\n  {  4670,  6394,     9, 1 },  /* mg */\n  {  5391,     0,     0, 1 },  /* mh */\n  {  5394,     0,     0, 1 },  /* miami */\n  {  5400,     0,     0, 1 },  /* microsoft */\n  {  4195,     0,     0, 1 },  /* mil */\n  {  5412,     0,     0, 1 },  /* mini */\n  {  4297,     0,     0, 1 },  /* mint */\n  {  5418,     0,     0, 1 },  /* mit */\n  {  5422,     0,     0, 1 },  /* mitsubishi */\n  {  5433,  6403,     8, 1 },  /* mk */\n  {  5436,  6411,     7, 1 },  /* ml */\n  {  4856,     0,     0, 1 },  /* mlb */\n  {  5095,     0,     0, 1 },  /* mls */\n  {  5441,  3687,     1, 0 },  /* mm */\n  {  5150,     0,     0, 1 },  /* mma */\n  {  5445,  6418,     4, 1 },  /* mn */\n  {  3600,  3651,     5, 1 },  /* mo */\n  {  5448,  6422,     1, 1 },  /* mobi */\n  {  5459,     0,     0, 1 },  /* mobile */\n  {  5466,     0,     0, 1 },  /* mobily */\n  {  5476,     0,     0, 1 },  /* moda */\n  {  5481,     0,     0, 1 },  /* moe */\n  {  5485,     0,     0, 1 },  /* moi */\n  {  5489,     0,     0, 1 },  /* mom */\n  {  5493,     0,     0, 1 },  /* monash */\n  {  5500,     0,     0, 1 },  /* money */\n  {  5506,     0,     0, 1 },  /* monster */\n  {  5514,     0,     0, 1 },  /* montblanc */\n  {  5524,     0,     0, 1 },  /* mopar */\n  {  5530,     0,     0, 1 },  /* mormon */\n  {  5537,     0,     0, 1 },  /* mortgage */\n  {  5546,     0,     0, 1 },  /* moscow */\n  {  5557,     0,     0, 1 },  /* moto */\n  {  5562,     0,     0, 1 },  /* motorcycles */\n  {  5574,     0,     0, 1 },  /* mov */\n  {  5578,     0,     0, 1 },  /* movie */\n  {  5584,     0,     0, 1 },  /* movistar */\n  {  1374,     0,     0, 1 },  /* mp */\n  {  5597,     0,     0, 1 },  /* mq */\n  {  5601,  4139,     2, 1 },  /* mr */\n  {  1059,  3651,     5, 1 },  /* ms */\n  {  5380,     0,     0, 1 },  /* msd */\n  {  5609,  2313,     4, 1 },  /* mt */\n  {  5612,     0,     0, 1 },  /* mtn */\n  {  5616,     0,     0, 1 },  /* mtpc */\n  {  5621,     0,     0, 1 },  /* mtr */\n  {  5627,  6423,     7, 1 },  /* mu */\n  {  5644,  6430,   548, 1 },  /* museum */\n  {  5663,     0,     0, 1 },  /* mutual */\n  {  5670,     0,     0, 1 },  /* mutuelle */\n  {  5679,  6978,    14, 1 },  /* mv */\n  {  1063,  6992,    11, 1 },  /* mw */\n  {  3604,  7003,     6, 1 },  /* mx */\n  {    70,  7009,     8, 1 },  /* my */\n  {  5687,  7017,     8, 1 },  /* mz */\n  {   172,  7025,    17, 1 },  /* na */\n  {  5704,     0,     0, 1 },  /* nab */\n  {  5708,     0,     0, 1 },  /* nadex */\n  {  5714,     0,     0, 1 },  /* nagoya */\n  {  5725,  2317,     2, 1 },  /* name */\n  {  5730,     0,     0, 1 },  /* nationwide */\n  {  5741,     0,     0, 1 },  /* natura */\n  {  5751,     0,     0, 1 },  /* navy */\n  {   688,     0,     0, 1 },  /* nba */\n  {  5521,  7043,     1, 1 },  /* nc */\n  {  1203,     0,     0, 1 },  /* ne */\n  {  5765,     0,     0, 1 },  /* nec */\n  {  4185,  2319,    78, 1 },  /* net */\n  {  5769,     0,     0, 1 },  /* netbank */\n  {  5777,     0,     0, 1 },  /* netflix */\n  {  3185,  2399,     1, 1 },  /* network */\n  {  5785,     0,     0, 1 },  /* neustar */\n  {  5793,     0,     0, 1 },  /* new */\n  {  5797,     0,     0, 1 },  /* newholland */\n  {  5808,     0,     0, 1 },  /* news */\n  {  5813,     0,     0, 1 },  /* next */\n  {  2410,     0,     0, 1 },  /* nextdirect */\n  {  5818,     0,     0, 1 },  /* nexus */\n  {  5825,  7050,    10, 1 },  /* nf */\n  {  5828,     0,     0, 1 },  /* nfl */\n  {   971,  2400,    10, 1 },  /* ng */\n  {   976,     0,     0, 1 },  /* ngo */\n  {  3939,     0,     0, 1 },  /* nhk */\n  {  1722,  7060,    14, 1 },  /* ni */\n  {  5846,     0,     0, 1 },  /* nico */\n  {  5851,     0,     0, 1 },  /* nike */\n  {  5856,     0,     0, 1 },  /* nikon */\n  {  5862,     0,     0, 1 },  /* ninja */\n  {  5868,     0,     0, 1 },  /* nissan */\n  {  5875,     0,     0, 1 },  /* nissay */\n  {  1071,  2410,     5, 1 },  /* nl */\n  {  1517,  2415,   726, 1 },  /* no */\n  {  4589,     0,     0, 1 },  /* nokia */\n  {  5651,     0,     0, 1 },  /* northwesternmutual */\n  {  5887,     0,     0, 1 },  /* norton */\n  {  5894,     0,     0, 1 },  /* now */\n  {  5898,     0,     0, 1 },  /* nowruz */\n  {  5905,     0,     0, 1 },  /* nowtv */\n  {  2478,  3687,     1, 0 },  /* np */\n  {  5912,  6243,     7, 1 },  /* nr */\n  {  5917,     0,     0, 1 },  /* nra */\n  {  5921,     0,     0, 1 },  /* nrw */\n  {  5925,     0,     0, 1 },  /* ntt */\n  {  5372,  7093,     3, 1 },  /* nu */\n  {  5933,     0,     0, 1 },  /* nyc */\n  {   325,  3141,    16, 1 },  /* nz */\n  {  5449,     0,     0, 1 },  /* obi */\n  {  5942,     0,     0, 1 },  /* observer */\n  {  5951,     0,     0, 1 },  /* off */\n  {  5959,     0,     0, 1 },  /* office */\n  {  5966,     0,     0, 1 },  /* okinawa */\n  {  5974,     0,     0, 1 },  /* olayan */\n  {  5981,     0,     0, 1 },  /* olayangroup */\n  {  5748,     0,     0, 1 },  /* oldnavy */\n  {  5993,     0,     0, 1 },  /* ollo */\n  {   353,  7096,     9, 1 },  /* om */\n  {  6002,     0,     0, 1 },  /* omega */\n  {  1202,  7105,     1, 1 },  /* one */\n  {  6015,     0,     0, 1 },  /* ong */\n  {  6019,     0,     0, 1 },  /* onl */\n  {  6023,     0,     0, 1 },  /* online */\n  {  6030,     0,     0, 1 },  /* onyourside */\n  {  6041,     0,     0, 1 },  /* ooo */\n  {  6045,     0,     0, 1 },  /* open */\n  {  6050,     0,     0, 1 },  /* oracle */\n  {  6057,     0,     0, 1 },  /* orange */\n  {  6070,  3157,    90, 1 },  /* org */\n  {  6081,     0,     0, 1 },  /* organic */\n  {  2870,     0,     0, 1 },  /* orientexpress */\n  {  6089,     0,     0, 1 },  /* origins */\n  {  6098,     0,     0, 1 },  /* osaka */\n  {  6107,     0,     0, 1 },  /* otsuka */\n  {    23,     0,     0, 1 },  /* ott */\n  {  6114,  7167,     1, 1 },  /* ovh */\n  {   522,  7168,    11, 1 },  /* pa */\n  {  6118,     0,     0, 1 },  /* page */\n  {  6123,     0,     0, 1 },  /* pamperedchef */\n  {  6136,     0,     0, 1 },  /* panasonic */\n  {  6146,     0,     0, 1 },  /* panerai */\n  {  6154,     0,     0, 1 },  /* paris */\n  {  6160,     0,     0, 1 },  /* pars */\n  {  6165,     0,     0, 1 },  /* partners */\n  {  6174,     0,     0, 1 },  /* parts */\n  {  6180,  3961,     1, 1 },  /* party */\n  {  6186,     0,     0, 1 },  /* passagens */\n  {   314,     0,     0, 1 },  /* pay */\n  {  2179,     0,     0, 1 },  /* pccw */\n  {  3739,  7179,     8, 1 },  /* pe */\n  {  6196,     0,     0, 1 },  /* pet */\n  {  6200,  7187,     3, 1 },  /* pf */\n  {  6203,     0,     0, 1 },  /* pfizer */\n  {  6211,  3687,     1, 0 },  /* pg */\n  {  6214,  7190,     8, 1 },  /* ph */\n  {  6217,     0,     0, 1 },  /* pharmacy */\n  {  6226,     0,     0, 1 },  /* phd */\n  {  6230,     0,     0, 1 },  /* philips */\n  {  6008,     0,     0, 1 },  /* phone */\n  {  6238,     0,     0, 1 },  /* photo */\n  {  6244,     0,     0, 1 },  /* photography */\n  {  6258,     0,     0, 1 },  /* photos */\n  {  6265,     0,     0, 1 },  /* physio */\n  {  6272,     0,     0, 1 },  /* piaget */\n  {  6284,     0,     0, 1 },  /* pics */\n  {  6289,     0,     0, 1 },  /* pictet */\n  {  6296,     0,     0, 1 },  /* pictures */\n  {  6305,     0,     0, 1 },  /* pid */\n  {  5126,     0,     0, 1 },  /* pin */\n  {  6313,     0,     0, 1 },  /* ping */\n  {  4261,     0,     0, 1 },  /* pink */\n  {  6318,     0,     0, 1 },  /* pioneer */\n  {  6326,     0,     0, 1 },  /* pizza */\n  {  6332,  7198,    14, 1 },  /* pk */\n  {  5089,  3248,   166, 1 },  /* pl */\n  {  6340,     0,     0, 1 },  /* place */\n  {  6346,     0,     0, 1 },  /* play */\n  {  6351,     0,     0, 1 },  /* playstation */\n  {   965,     0,     0, 1 },  /* plumbing */\n  {  6365,     0,     0, 1 },  /* plus */\n  {  6370,     0,     0, 1 },  /* pm */\n  {  4674,  7259,     5, 1 },  /* pn */\n  {  5756,     0,     0, 1 },  /* pnc */\n  {  6373,     0,     0, 1 },  /* pohl */\n  {  6378,     0,     0, 1 },  /* poker */\n  {  6384,     0,     0, 1 },  /* politie */\n  {  6392,     0,     0, 1 },  /* porn */\n  {   617,     0,     0, 1 },  /* post */\n  {  6402,  7264,    13, 1 },  /* pr */\n  {  6405,     0,     0, 1 },  /* pramerica */\n  {  6415,     0,     0, 1 },  /* praxi */\n  {   371,     0,     0, 1 },  /* press */\n  {  6421,     0,     0, 1 },  /* prime */\n  {  6427,  7277,    12, 1 },  /* pro */\n  {  6431,     0,     0, 1 },  /* prod */\n  {  6436,     0,     0, 1 },  /* productions */\n  {  6448,     0,     0, 1 },  /* prof */\n  {  6453,     0,     0, 1 },  /* progressive */\n  {  6465,     0,     0, 1 },  /* promo */\n  {  4564,     0,     0, 1 },  /* properties */\n  {  6471,     0,     0, 1 },  /* property */\n  {  6480,     0,     0, 1 },  /* protection */\n  {  6491,     0,     0, 1 },  /* pru */\n  {  6495,     0,     0, 1 },  /* prudential */\n  {  6235,  7289,     7, 1 },  /* ps */\n  {  6510,  7296,     9, 1 },  /* pt */\n  {  6513,     0,     0, 1 },  /* pub */\n  {  6517,  7305,     7, 1 },  /* pw */\n  {  6520,     0,     0, 1 },  /* pwc */\n  {  6525,  7312,     7, 1 },  /* py */\n  {  6539,  7319,     9, 1 },  /* qa */\n  {  6542,     0,     0, 1 },  /* qpon */\n  {  6547,     0,     0, 1 },  /* quebec */\n  {  6554,     0,     0, 1 },  /* quest */\n  {  6560,     0,     0, 1 },  /* qvc */\n  {  6564,     0,     0, 1 },  /* racing */\n  {  6571,     0,     0, 1 },  /* radio */\n  {  6577,     0,     0, 1 },  /* raid */\n  {    80,  7328,     4, 1 },  /* re */\n  {  6594,     0,     0, 1 },  /* read */\n  {  2765,     0,     0, 1 },  /* realestate */\n  {  6599,     0,     0, 1 },  /* realtor */\n  {  6607,     0,     0, 1 },  /* realty */\n  {  6614,     0,     0, 1 },  /* recipes */\n  {  4687,     0,     0, 1 },  /* red */\n  {  6622,     0,     0, 1 },  /* redstone */\n  {  6631,     0,     0, 1 },  /* redumbrella */\n  {  6643,     0,     0, 1 },  /* rehab */\n  {  6649,     0,     0, 1 },  /* reise */\n  {  6655,     0,     0, 1 },  /* reisen */\n  {  6662,     0,     0, 1 },  /* reit */\n  {  6667,     0,     0, 1 },  /* reliance */\n  {  6678,     0,     0, 1 },  /* ren */\n  {  6691,     0,     0, 1 },  /* rent */\n  {  6696,     0,     0, 1 },  /* rentals */\n  {  6704,     0,     0, 1 },  /* repair */\n  {  6711,     0,     0, 1 },  /* report */\n  {  6723,     0,     0, 1 },  /* republican */\n  {  6734,     0,     0, 1 },  /* rest */\n  {  6739,     0,     0, 1 },  /* restaurant */\n  {  6750,  3961,     1, 1 },  /* review */\n  {  6757,     0,     0, 1 },  /* reviews */\n  {  6765,     0,     0, 1 },  /* rexroth */\n  {  6776,     0,     0, 1 },  /* rich */\n  {  6781,     0,     0, 1 },  /* richardli */\n  {  6791,     0,     0, 1 },  /* ricoh */\n  {  6797,     0,     0, 1 },  /* rightathome */\n  {  6809,     0,     0, 1 },  /* ril */\n  {  6817,     0,     0, 1 },  /* rio */\n  {  6829,     0,     0, 1 },  /* rip */\n  {  5417,     0,     0, 1 },  /* rmit */\n  {   166,  7332,    13, 1 },  /* ro */\n  {  6833,     0,     0, 1 },  /* rocher */\n  {  6840,     0,     0, 1 },  /* rocks */\n  {  6846,     0,     0, 1 },  /* rodeo */\n  {  6852,     0,     0, 1 },  /* rogers */\n  {  6859,     0,     0, 1 },  /* room */\n  {  1272,  7345,     7, 1 },  /* rs */\n  {  6864,     0,     0, 1 },  /* rsvp */\n  {  2190,  7352,     7, 1 },  /* ru */\n  {  4116,     0,     0, 1 },  /* ruhr */\n  {  6869,     0,     0, 1 },  /* run */\n  {  5922,  7359,     9, 1 },  /* rw */\n  {  6873,     0,     0, 1 },  /* rwe */\n  {  6877,     0,     0, 1 },  /* ryukyu */\n  {  1493,  7368,     8, 1 },  /* sa */\n  {  6888,     0,     0, 1 },  /* saarland */\n  {  6897,     0,     0, 1 },  /* safe */\n  {  6902,     0,     0, 1 },  /* safety */\n  {  6909,     0,     0, 1 },  /* sakura */\n  {  3218,     0,     0, 1 },  /* sale */\n  {  6916,     0,     0, 1 },  /* salon */\n  {  6922,     0,     0, 1 },  /* samsclub */\n  {  6931,     0,     0, 1 },  /* samsung */\n  {  6939,     0,     0, 1 },  /* sandvik */\n  {  6947,     0,     0, 1 },  /* sandvikcoromant */\n  {  3005,     0,     0, 1 },  /* sanofi */\n  {  6963,     0,     0, 1 },  /* sap */\n  {  6967,     0,     0, 1 },  /* sapo */\n  {  6972,     0,     0, 1 },  /* sarl */\n  {  6977,     0,     0, 1 },  /* sas */\n  {  6981,     0,     0, 1 },  /* save */\n  {  6986,     0,     0, 1 },  /* saxo */\n  {  6991,  3651,     5, 1 },  /* sb */\n  {   946,     0,     0, 1 },  /* sbi */\n  {  6994,     0,     0, 1 },  /* sbs */\n  {  2158,  3651,     5, 1 },  /* sc */\n  {  7002,     0,     0, 1 },  /* sca */\n  {  7006,     0,     0, 1 },  /* scb */\n  {  7010,     0,     0, 1 },  /* schaeffler */\n  {  7021,     0,     0, 1 },  /* schmidt */\n  {  7029,     0,     0, 1 },  /* scholarships */\n  {  7042,     0,     0, 1 },  /* school */\n  {  7049,     0,     0, 1 },  /* schule */\n  {  7056,     0,     0, 1 },  /* schwarz */\n  {  7073,  3961,     1, 1 },  /* science */\n  {  7081,     0,     0, 1 },  /* scjohnson */\n  {  7091,     0,     0, 1 },  /* scor */\n  {  7096,     0,     0, 1 },  /* scot */\n  {  5381,  7376,     8, 1 },  /* sd */\n  {  1498,  7384,    41, 1 },  /* se */\n  {  1385,     0,     0, 1 },  /* search */\n  {  2603,     0,     0, 1 },  /* seat */\n  {  7120,     0,     0, 1 },  /* secure */\n  {  7127,     0,     0, 1 },  /* security */\n  {  7136,     0,     0, 1 },  /* seek */\n  {  4365,     0,     0, 1 },  /* select */\n  {  7141,     0,     0, 1 },  /* sener */\n  {  7147,     0,     0, 1 },  /* services */\n  {  2087,     0,     0, 1 },  /* ses */\n  {  7156,     0,     0, 1 },  /* seven */\n  {  7162,     0,     0, 1 },  /* sew */\n  {  7168,     0,     0, 1 },  /* sex */\n  {  7172,     0,     0, 1 },  /* sexy */\n  {  3244,     0,     0, 1 },  /* sfr */\n  {  7192,  7425,     7, 1 },  /* sg */\n  {  1510,  3414,     8, 1 },  /* sh */\n  {  7195,     0,     0, 1 },  /* shangrila */\n  {  7205,     0,     0, 1 },  /* sharp */\n  {  7211,     0,     0, 1 },  /* shaw */\n  {  7216,     0,     0, 1 },  /* shell */\n  {  7222,     0,     0, 1 },  /* shia */\n  {  7227,     0,     0, 1 },  /* shiksha */\n  {  7235,     0,     0, 1 },  /* shoes */\n  {  7245,     0,     0, 1 },  /* shop */\n  {  6309,     0,     0, 1 },  /* shopping */\n  {  7250,     0,     0, 1 },  /* shouji */\n  {  4111,     0,     0, 1 },  /* show */\n  {  7257,     0,     0, 1 },  /* showtime */\n  {  7266,     0,     0, 1 },  /* shriram */\n  {  2364,  3672,     1, 1 },  /* si */\n  {  7278,     0,     0, 1 },  /* silk */\n  {  7286,     0,     0, 1 },  /* sina */\n  {  7291,     0,     0, 1 },  /* singles */\n  {  7303,  7432,     1, 1 },  /* site */\n  {  7308,     0,     0, 1 },  /* sj */\n  {  7312,  3672,     1, 1 },  /* sk */\n  {  4585,     0,     0, 1 },  /* ski */\n  {  7315,     0,     0, 1 },  /* skin */\n  {  4704,     0,     0, 1 },  /* sky */\n  {  7320,     0,     0, 1 },  /* skype */\n  {  7327,  3651,     5, 1 },  /* sl */\n  {  4255,     0,     0, 1 },  /* sling */\n  {  7331,     0,     0, 1 },  /* sm */\n  {   525,     0,     0, 1 },  /* smart */\n  {  7334,     0,     0, 1 },  /* smile */\n  {  7341,  7433,     8, 1 },  /* sn */\n  {  1609,     0,     0, 1 },  /* sncf */\n  {  7345,  7441,     3, 1 },  /* so */\n  {  7348,     0,     0, 1 },  /* soccer */\n  {  7355,     0,     0, 1 },  /* social */\n  {  7362,     0,     0, 1 },  /* softbank */\n  {  7371,     0,     0, 1 },  /* software */\n  {  4136,     0,     0, 1 },  /* sohu */\n  {  7380,     0,     0, 1 },  /* solar */\n  {  7386,     0,     0, 1 },  /* solutions */\n  {  6014,     0,     0, 1 },  /* song */\n  {  7396,     0,     0, 1 },  /* sony */\n  {  7403,     0,     0, 1 },  /* soy */\n  {  2889,  7444,     1, 1 },  /* space */\n  {  7407,     0,     0, 1 },  /* spiegel */\n  {  7418,     0,     0, 1 },  /* spot */\n  {  7423,     0,     0, 1 },  /* spreadbetting */\n  {  7437,     0,     0, 1 },  /* sr */\n  {  7440,     0,     0, 1 },  /* srl */\n  {  7444,     0,     0, 1 },  /* srt */\n  {   619,  7445,    12, 1 },  /* st */\n  {  7452,     0,     0, 1 },  /* stada */\n  {  7458,     0,     0, 1 },  /* staples */\n  {  5588,     0,     0, 1 },  /* star */\n  {  7466,     0,     0, 1 },  /* starhub */\n  {  7474,     0,     0, 1 },  /* statebank */\n  {  2943,     0,     0, 1 },  /* statefarm */\n  {  7484,     0,     0, 1 },  /* statoil */\n  {  7492,     0,     0, 1 },  /* stc */\n  {  3750,     0,     0, 1 },  /* stcgroup */\n  {  7496,     0,     0, 1 },  /* stockholm */\n  {  7506,     0,     0, 1 },  /* storage */\n  {  7514,     0,     0, 1 },  /* store */\n  {  7520,     0,     0, 1 },  /* stream */\n  {  7527,     0,     0, 1 },  /* studio */\n  {  7534,     0,     0, 1 },  /* study */\n  {  4941,     0,     0, 1 },  /* style */\n  {  3310,  7457,    32, 1 },  /* su */\n  {  7545,     0,     0, 1 },  /* sucks */\n  {  7551,     0,     0, 1 },  /* supplies */\n  {  7560,     0,     0, 1 },  /* supply */\n  {  7567,     0,     0, 1 },  /* support */\n  {  7575,     0,     0, 1 },  /* surf */\n  {  7580,     0,     0, 1 },  /* surgery */\n  {  7588,     0,     0, 1 },  /* suzuki */\n  {  7595,  7489,     5, 1 },  /* sv */\n  {  7598,     0,     0, 1 },  /* swatch */\n  {  7605,     0,     0, 1 },  /* swiftcover */\n  {  7616,     0,     0, 1 },  /* swiss */\n  {  7625,  3685,     1, 1 },  /* sx */\n  {  5006,  3549,     6, 1 },  /* sy */\n  {  7628,     0,     0, 1 },  /* sydney */\n  {  7635,     0,     0, 1 },  /* symantec */\n  {  7644,  7494,     1, 1 },  /* systems */\n  {  7654,  7495,     3, 1 },  /* sz */\n  {  7657,     0,     0, 1 },  /* tab */\n  {  7661,     0,     0, 1 },  /* taipei */\n  {  7680,     0,     0, 1 },  /* talk */\n  {  7685,     0,     0, 1 },  /* taobao */\n  {  7692,     0,     0, 1 },  /* target */\n  {  7699,     0,     0, 1 },  /* tatamotors */\n  {  7710,     0,     0, 1 },  /* tatar */\n  {  7716,     0,     0, 1 },  /* tattoo */\n  {   662,     0,     0, 1 },  /* tax */\n  {  7723,     0,     0, 1 },  /* taxi */\n  {  4133,     0,     0, 1 },  /* tc */\n  {  1712,     0,     0, 1 },  /* tci */\n  {  5104,  3672,     1, 1 },  /* td */\n  {  2469,     0,     0, 1 },  /* tdk */\n  {  7733,     0,     0, 1 },  /* team */\n  {  1622,     0,     0, 1 },  /* tech */\n  {  7738,     0,     0, 1 },  /* technology */\n  {   279,     0,     0, 1 },  /* tel */\n  {  7755,     0,     0, 1 },  /* telecity */\n  {  7764,     0,     0, 1 },  /* telefonica */\n  {  7775,     0,     0, 1 },  /* temasek */\n  {  7783,     0,     0, 1 },  /* tennis */\n  {  7790,     0,     0, 1 },  /* teva */\n  {  7796,     0,     0, 1 },  /* tf */\n  {  7799,     0,     0, 1 },  /* tg */\n  {    13,  7498,     7, 1 },  /* th */\n  {  7806,     0,     0, 1 },  /* thd */\n  {  7810,     0,     0, 1 },  /* theater */\n  {  7818,     0,     0, 1 },  /* theatre */\n  {  3771,     0,     0, 1 },  /* theguardian */\n  {  7826,     0,     0, 1 },  /* tiaa */\n  {  7831,     0,     0, 1 },  /* tickets */\n  {  7839,     0,     0, 1 },  /* tienda */\n  {  7846,     0,     0, 1 },  /* tiffany */\n  {  7854,     0,     0, 1 },  /* tips */\n  {  7859,     0,     0, 1 },  /* tires */\n  {  7874,     0,     0, 1 },  /* tirol */\n  {  7880,  7505,    15, 1 },  /* tj */\n  {  7883,     0,     0, 1 },  /* tjmaxx */\n  {  7890,     0,     0, 1 },  /* tjx */\n  {  7894,     0,     0, 1 },  /* tk */\n  {  7897,     0,     0, 1 },  /* tkmaxx */\n  {  7906,  3685,     1, 1 },  /* tl */\n  {  7910,  7520,     8, 1 },  /* tm */\n  {  7913,     0,     0, 1 },  /* tmall */\n  {  5613,  7528,    20, 1 },  /* tn */\n  {   631,  3549,     6, 1 },  /* to */\n  {  2259,     0,     0, 1 },  /* today */\n  {  7924,     0,     0, 1 },  /* tokyo */\n  {  7930,     0,     0, 1 },  /* tools */\n  {  7936,     0,     0, 1 },  /* top */\n  {  7940,     0,     0, 1 },  /* toray */\n  {  7946,     0,     0, 1 },  /* toshiba */\n  {  7954,     0,     0, 1 },  /* total */\n  {  7960,     0,     0, 1 },  /* tours */\n  {  1402,     0,     0, 1 },  /* town */\n  {  7966,     0,     0, 1 },  /* toyota */\n  {  7973,     0,     0, 1 },  /* toys */\n  {  3302,  3422,    21, 1 },  /* tr */\n  {  7982,  3961,     1, 1 },  /* trade */\n  {  7988,     0,     0, 1 },  /* trading */\n  {  7996,     0,     0, 1 },  /* training */\n  {  8005,     0,     0, 1 },  /* travel */\n  {  1634,     0,     0, 1 },  /* travelchannel */\n  {  8012,     0,     0, 1 },  /* travelers */\n  {  8022,     0,     0, 1 },  /* travelersinsurance */\n  {  8041,     0,     0, 1 },  /* trust */\n  {  8047,     0,     0, 1 },  /* trv */\n  {    24,  7548,    17, 1 },  /* tt */\n  {  8058,     0,     0, 1 },  /* tube */\n  {  8063,     0,     0, 1 },  /* tui */\n  {  8067,     0,     0, 1 },  /* tunes */\n  {  8073,     0,     0, 1 },  /* tushu */\n  {  2546,  7565,     4, 1 },  /* tv */\n  {  8079,     0,     0, 1 },  /* tvs */\n  {  8083,  7569,    14, 1 },  /* tw */\n  {  8091,  7583,    12, 1 },  /* tz */\n  {  8097,  7595,    82, 1 },  /* ua */\n  {   730,     0,     0, 1 },  /* ubank */\n  {  8100,     0,     0, 1 },  /* ubs */\n  {  8104,     0,     0, 1 },  /* uconnect */\n  {  8114,  7677,     9, 1 },  /* ug */\n  {  8122,  3443,    11, 1 },  /* uk */\n  {  8125,     0,     0, 1 },  /* unicom */\n  {  8132,     0,     0, 1 },  /* university */\n  {  8146,     0,     0, 1 },  /* uno */\n  {  8150,     0,     0, 1 },  /* uol */\n  {  6506,     0,     0, 1 },  /* ups */\n  {   264,  3454,    68, 1 },  /* us */\n  {   911,  3525,     6, 1 },  /* uy */\n  {  5902,  7700,     4, 1 },  /* uz */\n  {   834,     0,     0, 1 },  /* va */\n  {  8163,     0,     0, 1 },  /* vacations */\n  {  8173,     0,     0, 1 },  /* vana */\n  {  8178,     0,     0, 1 },  /* vanguard */\n  {  6561,  3549,     6, 1 },  /* vc */\n  {   125,  7704,    17, 1 },  /* ve */\n  {  8187,     0,     0, 1 },  /* vegas */\n  {  8193,     0,     0, 1 },  /* ventures */\n  {  8202,     0,     0, 1 },  /* verisign */\n  {  8211,     0,     0, 1 },  /* versicherung */\n  {  8229,     0,     0, 1 },  /* vet */\n  {  8234,     0,     0, 1 },  /* vg */\n  {  8237,  7721,     5, 1 },  /* vi */\n  {  8240,     0,     0, 1 },  /* viajes */\n  {  8247,     0,     0, 1 },  /* video */\n  {  8253,     0,     0, 1 },  /* vig */\n  {  8257,     0,     0, 1 },  /* viking */\n  {  8264,     0,     0, 1 },  /* villas */\n  {  8275,     0,     0, 1 },  /* vin */\n  {  8279,     0,     0, 1 },  /* vip */\n  {  8283,     0,     0, 1 },  /* virgin */\n  {  8290,     0,     0, 1 },  /* visa */\n  {  2805,     0,     0, 1 },  /* vision */\n  {  8306,     0,     0, 1 },  /* vista */\n  {  8312,     0,     0, 1 },  /* vistaprint */\n  {  8323,     0,     0, 1 },  /* viva */\n  {  8328,     0,     0, 1 },  /* vivo */\n  {  8333,     0,     0, 1 },  /* vlaanderen */\n  {  8352,  7726,    13, 1 },  /* vn */\n  {  8355,     0,     0, 1 },  /* vodka */\n  {  8361,     0,     0, 1 },  /* volkswagen */\n  {  8372,     0,     0, 1 },  /* volvo */\n  {  8378,     0,     0, 1 },  /* vote */\n  {  8383,     0,     0, 1 },  /* voting */\n  {  8390,     0,     0, 1 },  /* voto */\n  {  8395,     0,     0, 1 },  /* voyage */\n  {  8402,  3903,     4, 1 },  /* vu */\n  {  8405,     0,     0, 1 },  /* vuelos */\n  {  8412,     0,     0, 1 },  /* wales */\n  {  8418,     0,     0, 1 },  /* walmart */\n  {  8426,     0,     0, 1 },  /* walter */\n  {  8433,     0,     0, 1 },  /* wang */\n  {  8438,     0,     0, 1 },  /* wanggou */\n  {  8446,     0,     0, 1 },  /* warman */\n  {  7599,     0,     0, 1 },  /* watch */\n  {  8453,     0,     0, 1 },  /* watches */\n  {  8461,     0,     0, 1 },  /* weather */\n  {  8469,     0,     0, 1 },  /* weatherchannel */\n  {  1340,     0,     0, 1 },  /* webcam */\n  {  8484,     0,     0, 1 },  /* weber */\n  {  8493,     0,     0, 1 },  /* website */\n  {  8501,     0,     0, 1 },  /* wed */\n  {  8505,     0,     0, 1 },  /* wedding */\n  {  8513,     0,     0, 1 },  /* weibo */\n  {  8519,     0,     0, 1 },  /* weir */\n  {  8524,     0,     0, 1 },  /* wf */\n  {  8527,     0,     0, 1 },  /* whoswho */\n  {  8535,     0,     0, 1 },  /* wien */\n  {  8547,     0,     0, 1 },  /* wiki */\n  {  8552,     0,     0, 1 },  /* williamhill */\n  {  8564,     0,     0, 1 },  /* win */\n  {  8568,     0,     0, 1 },  /* windows */\n  {  8576,     0,     0, 1 },  /* wine */\n  {  8581,     0,     0, 1 },  /* winners */\n  {  5323,     0,     0, 1 },  /* wme */\n  {  8589,     0,     0, 1 },  /* wolterskluwer */\n  {  8603,     0,     0, 1 },  /* woodside */\n  {  3188,     0,     0, 1 },  /* work */\n  {  8612,     0,     0, 1 },  /* works */\n  {  8618,     0,     0, 1 },  /* world */\n  {  8624,     0,     0, 1 },  /* wow */\n  {   659,  7739,     7, 1 },  /* ws */\n  {  8628,     0,     0, 1 },  /* wtc */\n  {  7795,     0,     0, 1 },  /* wtf */\n  {  1176,     0,     0, 1 },  /* xbox */\n  {  3317,     0,     0, 1 },  /* xerox */\n  {  8632,     0,     0, 1 },  /* xfinity */\n  {  8640,     0,     0, 1 },  /* xihuan */\n  {  8647,     0,     0, 1 },  /* xin */\n  {  8651,     0,     0, 1 },  /* xn--11b4c3d */\n  {  8663,     0,     0, 1 },  /* xn--1ck2e1b */\n  {  8675,     0,     0, 1 },  /* xn--1qqw23a */\n  {  8687,     0,     0, 1 },  /* xn--30rr7y */\n  {  8698,     0,     0, 1 },  /* xn--3bst00m */\n  {  8710,     0,     0, 1 },  /* xn--3ds443g */\n  {  8722,     0,     0, 1 },  /* xn--3e0b707e */\n  {  8735,     0,     0, 1 },  /* xn--3oq18vl8pn36a */\n  {  8753,     0,     0, 1 },  /* xn--3pxu8k */\n  {  8764,     0,     0, 1 },  /* xn--42c2d9a */\n  {  8776,     0,     0, 1 },  /* xn--45brj9c */\n  {  8788,     0,     0, 1 },  /* xn--45q11c */\n  {  8799,     0,     0, 1 },  /* xn--4gbrim */\n  {  8810,     0,     0, 1 },  /* xn--4gq48lf9j */\n  {  8824,     0,     0, 1 },  /* xn--54b7fta0cc */\n  {  8839,     0,     0, 1 },  /* xn--55qw42g */\n  {  8851,     0,     0, 1 },  /* xn--55qx5d */\n  {  7177,     0,     0, 1 },  /* xn--5su34j936bgsg */\n  {  8862,     0,     0, 1 },  /* xn--5tzm5g */\n  {  8873,     0,     0, 1 },  /* xn--6frz82g */\n  {  8885,     0,     0, 1 },  /* xn--6qq986b3xl */\n  {  8900,     0,     0, 1 },  /* xn--80adxhks */\n  {  8913,     0,     0, 1 },  /* xn--80ao21a */\n  {  8925,     0,     0, 1 },  /* xn--80aqecdr1a */\n  {  8940,     0,     0, 1 },  /* xn--80asehdb */\n  {  8953,     0,     0, 1 },  /* xn--80aswg */\n  {  8964,     0,     0, 1 },  /* xn--8y0a063a */\n  {  8977,  7746,     6, 1 },  /* xn--90a3ac */\n  {  8988,     0,     0, 1 },  /* xn--90ais */\n  {  8998,     0,     0, 1 },  /* xn--9dbq2a */\n  {  9009,     0,     0, 1 },  /* xn--9et52u */\n  {  9020,     0,     0, 1 },  /* xn--9krt00a */\n  {  9032,     0,     0, 1 },  /* xn--b4w605ferd */\n  {  9047,     0,     0, 1 },  /* xn--bck1b9a5dre4c */\n  {  9065,     0,     0, 1 },  /* xn--c1avg */\n  {  9075,     0,     0, 1 },  /* xn--c2br7g */\n  {  9086,     0,     0, 1 },  /* xn--cck2b3b */\n  {  9098,     0,     0, 1 },  /* xn--cg4bki */\n  {  9109,     0,     0, 1 },  /* xn--clchc0ea0b2g2a9gcd */\n  {  9132,     0,     0, 1 },  /* xn--czr694b */\n  {  9144,     0,     0, 1 },  /* xn--czrs0t */\n  {  9155,     0,     0, 1 },  /* xn--czru2d */\n  {  9166,     0,     0, 1 },  /* xn--d1acj3b */\n  {  9178,     0,     0, 1 },  /* xn--d1alf */\n  {  9188,     0,     0, 1 },  /* xn--e1a4c */\n  {  9198,     0,     0, 1 },  /* xn--eckvdtc9d */\n  {  9212,     0,     0, 1 },  /* xn--efvy88h */\n  {  9224,     0,     0, 1 },  /* xn--estv75g */\n  {  9236,     0,     0, 1 },  /* xn--fct429k */\n  {  9248,     0,     0, 1 },  /* xn--fhbei */\n  {  9258,     0,     0, 1 },  /* xn--fiq228c5hs */\n  {  9273,     0,     0, 1 },  /* xn--fiq64b */\n  {  9284,     0,     0, 1 },  /* xn--fiqs8s */\n  {  9295,     0,     0, 1 },  /* xn--fiqz9s */\n  {  9306,     0,     0, 1 },  /* xn--fjq720a */\n  {  9318,     0,     0, 1 },  /* xn--flw351e */\n  {  9330,     0,     0, 1 },  /* xn--fpcrj9c3d */\n  {  9344,     0,     0, 1 },  /* xn--fzc2c9e2c */\n  {  3576,     0,     0, 1 },  /* xn--fzys8d69uvgm */\n  {  9358,     0,     0, 1 },  /* xn--g2xx48c */\n  {  9370,     0,     0, 1 },  /* xn--gckr3f0f */\n  {  9383,     0,     0, 1 },  /* xn--gecrj9c */\n  {  9395,     0,     0, 1 },  /* xn--gk3at1e */\n  {  9407,     0,     0, 1 },  /* xn--h2brj9c */\n  {  9419,     0,     0, 1 },  /* xn--hxt814e */\n  {  9431,     0,     0, 1 },  /* xn--i1b6b1a6a2e */\n  {  9447,     0,     0, 1 },  /* xn--imr513n */\n  {  9459,     0,     0, 1 },  /* xn--io0a7i */\n  {  9470,     0,     0, 1 },  /* xn--j1aef */\n  {  5384,     0,     0, 1 },  /* xn--j1amh */\n  {  9480,     0,     0, 1 },  /* xn--j6w193g */\n  {  9492,     0,     0, 1 },  /* xn--jlq61u9w7b */\n  {  9507,     0,     0, 1 },  /* xn--jvr189m */\n  {  9519,     0,     0, 1 },  /* xn--kcrx77d1x4a */\n  {  9535,     0,     0, 1 },  /* xn--kprw13d */\n  {  9547,     0,     0, 1 },  /* xn--kpry57d */\n  {  9559,     0,     0, 1 },  /* xn--kpu716f */\n  {  9571,     0,     0, 1 },  /* xn--kput3i */\n  {  1572,     0,     0, 1 },  /* xn--l1acc */\n  {  9582,     0,     0, 1 },  /* xn--lgbbat1ad8j */\n  {  9598,     0,     0, 1 },  /* xn--mgb2ddes */\n  {   918,     0,     0, 1 },  /* xn--mgb9awbf */\n  {  9611,     0,     0, 1 },  /* xn--mgba3a3ejt */\n  {  9626,     0,     0, 1 },  /* xn--mgba3a4f16a */\n  {  9642,     0,     0, 1 },  /* xn--mgba3a4fra */\n  {  9657,     0,     0, 1 },  /* xn--mgba7c0bbn0a */\n  {  9674,     0,     0, 1 },  /* xn--mgbaakc7dvf */\n  {  9690,     0,     0, 1 },  /* xn--mgbaam7a8h */\n  {   845,     0,     0, 1 },  /* xn--mgbab2bd */\n  {  9705,     0,     0, 1 },  /* xn--mgbai9a5eva00b */\n  {  9724,     0,     0, 1 },  /* xn--mgbai9azgqp6j */\n  {  9742,     0,     0, 1 },  /* xn--mgbayh7gpa */\n  {  9757,     0,     0, 1 },  /* xn--mgbb9fbpob */\n  {  9772,     0,     0, 1 },  /* xn--mgbbh1a71e */\n  {  9787,     0,     0, 1 },  /* xn--mgbc0a9azcg */\n  {  9803,     0,     0, 1 },  /* xn--mgbca7dzdo */\n  {  9818,     0,     0, 1 },  /* xn--mgberp4a5d4a87g */\n  {  9838,     0,     0, 1 },  /* xn--mgberp4a5d4ar */\n  {  9856,     0,     0, 1 },  /* xn--mgbi4ecexp */\n  {  9871,     0,     0, 1 },  /* xn--mgbpl2fh */\n  {  9884,     0,     0, 1 },  /* xn--mgbqly7c0a67fbc */\n  {  9904,     0,     0, 1 },  /* xn--mgbqly7cvafr */\n  {  9921,     0,     0, 1 },  /* xn--mgbt3dhd */\n  {  9934,     0,     0, 1 },  /* xn--mgbtf8fl */\n  {  9947,     0,     0, 1 },  /* xn--mgbtx2b */\n  {  9959,     0,     0, 1 },  /* xn--mgbx4cd0ab */\n  {  9974,     0,     0, 1 },  /* xn--mix082f */\n  {  9986,     0,     0, 1 },  /* xn--mix891f */\n  {  9998,     0,     0, 1 },  /* xn--mk1bu44c */\n  { 10011,     0,     0, 1 },  /* xn--mxtq1m */\n  { 10022,     0,     0, 1 },  /* xn--ngbc5azd */\n  { 10035,     0,     0, 1 },  /* xn--ngbe9e0a */\n  { 10048,     0,     0, 1 },  /* xn--ngbrx */\n  { 10058,     0,     0, 1 },  /* xn--nnx388a */\n  { 10070,     0,     0, 1 },  /* xn--node */\n  { 10079,     0,     0, 1 },  /* xn--nqv7f */\n  { 10089,     0,     0, 1 },  /* xn--nqv7fs00ema */\n  { 10105,     0,     0, 1 },  /* xn--nyqy26a */\n  { 10117,     0,     0, 1 },  /* xn--o3cw4h */\n  { 10128,     0,     0, 1 },  /* xn--ogbpf8fl */\n  { 10141,     0,     0, 1 },  /* xn--p1acf */\n  { 10151,     0,     0, 1 },  /* xn--p1ai */\n  { 10160,     0,     0, 1 },  /* xn--pbt977c */\n  { 10172,     0,     0, 1 },  /* xn--pgbs0dh */\n  { 10184,     0,     0, 1 },  /* xn--pssy2u */\n  { 10195,     0,     0, 1 },  /* xn--q9jyb4c */\n  {  5297,     0,     0, 1 },  /* xn--qcka1pmc */\n  { 10207,     0,     0, 1 },  /* xn--qxam */\n  { 10216,     0,     0, 1 },  /* xn--rhqv96g */\n  { 10228,     0,     0, 1 },  /* xn--rovu88b */\n  { 10240,     0,     0, 1 },  /* xn--s9brj9c */\n  { 10252,     0,     0, 1 },  /* xn--ses554g */\n  { 10264,     0,     0, 1 },  /* xn--t60b56a */\n  { 10276,     0,     0, 1 },  /* xn--tckwe */\n  { 10286,     0,     0, 1 },  /* xn--tiq49xqyj */\n  { 10300,     0,     0, 1 },  /* xn--unup4y */\n  { 10311,     0,     0, 1 },  /* xn--vermgensberater-ctb */\n  { 10335,     0,     0, 1 },  /* xn--vermgensberatung-pwb */\n  { 10360,     0,     0, 1 },  /* xn--vhquv */\n  { 10370,     0,     0, 1 },  /* xn--vuq861b */\n  { 10382,     0,     0, 1 },  /* xn--w4r85el8fhu5dnra */\n  { 10403,     0,     0, 1 },  /* xn--w4rs40l */\n  { 10415,     0,     0, 1 },  /* xn--wgbh1c */\n  { 10426,     0,     0, 1 },  /* xn--wgbl6a */\n  { 10437,     0,     0, 1 },  /* xn--xhq521b */\n  { 10449,     0,     0, 1 },  /* xn--xkc2al3hye2a */\n  { 10466,     0,     0, 1 },  /* xn--xkc2dl3a5ee0h */\n  { 10484,     0,     0, 1 },  /* xn--y9a3aq */\n  { 10495,     0,     0, 1 },  /* xn--yfro4i67o */\n  { 10509,     0,     0, 1 },  /* xn--ygbi2ammx */\n  { 10523,     0,     0, 1 },  /* xn--zfr164b */\n  { 10535,     0,     0, 1 },  /* xperia */\n  { 10542,     0,     0, 1 },  /* xxx */\n  { 10546,  7752,     1, 1 },  /* xyz */\n  { 10550,     0,     0, 1 },  /* yachts */\n  { 10557,     0,     0, 1 },  /* yahoo */\n  { 10563,     0,     0, 1 },  /* yamaxun */\n  { 10571,     0,     0, 1 },  /* yandex */\n  { 10578,  3687,     1, 0 },  /* ye */\n  { 10581,     0,     0, 1 },  /* yodobashi */\n  { 10599,     0,     0, 1 },  /* yoga */\n  { 10604,     0,     0, 1 },  /* yokohama */\n  {  2194,     0,     0, 1 },  /* you */\n  {  8055,     0,     0, 1 },  /* youtube */\n  { 10613,     0,     0, 1 },  /* yt */\n  { 10616,     0,     0, 1 },  /* yun */\n  {  6329,  3531,    17, 0 },  /* za */\n  { 10625,     0,     0, 1 },  /* zappos */\n  { 10632,     0,     0, 1 },  /* zara */\n  { 10637,     0,     0, 1 },  /* zero */\n  { 10642,     0,     0, 1 },  /* zip */\n  { 10646,     0,     0, 1 },  /* zippo */\n  { 10652,  7753,    11, 1 },  /* zm */\n  { 10658,  3548,     1, 1 },  /* zone */\n  {  6773,     0,     0, 1 },  /* zuerich */\n  { 10663,  3687,     1, 0 },  /* zw */\n  {  1913,  3672,     1, 1 },  /* com.ar */\n  {  2624,     0,     0, 1 },  /* edu.ar */\n  { 11325,     0,     0, 1 },  /* gob.ar */\n  {  3686,     0,     0, 1 },  /* gov.ar */\n  {  3632,     0,     0, 1 },  /* int.ar */\n  {  4195,     0,     0, 1 },  /* mil.ar */\n  {  4185,     0,     0, 1 },  /* net.ar */\n  {  6070,     0,     0, 1 },  /* org.ar */\n  { 11335,     0,     0, 1 },  /* tur.ar */\n  {    62,     0,     0, 1 },  /* ac.at */\n  {   985,     0,     0, 1 },  /* biz.at */\n  {   113,  3672,     1, 1 },  /* co.at */\n  {  4056,     0,     0, 1 },  /* futurehosting.at */\n  { 11375,     0,     0, 1 },  /* futuremailing.at */\n  { 11318,     0,     0, 1 },  /* gv.at */\n  {  3167,     0,     0, 1 },  /* info.at */\n  {   137,     0,     0, 1 },  /* or.at */\n  {  3163,  1572,     2, 0 },  /* ortsinfo.at */\n  { 11393,     0,     0, 1 },  /* priv.at */\n  {   397,  3687,     1, 0 },  /* ex.ortsinfo.at */\n  { 11403,  3687,     1, 0 },  /* kunden.ortsinfo.at */\n  {  2003,     0,     0, 1 },  /* act.au */\n  {  7340,     0,     0, 1 },  /* asn.au */\n  {  1913,  3672,     1, 1 },  /* com.au */\n  { 11412,     0,     0, 1 },  /* conf.au */\n  {  2624,  3688,     8, 1 },  /* edu.au */\n  {  3686,  3696,     5, 1 },  /* gov.au */\n  {   437,     0,     0, 1 },  /* id.au */\n  {  3167,     0,     0, 1 },  /* info.au */\n  {  4185,     0,     0, 1 },  /* net.au */\n  { 11417,     0,     0, 1 },  /* nsw.au */\n  {    97,     0,     0, 1 },  /* nt.au */\n  {  6070,     0,     0, 1 },  /* org.au */\n  { 11427,     0,     0, 1 },  /* oz.au */\n  { 11430,     0,     0, 1 },  /* qld.au */\n  {  1493,     0,     0, 1 },  /* sa.au */\n  {   536,     0,     0, 1 },  /* tas.au */\n  { 11435,     0,     0, 1 },  /* vic.au */\n  {  5971,     0,     0, 1 },  /* wa.au */\n  {    62,     0,     0, 1 },  /* ac.be */\n  { 10666,     0,     0, 1 },  /* blogspot.be */\n  { 11450,  3687,     1, 0 },  /* transurl.be */\n  {  2473,     0,     0, 1 },  /* adm.br */\n  { 11632,     0,     0, 1 },  /* adv.br */\n  {  3696,     0,     0, 1 },  /* agr.br */\n  {   358,     0,     0, 1 },  /* am.br */\n  { 11636,     0,     0, 1 },  /* arq.br */\n  {   527,     0,     0, 1 },  /* art.br */\n  { 11641,     0,     0, 1 },  /* ato.br */\n  {    18,     0,     0, 1 },  /* b.br */\n  {   980,     0,     0, 1 },  /* bio.br */\n  {  1034,     0,     0, 1 },  /* blog.br */\n  {  5319,     0,     0, 1 },  /* bmd.br */\n  {  4199,     0,     0, 1 },  /* cim.br */\n  {  5832,     0,     0, 1 },  /* cng.br */\n  { 11421,     0,     0, 1 },  /* cnt.br */\n  {  1913,  3672,     1, 1 },  /* com.br */\n  {  2047,     0,     0, 1 },  /* coop.br */\n  {  1866,     0,     0, 1 },  /* ecn.br */\n  {  2614,     0,     0, 1 },  /* eco.br */\n  {  2624,     0,     0, 1 },  /* edu.br */\n  {  5593,     0,     0, 1 },  /* emp.br */\n  { 11645,     0,     0, 1 },  /* eng.br */\n  { 11649,     0,     0, 1 },  /* esp.br */\n  {  7728,     0,     0, 1 },  /* etc.br */\n  { 11655,     0,     0, 1 },  /* eti.br */\n  {   493,     0,     0, 1 },  /* far.br */\n  { 11659,     0,     0, 1 },  /* flog.br */\n  {  3160,     0,     0, 1 },  /* fm.br */\n  { 11664,     0,     0, 1 },  /* fnd.br */\n  { 11668,     0,     0, 1 },  /* fot.br */\n  {  7448,     0,     0, 1 },  /* fst.br */\n  { 11469,     0,     0, 1 },  /* g12.br */\n  {  3485,     0,     0, 1 },  /* ggf.br */\n  {  3686,     0,     0, 1 },  /* gov.br */\n  { 11672,     0,     0, 1 },  /* imb.br */\n  { 11676,     0,     0, 1 },  /* ind.br */\n  {  5824,     0,     0, 1 },  /* inf.br */\n  { 11389,     0,     0, 1 },  /* jor.br */\n  {  8154,     0,     0, 1 },  /* jus.br */\n  {  2646,  3791,    27, 1 },  /* leg.br */\n  { 11680,     0,     0, 1 },  /* lel.br */\n  {  4206,     0,     0, 1 },  /* mat.br */\n  {  1858,     0,     0, 1 },  /* med.br */\n  {  4195,     0,     0, 1 },  /* mil.br */\n  {  1374,     0,     0, 1 },  /* mp.br */\n  { 11684,     0,     0, 1 },  /* mus.br */\n  {  4185,     0,     0, 1 },  /* net.br */\n  {  5998,  3687,     1, 0 },  /* nom.br */\n  { 11688,     0,     0, 1 },  /* not.br */\n  {  7978,     0,     0, 1 },  /* ntr.br */\n  {  2482,     0,     0, 1 },  /* odo.br */\n  {  6070,     0,     0, 1 },  /* org.br */\n  {  6210,     0,     0, 1 },  /* ppg.br */\n  {  6427,     0,     0, 1 },  /* pro.br */\n  {  6998,     0,     0, 1 },  /* psc.br */\n  {  7274,     0,     0, 1 },  /* psi.br */\n  {  7326,     0,     0, 1 },  /* qsl.br */\n  {  6571,     0,     0, 1 },  /* radio.br */\n  {  2608,     0,     0, 1 },  /* rec.br */\n  { 11692,     0,     0, 1 },  /* slg.br */\n  { 11696,     0,     0, 1 },  /* srv.br */\n  {  7723,     0,     0, 1 },  /* taxi.br */\n  { 11700,     0,     0, 1 },  /* teo.br */\n  { 11704,     0,     0, 1 },  /* tmp.br */\n  { 11708,     0,     0, 1 },  /* trd.br */\n  { 11335,     0,     0, 1 },  /* tur.br */\n  {  2546,     0,     0, 1 },  /* tv.br */\n  {  8229,     0,     0, 1 },  /* vet.br */\n  { 11712,     0,     0, 1 },  /* vlog.br */\n  {  8547,     0,     0, 1 },  /* wiki.br */\n  { 11717,     0,     0, 1 },  /* zlg.br */\n  {  1913,  3672,     1, 1 },  /* com.by */\n  {  3686,     0,     0, 1 },  /* gov.by */\n  {  4195,     0,     0, 1 },  /* mil.by */\n  {  6450,     0,     0, 1 },  /* of.by */\n  { 11844,  3687,     1, 0 },  /* magentosite.cloud */\n  { 11856,     0,     0, 1 },  /* myfusion.cloud */\n  { 11865,  3687,     1, 0 },  /* statics.cloud */\n  {    62,     0,     0, 1 },  /* ac.cn */\n  { 11875,     0,     0, 1 },  /* ah.cn */\n  {   989,     0,     0, 1 },  /* bj.cn */\n  {  1913,  1716,     1, 1 },  /* com.cn */\n  { 11509,     0,     0, 1 },  /* cq.cn */\n  {  2624,     0,     0, 1 },  /* edu.cn */\n  {  3112,     0,     0, 1 },  /* fj.cn */\n  {  3449,     0,     0, 1 },  /* gd.cn */\n  {  3686,     0,     0, 1 },  /* gov.cn */\n  {  3760,     0,     0, 1 },  /* gs.cn */\n  { 11515,     0,     0, 1 },  /* gx.cn */\n  { 11878,     0,     0, 1 },  /* gz.cn */\n  {  2515,     0,     0, 1 },  /* ha.cn */\n  { 11491,     0,     0, 1 },  /* hb.cn */\n  { 11572,     0,     0, 1 },  /* he.cn */\n  {   512,     0,     0, 1 },  /* hi.cn */\n  {  3940,     0,     0, 1 },  /* hk.cn */\n  {  2385,     0,     0, 1 },  /* hl.cn */\n  {  3954,     0,     0, 1 },  /* hn.cn */\n  { 11506,     0,     0, 1 },  /* jl.cn */\n  { 11512,     0,     0, 1 },  /* js.cn */\n  {  7891,     0,     0, 1 },  /* jx.cn */\n  {  4639,     0,     0, 1 },  /* ln.cn */\n  {  4195,     0,     0, 1 },  /* mil.cn */\n  {  3600,     0,     0, 1 },  /* mo.cn */\n  {  4185,     0,     0, 1 },  /* net.cn */\n  { 11902,     0,     0, 1 },  /* nm.cn */\n  { 11907,     0,     0, 1 },  /* nx.cn */\n  {  6070,     0,     0, 1 },  /* org.cn */\n  { 11500,     0,     0, 1 },  /* qh.cn */\n  {  2158,     0,     0, 1 },  /* sc.cn */\n  {  5381,     0,     0, 1 },  /* sd.cn */\n  {  1510,     0,     0, 1 },  /* sh.cn */\n  {  7341,     0,     0, 1 },  /* sn.cn */\n  {  7625,     0,     0, 1 },  /* sx.cn */\n  {  7880,     0,     0, 1 },  /* tj.cn */\n  {  8083,     0,     0, 1 },  /* tw.cn */\n  { 11910,     0,     0, 1 },  /* xj.cn */\n  {  8851,     0,     0, 1 },  /* xn--55qx5d.cn */\n  {  9459,     0,     0, 1 },  /* xn--io0a7i.cn */\n  { 11913,     0,     0, 1 },  /* xn--od0alg.cn */\n  { 11924,     0,     0, 1 },  /* xz.cn */\n  { 11930,     0,     0, 1 },  /* yn.cn */\n  { 11933,     0,     0, 1 },  /* zj.cn */\n  {   652,  1717,     3, 0 },  /* amazonaws.com.cn */\n  { 11936,  3878,     2, 0 },  /* cn-north-1.amazonaws.com.cn */\n  { 11947,  3687,     1, 0 },  /* compute.amazonaws.com.cn */\n  { 11955,  3687,     1, 0 },  /* elb.amazonaws.com.cn */\n  {  6175,     0,     0, 1 },  /* arts.co */\n  {  1913,  3672,     1, 1 },  /* com.co */\n  {  2624,     0,     0, 1 },  /* edu.co */\n  { 11959,     0,     0, 1 },  /* firm.co */\n  {  3686,     0,     0, 1 },  /* gov.co */\n  {  3167,     0,     0, 1 },  /* info.co */\n  {  3632,     0,     0, 1 },  /* int.co */\n  {  4195,     0,     0, 1 },  /* mil.co */\n  {  4185,     0,     0, 1 },  /* net.co */\n  {  5998,     0,     0, 1 },  /* nom.co */\n  {  6070,     0,     0, 1 },  /* org.co */\n  {  2608,     0,     0, 1 },  /* rec.co */\n  { 11967,     0,     0, 1 },  /* web.co */\n  {  5439,  3687,     1, 0 },  /* 0emm.com */\n  { 11971,     0,     0, 1 },  /* 1kapp.com */\n  { 11977,     0,     0, 1 },  /* 3utilities.com */\n  { 11996,     0,     0, 1 },  /* 4u.com */\n  {   217,     0,     0, 1 },  /* africa.com */\n  { 11999,     0,     0, 1 },  /* alpha-myqnapcloud.com */\n  {   652,  2006,    38, 1 },  /* amazonaws.com */\n  { 12017,     0,     0, 1 },  /* appchizi.com */\n  { 12026,     0,     0, 1 },  /* applinzi.com */\n  {  7415,     0,     0, 1 },  /* appspot.com */\n  {   494,     0,     0, 1 },  /* ar.com */\n  { 12035,     0,     0, 1 },  /* betainabox.com */\n  { 12046,     0,     0, 1 },  /* blogdns.com */\n  { 10666,     0,     0, 1 },  /* blogspot.com */\n  { 12054,     0,     0, 1 },  /* blogsyte.com */\n  { 12063,     0,     0, 1 },  /* bloxcms.com */\n  { 12071,  3881,     2, 1 },  /* bounty-full.com */\n  {  1182,     0,     0, 1 },  /* br.com */\n  { 12083,     0,     0, 1 },  /* cechire.com */\n  { 12091,     0,     0, 1 },  /* ciscofreak.com */\n  { 12102,     0,     0, 1 },  /* cloudcontrolapp.com */\n  { 12118,     0,     0, 1 },  /* cloudcontrolled.com */\n  {   842,     0,     0, 1 },  /* cn.com */\n  {   113,     0,     0, 1 },  /* co.com */\n  { 12134,     0,     0, 1 },  /* codespot.com */\n  { 12143,     0,     0, 1 },  /* damnserver.com */\n  { 12154,     0,     0, 1 },  /* ddnsking.com */\n  {  2276,     0,     0, 1 },  /* de.com */\n  { 12163,     0,     0, 1 },  /* dev-myqnapcloud.com */\n  {  6821,     0,     0, 1 },  /* ditchyourip.com */\n  { 12179,     0,     0, 1 },  /* dnsalias.com */\n  { 12188,     0,     0, 1 },  /* dnsdojo.com */\n  { 12196,     0,     0, 1 },  /* dnsiskinky.com */\n  { 12207,     0,     0, 1 },  /* doesntexist.com */\n  { 12219,     0,     0, 1 },  /* dontexist.com */\n  { 12229,     0,     0, 1 },  /* doomdns.com */\n  { 12237,     0,     0, 1 },  /* dreamhosters.com */\n  { 12250,     0,     0, 1 },  /* dsmynas.com */\n  { 12258,     0,     0, 1 },  /* dyn-o-saur.com */\n  { 12269,     0,     0, 1 },  /* dynalias.com */\n  { 12278,     0,     0, 1 },  /* dyndns-at-home.com */\n  { 12293,     0,     0, 1 },  /* dyndns-at-work.com */\n  { 12308,     0,     0, 1 },  /* dyndns-blog.com */\n  {  3248,     0,     0, 1 },  /* dyndns-free.com */\n  { 12320,     0,     0, 1 },  /* dyndns-home.com */\n  { 12332,     0,     0, 1 },  /* dyndns-ip.com */\n  { 12342,     0,     0, 1 },  /* dyndns-mail.com */\n  { 12354,     0,     0, 1 },  /* dyndns-office.com */\n  { 12368,     0,     0, 1 },  /* dyndns-pics.com */\n  { 12380,     0,     0, 1 },  /* dyndns-remote.com */\n  { 12394,     0,     0, 1 },  /* dyndns-server.com */\n  { 12408,     0,     0, 1 },  /* dyndns-web.com */\n  {  8540,     0,     0, 1 },  /* dyndns-wiki.com */\n  { 12419,     0,     0, 1 },  /* dyndns-work.com */\n  { 12431,     0,     0, 1 },  /* dynns.com */\n  {  7668,  3687,     1, 0 },  /* elasticbeanstalk.com */\n  {  5172,     0,     0, 1 },  /* est-a-la-maison.com */\n  { 12437,     0,     0, 1 },  /* est-a-la-masion.com */\n  { 12453,     0,     0, 1 },  /* est-le-patron.com */\n  { 12467,     0,     0, 1 },  /* est-mon-blogueur.com */\n  {  2798,     0,     0, 1 },  /* eu.com */\n  { 12484,  3883,     4, 1 },  /* evennode.com */\n  { 12493,     0,     0, 1 },  /* familyds.com */\n  { 12502,  3887,     1, 1 },  /* fbsbx.com */\n  { 12508,     0,     0, 1 },  /* firebaseapp.com */\n  { 12520,     0,     0, 1 },  /* firewall-gateway.com */\n  { 12537,     0,     0, 1 },  /* flynnhub.com */\n  { 12546,     0,     0, 1 },  /* freebox-os.com */\n  { 12557,     0,     0, 1 },  /* freeboxos.com */\n  { 12567,     0,     0, 1 },  /* from-ak.com */\n  { 12575,     0,     0, 1 },  /* from-al.com */\n  { 12583,     0,     0, 1 },  /* from-ar.com */\n  { 12591,     0,     0, 1 },  /* from-ca.com */\n  { 12599,     0,     0, 1 },  /* from-ct.com */\n  { 12607,     0,     0, 1 },  /* from-dc.com */\n  { 12615,     0,     0, 1 },  /* from-de.com */\n  { 12623,     0,     0, 1 },  /* from-fl.com */\n  { 12631,     0,     0, 1 },  /* from-ga.com */\n  { 12639,     0,     0, 1 },  /* from-hi.com */\n  { 12647,     0,     0, 1 },  /* from-ia.com */\n  { 12655,     0,     0, 1 },  /* from-id.com */\n  { 12663,     0,     0, 1 },  /* from-il.com */\n  { 12671,     0,     0, 1 },  /* from-in.com */\n  { 12679,     0,     0, 1 },  /* from-ks.com */\n  { 12687,     0,     0, 1 },  /* from-ky.com */\n  { 12695,     0,     0, 1 },  /* from-ma.com */\n  { 12703,     0,     0, 1 },  /* from-md.com */\n  { 12711,     0,     0, 1 },  /* from-mi.com */\n  { 12719,     0,     0, 1 },  /* from-mn.com */\n  { 12727,     0,     0, 1 },  /* from-mo.com */\n  { 12735,     0,     0, 1 },  /* from-ms.com */\n  {  5604,     0,     0, 1 },  /* from-mt.com */\n  { 12743,     0,     0, 1 },  /* from-nc.com */\n  { 12751,     0,     0, 1 },  /* from-nd.com */\n  { 12759,     0,     0, 1 },  /* from-ne.com */\n  { 12767,     0,     0, 1 },  /* from-nh.com */\n  { 12775,     0,     0, 1 },  /* from-nj.com */\n  { 11897,     0,     0, 1 },  /* from-nm.com */\n  { 12783,     0,     0, 1 },  /* from-nv.com */\n  { 12791,     0,     0, 1 },  /* from-oh.com */\n  { 12799,     0,     0, 1 },  /* from-ok.com */\n  { 12807,     0,     0, 1 },  /* from-or.com */\n  { 12815,     0,     0, 1 },  /* from-pa.com */\n  {  6397,     0,     0, 1 },  /* from-pr.com */\n  { 12823,     0,     0, 1 },  /* from-ri.com */\n  { 12831,     0,     0, 1 },  /* from-sc.com */\n  {  7101,     0,     0, 1 },  /* from-sd.com */\n  { 12839,     0,     0, 1 },  /* from-tn.com */\n  { 12847,     0,     0, 1 },  /* from-tx.com */\n  { 12855,     0,     0, 1 },  /* from-ut.com */\n  { 12863,     0,     0, 1 },  /* from-va.com */\n  { 12871,     0,     0, 1 },  /* from-vt.com */\n  { 12879,     0,     0, 1 },  /* from-wa.com */\n  { 12887,     0,     0, 1 },  /* from-wi.com */\n  { 12895,     0,     0, 1 },  /* from-wv.com */\n  { 12903,     0,     0, 1 },  /* from-wy.com */\n  {  3441,     0,     0, 1 },  /* gb.com */\n  { 12911,     0,     0, 1 },  /* geekgalaxy.com */\n  { 12922,     0,     0, 1 },  /* getmyip.com */\n  { 12930,  2065,     3, 1 },  /* githubcloud.com */\n  { 12942,  3687,     1, 0 },  /* githubcloudusercontent.com */\n  { 12965,     0,     0, 1 },  /* githubusercontent.com */\n  { 12983,     0,     0, 1 },  /* googleapis.com */\n  { 12994,     0,     0, 1 },  /* googlecode.com */\n  { 11809,     0,     0, 1 },  /* gotdns.com */\n  { 13005,     0,     0, 1 },  /* gotpantheon.com */\n  {  3697,     0,     0, 1 },  /* gr.com */\n  { 13017,     0,     0, 1 },  /* health-carereform.com */\n  { 13035,     0,     0, 1 },  /* herokuapp.com */\n  { 13045,     0,     0, 1 },  /* herokussl.com */\n  {  3940,     0,     0, 1 },  /* hk.com */\n  { 13055,     0,     0, 1 },  /* hobby-site.com */\n  { 13066,     0,     0, 1 },  /* homelinux.com */\n  { 13076,     0,     0, 1 },  /* homesecuritymac.com */\n  { 13092,     0,     0, 1 },  /* homesecuritypc.com */\n  { 13107,     0,     0, 1 },  /* homeunix.com */\n  {  4138,     0,     0, 1 },  /* hu.com */\n  { 13116,     0,     0, 1 },  /* iamallama.com */\n  { 13126,     0,     0, 1 },  /* is-a-anarchist.com */\n  { 13141,     0,     0, 1 },  /* is-a-blogger.com */\n  { 13154,     0,     0, 1 },  /* is-a-bookkeeper.com */\n  { 13170,     0,     0, 1 },  /* is-a-bulls-fan.com */\n  { 13185,     0,     0, 1 },  /* is-a-caterer.com */\n  { 13198,     0,     0, 1 },  /* is-a-chef.com */\n  { 13208,     0,     0, 1 },  /* is-a-conservative.com */\n  { 13226,     0,     0, 1 },  /* is-a-cpa.com */\n  { 13235,     0,     0, 1 },  /* is-a-cubicle-slave.com */\n  {  2333,     0,     0, 1 },  /* is-a-democrat.com */\n  { 13254,     0,     0, 1 },  /* is-a-designer.com */\n  {  2491,     0,     0, 1 },  /* is-a-doctor.com */\n  { 13268,     0,     0, 1 },  /* is-a-financialadvisor.com */\n  { 13290,     0,     0, 1 },  /* is-a-geek.com */\n  {  3725,     0,     0, 1 },  /* is-a-green.com */\n  {  3808,     0,     0, 1 },  /* is-a-guru.com */\n  { 13300,     0,     0, 1 },  /* is-a-hard-worker.com */\n  { 13317,     0,     0, 1 },  /* is-a-hunter.com */\n  { 13329,     0,     0, 1 },  /* is-a-landscaper.com */\n  {  4844,     0,     0, 1 },  /* is-a-lawyer.com */\n  { 13345,     0,     0, 1 },  /* is-a-liberal.com */\n  { 13358,     0,     0, 1 },  /* is-a-libertarian.com */\n  { 13375,     0,     0, 1 },  /* is-a-llama.com */\n  { 13386,     0,     0, 1 },  /* is-a-musician.com */\n  { 13400,     0,     0, 1 },  /* is-a-nascarfan.com */\n  { 13415,     0,     0, 1 },  /* is-a-nurse.com */\n  { 13426,     0,     0, 1 },  /* is-a-painter.com */\n  { 11280,     0,     0, 1 },  /* is-a-personaltrainer.com */\n  { 13439,     0,     0, 1 },  /* is-a-photographer.com */\n  { 13457,     0,     0, 1 },  /* is-a-player.com */\n  {  6718,     0,     0, 1 },  /* is-a-republican.com */\n  { 13469,     0,     0, 1 },  /* is-a-rockstar.com */\n  { 13483,     0,     0, 1 },  /* is-a-socialist.com */\n  { 11260,     0,     0, 1 },  /* is-a-student.com */\n  { 13498,     0,     0, 1 },  /* is-a-teacher.com */\n  { 13511,     0,     0, 1 },  /* is-a-techie.com */\n  { 13523,     0,     0, 1 },  /* is-a-therapist.com */\n  {    83,     0,     0, 1 },  /* is-an-accountant.com */\n  {   128,     0,     0, 1 },  /* is-an-actor.com */\n  { 13538,     0,     0, 1 },  /* is-an-actress.com */\n  { 13552,     0,     0, 1 },  /* is-an-anarchist.com */\n  { 13568,     0,     0, 1 },  /* is-an-artist.com */\n  {  2670,     0,     0, 1 },  /* is-an-engineer.com */\n  { 13581,     0,     0, 1 },  /* is-an-entertainer.com */\n  { 13599,     0,     0, 1 },  /* is-certified.com */\n  { 13612,     0,     0, 1 },  /* is-gone.com */\n  { 13620,     0,     0, 1 },  /* is-into-anime.com */\n  {  1470,     0,     0, 1 },  /* is-into-cars.com */\n  { 13634,     0,     0, 1 },  /* is-into-cartoons.com */\n  {  3397,     0,     0, 1 },  /* is-into-games.com */\n  { 13651,     0,     0, 1 },  /* is-leet.com */\n  { 13659,     0,     0, 1 },  /* is-not-certified.com */\n  { 13676,     0,     0, 1 },  /* is-slick.com */\n  { 13685,     0,     0, 1 },  /* is-uberleet.com */\n  { 13697,     0,     0, 1 },  /* is-with-theband.com */\n  { 13713,     0,     0, 1 },  /* isa-geek.com */\n  { 13722,     0,     0, 1 },  /* isa-hockeynut.com */\n  { 13736,     0,     0, 1 },  /* issmarterthanyou.com */\n  { 13753,  2068,     1, 0 },  /* joyent.com */\n  { 13760,     0,     0, 1 },  /* jpn.com */\n  {  3123,     0,     0, 1 },  /* kr.com */\n  { 13764,     0,     0, 1 },  /* likes-pie.com */\n  { 13774,     0,     0, 1 },  /* likescandy.com */\n  { 13785,     0,     0, 1 },  /* logoip.com */\n  { 13792,  3888,     1, 1 },  /* meteorapp.com */\n  {   396,     0,     0, 1 },  /* mex.com */\n  {  2421,     0,     0, 1 },  /* myactivedirectory.com */\n  { 13802,     0,     0, 1 },  /* myasustor.com */\n  { 13812,     0,     0, 1 },  /* mydrobo.com */\n  { 12005,     0,     0, 1 },  /* myqnapcloud.com */\n  {  1347,     0,     0, 1 },  /* mysecuritycamera.com */\n  { 13820,     0,     0, 1 },  /* myshopblocks.com */\n  { 13833,     0,     0, 1 },  /* myvnc.com */\n  { 13839,     0,     0, 1 },  /* neat-url.com */\n  { 13848,     0,     0, 1 },  /* net-freaks.com */\n  {  4048,     0,     0, 1 },  /* nfshost.com */\n  {  1517,     0,     0, 1 },  /* no.com */\n  { 13859,     0,     0, 1 },  /* on-aptible.com */\n  { 13870,     0,     0, 1 },  /* onthewifi.com */\n  { 13880,     0,     0, 1 },  /* operaunite.com */\n  { 13891,     0,     0, 1 },  /* outsystemscloud.com */\n  { 13907,     0,     0, 1 },  /* ownprovider.com */\n  { 13919,     0,     0, 1 },  /* pagefrontapp.com */\n  { 13932,     0,     0, 1 },  /* pagespeedmobilizer.com */\n  { 13951,     0,     0, 1 },  /* pgfog.com */\n  { 13957,     0,     0, 1 },  /* point2this.com */\n  { 13968,  3889,     1, 1 },  /* prgmr.com */\n  { 13974,     0,     0, 1 },  /* publishproxy.com */\n  { 13987,     0,     0, 1 },  /* qa2.com */\n  { 11494,     0,     0, 1 },  /* qc.com */\n  { 13991,     0,     0, 1 },  /* quicksytes.com */\n  { 14002,     0,     0, 1 },  /* rackmaze.com */\n  { 14011,     0,     0, 1 },  /* remotewd.com */\n  {  1837,     0,     0, 1 },  /* rhcloud.com */\n  {  2190,     0,     0, 1 },  /* ru.com */\n  {  1493,     0,     0, 1 },  /* sa.com */\n  { 14020,     0,     0, 1 },  /* saves-the-whales.com */\n  {  1498,     0,     0, 1 },  /* se.com */\n  { 14037,     0,     0, 1 },  /* securitytactics.com */\n  { 11594,     0,     0, 1 },  /* selfip.com */\n  { 14053,     0,     0, 1 },  /* sells-for-less.com */\n  { 14068,     0,     0, 1 },  /* sells-for-u.com */\n  { 14080,     0,     0, 1 },  /* servebbs.com */\n  {   876,     0,     0, 1 },  /* servebeer.com */\n  { 14089,     0,     0, 1 },  /* servecounterstrike.com */\n  {  2832,     0,     0, 1 },  /* serveexchange.com */\n  { 14108,     0,     0, 1 },  /* serveftp.com */\n  { 14117,     0,     0, 1 },  /* servegame.com */\n  { 14127,     0,     0, 1 },  /* servehalflife.com */\n  { 14141,     0,     0, 1 },  /* servehttp.com */\n  { 14151,     0,     0, 1 },  /* servehumour.com */\n  { 14163,     0,     0, 1 },  /* serveirc.com */\n  { 14172,     0,     0, 1 },  /* servemp3.com */\n  { 14181,     0,     0, 1 },  /* servep2p.com */\n  {  6279,     0,     0, 1 },  /* servepics.com */\n  { 14190,     0,     0, 1 },  /* servequake.com */\n  { 14201,     0,     0, 1 },  /* servesarcasm.com */\n  { 14214,     0,     0, 1 },  /* simple-url.com */\n  { 14228,     0,     0, 1 },  /* sinaapp.com */\n  {  6682,     0,     0, 1 },  /* space-to-rent.com */\n  {  6587,     0,     0, 1 },  /* stufftoread.com */\n  { 10591,     0,     0, 1 },  /* teaches-yoga.com */\n  { 14236,     0,     0, 1 },  /* townnews-staging.com */\n  {  8122,     0,     0, 1 },  /* uk.com */\n  { 14253,     0,     0, 1 },  /* unusualperson.com */\n  {   264,     0,     0, 1 },  /* us.com */\n  {   911,     0,     0, 1 },  /* uy.com */\n  { 14225,     0,     0, 1 },  /* vipsinaapp.com */\n  {  3552,     0,     0, 1 },  /* withgoogle.com */\n  {  8051,     0,     0, 1 },  /* withyoutube.com */\n  { 14267,     0,     0, 1 },  /* workisboring.com */\n  { 14280,     0,     0, 1 },  /* writesthisblog.com */\n  {   674,     0,     0, 1 },  /* xenapponazure.com */\n  { 14295,     0,     0, 1 },  /* yolasite.com */\n  {  6329,     0,     0, 1 },  /* za.com */\n  { 14307,  2044,     1, 0 },  /* ap-northeast-1.amazonaws.com */\n  { 14325,  2045,     3, 0 },  /* ap-northeast-2.amazonaws.com */\n  { 14343,  2048,     3, 0 },  /* ap-south-1.amazonaws.com */\n  { 14357,  2051,     1, 0 },  /* ap-southeast-1.amazonaws.com */\n  { 14375,  2052,     1, 0 },  /* ap-southeast-2.amazonaws.com */\n  { 14393,  2053,     3, 0 },  /* ca-central-1.amazonaws.com */\n  { 11947,  3687,     1, 0 },  /* compute.amazonaws.com */\n  { 14406,  3687,     1, 0 },  /* compute-1.amazonaws.com */\n  { 11955,  3687,     1, 0 },  /* elb.amazonaws.com */\n  { 14419,  2056,     3, 0 },  /* eu-central-1.amazonaws.com */\n  { 14435,  2059,     1, 0 },  /* eu-west-1.amazonaws.com */\n  { 11473,  3687,     1, 0 },  /* s3.amazonaws.com */\n  { 14304,     0,     0, 1 },  /* s3-ap-northeast-1.amazonaws.com */\n  { 14322,     0,     0, 1 },  /* s3-ap-northeast-2.amazonaws.com */\n  { 14340,     0,     0, 1 },  /* s3-ap-south-1.amazonaws.com */\n  { 14354,     0,     0, 1 },  /* s3-ap-southeast-1.amazonaws.com */\n  { 14372,     0,     0, 1 },  /* s3-ap-southeast-2.amazonaws.com */\n  { 14390,     0,     0, 1 },  /* s3-ca-central-1.amazonaws.com */\n  { 14416,     0,     0, 1 },  /* s3-eu-central-1.amazonaws.com */\n  { 14432,     0,     0, 1 },  /* s3-eu-west-1.amazonaws.com */\n  { 14445,     0,     0, 1 },  /* s3-external-1.amazonaws.com */\n  { 14459,     0,     0, 1 },  /* s3-fips-us-gov-west-1.amazonaws.com */\n  { 14481,     0,     0, 1 },  /* s3-sa-east-1.amazonaws.com */\n  { 14494,     0,     0, 1 },  /* s3-us-east-2.amazonaws.com */\n  { 14507,     0,     0, 1 },  /* s3-us-gov-west-1.amazonaws.com */\n  { 14524,     0,     0, 1 },  /* s3-us-west-1.amazonaws.com */\n  { 14537,     0,     0, 1 },  /* s3-us-west-2.amazonaws.com */\n  { 14550,     0,     0, 1 },  /* s3-website-ap-northeast-1.amazonaws.com */\n  { 14576,     0,     0, 1 },  /* s3-website-ap-southeast-1.amazonaws.com */\n  { 14602,     0,     0, 1 },  /* s3-website-ap-southeast-2.amazonaws.com */\n  { 14628,     0,     0, 1 },  /* s3-website-eu-west-1.amazonaws.com */\n  { 14649,     0,     0, 1 },  /* s3-website-sa-east-1.amazonaws.com */\n  { 14670,     0,     0, 1 },  /* s3-website-us-east-1.amazonaws.com */\n  { 14691,     0,     0, 1 },  /* s3-website-us-west-1.amazonaws.com */\n  { 14712,     0,     0, 1 },  /* s3-website-us-west-2.amazonaws.com */\n  { 14484,  2060,     1, 0 },  /* sa-east-1.amazonaws.com */\n  { 14681,  2061,     1, 1 },  /* us-east-1.amazonaws.com */\n  { 14497,  2062,     3, 0 },  /* us-east-2.amazonaws.com */\n  { 14733,  3880,     1, 0 },  /* dualstack.ap-northeast-1.amazonaws.com */\n  { 14733,  3880,     1, 0 },  /* dualstack.ap-northeast-2.amazonaws.com */\n  { 11473,     0,     0, 1 },  /* s3.ap-northeast-2.amazonaws.com */\n  {  8490,     0,     0, 1 },  /* s3-website.ap-northeast-2.amazonaws.com */\n  { 14733,  3880,     1, 0 },  /* dualstack.ap-south-1.amazonaws.com */\n  { 11473,     0,     0, 1 },  /* s3.ap-south-1.amazonaws.com */\n  {  8490,     0,     0, 1 },  /* s3-website.ap-south-1.amazonaws.com */\n  { 14733,  3880,     1, 0 },  /* dualstack.ap-southeast-1.amazonaws.com */\n  { 14733,  3880,     1, 0 },  /* dualstack.ap-southeast-2.amazonaws.com */\n  { 14733,  3880,     1, 0 },  /* dualstack.ca-central-1.amazonaws.com */\n  { 11473,     0,     0, 1 },  /* s3.ca-central-1.amazonaws.com */\n  {  8490,     0,     0, 1 },  /* s3-website.ca-central-1.amazonaws.com */\n  { 14733,  3880,     1, 0 },  /* dualstack.eu-central-1.amazonaws.com */\n  { 11473,     0,     0, 1 },  /* s3.eu-central-1.amazonaws.com */\n  {  8490,     0,     0, 1 },  /* s3-website.eu-central-1.amazonaws.com */\n  { 14733,  3880,     1, 0 },  /* dualstack.eu-west-1.amazonaws.com */\n  { 14733,  3880,     1, 0 },  /* dualstack.sa-east-1.amazonaws.com */\n  { 14733,  3880,     1, 1 },  /* dualstack.us-east-1.amazonaws.com */\n  { 14733,  3880,     1, 0 },  /* dualstack.us-east-2.amazonaws.com */\n  { 11473,     0,     0, 1 },  /* s3.us-east-2.amazonaws.com */\n  {  8490,     0,     0, 1 },  /* s3-website.us-east-2.amazonaws.com */\n  { 11736,  3687,     1, 0 },  /* api.githubcloud.com */\n  {  5814,  3687,     1, 0 },  /* ext.githubcloud.com */\n  {  4380,     0,     0, 1 },  /* gist.githubcloud.com */\n  { 14774,  3687,     1, 0 },  /* cns.joyent.com */\n  {    62,     0,     0, 1 },  /* ac.cy */\n  {   985,     0,     0, 1 },  /* biz.cy */\n  {  1913,  3672,     1, 1 },  /* com.cy */\n  { 14782,     0,     0, 1 },  /* ekloges.cy */\n  {  3686,     0,     0, 1 },  /* gov.cy */\n  {  5103,     0,     0, 1 },  /* ltd.cy */\n  {  5725,     0,     0, 1 },  /* name.cy */\n  {  4185,     0,     0, 1 },  /* net.cy */\n  {  6070,     0,     0, 1 },  /* org.cy */\n  { 14790,     0,     0, 1 },  /* parliament.cy */\n  {   371,     0,     0, 1 },  /* press.cy */\n  {  6427,     0,     0, 1 },  /* pro.cy */\n  {  7910,     0,     0, 1 },  /* tm.cy */\n  { 10666,     0,     0, 1 },  /* blogspot.de */\n  {  1913,     0,     0, 1 },  /* com.de */\n  { 14807,  3913,     1, 1 },  /* cosidns.de */\n  { 14815,     0,     0, 1 },  /* dd-dns.de */\n  { 14822,  3914,     2, 1 },  /* ddnss.de */\n  { 14828,     0,     0, 1 },  /* dnshome.de */\n  { 14836,     0,     0, 1 },  /* dnsupdater.de */\n  { 14847,     0,     0, 1 },  /* dray-dns.de */\n  { 14856,     0,     0, 1 },  /* draydns.de */\n  { 14864,     0,     0, 1 },  /* dyn-ip24.de */\n  { 14873,     0,     0, 1 },  /* dyn-vpn.de */\n  { 14881,     0,     0, 1 },  /* dynamisches-dns.de */\n  { 14897,     0,     0, 1 },  /* dyndns1.de */\n  { 14905,     0,     0, 1 },  /* dynvpn.de */\n  { 12520,     0,     0, 1 },  /* firewall-gateway.de */\n  { 14912,     0,     0, 1 },  /* fuettertdasnetz.de */\n  { 13787,     0,     0, 1 },  /* goip.de */\n  { 14928,  3913,     1, 1 },  /* home-webserver.de */\n  { 14943,     0,     0, 1 },  /* internet-dns.de */\n  { 14956,     0,     0, 1 },  /* isteingeek.de */\n  { 14967,     0,     0, 1 },  /* istmein.de */\n  { 14975,     0,     0, 1 },  /* keymachine.de */\n  { 14986,     0,     0, 1 },  /* l-o-g-i-n.de */\n  { 14996,     0,     0, 1 },  /* lebtimnetz.de */\n  { 15007,     0,     0, 1 },  /* leitungsen.de */\n  { 13785,     0,     0, 1 },  /* logoip.de */\n  { 15018,     0,     0, 1 },  /* mein-vigor.de */\n  { 15029,     0,     0, 1 },  /* my-gateway.de */\n  { 15040,     0,     0, 1 },  /* my-router.de */\n  { 15050,     0,     0, 1 },  /* my-vigor.de */\n  { 15059,     0,     0, 1 },  /* my-wan.de */\n  { 15066,     0,     0, 1 },  /* myhome-server.de */\n  { 15080,     0,     0, 1 },  /* spdns.de */\n  { 15086,     0,     0, 1 },  /* syno-ds.de */\n  { 15094,     0,     0, 1 },  /* synology-diskstation.de */\n  { 15115,     0,     0, 1 },  /* synology-ds.de */\n  { 15127,     0,     0, 1 },  /* taifun-dns.de */\n  { 15138,     0,     0, 1 },  /* traeumtgerade.de */\n  { 15178,     0,     0, 1 },  /* aip.ee */\n  {  1913,  3672,     1, 1 },  /* com.ee */\n  {  2624,     0,     0, 1 },  /* edu.ee */\n  {  4174,     0,     0, 1 },  /* fie.ee */\n  {  3686,     0,     0, 1 },  /* gov.ee */\n  { 15182,     0,     0, 1 },  /* lib.ee */\n  {  1858,     0,     0, 1 },  /* med.ee */\n  {  6070,     0,     0, 1 },  /* org.ee */\n  { 15186,     0,     0, 1 },  /* pri.ee */\n  { 15190,     0,     0, 1 },  /* riik.ee */\n  {  1913,  3672,     1, 1 },  /* com.eg */\n  {  2624,     0,     0, 1 },  /* edu.eg */\n  { 15195,     0,     0, 1 },  /* eun.eg */\n  {  3686,     0,     0, 1 },  /* gov.eg */\n  {  4195,     0,     0, 1 },  /* mil.eg */\n  {  5725,     0,     0, 1 },  /* name.eg */\n  {  4185,     0,     0, 1 },  /* net.eg */\n  {  6070,     0,     0, 1 },  /* org.eg */\n  { 15209,     0,     0, 1 },  /* sci.eg */\n  {  1913,  3672,     1, 1 },  /* com.es */\n  {  2624,     0,     0, 1 },  /* edu.es */\n  { 11325,     0,     0, 1 },  /* gob.es */\n  {  5998,     0,     0, 1 },  /* nom.es */\n  {  6070,     0,     0, 1 },  /* org.es */\n  { 11947,  3687,     1, 0 },  /* compute.estate */\n  { 11367,     0,     0, 1 },  /* cloudns.eu */\n  { 15103,     0,     0, 1 },  /* diskstation.eu */\n  { 15213,     0,     0, 1 },  /* mycd.eu */\n  { 15080,     0,     0, 1 },  /* spdns.eu */\n  { 11450,  3687,     1, 0 },  /* transurl.eu */\n  { 15218,     0,     0, 1 },  /* wellbeingzone.eu */\n  {  6180,  3960,     1, 1 },  /* party.eus */\n  {    62,     0,     0, 1 },  /* ac.id */\n  {   985,     0,     0, 1 },  /* biz.id */\n  {   113,  3672,     1, 1 },  /* co.id */\n  { 15714,     0,     0, 1 },  /* desa.id */\n  {   257,     0,     0, 1 },  /* go.id */\n  {  4195,     0,     0, 1 },  /* mil.id */\n  {    70,     0,     0, 1 },  /* my.id */\n  {  4185,     0,     0, 1 },  /* net.id */\n  {   137,     0,     0, 1 },  /* or.id */\n  {  1145,     0,     0, 1 },  /* sch.id */\n  { 11967,     0,     0, 1 },  /* web.id */\n  {    62,     0,     0, 1 },  /* ac.il */\n  {   113,  3672,     1, 1 },  /* co.il */\n  {  3686,     0,     0, 1 },  /* gov.il */\n  { 11727,     0,     0, 1 },  /* idf.il */\n  { 15174,     0,     0, 1 },  /* k12.il */\n  { 15719,     0,     0, 1 },  /* muni.il */\n  {  4185,     0,     0, 1 },  /* net.il */\n  {  6070,     0,     0, 1 },  /* org.il */\n  {    62,     0,     0, 1 },  /* ac.im */\n  {   113,  4141,     2, 1 },  /* co.im */\n  {  1913,     0,     0, 1 },  /* com.im */\n  {  4185,     0,     0, 1 },  /* net.im */\n  {  6070,     0,     0, 1 },  /* org.im */\n  {   166,     0,     0, 1 },  /* ro.im */\n  {    24,     0,     0, 1 },  /* tt.im */\n  {  2546,     0,     0, 1 },  /* tv.im */\n  { 15840,     0,     0, 1 },  /* backplaneapp.io */\n  { 15853,     0,     0, 1 },  /* boxfuse.io */\n  { 15861,     0,     0, 1 },  /* browsersafetymark.io */\n  {  1913,     0,     0, 1 },  /* com.io */\n  { 15152,     0,     0, 1 },  /* dedyn.io */\n  { 15879,     0,     0, 1 },  /* drud.io */\n  { 15884,  4173,     1, 1 },  /* enonic.io */\n  { 15891,     0,     0, 1 },  /* github.io */\n  { 15898,     0,     0, 1 },  /* gitlab.io */\n  { 15905,     0,     0, 1 },  /* hasura-app.io */\n  { 15916,     0,     0, 1 },  /* hzc.io */\n  { 15920,  3887,     1, 1 },  /* lair.io */\n  { 15925,     0,     0, 1 },  /* ngrok.io */\n  { 15931,     0,     0, 1 },  /* nid.io */\n  { 15935,     0,     0, 1 },  /* pantheonsite.io */\n  { 15948,     0,     0, 1 },  /* protonet.io */\n  { 15957,     0,     0, 1 },  /* sandcats.io */\n  { 15966,     0,     0, 1 },  /* shiftedit.io */\n  { 15976,     0,     0, 1 },  /* spacekit.io */\n  { 15985,  3687,     1, 0 },  /* stolos.io */\n  {    62,     0,     0, 1 },  /* ac.jp */\n  {   141,     0,     0, 1 },  /* ad.jp */\n  { 18576,  4568,    52, 1 },  /* aichi.jp */\n  { 18585,  4620,    28, 1 },  /* akita.jp */\n  { 18591,  4648,    22, 1 },  /* aomori.jp */\n  { 10666,     0,     0, 1 },  /* blogspot.jp */\n  { 18603,  4670,    58, 1 },  /* chiba.jp */\n  {   113,     0,     0, 1 },  /* co.jp */\n  {  1859,     0,     0, 1 },  /* ed.jp */\n  { 18609,  4728,    22, 1 },  /* ehime.jp */\n  { 18615,  4750,    15, 1 },  /* fukui.jp */\n  { 18621,  4765,    63, 1 },  /* fukuoka.jp */\n  { 18633,  4828,    51, 1 },  /* fukushima.jp */\n  { 18643,  4879,    38, 1 },  /* gifu.jp */\n  {   257,     0,     0, 1 },  /* go.jp */\n  {  3697,     0,     0, 1 },  /* gr.jp */\n  { 18648,  4917,    36, 1 },  /* gunma.jp */\n  { 18658,  4953,    25, 1 },  /* hiroshima.jp */\n  { 18668,  4978,   142, 1 },  /* hokkaido.jp */\n  { 18677,  5120,    46, 1 },  /* hyogo.jp */\n  { 18683,  5166,    51, 1 },  /* ibaraki.jp */\n  { 18692,  5217,    19, 1 },  /* ishikawa.jp */\n  { 18701,  5236,    34, 1 },  /* iwate.jp */\n  { 18709,  5270,    15, 1 },  /* kagawa.jp */\n  { 18716,  5285,    20, 1 },  /* kagoshima.jp */\n  { 18726,  5305,    30, 1 },  /* kanagawa.jp */\n  { 18735,  5335,     2, 0 },  /* kawasaki.jp */\n  { 18744,  5335,     2, 0 },  /* kitakyushu.jp */\n  {   858,  5335,     2, 0 },  /* kobe.jp */\n  { 18755,  5337,    31, 1 },  /* kochi.jp */\n  {  5553,  5368,    23, 1 },  /* kumamoto.jp */\n  {  4708,  5391,    31, 1 },  /* kyoto.jp */\n  { 11693,     0,     0, 1 },  /* lg.jp */\n  { 18763,  5422,    30, 1 },  /* mie.jp */\n  { 18767,  5452,    32, 1 },  /* miyagi.jp */\n  { 18774,  5484,    27, 1 },  /* miyazaki.jp */\n  { 18790,  5511,    75, 1 },  /* nagano.jp */\n  { 18797,  5586,    22, 1 },  /* nagasaki.jp */\n  {  5714,  5335,     2, 0 },  /* nagoya.jp */\n  { 17635,  5608,    38, 1 },  /* nara.jp */\n  {  1203,     0,     0, 1 },  /* ne.jp */\n  { 18806,  5646,    34, 1 },  /* niigata.jp */\n  { 18815,  5680,    19, 1 },  /* oita.jp */\n  { 18820,  5699,    26, 1 },  /* okayama.jp */\n  {  5966,  5725,    42, 1 },  /* okinawa.jp */\n  {   137,     0,     0, 1 },  /* or.jp */\n  {  6098,  5767,    50, 1 },  /* osaka.jp */\n  {  3353,  5817,    26, 1 },  /* saga.jp */\n  { 18828,  5843,    69, 1 },  /* saitama.jp */\n  { 18836,  5335,     2, 0 },  /* sapporo.jp */\n  { 18851,  5335,     2, 0 },  /* sendai.jp */\n  { 18858,  5912,    23, 1 },  /* shiga.jp */\n  { 18864,  5935,    23, 1 },  /* shimane.jp */\n  { 18872,  5958,    36, 1 },  /* shizuoka.jp */\n  { 18881,  5994,    31, 1 },  /* tochigi.jp */\n  { 18889,  6025,    17, 1 },  /* tokushima.jp */\n  {  7924,  6042,    57, 1 },  /* tokyo.jp */\n  { 18899,  6099,    13, 1 },  /* tottori.jp */\n  { 18909,  6112,    24, 1 },  /* toyama.jp */\n  { 18916,  6136,    29, 1 },  /* wakayama.jp */\n  { 18925,     0,     0, 1 },  /* xn--0trq7p7nn.jp */\n  { 18939,     0,     0, 1 },  /* xn--1ctwo.jp */\n  { 18949,     0,     0, 1 },  /* xn--1lqs03n.jp */\n  { 18961,     0,     0, 1 },  /* xn--1lqs71d.jp */\n  { 18973,     0,     0, 1 },  /* xn--2m4a15e.jp */\n  { 18985,     0,     0, 1 },  /* xn--32vp30h.jp */\n  { 18997,     0,     0, 1 },  /* xn--4it168d.jp */\n  { 19009,     0,     0, 1 },  /* xn--4it797k.jp */\n  { 19021,     0,     0, 1 },  /* xn--4pvxs.jp */\n  { 19031,     0,     0, 1 },  /* xn--5js045d.jp */\n  { 19043,     0,     0, 1 },  /* xn--5rtp49c.jp */\n  { 19055,     0,     0, 1 },  /* xn--5rtq34k.jp */\n  { 19067,     0,     0, 1 },  /* xn--6btw5a.jp */\n  { 19078,     0,     0, 1 },  /* xn--6orx2r.jp */\n  { 19089,     0,     0, 1 },  /* xn--7t0a264c.jp */\n  { 19102,     0,     0, 1 },  /* xn--8ltr62k.jp */\n  { 11988,     0,     0, 1 },  /* xn--8pvr4u.jp */\n  { 19114,     0,     0, 1 },  /* xn--c3s14m.jp */\n  { 19125,     0,     0, 1 },  /* xn--d5qv7z876c.jp */\n  { 19140,     0,     0, 1 },  /* xn--djrs72d6uy.jp */\n  { 19155,     0,     0, 1 },  /* xn--djty4k.jp */\n  { 19166,     0,     0, 1 },  /* xn--efvn9s.jp */\n  { 19177,     0,     0, 1 },  /* xn--ehqz56n.jp */\n  { 19189,     0,     0, 1 },  /* xn--elqq16h.jp */\n  { 19201,     0,     0, 1 },  /* xn--f6qx53a.jp */\n  { 19213,     0,     0, 1 },  /* xn--k7yn95e.jp */\n  { 19225,     0,     0, 1 },  /* xn--kbrq7o.jp */\n  { 19236,     0,     0, 1 },  /* xn--klt787d.jp */\n  { 19248,     0,     0, 1 },  /* xn--kltp7d.jp */\n  { 19259,     0,     0, 1 },  /* xn--kltx9a.jp */\n  { 19270,     0,     0, 1 },  /* xn--klty5x.jp */\n  { 19281,     0,     0, 1 },  /* xn--mkru45i.jp */\n  { 19293,     0,     0, 1 },  /* xn--nit225k.jp */\n  { 19305,     0,     0, 1 },  /* xn--ntso0iqx3a.jp */\n  { 19320,     0,     0, 1 },  /* xn--ntsq17g.jp */\n  { 19332,     0,     0, 1 },  /* xn--pssu33l.jp */\n  { 19344,     0,     0, 1 },  /* xn--qqqt11m.jp */\n  { 19356,     0,     0, 1 },  /* xn--rht27z.jp */\n  { 19367,     0,     0, 1 },  /* xn--rht3d.jp */\n  { 19377,     0,     0, 1 },  /* xn--rht61e.jp */\n  { 19388,     0,     0, 1 },  /* xn--rny31h.jp */\n  { 19399,     0,     0, 1 },  /* xn--tor131o.jp */\n  { 19411,     0,     0, 1 },  /* xn--uist22h.jp */\n  { 19423,     0,     0, 1 },  /* xn--uisz3g.jp */\n  { 19434,     0,     0, 1 },  /* xn--uuwu58a.jp */\n  { 19446,     0,     0, 1 },  /* xn--vgu402c.jp */\n  { 19458,     0,     0, 1 },  /* xn--zbx025d.jp */\n  { 19470,  6165,    34, 1 },  /* yamagata.jp */\n  { 19479,  6199,    16, 1 },  /* yamaguchi.jp */\n  { 19489,  6215,    28, 1 },  /* yamanashi.jp */\n  { 10604,  5335,     2, 0 },  /* yokohama.jp */\n  { 11410,     0,     0, 1 },  /* *.ke */\n  {   113,  3672,     1, 1 },  /* co.ke */\n  { 29741,  6319,     2, 1 },  /* static.land */\n  {  1913,  3672,     1, 1 },  /* com.mt */\n  {  2624,     0,     0, 1 },  /* edu.mt */\n  {  4185,     0,     0, 1 },  /* net.mt */\n  {  6070,     0,     0, 1 },  /* org.mt */\n  {  1226,  7042,     1, 1 },  /* her.name */\n  { 13964,  7042,     1, 1 },  /* his.name */\n  {  2225,  3687,     1, 0 },  /* alwaysdata.net */\n  {  1364,     0,     0, 1 },  /* at-band-camp.net */\n  {  5453,     0,     0, 1 },  /* azure-mobile.net */\n  { 29748,     0,     0, 1 },  /* azurewebsites.net */\n  { 12046,     0,     0, 1 },  /* blogdns.net */\n  { 33891,     0,     0, 1 },  /* bounceme.net */\n  { 33900,     0,     0, 1 },  /* broke-it.net */\n  { 33909,     0,     0, 1 },  /* buyshouses.net */\n  { 11481,  7044,     1, 1 },  /* cdn77.net */\n  { 33920,     0,     0, 1 },  /* cdn77-ssl.net */\n  { 33930,     0,     0, 1 },  /* cloudapp.net */\n  { 33939,     0,     0, 1 },  /* cloudfront.net */\n  { 33950,     0,     0, 1 },  /* cloudfunctions.net */\n  { 33965,  3687,     1, 0 },  /* cryptonomic.net */\n  { 29802,     0,     0, 1 },  /* ddns.net */\n  { 12179,     0,     0, 1 },  /* dnsalias.net */\n  { 12188,     0,     0, 1 },  /* dnsdojo.net */\n  { 33977,     0,     0, 1 },  /* does-it.net */\n  { 12219,     0,     0, 1 },  /* dontexist.net */\n  { 12250,     0,     0, 1 },  /* dsmynas.net */\n  { 12269,     0,     0, 1 },  /* dynalias.net */\n  { 33985,     0,     0, 1 },  /* dynathome.net */\n  { 33995,     0,     0, 1 },  /* dynv6.net */\n  {  6074,     0,     0, 1 },  /* eating-organic.net */\n  { 34001,     0,     0, 1 },  /* endofinternet.net */\n  { 12493,     0,     0, 1 },  /* familyds.net */\n  { 34015,  2397,     2, 0 },  /* fastly.net */\n  { 34022,     0,     0, 1 },  /* feste-ip.net */\n  { 12520,     0,     0, 1 },  /* firewall-gateway.net */\n  { 34031,     0,     0, 1 },  /* from-az.net */\n  { 34039,     0,     0, 1 },  /* from-co.net */\n  { 34047,     0,     0, 1 },  /* from-la.net */\n  { 34055,     0,     0, 1 },  /* from-ny.net */\n  {  3441,     0,     0, 1 },  /* gb.net */\n  { 34063,     0,     0, 1 },  /* gets-it.net */\n  { 34071,     0,     0, 1 },  /* ham-radio-op.net */\n  { 34084,     0,     0, 1 },  /* homeftp.net */\n  { 34092,     0,     0, 1 },  /* homeip.net */\n  { 13066,     0,     0, 1 },  /* homelinux.net */\n  { 13107,     0,     0, 1 },  /* homeunix.net */\n  {  4138,     0,     0, 1 },  /* hu.net */\n  {   898,     0,     0, 1 },  /* in.net */\n  {   718,     0,     0, 1 },  /* in-the-band.net */\n  { 13198,     0,     0, 1 },  /* is-a-chef.net */\n  { 13290,     0,     0, 1 },  /* is-a-geek.net */\n  { 13713,     0,     0, 1 },  /* isa-geek.net */\n  {  4495,     0,     0, 1 },  /* jp.net */\n  { 34099,     0,     0, 1 },  /* kicks-ass.net */\n  { 34109,     0,     0, 1 },  /* knx-server.net */\n  { 34120,     0,     0, 1 },  /* mydissent.net */\n  { 34130,     0,     0, 1 },  /* myeffect.net */\n  {  8086,     0,     0, 1 },  /* myfritz.net */\n  { 34139,     0,     0, 1 },  /* mymediapc.net */\n  {  7622,     0,     0, 1 },  /* mypsx.net */\n  {  1347,     0,     0, 1 },  /* mysecuritycamera.net */\n  { 34149,     0,     0, 1 },  /* nhlfan.net */\n  { 11588,     0,     0, 1 },  /* no-ip.net */\n  { 34156,     0,     0, 1 },  /* office-on-the.net */\n  { 34170,     0,     0, 1 },  /* pgafan.net */\n  { 10655,     0,     0, 1 },  /* podzone.net */\n  { 34177,     0,     0, 1 },  /* privatizehealthinsurance.net */\n  { 14002,     0,     0, 1 },  /* rackmaze.net */\n  { 34202,     0,     0, 1 },  /* redirectme.net */\n  { 34213,     0,     0, 1 },  /* scrapper-site.net */\n  {  1498,     0,     0, 1 },  /* se.net */\n  { 11594,     0,     0, 1 },  /* selfip.net */\n  { 34227,     0,     0, 1 },  /* sells-it.net */\n  { 14080,     0,     0, 1 },  /* servebbs.net */\n  {  1029,     0,     0, 1 },  /* serveblog.net */\n  { 14108,     0,     0, 1 },  /* serveftp.net */\n  { 34236,     0,     0, 1 },  /* serveminecraft.net */\n  { 34251,     0,     0, 1 },  /* static-access.net */\n  { 13996,     0,     0, 1 },  /* sytes.net */\n  { 34265,     0,     0, 1 },  /* t3l3p0rt.net */\n  {  3883,     0,     0, 1 },  /* thruhere.net */\n  {  8122,     0,     0, 1 },  /* uk.net */\n  { 11601,     0,     0, 1 },  /* webhop.net */\n  {  6329,     0,     0, 1 },  /* za.net */\n  {  6431,  7045,     2, 0 },  /* prod.fastly.net */\n  { 13051,  7047,     3, 0 },  /* ssl.fastly.net */\n  { 34274,  3687,     1, 0 },  /* alces.network */\n  {  1913,  3672,     1, 1 },  /* com.ng */\n  {  2624,     0,     0, 1 },  /* edu.ng */\n  {  3686,     0,     0, 1 },  /* gov.ng */\n  {    58,     0,     0, 1 },  /* i.ng */\n  {  4195,     0,     0, 1 },  /* mil.ng */\n  {  5448,     0,     0, 1 },  /* mobi.ng */\n  {  5725,     0,     0, 1 },  /* name.ng */\n  {  4185,     0,     0, 1 },  /* net.ng */\n  {  6070,     0,     0, 1 },  /* org.ng */\n  {  1145,     0,     0, 1 },  /* sch.ng */\n  { 10666,     0,     0, 1 },  /* blogspot.nl */\n  {  1289,     0,     0, 1 },  /* bv.nl */\n  {   113,     0,     0, 1 },  /* co.nl */\n  { 11450,  3687,     1, 0 },  /* transurl.nl */\n  { 34280,     0,     0, 1 },  /* virtueeldomein.nl */\n  {     1,  7074,     1, 1 },  /* aa.no */\n  { 34295,     0,     0, 1 },  /* aarborte.no */\n  { 34304,     0,     0, 1 },  /* aejrie.no */\n  { 34312,     0,     0, 1 },  /* afjord.no */\n  { 34319,     0,     0, 1 },  /* agdenes.no */\n  { 11875,  7074,     1, 1 },  /* ah.no */\n  { 34327,  7075,     1, 1 },  /* akershus.no */\n  { 34336,     0,     0, 1 },  /* aknoluokta.no */\n  { 34347,     0,     0, 1 },  /* akrehamn.no */\n  {   290,     0,     0, 1 },  /* al.no */\n  { 34356,     0,     0, 1 },  /* alaheadju.no */\n  { 34366,     0,     0, 1 },  /* alesund.no */\n  { 34374,     0,     0, 1 },  /* algard.no */\n  { 34381,     0,     0, 1 },  /* alstahaug.no */\n  { 34392,     0,     0, 1 },  /* alta.no */\n  { 34397,     0,     0, 1 },  /* alvdal.no */\n  { 34404,     0,     0, 1 },  /* amli.no */\n  { 34409,     0,     0, 1 },  /* amot.no */\n  { 34414,     0,     0, 1 },  /* andasuolo.no */\n  { 34424,     0,     0, 1 },  /* andebu.no */\n  { 34432,     0,     0, 1 },  /* andoy.no */\n  { 34439,     0,     0, 1 },  /* ardal.no */\n  { 34445,     0,     0, 1 },  /* aremark.no */\n  { 34453,     0,     0, 1 },  /* arendal.no */\n  {  5690,     0,     0, 1 },  /* arna.no */\n  { 34461,     0,     0, 1 },  /* aseral.no */\n  { 34468,     0,     0, 1 },  /* asker.no */\n  {  4595,     0,     0, 1 },  /* askim.no */\n  { 34474,     0,     0, 1 },  /* askoy.no */\n  { 34480,     0,     0, 1 },  /* askvoll.no */\n  { 34488,     0,     0, 1 },  /* asnes.no */\n  { 34494,     0,     0, 1 },  /* audnedaln.no */\n  { 34504,     0,     0, 1 },  /* aukra.no */\n  { 34510,     0,     0, 1 },  /* aure.no */\n  { 34515,     0,     0, 1 },  /* aurland.no */\n  { 34523,     0,     0, 1 },  /* aurskog-holand.no */\n  { 34538,     0,     0, 1 },  /* austevoll.no */\n  { 34548,     0,     0, 1 },  /* austrheim.no */\n  { 34558,     0,     0, 1 },  /* averoy.no */\n  { 34565,     0,     0, 1 },  /* badaddja.no */\n  { 34574,     0,     0, 1 },  /* bahcavuotna.no */\n  { 34586,     0,     0, 1 },  /* bahccavuotna.no */\n  { 34599,     0,     0, 1 },  /* baidar.no */\n  { 34606,     0,     0, 1 },  /* bajddar.no */\n  {  4815,     0,     0, 1 },  /* balat.no */\n  { 34614,     0,     0, 1 },  /* balestrand.no */\n  { 34625,     0,     0, 1 },  /* ballangen.no */\n  { 34635,     0,     0, 1 },  /* balsfjord.no */\n  { 34645,     0,     0, 1 },  /* bamble.no */\n  { 34652,     0,     0, 1 },  /* bardu.no */\n  { 34658,     0,     0, 1 },  /* barum.no */\n  { 34664,     0,     0, 1 },  /* batsfjord.no */\n  { 34674,     0,     0, 1 },  /* bearalvahki.no */\n  { 34686,     0,     0, 1 },  /* beardu.no */\n  { 34693,     0,     0, 1 },  /* beiarn.no */\n  {  1044,     0,     0, 1 },  /* berg.no */\n  { 15724,     0,     0, 1 },  /* bergen.no */\n  { 34709,     0,     0, 1 },  /* berlevag.no */\n  { 34718,     0,     0, 1 },  /* bievat.no */\n  { 34725,     0,     0, 1 },  /* bindal.no */\n  { 34732,     0,     0, 1 },  /* birkenes.no */\n  { 34741,     0,     0, 1 },  /* bjarkoy.no */\n  { 34749,     0,     0, 1 },  /* bjerkreim.no */\n  {  3607,     0,     0, 1 },  /* bjugn.no */\n  { 10666,     0,     0, 1 },  /* blogspot.no */\n  { 34759,     0,     0, 1 },  /* bodo.no */\n  {  4631,     0,     0, 1 },  /* bokn.no */\n  { 34764,     0,     0, 1 },  /* bomlo.no */\n  { 34770,     0,     0, 1 },  /* bremanger.no */\n  { 34780,     0,     0, 1 },  /* bronnoy.no */\n  { 34788,     0,     0, 1 },  /* bronnoysund.no */\n  { 34800,     0,     0, 1 },  /* brumunddal.no */\n  { 34811,     0,     0, 1 },  /* bryne.no */\n  { 19705,  7074,     1, 1 },  /* bu.no */\n  { 34817,     0,     0, 1 },  /* budejju.no */\n  { 34825,  7075,     1, 1 },  /* buskerud.no */\n  { 34834,     0,     0, 1 },  /* bygland.no */\n  { 34842,     0,     0, 1 },  /* bykle.no */\n  { 34848,     0,     0, 1 },  /* cahcesuolo.no */\n  {   113,     0,     0, 1 },  /* co.no */\n  { 34859,     0,     0, 1 },  /* davvenjarga.no */\n  { 25699,     0,     0, 1 },  /* davvesiida.no */\n  { 34871,     0,     0, 1 },  /* deatnu.no */\n  { 34878,     0,     0, 1 },  /* dep.no */\n  { 34882,     0,     0, 1 },  /* dielddanuorri.no */\n  { 34896,     0,     0, 1 },  /* divtasvuodna.no */\n  { 34909,     0,     0, 1 },  /* divttasvuotna.no */\n  { 26989,     0,     0, 1 },  /* donna.no */\n  { 34923,     0,     0, 1 },  /* dovre.no */\n  {  5362,     0,     0, 1 },  /* drammen.no */\n  { 34929,     0,     0, 1 },  /* drangedal.no */\n  { 34939,     0,     0, 1 },  /* drobak.no */\n  { 34946,     0,     0, 1 },  /* dyroy.no */\n  { 34952,     0,     0, 1 },  /* egersund.no */\n  { 34964,     0,     0, 1 },  /* eid.no */\n  { 34968,     0,     0, 1 },  /* eidfjord.no */\n  { 34700,     0,     0, 1 },  /* eidsberg.no */\n  { 34977,     0,     0, 1 },  /* eidskog.no */\n  { 34985,     0,     0, 1 },  /* eidsvoll.no */\n  { 34994,     0,     0, 1 },  /* eigersund.no */\n  { 35004,     0,     0, 1 },  /* elverum.no */\n  { 35012,     0,     0, 1 },  /* enebakk.no */\n  { 35020,     0,     0, 1 },  /* engerdal.no */\n  {  5760,     0,     0, 1 },  /* etne.no */\n  { 35029,     0,     0, 1 },  /* etnedal.no */\n  { 35037,     0,     0, 1 },  /* evenassi.no */\n  { 35046,     0,     0, 1 },  /* evenes.no */\n  { 35053,     0,     0, 1 },  /* evje-og-hornnes.no */\n  { 35069,     0,     0, 1 },  /* farsund.no */\n  { 35077,     0,     0, 1 },  /* fauske.no */\n  {  4422,     0,     0, 1 },  /* fedje.no */\n  {  2785,     0,     0, 1 },  /* fet.no */\n  { 35084,     0,     0, 1 },  /* fetsund.no */\n  { 29704,     0,     0, 1 },  /* fhs.no */\n  { 35092,     0,     0, 1 },  /* finnoy.no */\n  { 35099,     0,     0, 1 },  /* fitjar.no */\n  { 35106,     0,     0, 1 },  /* fjaler.no */\n  { 35113,     0,     0, 1 },  /* fjell.no */\n  {  4717,     0,     0, 1 },  /* fla.no */\n  { 35119,     0,     0, 1 },  /* flakstad.no */\n  { 35128,     0,     0, 1 },  /* flatanger.no */\n  { 35138,     0,     0, 1 },  /* flekkefjord.no */\n  { 35150,     0,     0, 1 },  /* flesberg.no */\n  { 35159,     0,     0, 1 },  /* flora.no */\n  { 35165,     0,     0, 1 },  /* floro.no */\n  {  3160,  7074,     1, 1 },  /* fm.no */\n  { 35171,     0,     0, 1 },  /* folkebibl.no */\n  { 35181,     0,     0, 1 },  /* folldal.no */\n  { 35189,     0,     0, 1 },  /* forde.no */\n  { 35195,     0,     0, 1 },  /* forsand.no */\n  { 35203,     0,     0, 1 },  /* fosnes.no */\n  { 35210,     0,     0, 1 },  /* frana.no */\n  { 35216,     0,     0, 1 },  /* fredrikstad.no */\n  { 35228,     0,     0, 1 },  /* frei.no */\n  { 35233,     0,     0, 1 },  /* frogn.no */\n  { 35239,     0,     0, 1 },  /* froland.no */\n  { 35247,     0,     0, 1 },  /* frosta.no */\n  { 35254,     0,     0, 1 },  /* froya.no */\n  { 35260,     0,     0, 1 },  /* fuoisku.no */\n  { 35268,     0,     0, 1 },  /* fuossko.no */\n  { 20533,     0,     0, 1 },  /* fusa.no */\n  { 35276,     0,     0, 1 },  /* fylkesbibl.no */\n  { 35287,     0,     0, 1 },  /* fyresdal.no */\n  { 35296,     0,     0, 1 },  /* gaivuotna.no */\n  { 35306,     0,     0, 1 },  /* galsa.no */\n  { 35312,     0,     0, 1 },  /* gamvik.no */\n  { 35319,     0,     0, 1 },  /* gangaviika.no */\n  { 35330,     0,     0, 1 },  /* gaular.no */\n  { 35337,     0,     0, 1 },  /* gausdal.no */\n  { 35345,     0,     0, 1 },  /* giehtavuoatna.no */\n  { 35359,     0,     0, 1 },  /* gildeskal.no */\n  { 35369,     0,     0, 1 },  /* giske.no */\n  { 35375,     0,     0, 1 },  /* gjemnes.no */\n  { 35383,     0,     0, 1 },  /* gjerdrum.no */\n  { 35392,     0,     0, 1 },  /* gjerstad.no */\n  { 35401,     0,     0, 1 },  /* gjesdal.no */\n  { 35409,     0,     0, 1 },  /* gjovik.no */\n  { 35416,     0,     0, 1 },  /* gloppen.no */\n  { 35424,     0,     0, 1 },  /* gol.no */\n  { 35428,     0,     0, 1 },  /* gran.no */\n  { 35433,     0,     0, 1 },  /* grane.no */\n  {  8271,     0,     0, 1 },  /* granvin.no */\n  { 35439,     0,     0, 1 },  /* gratangen.no */\n  { 35449,     0,     0, 1 },  /* grimstad.no */\n  { 35458,     0,     0, 1 },  /* grong.no */\n  { 35464,     0,     0, 1 },  /* grue.no */\n  { 35469,     0,     0, 1 },  /* gulen.no */\n  { 35475,     0,     0, 1 },  /* guovdageaidnu.no */\n  {  2515,     0,     0, 1 },  /* ha.no */\n  { 35489,     0,     0, 1 },  /* habmer.no */\n  { 35496,     0,     0, 1 },  /* hadsel.no */\n  { 35503,     0,     0, 1 },  /* hagebostad.no */\n  { 35514,     0,     0, 1 },  /* halden.no */\n  { 35521,     0,     0, 1 },  /* halsa.no */\n  { 17217,     0,     0, 1 },  /* hamar.no */\n  { 35527,     0,     0, 1 },  /* hamaroy.no */\n  { 35535,     0,     0, 1 },  /* hammarfeasta.no */\n  { 35548,     0,     0, 1 },  /* hammerfest.no */\n  { 35559,     0,     0, 1 },  /* hapmir.no */\n  { 35566,     0,     0, 1 },  /* haram.no */\n  { 34961,     0,     0, 1 },  /* hareid.no */\n  { 35572,     0,     0, 1 },  /* harstad.no */\n  { 35580,     0,     0, 1 },  /* hasvik.no */\n  { 35587,     0,     0, 1 },  /* hattfjelldal.no */\n  { 35600,     0,     0, 1 },  /* haugesund.no */\n  { 35610,  7076,     3, 1 },  /* hedmark.no */\n  { 35618,     0,     0, 1 },  /* hemne.no */\n  { 35624,     0,     0, 1 },  /* hemnes.no */\n  { 35631,     0,     0, 1 },  /* hemsedal.no */\n  { 35643,     0,     0, 1 },  /* herad.no */\n  { 29615,     0,     0, 1 },  /* hitra.no */\n  { 35649,     0,     0, 1 },  /* hjartdal.no */\n  { 35658,     0,     0, 1 },  /* hjelmeland.no */\n  {  2385,  7074,     1, 1 },  /* hl.no */\n  {  3947,  7074,     1, 1 },  /* hm.no */\n  { 35669,     0,     0, 1 },  /* hobol.no */\n  { 30446,     0,     0, 1 },  /* hof.no */\n  { 35675,     0,     0, 1 },  /* hokksund.no */\n  { 35684,     0,     0, 1 },  /* hol.no */\n  { 35688,     0,     0, 1 },  /* hole.no */\n  { 35693,     0,     0, 1 },  /* holmestrand.no */\n  { 35705,     0,     0, 1 },  /* holtalen.no */\n  { 35714,     0,     0, 1 },  /* honefoss.no */\n  { 15252,  7079,     1, 1 },  /* hordaland.no */\n  { 35723,     0,     0, 1 },  /* hornindal.no */\n  { 35733,     0,     0, 1 },  /* horten.no */\n  { 35740,     0,     0, 1 },  /* hoyanger.no */\n  { 35749,     0,     0, 1 },  /* hoylandet.no */\n  { 35759,     0,     0, 1 },  /* hurdal.no */\n  { 35766,     0,     0, 1 },  /* hurum.no */\n  { 35772,     0,     0, 1 },  /* hvaler.no */\n  { 35779,     0,     0, 1 },  /* hyllestad.no */\n  { 35789,     0,     0, 1 },  /* ibestad.no */\n  { 35797,     0,     0, 1 },  /* idrett.no */\n  { 35804,     0,     0, 1 },  /* inderoy.no */\n  { 35812,     0,     0, 1 },  /* iveland.no */\n  {  3766,     0,     0, 1 },  /* ivgu.no */\n  { 35820,  7074,     1, 1 },  /* jan-mayen.no */\n  { 35830,     0,     0, 1 },  /* jessheim.no */\n  { 35839,     0,     0, 1 },  /* jevnaker.no */\n  { 35848,     0,     0, 1 },  /* jolster.no */\n  { 35856,     0,     0, 1 },  /* jondal.no */\n  { 35863,     0,     0, 1 },  /* jorpeland.no */\n  { 34311,     0,     0, 1 },  /* kafjord.no */\n  { 35873,     0,     0, 1 },  /* karasjohka.no */\n  { 35884,     0,     0, 1 },  /* karasjok.no */\n  { 35893,     0,     0, 1 },  /* karlsoy.no */\n  { 35901,     0,     0, 1 },  /* karmoy.no */\n  { 35908,     0,     0, 1 },  /* kautokeino.no */\n  { 35919,     0,     0, 1 },  /* kirkenes.no */\n  { 35928,     0,     0, 1 },  /* klabu.no */\n  { 11444,     0,     0, 1 },  /* klepp.no */\n  { 35934,     0,     0, 1 },  /* kommune.no */\n  { 35942,     0,     0, 1 },  /* kongsberg.no */\n  { 35952,     0,     0, 1 },  /* kongsvinger.no */\n  { 35964,     0,     0, 1 },  /* kopervik.no */\n  { 35973,     0,     0, 1 },  /* kraanghke.no */\n  { 35983,     0,     0, 1 },  /* kragero.no */\n  { 35991,     0,     0, 1 },  /* kristiansand.no */\n  { 36004,     0,     0, 1 },  /* kristiansund.no */\n  { 36017,     0,     0, 1 },  /* krodsherad.no */\n  { 36028,     0,     0, 1 },  /* krokstadelva.no */\n  { 36041,     0,     0, 1 },  /* kvafjord.no */\n  { 36050,     0,     0, 1 },  /* kvalsund.no */\n  {   356,     0,     0, 1 },  /* kvam.no */\n  { 36059,     0,     0, 1 },  /* kvanangen.no */\n  { 36069,     0,     0, 1 },  /* kvinesdal.no */\n  { 36079,     0,     0, 1 },  /* kvinnherad.no */\n  { 36090,     0,     0, 1 },  /* kviteseid.no */\n  { 36100,     0,     0, 1 },  /* kvitsoy.no */\n  { 36108,     0,     0, 1 },  /* laakesvuemie.no */\n  { 36121,     0,     0, 1 },  /* lahppi.no */\n  { 36128,     0,     0, 1 },  /* langevag.no */\n  { 34438,     0,     0, 1 },  /* lardal.no */\n  { 36137,     0,     0, 1 },  /* larvik.no */\n  { 36144,     0,     0, 1 },  /* lavagis.no */\n  { 36152,     0,     0, 1 },  /* lavangen.no */\n  { 36161,     0,     0, 1 },  /* leangaviika.no */\n  { 36173,     0,     0, 1 },  /* lebesby.no */\n  { 36181,     0,     0, 1 },  /* leikanger.no */\n  { 36191,     0,     0, 1 },  /* leirfjord.no */\n  { 36201,     0,     0, 1 },  /* leirvik.no */\n  { 36214,     0,     0, 1 },  /* leka.no */\n  { 36219,     0,     0, 1 },  /* leksvik.no */\n  { 36227,     0,     0, 1 },  /* lenvik.no */\n  { 36234,     0,     0, 1 },  /* lerdal.no */\n  { 36241,     0,     0, 1 },  /* lesja.no */\n  { 36247,     0,     0, 1 },  /* levanger.no */\n  {  2735,     0,     0, 1 },  /* lier.no */\n  { 36256,     0,     0, 1 },  /* lierne.no */\n  { 36263,     0,     0, 1 },  /* lillehammer.no */\n  { 36275,     0,     0, 1 },  /* lillesand.no */\n  { 36285,     0,     0, 1 },  /* lindas.no */\n  { 36292,     0,     0, 1 },  /* lindesnes.no */\n  { 36302,     0,     0, 1 },  /* loabat.no */\n  { 36309,     0,     0, 1 },  /* lodingen.no */\n  { 17163,     0,     0, 1 },  /* lom.no */\n  { 36318,     0,     0, 1 },  /* loppa.no */\n  { 36324,     0,     0, 1 },  /* lorenskog.no */\n  { 36334,     0,     0, 1 },  /* loten.no */\n  { 36342,     0,     0, 1 },  /* lund.no */\n  { 36347,     0,     0, 1 },  /* lunner.no */\n  { 36354,     0,     0, 1 },  /* luroy.no */\n  { 36360,     0,     0, 1 },  /* luster.no */\n  { 36367,     0,     0, 1 },  /* lyngdal.no */\n  { 36375,     0,     0, 1 },  /* lyngen.no */\n  { 36382,     0,     0, 1 },  /* malatvuopmi.no */\n  {  5142,     0,     0, 1 },  /* malselv.no */\n  { 36394,     0,     0, 1 },  /* malvik.no */\n  { 36401,     0,     0, 1 },  /* mandal.no */\n  { 36408,     0,     0, 1 },  /* marker.no */\n  { 36415,     0,     0, 1 },  /* marnardal.no */\n  { 36425,     0,     0, 1 },  /* masfjorden.no */\n  {  7401,     0,     0, 1 },  /* masoy.no */\n  { 36436,     0,     0, 1 },  /* matta-varjjat.no */\n  { 35662,     0,     0, 1 },  /* meland.no */\n  { 36450,     0,     0, 1 },  /* meldal.no */\n  { 36457,     0,     0, 1 },  /* melhus.no */\n  { 36464,     0,     0, 1 },  /* meloy.no */\n  { 36470,     0,     0, 1 },  /* meraker.no */\n  { 36478,     0,     0, 1 },  /* midsund.no */\n  { 36486,     0,     0, 1 },  /* midtre-gauldal.no */\n  {  4195,     0,     0, 1 },  /* mil.no */\n  { 36501,     0,     0, 1 },  /* mjondalen.no */\n  { 36511,     0,     0, 1 },  /* mo-i-rana.no */\n  { 36521,     0,     0, 1 },  /* moareke.no */\n  { 36529,     0,     0, 1 },  /* modalen.no */\n  { 36537,     0,     0, 1 },  /* modum.no */\n  { 36543,     0,     0, 1 },  /* molde.no */\n  { 36549,  7080,     2, 1 },  /* more-og-romsdal.no */\n  { 36565,     0,     0, 1 },  /* mosjoen.no */\n  { 36573,     0,     0, 1 },  /* moskenes.no */\n  { 17792,     0,     0, 1 },  /* moss.no */\n  { 36582,     0,     0, 1 },  /* mosvik.no */\n  {  5601,  7074,     1, 1 },  /* mr.no */\n  { 36589,     0,     0, 1 },  /* muosat.no */\n  {  5644,     0,     0, 1 },  /* museum.no */\n  { 36596,     0,     0, 1 },  /* naamesjevuemie.no */\n  { 36611,     0,     0, 1 },  /* namdalseid.no */\n  { 36622,     0,     0, 1 },  /* namsos.no */\n  { 36629,     0,     0, 1 },  /* namsskogan.no */\n  { 36640,     0,     0, 1 },  /* nannestad.no */\n  { 36650,     0,     0, 1 },  /* naroy.no */\n  { 36656,     0,     0, 1 },  /* narviika.no */\n  { 36665,     0,     0, 1 },  /* narvik.no */\n  { 36672,     0,     0, 1 },  /* naustdal.no */\n  { 36681,     0,     0, 1 },  /* navuotna.no */\n  { 36690,     0,     0, 1 },  /* nedre-eiker.no */\n  { 36702,     0,     0, 1 },  /* nesna.no */\n  { 36708,     0,     0, 1 },  /* nesodden.no */\n  { 36717,     0,     0, 1 },  /* nesoddtangen.no */\n  { 36730,     0,     0, 1 },  /* nesseby.no */\n  { 36738,     0,     0, 1 },  /* nesset.no */\n  { 36745,     0,     0, 1 },  /* nissedal.no */\n  { 36754,     0,     0, 1 },  /* nittedal.no */\n  {  1071,  7074,     1, 1 },  /* nl.no */\n  { 36763,     0,     0, 1 },  /* nord-aurdal.no */\n  { 36775,     0,     0, 1 },  /* nord-fron.no */\n  { 36785,     0,     0, 1 },  /* nord-odal.no */\n  { 36795,     0,     0, 1 },  /* norddal.no */\n  { 36803,     0,     0, 1 },  /* nordkapp.no */\n  { 36812,  7082,     4, 1 },  /* nordland.no */\n  { 36821,     0,     0, 1 },  /* nordre-land.no */\n  { 36833,     0,     0, 1 },  /* nordreisa.no */\n  { 36843,     0,     0, 1 },  /* nore-og-uvdal.no */\n  { 36857,     0,     0, 1 },  /* notodden.no */\n  { 36866,     0,     0, 1 },  /* notteroy.no */\n  {    97,  7074,     1, 1 },  /* nt.no */\n  { 36875,     0,     0, 1 },  /* odda.no */\n  {  6450,  7074,     1, 1 },  /* of.no */\n  { 36880,     0,     0, 1 },  /* oksnes.no */\n  {   452,  7074,     1, 1 },  /* ol.no */\n  { 36887,     0,     0, 1 },  /* omasvuotna.no */\n  { 36898,     0,     0, 1 },  /* oppdal.no */\n  { 36905,     0,     0, 1 },  /* oppegard.no */\n  { 36914,     0,     0, 1 },  /* orkanger.no */\n  { 36923,     0,     0, 1 },  /* orkdal.no */\n  {  4782,     0,     0, 1 },  /* orland.no */\n  { 36930,     0,     0, 1 },  /* orskog.no */\n  { 36937,     0,     0, 1 },  /* orsta.no */\n  { 26376,     0,     0, 1 },  /* osen.no */\n  { 36943,  7074,     1, 1 },  /* oslo.no */\n  { 36948,     0,     0, 1 },  /* osoyro.no */\n  { 36955,     0,     0, 1 },  /* osteroy.no */\n  { 36963,  7086,     1, 1 },  /* ostfold.no */\n  { 36971,     0,     0, 1 },  /* ostre-toten.no */\n  { 36983,     0,     0, 1 },  /* overhalla.no */\n  { 36993,     0,     0, 1 },  /* ovre-eiker.no */\n  { 37004,     0,     0, 1 },  /* oyer.no */\n  { 37009,     0,     0, 1 },  /* oygarden.no */\n  { 37018,     0,     0, 1 },  /* oystre-slidre.no */\n  { 37032,     0,     0, 1 },  /* porsanger.no */\n  { 37042,     0,     0, 1 },  /* porsangu.no */\n  { 37051,     0,     0, 1 },  /* porsgrunn.no */\n  { 11393,     0,     0, 1 },  /* priv.no */\n  {  7983,     0,     0, 1 },  /* rade.no */\n  { 37061,     0,     0, 1 },  /* radoy.no */\n  { 37067,     0,     0, 1 },  /* rahkkeravju.no */\n  { 37079,     0,     0, 1 },  /* raholt.no */\n  { 37086,     0,     0, 1 },  /* raisa.no */\n  { 37092,     0,     0, 1 },  /* rakkestad.no */\n  { 37102,     0,     0, 1 },  /* ralingen.no */\n  { 35211,     0,     0, 1 },  /* rana.no */\n  { 37111,     0,     0, 1 },  /* randaberg.no */\n  { 37121,     0,     0, 1 },  /* rauma.no */\n  { 37127,     0,     0, 1 },  /* rendalen.no */\n  { 37136,     0,     0, 1 },  /* rennebu.no */\n  { 37144,     0,     0, 1 },  /* rennesoy.no */\n  { 37153,     0,     0, 1 },  /* rindal.no */\n  { 37160,     0,     0, 1 },  /* ringebu.no */\n  { 37168,     0,     0, 1 },  /* ringerike.no */\n  { 37178,     0,     0, 1 },  /* ringsaker.no */\n  { 37188,     0,     0, 1 },  /* risor.no */\n  { 37194,     0,     0, 1 },  /* rissa.no */\n  {  3271,  7074,     1, 1 },  /* rl.no */\n  { 37200,     0,     0, 1 },  /* roan.no */\n  { 37205,     0,     0, 1 },  /* rodoy.no */\n  { 37211,     0,     0, 1 },  /* rollag.no */\n  { 37219,     0,     0, 1 },  /* romsa.no */\n  { 37225,     0,     0, 1 },  /* romskog.no */\n  { 37233,     0,     0, 1 },  /* roros.no */\n  { 37239,     0,     0, 1 },  /* rost.no */\n  { 37244,     0,     0, 1 },  /* royken.no */\n  { 37251,     0,     0, 1 },  /* royrvik.no */\n  { 37259,     0,     0, 1 },  /* ruovat.no */\n  { 37266,     0,     0, 1 },  /* rygge.no */\n  { 37272,     0,     0, 1 },  /* salangen.no */\n  {  2792,     0,     0, 1 },  /* salat.no */\n  { 37281,     0,     0, 1 },  /* saltdal.no */\n  { 37289,     0,     0, 1 },  /* samnanger.no */\n  { 37299,     0,     0, 1 },  /* sandefjord.no */\n  { 37310,     0,     0, 1 },  /* sandnes.no */\n  { 37318,     0,     0, 1 },  /* sandnessjoen.no */\n  { 34431,     0,     0, 1 },  /* sandoy.no */\n  {  6064,     0,     0, 1 },  /* sarpsborg.no */\n  { 37331,     0,     0, 1 },  /* sauda.no */\n  { 35640,     0,     0, 1 },  /* sauherad.no */\n  { 30198,     0,     0, 1 },  /* sel.no */\n  { 37337,     0,     0, 1 },  /* selbu.no */\n  { 37343,     0,     0, 1 },  /* selje.no */\n  { 37349,     0,     0, 1 },  /* seljord.no */\n  { 11497,  7074,     1, 1 },  /* sf.no */\n  { 37357,     0,     0, 1 },  /* siellak.no */\n  { 37365,     0,     0, 1 },  /* sigdal.no */\n  { 37372,     0,     0, 1 },  /* siljan.no */\n  { 37379,     0,     0, 1 },  /* sirdal.no */\n  { 37386,     0,     0, 1 },  /* skanit.no */\n  { 37393,     0,     0, 1 },  /* skanland.no */\n  { 37402,     0,     0, 1 },  /* skaun.no */\n  { 37408,     0,     0, 1 },  /* skedsmo.no */\n  { 37416,     0,     0, 1 },  /* skedsmokorset.no */\n  {  4585,     0,     0, 1 },  /* ski.no */\n  { 37430,     0,     0, 1 },  /* skien.no */\n  { 37436,     0,     0, 1 },  /* skierva.no */\n  {  8224,     0,     0, 1 },  /* skiptvet.no */\n  { 37444,     0,     0, 1 },  /* skjak.no */\n  { 37450,     0,     0, 1 },  /* skjervoy.no */\n  { 37459,     0,     0, 1 },  /* skodje.no */\n  { 37466,     0,     0, 1 },  /* slattum.no */\n  { 37474,     0,     0, 1 },  /* smola.no */\n  { 37480,     0,     0, 1 },  /* snaase.no */\n  { 37487,     0,     0, 1 },  /* snasa.no */\n  { 37493,     0,     0, 1 },  /* snillfjord.no */\n  { 37504,     0,     0, 1 },  /* snoasa.no */\n  { 37511,     0,     0, 1 },  /* sogndal.no */\n  { 37519,     0,     0, 1 },  /* sogne.no */\n  { 37525,     0,     0, 1 },  /* sokndal.no */\n  { 37533,     0,     0, 1 },  /* sola.no */\n  { 36340,     0,     0, 1 },  /* solund.no */\n  { 37538,     0,     0, 1 },  /* somna.no */\n  { 37544,     0,     0, 1 },  /* sondre-land.no */\n  { 37556,     0,     0, 1 },  /* songdalen.no */\n  { 37566,     0,     0, 1 },  /* sor-aurdal.no */\n  { 37577,     0,     0, 1 },  /* sor-fron.no */\n  { 37586,     0,     0, 1 },  /* sor-odal.no */\n  { 37595,     0,     0, 1 },  /* sor-varanger.no */\n  { 37608,     0,     0, 1 },  /* sorfold.no */\n  { 37616,     0,     0, 1 },  /* sorreisa.no */\n  { 37625,     0,     0, 1 },  /* sortland.no */\n  { 37634,     0,     0, 1 },  /* sorum.no */\n  { 37640,     0,     0, 1 },  /* spjelkavik.no */\n  { 37651,     0,     0, 1 },  /* spydeberg.no */\n  {   619,  7074,     1, 1 },  /* st.no */\n  { 37661,     0,     0, 1 },  /* stange.no */\n  { 37668,     0,     0, 1 },  /* stat.no */\n  { 37673,     0,     0, 1 },  /* stathelle.no */\n  { 37683,     0,     0, 1 },  /* stavanger.no */\n  { 37693,     0,     0, 1 },  /* stavern.no */\n  { 37701,     0,     0, 1 },  /* steigen.no */\n  { 37709,     0,     0, 1 },  /* steinkjer.no */\n  { 37719,     0,     0, 1 },  /* stjordal.no */\n  { 37728,     0,     0, 1 },  /* stjordalshalsen.no */\n  { 37744,     0,     0, 1 },  /* stokke.no */\n  { 37751,     0,     0, 1 },  /* stor-elvdal.no */\n  { 37763,     0,     0, 1 },  /* stord.no */\n  { 37769,     0,     0, 1 },  /* stordal.no */\n  { 37777,     0,     0, 1 },  /* storfjord.no */\n  { 34618,     0,     0, 1 },  /* strand.no */\n  { 37787,     0,     0, 1 },  /* stranda.no */\n  { 11927,     0,     0, 1 },  /* stryn.no */\n  { 37795,     0,     0, 1 },  /* sula.no */\n  { 37800,     0,     0, 1 },  /* suldal.no */\n  { 34369,     0,     0, 1 },  /* sund.no */\n  { 37807,     0,     0, 1 },  /* sunndal.no */\n  { 37815,     0,     0, 1 },  /* surnadal.no */\n  { 37824,  7074,     1, 1 },  /* svalbard.no */\n  { 37833,     0,     0, 1 },  /* sveio.no */\n  { 37839,     0,     0, 1 },  /* svelvik.no */\n  { 37847,     0,     0, 1 },  /* sykkylven.no */\n  { 26078,     0,     0, 1 },  /* tana.no */\n  { 37857,     0,     0, 1 },  /* tananger.no */\n  { 37866,  7087,     2, 1 },  /* telemark.no */\n  {  7261,     0,     0, 1 },  /* time.no */\n  { 37875,     0,     0, 1 },  /* tingvoll.no */\n  { 37884,     0,     0, 1 },  /* tinn.no */\n  { 37889,     0,     0, 1 },  /* tjeldsund.no */\n  { 37899,     0,     0, 1 },  /* tjome.no */\n  {  7910,  7074,     1, 1 },  /* tm.no */\n  { 37745,     0,     0, 1 },  /* tokke.no */\n  { 37905,     0,     0, 1 },  /* tolga.no */\n  { 37911,     0,     0, 1 },  /* tonsberg.no */\n  { 37920,     0,     0, 1 },  /* torsken.no */\n  {  3302,  7074,     1, 1 },  /* tr.no */\n  { 37928,     0,     0, 1 },  /* trana.no */\n  { 37934,     0,     0, 1 },  /* tranby.no */\n  { 37941,     0,     0, 1 },  /* tranoy.no */\n  { 37948,     0,     0, 1 },  /* troandin.no */\n  { 37957,     0,     0, 1 },  /* trogstad.no */\n  { 37218,     0,     0, 1 },  /* tromsa.no */\n  { 37966,     0,     0, 1 },  /* tromso.no */\n  { 37973,     0,     0, 1 },  /* trondheim.no */\n  { 37983,     0,     0, 1 },  /* trysil.no */\n  { 37990,     0,     0, 1 },  /* tvedestrand.no */\n  { 38002,     0,     0, 1 },  /* tydal.no */\n  { 38008,     0,     0, 1 },  /* tynset.no */\n  { 38015,     0,     0, 1 },  /* tysfjord.no */\n  { 38024,     0,     0, 1 },  /* tysnes.no */\n  { 38031,     0,     0, 1 },  /* tysvar.no */\n  { 38038,     0,     0, 1 },  /* ullensaker.no */\n  { 38049,     0,     0, 1 },  /* ullensvang.no */\n  { 38060,     0,     0, 1 },  /* ulvik.no */\n  { 38066,     0,     0, 1 },  /* unjarga.no */\n  { 38074,     0,     0, 1 },  /* utsira.no */\n  {   834,  7074,     1, 1 },  /* va.no */\n  { 38081,     0,     0, 1 },  /* vaapste.no */\n  { 38089,     0,     0, 1 },  /* vadso.no */\n  { 38095,     0,     0, 1 },  /* vaga.no */\n  { 38100,     0,     0, 1 },  /* vagan.no */\n  { 38106,     0,     0, 1 },  /* vagsoy.no */\n  { 38113,     0,     0, 1 },  /* vaksdal.no */\n  { 38121,     0,     0, 1 },  /* valle.no */\n  { 38055,     0,     0, 1 },  /* vang.no */\n  { 38127,     0,     0, 1 },  /* vanylven.no */\n  { 38136,     0,     0, 1 },  /* vardo.no */\n  { 38142,     0,     0, 1 },  /* varggat.no */\n  { 38150,     0,     0, 1 },  /* varoy.no */\n  { 38156,     0,     0, 1 },  /* vefsn.no */\n  { 38162,     0,     0, 1 },  /* vega.no */\n  { 38167,     0,     0, 1 },  /* vegarshei.no */\n  { 38177,     0,     0, 1 },  /* vennesla.no */\n  { 38186,     0,     0, 1 },  /* verdal.no */\n  { 38193,     0,     0, 1 },  /* verran.no */\n  { 38200,     0,     0, 1 },  /* vestby.no */\n  { 38207,  7089,     1, 1 },  /* vestfold.no */\n  { 38216,     0,     0, 1 },  /* vestnes.no */\n  { 38224,     0,     0, 1 },  /* vestre-slidre.no */\n  { 38238,     0,     0, 1 },  /* vestre-toten.no */\n  { 38251,     0,     0, 1 },  /* vestvagoy.no */\n  { 38261,     0,     0, 1 },  /* vevelstad.no */\n  {  9687,  7074,     1, 1 },  /* vf.no */\n  {  3759,     0,     0, 1 },  /* vgs.no */\n  {  6943,     0,     0, 1 },  /* vik.no */\n  { 38271,     0,     0, 1 },  /* vikna.no */\n  { 38277,     0,     0, 1 },  /* vindafjord.no */\n  { 38288,     0,     0, 1 },  /* voagat.no */\n  { 38295,     0,     0, 1 },  /* volda.no */\n  { 38301,     0,     0, 1 },  /* voss.no */\n  { 38306,     0,     0, 1 },  /* vossevangen.no */\n  { 38318,     0,     0, 1 },  /* xn--andy-ira.no */\n  { 38331,     0,     0, 1 },  /* xn--asky-ira.no */\n  { 38344,     0,     0, 1 },  /* xn--aurskog-hland-jnb.no */\n  { 38366,     0,     0, 1 },  /* xn--avery-yua.no */\n  { 38380,     0,     0, 1 },  /* xn--bdddj-mrabd.no */\n  { 38396,     0,     0, 1 },  /* xn--bearalvhki-y4a.no */\n  { 38415,     0,     0, 1 },  /* xn--berlevg-jxa.no */\n  { 38431,     0,     0, 1 },  /* xn--bhcavuotna-s4a.no */\n  { 38450,     0,     0, 1 },  /* xn--bhccavuotna-k7a.no */\n  { 38470,     0,     0, 1 },  /* xn--bidr-5nac.no */\n  {  6528,     0,     0, 1 },  /* xn--bievt-0qa.no */\n  { 38484,     0,     0, 1 },  /* xn--bjarky-fya.no */\n  { 38499,     0,     0, 1 },  /* xn--bjddar-pta.no */\n  { 38514,     0,     0, 1 },  /* xn--blt-elab.no */\n  { 38527,     0,     0, 1 },  /* xn--bmlo-gra.no */\n  { 38540,     0,     0, 1 },  /* xn--bod-2na.no */\n  { 38552,     0,     0, 1 },  /* xn--brnny-wuac.no */\n  { 38567,     0,     0, 1 },  /* xn--brnnysund-m8ac.no */\n  { 38586,     0,     0, 1 },  /* xn--brum-voa.no */\n  { 38599,     0,     0, 1 },  /* xn--btsfjord-9za.no */\n  { 38616,     0,     0, 1 },  /* xn--davvenjrga-y4a.no */\n  { 38635,     0,     0, 1 },  /* xn--dnna-gra.no */\n  { 38648,     0,     0, 1 },  /* xn--drbak-wua.no */\n  { 38662,     0,     0, 1 },  /* xn--dyry-ira.no */\n  { 38675,     0,     0, 1 },  /* xn--eveni-0qa01ga.no */\n  { 38693,     0,     0, 1 },  /* xn--finny-yua.no */\n  { 38707,     0,     0, 1 },  /* xn--fjord-lra.no */\n  { 38721,     0,     0, 1 },  /* xn--fl-zia.no */\n  { 38732,     0,     0, 1 },  /* xn--flor-jra.no */\n  { 38745,     0,     0, 1 },  /* xn--frde-gra.no */\n  { 38758,     0,     0, 1 },  /* xn--frna-woa.no */\n  { 38771,     0,     0, 1 },  /* xn--frya-hra.no */\n  { 38784,     0,     0, 1 },  /* xn--ggaviika-8ya47h.no */\n  { 38804,     0,     0, 1 },  /* xn--gildeskl-g0a.no */\n  { 38821,     0,     0, 1 },  /* xn--givuotna-8ya.no */\n  { 38838,     0,     0, 1 },  /* xn--gjvik-wua.no */\n  { 38852,     0,     0, 1 },  /* xn--gls-elac.no */\n  { 38865,     0,     0, 1 },  /* xn--h-2fa.no */\n  { 38875,     0,     0, 1 },  /* xn--hbmer-xqa.no */\n  { 38889,     0,     0, 1 },  /* xn--hcesuolo-7ya35b.no */\n  { 38909,     0,     0, 1 },  /* xn--hgebostad-g3a.no */\n  { 38927,     0,     0, 1 },  /* xn--hmmrfeasta-s4ac.no */\n  { 38947,     0,     0, 1 },  /* xn--hnefoss-q1a.no */\n  { 38963,     0,     0, 1 },  /* xn--hobl-ira.no */\n  { 38976,     0,     0, 1 },  /* xn--holtlen-hxa.no */\n  { 38992,     0,     0, 1 },  /* xn--hpmir-xqa.no */\n  { 39006,     0,     0, 1 },  /* xn--hyanger-q1a.no */\n  { 39022,     0,     0, 1 },  /* xn--hylandet-54a.no */\n  { 39039,     0,     0, 1 },  /* xn--indery-fya.no */\n  { 39054,     0,     0, 1 },  /* xn--jlster-bya.no */\n  { 39069,     0,     0, 1 },  /* xn--jrpeland-54a.no */\n  { 39086,     0,     0, 1 },  /* xn--karmy-yua.no */\n  { 39100,     0,     0, 1 },  /* xn--kfjord-iua.no */\n  { 39115,     0,     0, 1 },  /* xn--klbu-woa.no */\n  { 39128,     0,     0, 1 },  /* xn--koluokta-7ya57h.no */\n  { 39148,     0,     0, 1 },  /* xn--krager-gya.no */\n  { 39163,     0,     0, 1 },  /* xn--kranghke-b0a.no */\n  { 39180,     0,     0, 1 },  /* xn--krdsherad-m8a.no */\n  { 39198,     0,     0, 1 },  /* xn--krehamn-dxa.no */\n  { 39214,     0,     0, 1 },  /* xn--krjohka-hwab49j.no */\n  { 39234,     0,     0, 1 },  /* xn--ksnes-uua.no */\n  { 39248,     0,     0, 1 },  /* xn--kvfjord-nxa.no */\n  { 39264,     0,     0, 1 },  /* xn--kvitsy-fya.no */\n  { 39279,     0,     0, 1 },  /* xn--kvnangen-k0a.no */\n  { 39296,     0,     0, 1 },  /* xn--l-1fa.no */\n  { 39306,     0,     0, 1 },  /* xn--laheadju-7ya.no */\n  { 39323,     0,     0, 1 },  /* xn--langevg-jxa.no */\n  { 39339,     0,     0, 1 },  /* xn--ldingen-q1a.no */\n  { 39355,     0,     0, 1 },  /* xn--leagaviika-52b.no */\n  { 39374,     0,     0, 1 },  /* xn--lesund-hua.no */\n  { 39389,     0,     0, 1 },  /* xn--lgrd-poac.no */\n  { 39403,     0,     0, 1 },  /* xn--lhppi-xqa.no */\n  { 39417,     0,     0, 1 },  /* xn--linds-pra.no */\n  { 39431,     0,     0, 1 },  /* xn--loabt-0qa.no */\n  { 39445,     0,     0, 1 },  /* xn--lrdal-sra.no */\n  { 39459,     0,     0, 1 },  /* xn--lrenskog-54a.no */\n  { 39476,     0,     0, 1 },  /* xn--lt-liac.no */\n  { 39488,     0,     0, 1 },  /* xn--lten-gra.no */\n  { 39501,     0,     0, 1 },  /* xn--lury-ira.no */\n  { 39514,     0,     0, 1 },  /* xn--mely-ira.no */\n  { 39527,     0,     0, 1 },  /* xn--merker-kua.no */\n  { 39542,     0,     0, 1 },  /* xn--mjndalen-64a.no */\n  { 39559,     0,     0, 1 },  /* xn--mlatvuopmi-s4a.no */\n  { 39578,     0,     0, 1 },  /* xn--mli-tla.no */\n  { 39590,     0,     0, 1 },  /* xn--mlselv-iua.no */\n  { 39605,     0,     0, 1 },  /* xn--moreke-jua.no */\n  { 39620,     0,     0, 1 },  /* xn--mosjen-eya.no */\n  { 39635,     0,     0, 1 },  /* xn--mot-tla.no */\n  { 39647,  7090,     2, 1 },  /* xn--mre-og-romsdal-qqb.no */\n  { 39670,     0,     0, 1 },  /* xn--msy-ula0h.no */\n  { 39684,     0,     0, 1 },  /* xn--mtta-vrjjat-k7af.no */\n  { 39705,     0,     0, 1 },  /* xn--muost-0qa.no */\n  {  1545,     0,     0, 1 },  /* xn--nmesjevuemie-tcba.no */\n  { 39719,     0,     0, 1 },  /* xn--nry-yla5g.no */\n  { 39733,     0,     0, 1 },  /* xn--nttery-byae.no */\n  { 39749,     0,     0, 1 },  /* xn--nvuotna-hwa.no */\n  { 39765,     0,     0, 1 },  /* xn--oppegrd-ixa.no */\n  { 39781,     0,     0, 1 },  /* xn--ostery-fya.no */\n  { 39796,     0,     0, 1 },  /* xn--osyro-wua.no */\n  { 39810,     0,     0, 1 },  /* xn--porsgu-sta26f.no */\n  { 39828,     0,     0, 1 },  /* xn--rady-ira.no */\n  { 39841,     0,     0, 1 },  /* xn--rdal-poa.no */\n  { 39854,     0,     0, 1 },  /* xn--rde-ula.no */\n  {  5695,     0,     0, 1 },  /* xn--rdy-0nab.no */\n  { 39866,     0,     0, 1 },  /* xn--rennesy-v1a.no */\n  {   175,     0,     0, 1 },  /* xn--rhkkervju-01af.no */\n  { 39882,     0,     0, 1 },  /* xn--rholt-mra.no */\n  { 39896,     0,     0, 1 },  /* xn--risa-5na.no */\n  { 39909,     0,     0, 1 },  /* xn--risr-ira.no */\n  { 39922,     0,     0, 1 },  /* xn--rland-uua.no */\n  { 39936,     0,     0, 1 },  /* xn--rlingen-mxa.no */\n  { 39952,     0,     0, 1 },  /* xn--rmskog-bya.no */\n  { 39967,     0,     0, 1 },  /* xn--rros-gra.no */\n  { 39980,     0,     0, 1 },  /* xn--rskog-uua.no */\n  { 39994,     0,     0, 1 },  /* xn--rst-0na.no */\n  { 40006,     0,     0, 1 },  /* xn--rsta-fra.no */\n  { 40019,     0,     0, 1 },  /* xn--ryken-vua.no */\n  { 40033,     0,     0, 1 },  /* xn--ryrvik-bya.no */\n  { 40048,     0,     0, 1 },  /* xn--s-1fa.no */\n  {  3424,     0,     0, 1 },  /* xn--sandnessjen-ogb.no */\n  { 40058,     0,     0, 1 },  /* xn--sandy-yua.no */\n  { 40072,     0,     0, 1 },  /* xn--seral-lra.no */\n  { 40086,     0,     0, 1 },  /* xn--sgne-gra.no */\n  { 40099,     0,     0, 1 },  /* xn--skierv-uta.no */\n  { 40114,     0,     0, 1 },  /* xn--skjervy-v1a.no */\n  { 40130,     0,     0, 1 },  /* xn--skjk-soa.no */\n  { 40143,     0,     0, 1 },  /* xn--sknit-yqa.no */\n  { 40157,     0,     0, 1 },  /* xn--sknland-fxa.no */\n  { 40173,     0,     0, 1 },  /* xn--slat-5na.no */\n  { 40186,     0,     0, 1 },  /* xn--slt-elab.no */\n  { 40199,     0,     0, 1 },  /* xn--smla-hra.no */\n  { 40212,     0,     0, 1 },  /* xn--smna-gra.no */\n  { 40225,     0,     0, 1 },  /* xn--snase-nra.no */\n  { 40239,     0,     0, 1 },  /* xn--sndre-land-0cb.no */\n  { 40258,     0,     0, 1 },  /* xn--snes-poa.no */\n  { 40271,     0,     0, 1 },  /* xn--snsa-roa.no */\n  { 40284,     0,     0, 1 },  /* xn--sr-aurdal-l8a.no */\n  { 40302,     0,     0, 1 },  /* xn--sr-fron-q1a.no */\n  { 40318,     0,     0, 1 },  /* xn--sr-odal-q1a.no */\n  { 40334,     0,     0, 1 },  /* xn--sr-varanger-ggb.no */\n  { 40354,     0,     0, 1 },  /* xn--srfold-bya.no */\n  { 40369,     0,     0, 1 },  /* xn--srreisa-q1a.no */\n  { 40385,     0,     0, 1 },  /* xn--srum-gra.no */\n  { 40398,  7092,     1, 1 },  /* xn--stfold-9xa.no */\n  { 40413,     0,     0, 1 },  /* xn--stjrdal-s1a.no */\n  { 40429,     0,     0, 1 },  /* xn--stjrdalshalsen-sqb.no */\n  { 40452,     0,     0, 1 },  /* xn--stre-toten-zcb.no */\n  { 40471,     0,     0, 1 },  /* xn--tjme-hra.no */\n  { 40484,     0,     0, 1 },  /* xn--tnsberg-q1a.no */\n  { 40500,     0,     0, 1 },  /* xn--trany-yua.no */\n  { 40514,     0,     0, 1 },  /* xn--trgstad-r1a.no */\n  { 40530,     0,     0, 1 },  /* xn--trna-woa.no */\n  { 40543,     0,     0, 1 },  /* xn--troms-zua.no */\n  { 40557,     0,     0, 1 },  /* xn--tysvr-vra.no */\n  { 40571,     0,     0, 1 },  /* xn--unjrga-rta.no */\n  { 40586,     0,     0, 1 },  /* xn--vads-jra.no */\n  { 40599,     0,     0, 1 },  /* xn--vard-jra.no */\n  { 40612,     0,     0, 1 },  /* xn--vegrshei-c0a.no */\n  { 40629,     0,     0, 1 },  /* xn--vestvgy-ixa6o.no */\n  { 40647,     0,     0, 1 },  /* xn--vg-yiab.no */\n  { 40659,     0,     0, 1 },  /* xn--vgan-qoa.no */\n  { 40672,     0,     0, 1 },  /* xn--vgsy-qoa0j.no */\n  { 40687,     0,     0, 1 },  /* xn--vre-eiker-k8a.no */\n  { 40705,     0,     0, 1 },  /* xn--vrggt-xqad.no */\n  { 40720,     0,     0, 1 },  /* xn--vry-yla5g.no */\n  { 40734,     0,     0, 1 },  /* xn--yer-zna.no */\n  { 40746,     0,     0, 1 },  /* xn--ygarden-p1a.no */\n  { 40762,     0,     0, 1 },  /* xn--ystre-slidre-ujb.no */\n  {    62,     0,     0, 1 },  /* ac.nz */\n  {   113,  3672,     1, 1 },  /* co.nz */\n  { 40854,     0,     0, 1 },  /* cri.nz */\n  { 13295,     0,     0, 1 },  /* geek.nz */\n  {  8368,     0,     0, 1 },  /* gen.nz */\n  { 40858,     0,     0, 1 },  /* govt.nz */\n  {  3862,     0,     0, 1 },  /* health.nz */\n  {  4624,     0,     0, 1 },  /* iwi.nz */\n  {  4623,     0,     0, 1 },  /* kiwi.nz */\n  { 40863,     0,     0, 1 },  /* maori.nz */\n  {  4195,     0,     0, 1 },  /* mil.nz */\n  {  4185,     0,     0, 1 },  /* net.nz */\n  {  6070,     0,     0, 1 },  /* org.nz */\n  { 14790,     0,     0, 1 },  /* parliament.nz */\n  {  7042,     0,     0, 1 },  /* school.nz */\n  { 40869,     0,     0, 1 },  /* xn--mori-qsa.nz */\n  {   157,     0,     0, 1 },  /* ae.org */\n  { 40882,  7106,     1, 1 },  /* amune.org */\n  { 12046,     0,     0, 1 },  /* blogdns.org */\n  {  7299,     0,     0, 1 },  /* blogsite.org */\n  { 40888,     0,     0, 1 },  /* bmoattachments.org */\n  { 40903,     0,     0, 1 },  /* boldlygoingnowhere.org */\n  { 40922,     0,     0, 1 },  /* cable-modem.org */\n  { 11481,  7107,     2, 1 },  /* cdn77.org */\n  {  7114,  3247,     1, 0 },  /* cdn77-secure.org */\n  { 40934,     0,     0, 1 },  /* certmgr.org */\n  { 11367,     0,     0, 1 },  /* cloudns.org */\n  { 40942,     0,     0, 1 },  /* collegefan.org */\n  { 40953,     0,     0, 1 },  /* couchpotatofries.org */\n  { 14822,     0,     0, 1 },  /* ddnss.org */\n  { 15103,     0,     0, 1 },  /* diskstation.org */\n  { 12179,     0,     0, 1 },  /* dnsalias.org */\n  { 12188,     0,     0, 1 },  /* dnsdojo.org */\n  { 12207,     0,     0, 1 },  /* doesntexist.org */\n  { 12219,     0,     0, 1 },  /* dontexist.org */\n  { 12229,     0,     0, 1 },  /* doomdns.org */\n  { 12250,     0,     0, 1 },  /* dsmynas.org */\n  { 40970,     0,     0, 1 },  /* duckdns.org */\n  { 40978,     0,     0, 1 },  /* dvrdns.org */\n  { 12269,     0,     0, 1 },  /* dynalias.org */\n  { 11526,  7110,     2, 1 },  /* dyndns.org */\n  { 34001,     0,     0, 1 },  /* endofinternet.org */\n  { 40985,     0,     0, 1 },  /* endoftheinternet.org */\n  {  2798,  7112,    55, 1 },  /* eu.org */\n  { 12493,     0,     0, 1 },  /* familyds.org */\n  { 41002,     0,     0, 1 },  /* from-me.org */\n  { 41010,     0,     0, 1 },  /* game-host.org */\n  { 11809,     0,     0, 1 },  /* gotdns.org */\n  { 41020,     0,     0, 1 },  /* hepforge.org */\n  {  3940,     0,     0, 1 },  /* hk.org */\n  { 13055,     0,     0, 1 },  /* hobby-site.org */\n  { 41029,     0,     0, 1 },  /* homedns.org */\n  { 34084,     0,     0, 1 },  /* homeftp.org */\n  { 13066,     0,     0, 1 },  /* homelinux.org */\n  { 13107,     0,     0, 1 },  /* homeunix.org */\n  { 29814,     0,     0, 1 },  /* hopto.org */\n  { 41037,     0,     0, 1 },  /* is-a-bruinsfan.org */\n  { 41052,     0,     0, 1 },  /* is-a-candidate.org */\n  { 41067,     0,     0, 1 },  /* is-a-celticsfan.org */\n  { 13198,     0,     0, 1 },  /* is-a-chef.org */\n  { 13290,     0,     0, 1 },  /* is-a-geek.org */\n  { 41083,     0,     0, 1 },  /* is-a-knight.org */\n  { 15232,     0,     0, 1 },  /* is-a-linux-user.org */\n  { 41095,     0,     0, 1 },  /* is-a-patsfan.org */\n  { 41108,     0,     0, 1 },  /* is-a-soxfan.org */\n  { 41120,     0,     0, 1 },  /* is-found.org */\n  { 41129,     0,     0, 1 },  /* is-lost.org */\n  { 41137,     0,     0, 1 },  /* is-saved.org */\n  { 41146,     0,     0, 1 },  /* is-very-bad.org */\n  { 41158,     0,     0, 1 },  /* is-very-evil.org */\n  { 41171,     0,     0, 1 },  /* is-very-good.org */\n  { 41184,     0,     0, 1 },  /* is-very-nice.org */\n  { 41197,     0,     0, 1 },  /* is-very-sweet.org */\n  { 13713,     0,     0, 1 },  /* isa-geek.org */\n  { 11512,     0,     0, 1 },  /* js.org */\n  { 34099,     0,     0, 1 },  /* kicks-ass.org */\n  { 41211,     0,     0, 1 },  /* misconfused.org */\n  {  2931,     0,     0, 1 },  /* mlbfan.org */\n  { 41223,     0,     0, 1 },  /* my-firewall.org */\n  { 41235,     0,     0, 1 },  /* myfirewall.org */\n  { 11582,     0,     0, 1 },  /* myftp.org */\n  {  1347,     0,     0, 1 },  /* mysecuritycamera.org */\n  { 41246,     0,     0, 1 },  /* nflfan.org */\n  { 11588,     0,     0, 1 },  /* no-ip.org */\n  { 41253,     0,     0, 1 },  /* pimienta.org */\n  { 10655,     0,     0, 1 },  /* podzone.org */\n  { 41262,     0,     0, 1 },  /* poivron.org */\n  { 41270,     0,     0, 1 },  /* potager.org */\n  { 41278,     0,     0, 1 },  /* read-books.org */\n  { 41289,     0,     0, 1 },  /* readmyblog.org */\n  { 11594,     0,     0, 1 },  /* selfip.org */\n  { 41300,     0,     0, 1 },  /* sellsyourhome.org */\n  { 14080,     0,     0, 1 },  /* servebbs.org */\n  { 14108,     0,     0, 1 },  /* serveftp.org */\n  { 14117,     0,     0, 1 },  /* servegame.org */\n  { 15080,     0,     0, 1 },  /* spdns.org */\n  { 41314,     0,     0, 1 },  /* stuff-4-sale.org */\n  { 41327,     0,     0, 1 },  /* sweetpepper.org */\n  { 41339,     0,     0, 1 },  /* tunk.org */\n  {  2921,     0,     0, 1 },  /* tuxfamily.org */\n  { 41344,     0,     0, 1 },  /* ufcfan.org */\n  {   264,     0,     0, 1 },  /* us.org */\n  { 11601,     0,     0, 1 },  /* webhop.org */\n  { 41351,     0,     0, 1 },  /* wmflabs.org */\n  {  6329,     0,     0, 1 },  /* za.org */\n  { 41359,     0,     0, 1 },  /* zapto.org */\n  { 41369,  7109,     1, 0 },  /* origin.cdn77-secure.org */\n  { 41384,     0,     0, 1 },  /* agro.pl */\n  {  6578,     0,     0, 1 },  /* aid.pl */\n  {   527,     0,     0, 1 },  /* art.pl */\n  {  7909,     0,     0, 1 },  /* atm.pl */\n  { 41389,     0,     0, 1 },  /* augustow.pl */\n  {   629,     0,     0, 1 },  /* auto.pl */\n  { 41398,     0,     0, 1 },  /* babia-gora.pl */\n  { 41409,     0,     0, 1 },  /* bedzin.pl */\n  { 41416,     0,     0, 1 },  /* beep.pl */\n  { 41421,     0,     0, 1 },  /* beskidy.pl */\n  { 41429,     0,     0, 1 },  /* bialowieza.pl */\n  { 41440,     0,     0, 1 },  /* bialystok.pl */\n  { 41450,     0,     0, 1 },  /* bielawa.pl */\n  { 41458,     0,     0, 1 },  /* bieszczady.pl */\n  {   985,     0,     0, 1 },  /* biz.pl */\n  { 41469,     0,     0, 1 },  /* boleslawiec.pl */\n  { 41481,     0,     0, 1 },  /* bydgoszcz.pl */\n  { 41491,     0,     0, 1 },  /* bytom.pl */\n  { 41497,     0,     0, 1 },  /* cieszyn.pl */\n  {   113,     0,     0, 1 },  /* co.pl */\n  {  1913,     0,     0, 1 },  /* com.pl */\n  {  2589,     0,     0, 1 },  /* czeladz.pl */\n  { 41505,     0,     0, 1 },  /* czest.pl */\n  { 36209,     0,     0, 1 },  /* dlugoleka.pl */\n  {  2624,     0,     0, 1 },  /* edu.pl */\n  { 41511,     0,     0, 1 },  /* elblag.pl */\n  {  5027,     0,     0, 1 },  /* elk.pl */\n  { 41522,     0,     0, 1 },  /* gda.pl */\n  { 41526,     0,     0, 1 },  /* gdansk.pl */\n  { 41533,     0,     0, 1 },  /* gdynia.pl */\n  { 41540,     0,     0, 1 },  /* gliwice.pl */\n  { 41548,     0,     0, 1 },  /* glogow.pl */\n  { 41555,     0,     0, 1 },  /* gmina.pl */\n  { 41561,     0,     0, 1 },  /* gniezno.pl */\n  { 41569,     0,     0, 1 },  /* gorlice.pl */\n  {  3686,  7212,    47, 1 },  /* gov.pl */\n  { 41577,     0,     0, 1 },  /* grajewo.pl */\n  {  7330,     0,     0, 1 },  /* gsm.pl */\n  { 41585,     0,     0, 1 },  /* ilawa.pl */\n  {  3167,     0,     0, 1 },  /* info.pl */\n  { 41591,     0,     0, 1 },  /* jaworzno.pl */\n  { 41600,     0,     0, 1 },  /* jelenia-gora.pl */\n  { 41613,     0,     0, 1 },  /* jgora.pl */\n  { 41619,     0,     0, 1 },  /* kalisz.pl */\n  { 41626,     0,     0, 1 },  /* karpacz.pl */\n  { 41634,     0,     0, 1 },  /* kartuzy.pl */\n  { 41642,     0,     0, 1 },  /* kaszuby.pl */\n  { 41650,     0,     0, 1 },  /* katowice.pl */\n  { 41659,     0,     0, 1 },  /* kazimierz-dolny.pl */\n  { 41675,     0,     0, 1 },  /* kepno.pl */\n  { 41681,     0,     0, 1 },  /* ketrzyn.pl */\n  { 41689,     0,     0, 1 },  /* klodzko.pl */\n  { 41697,     0,     0, 1 },  /* kobierzyce.pl */\n  { 41708,     0,     0, 1 },  /* kolobrzeg.pl */\n  { 41718,     0,     0, 1 },  /* konin.pl */\n  { 41724,     0,     0, 1 },  /* konskowola.pl */\n  { 41735,     0,     0, 1 },  /* krakow.pl */\n  { 41742,     0,     0, 1 },  /* kutno.pl */\n  { 41748,     0,     0, 1 },  /* lapy.pl */\n  { 41753,     0,     0, 1 },  /* lebork.pl */\n  { 41760,     0,     0, 1 },  /* legnica.pl */\n  { 41768,     0,     0, 1 },  /* lezajsk.pl */\n  { 41776,     0,     0, 1 },  /* limanowa.pl */\n  { 41785,     0,     0, 1 },  /* lomza.pl */\n  {  2198,     0,     0, 1 },  /* lowicz.pl */\n  { 41791,     0,     0, 1 },  /* lubin.pl */\n  { 41797,     0,     0, 1 },  /* lukow.pl */\n  {  2651,     0,     0, 1 },  /* mail.pl */\n  { 41803,     0,     0, 1 },  /* malbork.pl */\n  { 41811,     0,     0, 1 },  /* malopolska.pl */\n  { 41822,     0,     0, 1 },  /* mazowsze.pl */\n  { 41831,     0,     0, 1 },  /* mazury.pl */\n  {  1858,     0,     0, 1 },  /* med.pl */\n  {  5327,     0,     0, 1 },  /* media.pl */\n  { 41838,     0,     0, 1 },  /* miasta.pl */\n  { 41845,     0,     0, 1 },  /* mielec.pl */\n  { 41852,     0,     0, 1 },  /* mielno.pl */\n  {  4195,     0,     0, 1 },  /* mil.pl */\n  { 41859,     0,     0, 1 },  /* mragowo.pl */\n  { 41867,     0,     0, 1 },  /* naklo.pl */\n  {  4185,     0,     0, 1 },  /* net.pl */\n  { 15199,     0,     0, 1 },  /* nieruchomosci.pl */\n  {  5998,     0,     0, 1 },  /* nom.pl */\n  { 41873,     0,     0, 1 },  /* nowaruda.pl */\n  { 41882,     0,     0, 1 },  /* nysa.pl */\n  { 41887,     0,     0, 1 },  /* olawa.pl */\n  { 41893,     0,     0, 1 },  /* olecko.pl */\n  { 41900,     0,     0, 1 },  /* olkusz.pl */\n  { 41907,     0,     0, 1 },  /* olsztyn.pl */\n  { 41915,     0,     0, 1 },  /* opoczno.pl */\n  { 41923,     0,     0, 1 },  /* opole.pl */\n  {  6070,     0,     0, 1 },  /* org.pl */\n  { 41929,     0,     0, 1 },  /* ostroda.pl */\n  { 41937,     0,     0, 1 },  /* ostroleka.pl */\n  { 41947,     0,     0, 1 },  /* ostrowiec.pl */\n  {  4657,     0,     0, 1 },  /* ostrowwlkp.pl */\n  {  5618,     0,     0, 1 },  /* pc.pl */\n  { 41957,     0,     0, 1 },  /* pila.pl */\n  {  7652,     0,     0, 1 },  /* pisz.pl */\n  { 41962,     0,     0, 1 },  /* podhale.pl */\n  { 41970,     0,     0, 1 },  /* podlasie.pl */\n  { 41979,     0,     0, 1 },  /* polkowice.pl */\n  { 41989,     0,     0, 1 },  /* pomorskie.pl */\n  { 41999,     0,     0, 1 },  /* pomorze.pl */\n  { 42007,     0,     0, 1 },  /* powiat.pl */\n  { 42014,     0,     0, 1 },  /* poznan.pl */\n  { 11393,     0,     0, 1 },  /* priv.pl */\n  { 42021,     0,     0, 1 },  /* prochowice.pl */\n  { 42032,     0,     0, 1 },  /* pruszkow.pl */\n  { 42041,     0,     0, 1 },  /* przeworsk.pl */\n  { 42051,     0,     0, 1 },  /* pulawy.pl */\n  { 42058,     0,     0, 1 },  /* radom.pl */\n  { 42064,     0,     0, 1 },  /* rawa-maz.pl */\n  {  2765,     0,     0, 1 },  /* realestate.pl */\n  { 15620,     0,     0, 1 },  /* rel.pl */\n  { 42073,     0,     0, 1 },  /* rybnik.pl */\n  { 42080,     0,     0, 1 },  /* rzeszow.pl */\n  { 42088,     0,     0, 1 },  /* sanok.pl */\n  { 42094,     0,     0, 1 },  /* sejny.pl */\n  {  7168,     0,     0, 1 },  /* sex.pl */\n  {  7245,     0,     0, 1 },  /* shop.pl */\n  { 42100,     0,     0, 1 },  /* sklep.pl */\n  { 42106,     0,     0, 1 },  /* skoczow.pl */\n  { 42114,     0,     0, 1 },  /* slask.pl */\n  { 42120,     0,     0, 1 },  /* slupsk.pl */\n  { 42127,     0,     0, 1 },  /* sopot.pl */\n  { 36625,     0,     0, 1 },  /* sos.pl */\n  { 42133,     0,     0, 1 },  /* sosnowiec.pl */\n  { 42143,     0,     0, 1 },  /* stalowa-wola.pl */\n  { 42156,     0,     0, 1 },  /* starachowice.pl */\n  { 42169,     0,     0, 1 },  /* stargard.pl */\n  { 42178,     0,     0, 1 },  /* suwalki.pl */\n  { 42186,     0,     0, 1 },  /* swidnica.pl */\n  { 42195,     0,     0, 1 },  /* swiebodzin.pl */\n  { 42206,     0,     0, 1 },  /* swinoujscie.pl */\n  { 42218,     0,     0, 1 },  /* szczecin.pl */\n  { 42227,     0,     0, 1 },  /* szczytno.pl */\n  { 42236,     0,     0, 1 },  /* szkola.pl */\n  { 42243,     0,     0, 1 },  /* targi.pl */\n  { 42249,     0,     0, 1 },  /* tarnobrzeg.pl */\n  { 42260,     0,     0, 1 },  /* tgory.pl */\n  {  7910,     0,     0, 1 },  /* tm.pl */\n  { 42266,     0,     0, 1 },  /* tourism.pl */\n  {  8005,     0,     0, 1 },  /* travel.pl */\n  { 42274,     0,     0, 1 },  /* turek.pl */\n  { 42280,     0,     0, 1 },  /* turystyka.pl */\n  { 42290,     0,     0, 1 },  /* tychy.pl */\n  { 42296,     0,     0, 1 },  /* ustka.pl */\n  { 42302,     0,     0, 1 },  /* walbrzych.pl */\n  { 42312,     0,     0, 1 },  /* warmia.pl */\n  { 42319,     0,     0, 1 },  /* warszawa.pl */\n  {   648,     0,     0, 1 },  /* waw.pl */\n  { 42328,     0,     0, 1 },  /* wegrow.pl */\n  { 42335,     0,     0, 1 },  /* wielun.pl */\n  {  1784,     0,     0, 1 },  /* wlocl.pl */\n  { 42342,     0,     0, 1 },  /* wloclawek.pl */\n  { 42352,     0,     0, 1 },  /* wodzislaw.pl */\n  { 42362,     0,     0, 1 },  /* wolomin.pl */\n  { 42370,     0,     0, 1 },  /* wroc.pl */\n  {  4836,     0,     0, 1 },  /* wroclaw.pl */\n  { 42375,     0,     0, 1 },  /* zachpomor.pl */\n  { 42385,     0,     0, 1 },  /* zagan.pl */\n  { 42391,     0,     0, 1 },  /* zakopane.pl */\n  { 42400,     0,     0, 1 },  /* zarow.pl */\n  { 42406,     0,     0, 1 },  /* zgora.pl */\n  { 42412,     0,     0, 1 },  /* zgorzelec.pl */\n  {  1913,     0,     0, 1 },  /* com.sh */\n  {  3686,     0,     0, 1 },  /* gov.sh */\n  { 42638,     0,     0, 1 },  /* hashbang.sh */\n  {  4195,     0,     0, 1 },  /* mil.sh */\n  {  4185,     0,     0, 1 },  /* net.sh */\n  {  5894,     0,     0, 1 },  /* now.sh */\n  {  6070,     0,     0, 1 },  /* org.sh */\n  { 42647,  3687,     1, 0 },  /* platform.sh */\n  { 16266,     0,     0, 1 },  /* av.tr */\n  { 14085,     0,     0, 1 },  /* bbs.tr */\n  { 42972,     0,     0, 1 },  /* bel.tr */\n  {   985,     0,     0, 1 },  /* biz.tr */\n  {  1913,  3672,     1, 1 },  /* com.tr */\n  { 11349,     0,     0, 1 },  /* dr.tr */\n  {  2624,     0,     0, 1 },  /* edu.tr */\n  {  8368,     0,     0, 1 },  /* gen.tr */\n  {  3686,     0,     0, 1 },  /* gov.tr */\n  {  3167,     0,     0, 1 },  /* info.tr */\n  { 15174,     0,     0, 1 },  /* k12.tr */\n  { 42976,     0,     0, 1 },  /* kep.tr */\n  {  4195,     0,     0, 1 },  /* mil.tr */\n  {  5725,     0,     0, 1 },  /* name.tr */\n  {  5521,  3685,     1, 1 },  /* nc.tr */\n  {  4185,     0,     0, 1 },  /* net.tr */\n  {  6070,     0,     0, 1 },  /* org.tr */\n  { 15170,     0,     0, 1 },  /* pol.tr */\n  {   279,     0,     0, 1 },  /* tel.tr */\n  {  2546,     0,     0, 1 },  /* tv.tr */\n  { 11967,     0,     0, 1 },  /* web.tr */\n  {    62,     0,     0, 1 },  /* ac.uk */\n  {   113,  7686,     3, 1 },  /* co.uk */\n  {  3686,  7689,     2, 1 },  /* gov.uk */\n  {  5103,     0,     0, 1 },  /* ltd.uk */\n  {  1693,     0,     0, 1 },  /* me.uk */\n  {  4185,     0,     0, 1 },  /* net.uk */\n  { 43402,     0,     0, 1 },  /* nhs.uk */\n  {  6070,     0,     0, 1 },  /* org.uk */\n  {  4860,     0,     0, 1 },  /* plc.uk */\n  { 43406,     0,     0, 1 },  /* police.uk */\n  {  1145,  3687,     1, 0 },  /* sch.uk */\n  {  4892,  7691,     3, 1 },  /* ak.us */\n  {   290,  7691,     3, 1 },  /* al.us */\n  {   494,  7691,     3, 1 },  /* ar.us */\n  {   537,  7691,     3, 1 },  /* as.us */\n  {   671,  7691,     3, 1 },  /* az.us */\n  {   221,  7691,     3, 1 },  /* ca.us */\n  { 11367,     0,     0, 1 },  /* cloudns.us */\n  {   113,  7691,     3, 1 },  /* co.us */\n  {  2004,  7691,     3, 1 },  /* ct.us */\n  { 12612,  7691,     3, 1 },  /* dc.us */\n  {  2276,  7691,     3, 1 },  /* de.us */\n  {  5842,     0,     0, 1 },  /* dni.us */\n  { 15879,     0,     0, 1 },  /* drud.us */\n  { 11314,     0,     0, 1 },  /* fed.us */\n  {   210,  7691,     3, 1 },  /* fl.us */\n  {  3355,  7691,     3, 1 },  /* ga.us */\n  { 43421,     0,     0, 1 },  /* golffan.us */\n  {  3768,  7691,     3, 1 },  /* gu.us */\n  {   512,  7694,     2, 1 },  /* hi.us */\n  {   547,  7691,     3, 1 },  /* ia.us */\n  {   437,  7691,     3, 1 },  /* id.us */\n  {  2653,  7691,     3, 1 },  /* il.us */\n  {   898,  7691,     3, 1 },  /* in.us */\n  { 43429,     0,     0, 1 },  /* is-by.us */\n  {  8291,     0,     0, 1 },  /* isa.us */\n  { 31995,     0,     0, 1 },  /* kids.us */\n  {  6843,  7691,     3, 1 },  /* ks.us */\n  {  4705,  7691,     3, 1 },  /* ky.us */\n  {  2173,  7691,     3, 1 },  /* la.us */\n  { 43435,     0,     0, 1 },  /* land-4-sale.us */\n  {  5151,  3522,     3, 1 },  /* ma.us */\n  {  5320,  7691,     3, 1 },  /* md.us */\n  {  1693,  7691,     3, 1 },  /* me.us */\n  {  5397,  7691,     3, 1 },  /* mi.us */\n  {  5445,  7691,     3, 1 },  /* mn.us */\n  {  3600,  7691,     3, 1 },  /* mo.us */\n  {  1059,  7691,     3, 1 },  /* ms.us */\n  {  5609,  7691,     3, 1 },  /* mt.us */\n  {  5521,  7691,     3, 1 },  /* nc.us */\n  {   727,  7694,     2, 1 },  /* nd.us */\n  {  1203,  7691,     3, 1 },  /* ne.us */\n  { 12772,  7691,     3, 1 },  /* nh.us */\n  {  4467,  7691,     3, 1 },  /* nj.us */\n  { 11902,  7691,     3, 1 },  /* nm.us */\n  { 29838,     0,     0, 1 },  /* noip.us */\n  { 43447,     0,     0, 1 },  /* nsn.us */\n  { 12788,  7691,     3, 1 },  /* nv.us */\n  {   206,  7691,     3, 1 },  /* ny.us */\n  {  6794,  7691,     3, 1 },  /* oh.us */\n  {  1126,  7691,     3, 1 },  /* ok.us */\n  {   137,  7691,     3, 1 },  /* or.us */\n  {   522,  7691,     3, 1 },  /* pa.us */\n  { 43451,     0,     0, 1 },  /* pointto.us */\n  {  6402,  7691,     3, 1 },  /* pr.us */\n  {  2994,  7691,     3, 1 },  /* ri.us */\n  {  2158,  7691,     3, 1 },  /* sc.us */\n  {  5381,  7694,     2, 1 },  /* sd.us */\n  { 41314,     0,     0, 1 },  /* stuff-4-sale.us */\n  {  5613,  7691,     3, 1 },  /* tn.us */\n  { 12852,  7691,     3, 1 },  /* tx.us */\n  {  3841,  7691,     3, 1 },  /* ut.us */\n  {   834,  7691,     3, 1 },  /* va.us */\n  {  8237,  7691,     3, 1 },  /* vi.us */\n  { 12876,  7691,     3, 1 },  /* vt.us */\n  {  5971,  7691,     3, 1 },  /* wa.us */\n  {  4625,  7691,     3, 1 },  /* wi.us */\n  { 12900,  7699,     1, 1 },  /* wv.us */\n  { 12908,  7691,     3, 1 },  /* wy.us */\n  {  1579,     0,     0, 1 },  /* cc.ma.us */\n  { 15174,  7696,     3, 1 },  /* k12.ma.us */\n  { 15182,     0,     0, 1 },  /* lib.ma.us */\n  {  1913,  3672,     1, 1 },  /* com.uy */\n  {  2624,     0,     0, 1 },  /* edu.uy */\n  { 43471,     0,     0, 1 },  /* gub.uy */\n  {  4195,     0,     0, 1 },  /* mil.uy */\n  {  4185,     0,     0, 1 },  /* net.uy */\n  {  6070,     0,     0, 1 },  /* org.uy */\n  {    62,     0,     0, 1 },  /* ac.za */\n  { 43533,     0,     0, 1 },  /* agric.za */\n  {  5099,     0,     0, 1 },  /* alt.za */\n  {   113,  3672,     1, 1 },  /* co.za */\n  {  2624,     0,     0, 1 },  /* edu.za */\n  {  3686,     0,     0, 1 },  /* gov.za */\n  { 43539,     0,     0, 1 },  /* grondar.za */\n  {  4840,     0,     0, 1 },  /* law.za */\n  {  4195,     0,     0, 1 },  /* mil.za */\n  {  4185,     0,     0, 1 },  /* net.za */\n  {   976,     0,     0, 1 },  /* ngo.za */\n  {  7786,     0,     0, 1 },  /* nis.za */\n  {  5998,     0,     0, 1 },  /* nom.za */\n  {  6070,     0,     0, 1 },  /* org.za */\n  {  7042,     0,     0, 1 },  /* school.za */\n  {  7910,     0,     0, 1 },  /* tm.za */\n  { 11967,     0,     0, 1 },  /* web.za */\n  { 43547,  3687,     1, 0 },  /* triton.zone */\n};\n\nstatic const REGISTRY_U16 kLeafNodeTable[] = {\n 1913,  /* com.ac */\n 2624,  /* edu.ac */\n 3686,  /* gov.ac */\n 4195,  /* mil.ac */\n 4185,  /* net.ac */\n 6070,  /* org.ac */\n 5998,  /* nom.ad */\n   62,  /* ac.ae */\n10666,  /* blogspot.ae */\n  113,  /* co.ae */\n 3686,  /* gov.ae */\n 4195,  /* mil.ae */\n 4185,  /* net.ae */\n 6070,  /* org.ae */\n 1145,  /* sch.ae */\n10675,  /* accident-investigation.aero */\n10698,  /* accident-prevention.aero */\n10718,  /* aerobatic.aero */\n 1845,  /* aeroclub.aero */\n10728,  /* aerodrome.aero */\n10738,  /* agents.aero */\n10745,  /* air-surveillance.aero */\n10762,  /* air-traffic-control.aero */\n10782,  /* aircraft.aero */\n10791,  /* airline.aero */\n10799,  /* airport.aero */\n10807,  /* airtraffic.aero */\n10818,  /* ambulance.aero */\n10828,  /* amusement.aero */\n10848,  /* association.aero */\n  622,  /* author.aero */\n10860,  /* ballooning.aero */\n 1215,  /* broker.aero */\n10871,  /* caa.aero */\n10875,  /* cargo.aero */\n 1527,  /* catering.aero */\n10881,  /* certification.aero */\n10895,  /* championship.aero */\n10908,  /* charter.aero */\n10916,  /* civilaviation.aero */\n 1849,  /* club.aero */\n10930,  /* conference.aero */\n10941,  /* consultant.aero */\n 1988,  /* consulting.aero */\n10774,  /* control.aero */\n10952,  /* council.aero */\n10960,  /* crew.aero */\n 2373,  /* design.aero */\n10965,  /* dgca.aero */\n10970,  /* educator.aero */\n10979,  /* emergency.aero */\n10989,  /* engine.aero */\n 2676,  /* engineer.aero */\n10996,  /* entertainment.aero */\n 2725,  /* equipment.aero */\n 2837,  /* exchange.aero */\n  369,  /* express.aero */\n11010,  /* federation.aero */\n11021,  /* flight.aero */\n11028,  /* freight.aero */\n11036,  /* fuel.aero */\n11045,  /* gliding.aero */\n11053,  /* government.aero */\n11064,  /* groundhandling.aero */\n 3753,  /* group.aero */\n11041,  /* hanggliding.aero */\n11079,  /* homebuilt.aero */\n 4280,  /* insurance.aero */\n11089,  /* journal.aero */\n11097,  /* journalist.aero */\n11108,  /* leasing.aero */\n 4549,  /* logistics.aero */\n11116,  /* magazine.aero */\n11125,  /* maintenance.aero */\n 5327,  /* media.aero */\n11137,  /* microlight.aero */\n11148,  /* modelling.aero */\n11158,  /* navigation.aero */\n11169,  /* parachuting.aero */\n11181,  /* paragliding.aero */\n10838,  /* passenger-association.aero */\n11193,  /* pilot.aero */\n  371,  /* press.aero */\n11199,  /* production.aero */\n11210,  /* recreation.aero */\n11221,  /* repbody.aero */\n 6301,  /* res.aero */\n 1383,  /* research.aero */\n11229,  /* rotorcraft.aero */\n 6902,  /* safety.aero */\n11240,  /* scientist.aero */\n 7147,  /* services.aero */\n 4111,  /* show.aero */\n11250,  /* skydiving.aero */\n 7371,  /* software.aero */\n11265,  /* student.aero */\n11273,  /* trader.aero */\n 7988,  /* trading.aero */\n11293,  /* trainer.aero */\n 2118,  /* union.aero */\n11301,  /* workinggroup.aero */\n 8612,  /* works.aero */\n 1913,  /* com.af */\n 2624,  /* edu.af */\n 3686,  /* gov.af */\n 4185,  /* net.af */\n 6070,  /* org.af */\n  113,  /* co.ag */\n 1913,  /* com.ag */\n 4185,  /* net.ag */\n 5998,  /* nom.ag */\n 6070,  /* org.ag */\n 1913,  /* com.ai */\n 4185,  /* net.ai */\n 5951,  /* off.ai */\n 6070,  /* org.ai */\n10666,  /* blogspot.al */\n 1913,  /* com.al */\n 2624,  /* edu.al */\n 3686,  /* gov.al */\n 4195,  /* mil.al */\n 4185,  /* net.al */\n 6070,  /* org.al */\n10666,  /* blogspot.am */\n  113,  /* co.ao */\n 1859,  /* ed.ao */\n11318,  /* gv.ao */\n 2098,  /* it.ao */\n 1036,  /* og.ao */\n11322,  /* pb.ao */\n11339,  /* e164.arpa */\n11344,  /* in-addr.arpa */\n11352,  /* ip6.arpa */\n 4359,  /* iris.arpa */\n11359,  /* uri.arpa */\n11363,  /* urn.arpa */\n 3686,  /* gov.as */\n11367,  /* cloudns.asia */\n11410,  /* *.ex.ortsinfo.at */\n 2003,  /* act.edu.au */\n11417,  /* nsw.edu.au */\n   97,  /* nt.edu.au */\n11430,  /* qld.edu.au */\n 1493,  /* sa.edu.au */\n  536,  /* tas.edu.au */\n11435,  /* vic.edu.au */\n 5971,  /* wa.edu.au */\n11430,  /* qld.gov.au */\n 1493,  /* sa.gov.au */\n  536,  /* tas.gov.au */\n11435,  /* vic.gov.au */\n 5971,  /* wa.gov.au */\n 1913,  /* com.aw */\n  985,  /* biz.az */\n 1913,  /* com.az */\n 2624,  /* edu.az */\n 3686,  /* gov.az */\n 3167,  /* info.az */\n 3632,  /* int.az */\n 4195,  /* mil.az */\n 5725,  /* name.az */\n 4185,  /* net.az */\n 6070,  /* org.az */\n  469,  /* pp.az */\n 6427,  /* pro.az */\n  985,  /* biz.bb */\n  113,  /* co.bb */\n 1913,  /* com.bb */\n 2624,  /* edu.bb */\n 3686,  /* gov.bb */\n 3167,  /* info.bb */\n 4185,  /* net.bb */\n 6070,  /* org.bb */\n 7514,  /* store.bb */\n 2546,  /* tv.bb */\n11462,  /* 0.bg */\n11467,  /* 1.bg */\n11471,  /* 2.bg */\n11474,  /* 3.bg */\n11342,  /* 4.bg */\n11479,  /* 5.bg */\n11354,  /* 6.bg */\n11485,  /* 7.bg */\n11487,  /* 8.bg */\n11489,  /* 9.bg */\n    2,  /* a.bg */\n   18,  /* b.bg */\n10666,  /* blogspot.bg */\n   36,  /* c.bg */\n  142,  /* d.bg */\n   32,  /* e.bg */\n  192,  /* f.bg */\n  162,  /* g.bg */\n   14,  /* h.bg */\n   58,  /* i.bg */\n  990,  /* j.bg */\n  734,  /* k.bg */\n  211,  /* l.bg */\n  354,  /* m.bg */\n  235,  /* n.bg */\n   49,  /* o.bg */\n    7,  /* p.bg */\n  481,  /* q.bg */\n  138,  /* r.bg */\n  110,  /* s.bg */\n   25,  /* t.bg */\n  585,  /* u.bg */\n 1290,  /* v.bg */\n  650,  /* w.bg */\n  398,  /* x.bg */\n   71,  /* y.bg */\n  326,  /* z.bg */\n  113,  /* co.bi */\n 1913,  /* com.bi */\n 2624,  /* edu.bi */\n  137,  /* or.bi */\n 6070,  /* org.bi */\n11367,  /* cloudns.biz */\n11518,  /* dscloud.biz */\n11526,  /* dyndns.biz */\n11533,  /* for-better.biz */\n11549,  /* for-more.biz */\n11558,  /* for-some.biz */\n11567,  /* for-the.biz */\n11575,  /* mmafan.biz */\n11582,  /* myftp.biz */\n11588,  /* no-ip.biz */\n11594,  /* selfip.biz */\n11601,  /* webhop.biz */\n11614,  /* asso.bj */\n11619,  /* barreau.bj */\n10666,  /* blogspot.bj */\n11627,  /* gouv.bj */\n 1913,  /* com.bo */\n 2624,  /* edu.bo */\n11325,  /* gob.bo */\n 3686,  /* gov.bo */\n 3632,  /* int.bo */\n 4195,  /* mil.bo */\n 4185,  /* net.bo */\n 6070,  /* org.bo */\n 2546,  /* tv.bo */\n   62,  /* ac.leg.br */\n  290,  /* al.leg.br */\n  358,  /* am.leg.br */\n 1662,  /* ap.leg.br */\n  308,  /* ba.leg.br */\n  273,  /* ce.leg.br */\n11728,  /* df.leg.br */\n  558,  /* es.leg.br */\n  257,  /* go.leg.br */\n 5151,  /* ma.leg.br */\n 4670,  /* mg.leg.br */\n 1059,  /* ms.leg.br */\n 5609,  /* mt.leg.br */\n  522,  /* pa.leg.br */\n11322,  /* pb.leg.br */\n 3739,  /* pe.leg.br */\n11737,  /* pi.leg.br */\n 6402,  /* pr.leg.br */\n11740,  /* rj.leg.br */\n  821,  /* rn.leg.br */\n  166,  /* ro.leg.br */\n11743,  /* rr.leg.br */\n 1272,  /* rs.leg.br */\n 2158,  /* sc.leg.br */\n 1498,  /* se.leg.br */\n11650,  /* sp.leg.br */\n  631,  /* to.leg.br */\n  113,  /* co.bw */\n 6070,  /* org.bw */\n 1913,  /* com.bz */\n 2624,  /* edu.bz */\n 3686,  /* gov.bz */\n 4185,  /* net.bz */\n 6070,  /* org.bz */\n 6329,  /* za.bz */\n  499,  /* ab.ca */\n   35,  /* bc.ca */\n10666,  /* blogspot.ca */\n  113,  /* co.ca */\n11746,  /* gc.ca */\n11673,  /* mb.ca */\n11751,  /* nb.ca */\n 5825,  /* nf.ca */\n 1071,  /* nl.ca */\n11588,  /* no-ip.ca */\n  786,  /* ns.ca */\n   97,  /* nt.ca */\n 5372,  /* nu.ca */\n  592,  /* on.ca */\n 3739,  /* pe.ca */\n11494,  /* qc.ca */\n 7312,  /* sk.ca */\n11503,  /* yk.ca */\n11367,  /* cloudns.cc */\n11763,  /* fantasyleague.cc */\n11777,  /* ftpaccess.cc */\n11787,  /* game-server.cc */\n 6256,  /* myphotos.cc */\n11799,  /* scrapping.cc */\n10666,  /* blogspot.ch */\n11809,  /* gotdns.ch */\n   62,  /* ac.ci */\n11614,  /* asso.ci */\n  113,  /* co.ci */\n 1913,  /* com.ci */\n 1859,  /* ed.ci */\n 2624,  /* edu.ci */\n  257,  /* go.ci */\n11627,  /* gouv.ci */\n 3632,  /* int.ci */\n 5320,  /* md.ci */\n 4185,  /* net.ci */\n  137,  /* or.ci */\n 6070,  /* org.ci */\n11816,  /* presse.ci */\n11823,  /* xn--aroport-bya.ci */\n11839,  /* !www.ck */\n11410,  /* *.ck */\n10666,  /* blogspot.cl */\n  113,  /* co.cl */\n11325,  /* gob.cl */\n 3686,  /* gov.cl */\n 4195,  /* mil.cl */\n  113,  /* co.cm */\n 1913,  /* com.cm */\n 3686,  /* gov.cm */\n 4185,  /* net.cm */\n 7668,  /* elasticbeanstalk.cn-north-1.amazonaws.com.cn */\n11473,  /* s3.cn-north-1.amazonaws.com.cn */\n11473,  /* s3.dualstack.ap-northeast-1.amazonaws.com */\n14743,  /* alpha.bounty-full.com */\n14749,  /* beta.bounty-full.com */\n11464,  /* eu-1.evennode.com */\n14754,  /* eu-2.evennode.com */\n14759,  /* us-1.evennode.com */\n14764,  /* us-2.evennode.com */\n14769,  /* apps.fbsbx.com */\n 2798,  /* eu.meteorapp.com */\n14778,  /* xen.prgmr.com */\n   62,  /* ac.cr */\n  113,  /* co.cr */\n 1859,  /* ed.cr */\n 3009,  /* fi.cr */\n  257,  /* go.cr */\n  137,  /* or.cr */\n 1493,  /* sa.cr */\n 1913,  /* com.cu */\n 2624,  /* edu.cu */\n 3686,  /* gov.cu */\n 5824,  /* inf.cu */\n 4185,  /* net.cu */\n 6070,  /* org.cu */\n 1913,  /* com.cw */\n 2624,  /* edu.cw */\n 4185,  /* net.cw */\n 6070,  /* org.cw */\n 7802,  /* ath.cx */\n 3686,  /* gov.cx */\n10666,  /* blogspot.cz */\n  113,  /* co.cz */\n11476,  /* e4.cz */\n14801,  /* realm.cz */\n15154,  /* dyn.cosidns.de */\n15154,  /* dyn.ddnss.de */\n11526,  /* dyndns.ddnss.de */\n  985,  /* biz.dk */\n10666,  /* blogspot.dk */\n  113,  /* co.dk */\n11959,  /* firm.dk */\n15158,  /* reg.dk */\n 7514,  /* store.dk */\n  527,  /* art.do */\n 1913,  /* com.do */\n 2624,  /* edu.do */\n11325,  /* gob.do */\n 3686,  /* gov.do */\n 4195,  /* mil.do */\n 4185,  /* net.do */\n 6070,  /* org.do */\n15162,  /* sld.do */\n11967,  /* web.do */\n  527,  /* art.dz */\n11614,  /* asso.dz */\n 1913,  /* com.dz */\n 2624,  /* edu.dz */\n 3686,  /* gov.dz */\n 4185,  /* net.dz */\n 6070,  /* org.dz */\n15170,  /* pol.dz */\n 1913,  /* com.ec */\n 2624,  /* edu.ec */\n 4231,  /* fin.ec */\n11325,  /* gob.ec */\n 3686,  /* gov.ec */\n 3167,  /* info.ec */\n15174,  /* k12.ec */\n 1858,  /* med.ec */\n 4195,  /* mil.ec */\n 4185,  /* net.ec */\n 6070,  /* org.ec */\n 6427,  /* pro.ec */\n  985,  /* biz.et */\n 1913,  /* com.et */\n 2624,  /* edu.et */\n 3686,  /* gov.et */\n 3167,  /* info.et */\n 5725,  /* name.et */\n 4185,  /* net.et */\n 6070,  /* org.et */\n15243,  /* user.party.eus */\n15248,  /* ybo.faith */\n15256,  /* aland.fi */\n10666,  /* blogspot.fi */\n 3618,  /* dy.fi */\n 8548,  /* iki.fi */\n 6363,  /* ptplus.fit */\n15272,  /* aeroport.fr */\n15281,  /* assedic.fr */\n11614,  /* asso.fr */\n 1520,  /* avocat.fr */\n15289,  /* avoues.fr */\n10666,  /* blogspot.fr */\n 3785,  /* cci.fr */\n15296,  /* chambagri.fr */\n15306,  /* chirurgiens-dentistes.fr */\n15328,  /* chirurgiens-dentistes-en-france.fr */\n 1913,  /* com.fr */\n15360,  /* experts-comptables.fr */\n15379,  /* fbx-os.fr */\n15386,  /* fbxos.fr */\n12546,  /* freebox-os.fr */\n12557,  /* freeboxos.fr */\n 2846,  /* geometre-expert.fr */\n11627,  /* gouv.fr */\n15392,  /* greta.fr */\n15398,  /* huissier-justice.fr */\n15415,  /* medecin.fr */\n 5998,  /* nom.fr */\n15423,  /* notaires.fr */\n11964,  /* on-web.fr */\n15432,  /* pharmacien.fr */\n 6713,  /* port.fr */\n15443,  /* prd.fr */\n11816,  /* presse.fr */\n 7910,  /* tm.fr */\n15447,  /* veterinaire.fr */\n 1913,  /* com.ge */\n 2624,  /* edu.ge */\n 3686,  /* gov.ge */\n 4195,  /* mil.ge */\n 4185,  /* net.ge */\n 6070,  /* org.ge */\n15459,  /* pvt.ge */\n  113,  /* co.gg */\n 4185,  /* net.gg */\n 6070,  /* org.gg */\n 1913,  /* com.gh */\n 2624,  /* edu.gh */\n 3686,  /* gov.gh */\n 4195,  /* mil.gh */\n 6070,  /* org.gh */\n 1913,  /* com.gi */\n 2624,  /* edu.gi */\n 3686,  /* gov.gi */\n 5103,  /* ltd.gi */\n15463,  /* mod.gi */\n 6070,  /* org.gi */\n  113,  /* co.gl */\n 1913,  /* com.gl */\n 2624,  /* edu.gl */\n 4185,  /* net.gl */\n 6070,  /* org.gl */\n   62,  /* ac.gn */\n 1913,  /* com.gn */\n 2624,  /* edu.gn */\n 3686,  /* gov.gn */\n 4185,  /* net.gn */\n 6070,  /* org.gn */\n11614,  /* asso.gp */\n 1913,  /* com.gp */\n 2624,  /* edu.gp */\n 5448,  /* mobi.gp */\n 4185,  /* net.gp */\n 6070,  /* org.gp */\n10666,  /* blogspot.gr */\n 1913,  /* com.gr */\n 2624,  /* edu.gr */\n 3686,  /* gov.gr */\n 4185,  /* net.gr */\n 6070,  /* org.gr */\n 1913,  /* com.gt */\n 2624,  /* edu.gt */\n11325,  /* gob.gt */\n11676,  /* ind.gt */\n 4195,  /* mil.gt */\n 4185,  /* net.gt */\n 6070,  /* org.gt */\n  113,  /* co.gy */\n 1913,  /* com.gy */\n 2624,  /* edu.gy */\n 3686,  /* gov.gy */\n 4185,  /* net.gy */\n 6070,  /* org.gy */\n10666,  /* blogspot.hk */\n 1913,  /* com.hk */\n 2624,  /* edu.hk */\n 3686,  /* gov.hk */\n15467,  /* idv.hk */\n15471,  /* inc.hk */\n 5103,  /* ltd.hk */\n 4185,  /* net.hk */\n 6070,  /* org.hk */\n 8851,  /* xn--55qx5d.hk */\n15475,  /* xn--ciqpn.hk */\n15485,  /* xn--gmq050i.hk */\n15497,  /* xn--gmqw5a.hk */\n 9459,  /* xn--io0a7i.hk */\n15508,  /* xn--lcvr32d.hk */\n15520,  /* xn--mk0axi.hk */\n10011,  /* xn--mxtq1m.hk */\n11913,  /* xn--od0alg.hk */\n15531,  /* xn--od0aq3b.hk */\n15543,  /* xn--tn0ag.hk */\n15553,  /* xn--uc0atv.hk */\n15564,  /* xn--uc0ay4a.hk */\n15576,  /* xn--wcvs22d.hk */\n15588,  /* xn--zf0avx.hk */\n 1913,  /* com.hn */\n 2624,  /* edu.hn */\n11325,  /* gob.hn */\n 4195,  /* mil.hn */\n 4185,  /* net.hn */\n 6070,  /* org.hn */\n15599,  /* opencraft.hosting */\n10666,  /* blogspot.hr */\n 1913,  /* com.hr */\n15609,  /* from.hr */\n  986,  /* iz.hr */\n 5725,  /* name.hr */\n  148,  /* adult.ht */\n  527,  /* art.ht */\n11614,  /* asso.ht */\n 1913,  /* com.ht */\n 2047,  /* coop.ht */\n 2624,  /* edu.ht */\n11959,  /* firm.ht */\n11627,  /* gouv.ht */\n 3167,  /* info.ht */\n 1858,  /* med.ht */\n 4185,  /* net.ht */\n 6070,  /* org.ht */\n15614,  /* perso.ht */\n15170,  /* pol.ht */\n 6427,  /* pro.ht */\n15620,  /* rel.ht */\n 7245,  /* shop.ht */\n11459,  /* 2000.hu */\n15624,  /* agrar.hu */\n10666,  /* blogspot.hu */\n15630,  /* bolt.hu */\n 1513,  /* casino.hu */\n 1765,  /* city.hu */\n  113,  /* co.hu */\n15635,  /* erotica.hu */\n15643,  /* erotika.hu */\n 3031,  /* film.hu */\n 3223,  /* forum.hu */\n 3405,  /* games.hu */\n 7749,  /* hotel.hu */\n 3167,  /* info.hu */\n15651,  /* ingatlan.hu */\n15660,  /* jogasz.hu */\n15667,  /* konyvelo.hu */\n15676,  /* lakas.hu */\n 5327,  /* media.hu */\n 5808,  /* news.hu */\n 6070,  /* org.hu */\n11393,  /* priv.hu */\n15682,  /* reklam.hu */\n 7168,  /* sex.hu */\n 7245,  /* shop.hu */\n15693,  /* sport.hu */\n 4911,  /* suli.hu */\n11398,  /* szex.hu */\n 7910,  /* tm.hu */\n15699,  /* tozsde.hu */\n15706,  /* utazas.hu */\n 8247,  /* video.hu */\n10666,  /* blogspot.ie */\n 3686,  /* gov.ie */\n 5103,  /* ltd.co.im */\n 4860,  /* plc.co.im */\n   62,  /* ac.in */\n10666,  /* blogspot.in */\n11367,  /* cloudns.in */\n  113,  /* co.in */\n 2624,  /* edu.in */\n11959,  /* firm.in */\n 8368,  /* gen.in */\n 3686,  /* gov.in */\n11676,  /* ind.in */\n 4195,  /* mil.in */\n 4185,  /* net.in */\n 1815,  /* nic.in */\n 6070,  /* org.in */\n 6301,  /* res.in */\n15731,  /* barrel-of-knowledge.info */\n15751,  /* barrell-of-knowledge.info */\n11367,  /* cloudns.info */\n15772,  /* dvrcam.info */\n15779,  /* dynamic-dns.info */\n11526,  /* dyndns.info */\n15791,  /* for-our.info */\n15799,  /* groks-the.info */\n15809,  /* groks-this.info */\n11544,  /* here-for-more.info */\n 1889,  /* ilovecollege.info */\n15820,  /* knowsitall.info */\n11588,  /* no-ip.info */\n15831,  /* nsupdate.info */\n11594,  /* selfip.info */\n11601,  /* webhop.info */\n15992,  /* customer.enonic.io */\n   62,  /* ac.ir */\n  113,  /* co.ir */\n 3686,  /* gov.ir */\n  437,  /* id.ir */\n 4185,  /* net.ir */\n 6070,  /* org.ir */\n 1145,  /* sch.ir */\n 9626,  /* xn--mgba3a4f16a.ir */\n 9642,  /* xn--mgba3a4fra.ir */\n10666,  /* blogspot.is */\n 1913,  /* com.is */\n16001,  /* cupcake.is */\n 2624,  /* edu.is */\n 3686,  /* gov.is */\n 3632,  /* int.is */\n 4185,  /* net.is */\n 6070,  /* org.is */\n 1181,  /* abr.it */\n16009,  /* abruzzo.it */\n  226,  /* ag.it */\n16017,  /* agrigento.it */\n  290,  /* al.it */\n16027,  /* alessandria.it */\n16047,  /* alto-adige.it */\n16066,  /* altoadige.it */\n  234,  /* an.it */\n16081,  /* ancona.it */\n16088,  /* andria-barletta-trani.it */\n16110,  /* andria-trani-barletta.it */\n16132,  /* andriabarlettatrani.it */\n16152,  /* andriatranibarletta.it */\n  448,  /* ao.it */\n16176,  /* aosta.it */\n16182,  /* aosta-valley.it */\n16195,  /* aostavalley.it */\n16213,  /* aoste.it */\n 1662,  /* ap.it */\n  480,  /* aq.it */\n16220,  /* aquila.it */\n  494,  /* ar.it */\n16227,  /* arezzo.it */\n16234,  /* ascoli-piceno.it */\n16248,  /* ascolipiceno.it */\n16261,  /* asti.it */\n  562,  /* at.it */\n16266,  /* av.it */\n16269,  /* avellino.it */\n  308,  /* ba.it */\n16278,  /* balsan.it */\n16287,  /* bari.it */\n16292,  /* barletta-trani-andria.it */\n16314,  /* barlettatraniandria.it */\n 1081,  /* bas.it */\n16334,  /* basilicata.it */\n16345,  /* belluno.it */\n16353,  /* benevento.it */\n16363,  /* bergamo.it */\n  931,  /* bg.it */\n   57,  /* bi.it */\n16371,  /* biella.it */\n16380,  /* bl.it */\n10666,  /* blogspot.it */\n 1067,  /* bn.it */\n 1086,  /* bo.it */\n16383,  /* bologna.it */\n16391,  /* bolzano.it */\n16399,  /* bozen.it */\n 1182,  /* br.it */\n16405,  /* brescia.it */\n16413,  /* brindisi.it */\n 1240,  /* bs.it */\n  829,  /* bt.it */\n 1295,  /* bz.it */\n  221,  /* ca.it */\n16422,  /* cagliari.it */\n 1319,  /* cal.it */\n16437,  /* calabria.it */\n16446,  /* caltanissetta.it */\n 1343,  /* cam.it */\n16460,  /* campania.it */\n16469,  /* campidano-medio.it */\n16485,  /* campidanomedio.it */\n11608,  /* campobasso.it */\n16500,  /* carbonia-iglesias.it */\n16518,  /* carboniaiglesias.it */\n16535,  /* carrara-massa.it */\n16549,  /* carraramassa.it */\n16562,  /* caserta.it */\n16570,  /* catania.it */\n16578,  /* catanzaro.it */\n 4415,  /* cb.it */\n  273,  /* ce.it */\n16588,  /* cesena-forli.it */\n16601,  /* cesenaforli.it */\n 1146,  /* ch.it */\n16613,  /* chieti.it */\n 1713,  /* ci.it */\n 1787,  /* cl.it */\n  842,  /* cn.it */\n  113,  /* co.it */\n16620,  /* como.it */\n16625,  /* cosenza.it */\n 2091,  /* cr.it */\n16633,  /* cremona.it */\n16641,  /* crotone.it */\n  429,  /* cs.it */\n 2004,  /* ct.it */\n16654,  /* cuneo.it */\n 2202,  /* cz.it */\n16660,  /* dell-ogliastra.it */\n16675,  /* dellogliastra.it */\n 2624,  /* edu.it */\n16689,  /* emilia-romagna.it */\n16704,  /* emiliaromagna.it */\n 5600,  /* emr.it */\n 3421,  /* en.it */\n16721,  /* enna.it */\n 3850,  /* fc.it */\n 1312,  /* fe.it */\n16726,  /* fermo.it */\n16732,  /* ferrara.it */\n16740,  /* fg.it */\n 3009,  /* fi.it */\n16743,  /* firenze.it */\n16751,  /* florence.it */\n 3160,  /* fm.it */\n16760,  /* foggia.it */\n16767,  /* forli-cesena.it */\n16780,  /* forlicesena.it */\n 3245,  /* fr.it */\n16792,  /* friuli-v-giulia.it */\n16808,  /* friuli-ve-giulia.it */\n16825,  /* friuli-vegiulia.it */\n16841,  /* friuli-venezia-giulia.it */\n16863,  /* friuli-veneziagiulia.it */\n16884,  /* friuli-vgiulia.it */\n16899,  /* friuliv-giulia.it */\n16914,  /* friulive-giulia.it */\n16930,  /* friulivegiulia.it */\n16945,  /* friulivenezia-giulia.it */\n16966,  /* friuliveneziagiulia.it */\n16986,  /* friulivgiulia.it */\n17000,  /* frosinone.it */\n 8233,  /* fvg.it */\n 1899,  /* ge.it */\n17010,  /* genoa.it */\n17016,  /* genova.it */\n  257,  /* go.it */\n17023,  /* gorizia.it */\n 3686,  /* gov.it */\n 3697,  /* gr.it */\n17031,  /* grosseto.it */\n17040,  /* iglesias-carbonia.it */\n17058,  /* iglesiascarbonia.it */\n 4200,  /* im.it */\n17075,  /* imperia.it */\n 3722,  /* is.it */\n17083,  /* isernia.it */\n 3123,  /* kr.it */\n17091,  /* la-spezia.it */\n16219,  /* laquila.it */\n17101,  /* laspezia.it */\n17110,  /* latina.it */\n  670,  /* laz.it */\n17117,  /* lazio.it */\n 4452,  /* lc.it */\n   40,  /* le.it */\n11721,  /* lecce.it */\n17128,  /* lecco.it */\n 4377,  /* li.it */\n17134,  /* lig.it */\n17138,  /* liguria.it */\n17146,  /* livorno.it */\n 3378,  /* lo.it */\n17158,  /* lodi.it */\n17163,  /* lom.it */\n17167,  /* lombardia.it */\n17177,  /* lombardy.it */\n  151,  /* lt.it */\n 5112,  /* lu.it */\n17186,  /* lucania.it */\n17194,  /* lucca.it */\n17200,  /* macerata.it */\n17209,  /* mantova.it */\n17219,  /* mar.it */\n11886,  /* marche.it */\n17223,  /* massa-carrara.it */\n17237,  /* massacarrara.it */\n17250,  /* matera.it */\n11673,  /* mb.it */\n 5307,  /* mc.it */\n 1693,  /* me.it */\n17257,  /* medio-campidano.it */\n17273,  /* mediocampidano.it */\n 7283,  /* messina.it */\n 5397,  /* mi.it */\n17294,  /* milan.it */\n17300,  /* milano.it */\n 5445,  /* mn.it */\n 3600,  /* mo.it */\n17307,  /* modena.it */\n17314,  /* mol.it */\n17318,  /* molise.it */\n17325,  /* monza.it */\n17331,  /* monza-brianza.it */\n17345,  /* monza-e-della-brianza.it */\n17367,  /* monzabrianza.it */\n17380,  /* monzaebrianza.it */\n17394,  /* monzaedellabrianza.it */\n 1059,  /* ms.it */\n 5609,  /* mt.it */\n  172,  /* na.it */\n17413,  /* naples.it */\n17420,  /* napoli.it */\n 1517,  /* no.it */\n17427,  /* novara.it */\n 5372,  /* nu.it */\n17434,  /* nuoro.it */\n 1036,  /* og.it */\n16665,  /* ogliastra.it */\n17440,  /* olbia-tempio.it */\n17453,  /* olbiatempio.it */\n  137,  /* or.it */\n17465,  /* oristano.it */\n  777,  /* ot.it */\n  522,  /* pa.it */\n17474,  /* padova.it */\n 8094,  /* padua.it */\n17481,  /* palermo.it */\n17489,  /* parma.it */\n17495,  /* pavia.it */\n 5618,  /* pc.it */\n17501,  /* pd.it */\n 3739,  /* pe.it */\n17504,  /* perugia.it */\n17512,  /* pesaro-urbino.it */\n17526,  /* pesarourbino.it */\n17539,  /* pescara.it */\n 6211,  /* pg.it */\n11737,  /* pi.it */\n17547,  /* piacenza.it */\n17556,  /* piedmont.it */\n17565,  /* piemonte.it */\n17574,  /* pisa.it */\n17579,  /* pistoia.it */\n 5444,  /* pmn.it */\n 4674,  /* pn.it */\n 6969,  /* po.it */\n17592,  /* pordenone.it */\n17602,  /* potenza.it */\n 6402,  /* pr.it */\n17610,  /* prato.it */\n 6510,  /* pt.it */\n17619,  /* pu.it */\n 8113,  /* pug.it */\n17622,  /* puglia.it */\n17629,  /* pv.it */\n17632,  /* pz.it */\n 1361,  /* ra.it */\n17640,  /* ragusa.it */\n16718,  /* ravenna.it */\n 4885,  /* rc.it */\n   80,  /* re.it */\n17647,  /* reggio-calabria.it */\n17663,  /* reggio-emilia.it */\n16431,  /* reggiocalabria.it */\n17677,  /* reggioemilia.it */\n 1046,  /* rg.it */\n 2994,  /* ri.it */\n11653,  /* rieti.it */\n 5410,  /* rimini.it */\n 2950,  /* rm.it */\n  821,  /* rn.it */\n  166,  /* ro.it */\n17699,  /* roma.it */\n 1691,  /* rome.it */\n17704,  /* rovigo.it */\n 1493,  /* sa.it */\n17711,  /* salerno.it */\n17719,  /* sar.it */\n17723,  /* sardegna.it */\n17732,  /* sardinia.it */\n17741,  /* sassari.it */\n17749,  /* savona.it */\n 2364,  /* si.it */\n17758,  /* sic.it */\n17762,  /* sicilia.it */\n17770,  /* sicily.it */\n17777,  /* siena.it */\n17783,  /* siracusa.it */\n 7345,  /* so.it */\n 6813,  /* sondrio.it */\n11650,  /* sp.it */\n 7437,  /* sr.it */\n  374,  /* ss.it */\n17805,  /* suedtirol.it */\n 7595,  /* sv.it */\n  570,  /* ta.it */\n17823,  /* taa.it */\n17827,  /* taranto.it */\n  334,  /* te.it */\n17835,  /* tempio-olbia.it */\n17848,  /* tempioolbia.it */\n17860,  /* teramo.it */\n 2749,  /* terni.it */\n 5613,  /* tn.it */\n  631,  /* to.it */\n17867,  /* torino.it */\n  636,  /* tos.it */\n17874,  /* toscana.it */\n11585,  /* tp.it */\n 3302,  /* tr.it */\n17882,  /* trani-andria-barletta.it */\n17904,  /* trani-barletta-andria.it */\n17926,  /* traniandriabarletta.it */\n17946,  /* tranibarlettaandria.it */\n17966,  /* trapani.it */\n17974,  /* trentino.it */\n17983,  /* trentino-a-adige.it */\n18000,  /* trentino-aadige.it */\n18016,  /* trentino-alto-adige.it */\n18036,  /* trentino-altoadige.it */\n18055,  /* trentino-s-tirol.it */\n18072,  /* trentino-stirol.it */\n18088,  /* trentino-sud-tirol.it */\n18107,  /* trentino-sudtirol.it */\n18125,  /* trentino-sued-tirol.it */\n18145,  /* trentino-suedtirol.it */\n18164,  /* trentinoa-adige.it */\n18180,  /* trentinoaadige.it */\n16039,  /* trentinoalto-adige.it */\n16058,  /* trentinoaltoadige.it */\n18195,  /* trentinos-tirol.it */\n 7865,  /* trentinostirol.it */\n18211,  /* trentinosud-tirol.it */\n18229,  /* trentinosudtirol.it */\n18246,  /* trentinosued-tirol.it */\n17797,  /* trentinosuedtirol.it */\n18265,  /* trento.it */\n18272,  /* treviso.it */\n18280,  /* trieste.it */\n  109,  /* ts.it */\n18292,  /* turin.it */\n18298,  /* tuscany.it */\n 2546,  /* tv.it */\n 1842,  /* ud.it */\n18306,  /* udine.it */\n18312,  /* umb.it */\n18316,  /* umbria.it */\n18323,  /* urbino-pesaro.it */\n18337,  /* urbinopesaro.it */\n  834,  /* va.it */\n18350,  /* val-d-aosta.it */\n18362,  /* val-daosta.it */\n18373,  /* vald-aosta.it */\n16172,  /* valdaosta.it */\n18384,  /* valle-aosta.it */\n18396,  /* valle-d-aosta.it */\n18410,  /* valle-daosta.it */\n18423,  /* valleaosta.it */\n18434,  /* valled-aosta.it */\n18447,  /* valledaosta.it */\n18459,  /* vallee-aoste.it */\n16207,  /* valleeaoste.it */\n  447,  /* vao.it */\n18472,  /* varese.it */\n18479,  /* vb.it */\n 6561,  /* vc.it */\n18482,  /* vda.it */\n  125,  /* ve.it */\n 7158,  /* ven.it */\n18486,  /* veneto.it */\n18493,  /* venezia.it */\n 4167,  /* venice.it */\n18501,  /* verbania.it */\n18510,  /* vercelli.it */\n18519,  /* verona.it */\n 8237,  /* vi.it */\n18526,  /* vibo-valentia.it */\n18540,  /* vibovalentia.it */\n18553,  /* vicenza.it */\n18561,  /* viterbo.it */\n 2582,  /* vr.it */\n 8080,  /* vs.it */\n12876,  /* vt.it */\n18569,  /* vv.it */\n 1913,  /* com.jo */\n 2624,  /* edu.jo */\n 3686,  /* gov.jo */\n 4195,  /* mil.jo */\n 5725,  /* name.jo */\n 4185,  /* net.jo */\n 6070,  /* org.jo */\n 1145,  /* sch.jo */\n  244,  /* aisai.aichi.jp */\n10609,  /* ama.aichi.jp */\n19505,  /* anjo.aichi.jp */\n19510,  /* asuke.aichi.jp */\n19516,  /* chiryu.aichi.jp */\n19523,  /* chita.aichi.jp */\n19529,  /* fuso.aichi.jp */\n19534,  /* gamagori.aichi.jp */\n19543,  /* handa.aichi.jp */\n19549,  /* hazu.aichi.jp */\n19554,  /* hekinan.aichi.jp */\n19562,  /* higashiura.aichi.jp */\n19573,  /* ichinomiya.aichi.jp */\n19584,  /* inazawa.aichi.jp */\n19592,  /* inuyama.aichi.jp */\n19600,  /* isshiki.aichi.jp */\n19608,  /* iwakura.aichi.jp */\n19616,  /* kanie.aichi.jp */\n19622,  /* kariya.aichi.jp */\n19629,  /* kasugai.aichi.jp */\n19637,  /* kira.aichi.jp */\n19642,  /* kiyosu.aichi.jp */\n19649,  /* komaki.aichi.jp */\n19656,  /* konan.aichi.jp */\n17815,  /* kota.aichi.jp */\n19662,  /* mihama.aichi.jp */\n19678,  /* miyoshi.aichi.jp */\n19686,  /* nishio.aichi.jp */\n19693,  /* nisshin.aichi.jp */\n19704,  /* obu.aichi.jp */\n19708,  /* oguchi.aichi.jp */\n19715,  /* oharu.aichi.jp */\n19721,  /* okazaki.aichi.jp */\n19729,  /* owariasahi.aichi.jp */\n17035,  /* seto.aichi.jp */\n19746,  /* shikatsu.aichi.jp */\n19755,  /* shinshiro.aichi.jp */\n19765,  /* shitara.aichi.jp */\n19773,  /* tahara.aichi.jp */\n19780,  /* takahama.aichi.jp */\n19789,  /* tobishima.aichi.jp */\n19799,  /* toei.aichi.jp */\n11731,  /* togo.aichi.jp */\n19804,  /* tokai.aichi.jp */\n 5721,  /* tokoname.aichi.jp */\n19810,  /* toyoake.aichi.jp */\n19818,  /* toyohashi.aichi.jp */\n19828,  /* toyokawa.aichi.jp */\n19837,  /* toyone.aichi.jp */\n 7966,  /* toyota.aichi.jp */\n19848,  /* tsushima.aichi.jp */\n19857,  /* yatomi.aichi.jp */\n18585,  /* akita.akita.jp */\n19864,  /* daisen.akita.jp */\n19871,  /* fujisato.akita.jp */\n19880,  /* gojome.akita.jp */\n19887,  /* hachirogata.akita.jp */\n19899,  /* happou.akita.jp */\n19906,  /* higashinaruse.akita.jp */\n19924,  /* honjo.akita.jp */\n19930,  /* honjyo.akita.jp */\n18695,  /* ikawa.akita.jp */\n19944,  /* kamikoani.akita.jp */\n19954,  /* kamioka.akita.jp */\n19962,  /* katagami.akita.jp */\n 8143,  /* kazuno.akita.jp */\n19971,  /* kitaakita.akita.jp */\n 6097,  /* kosaka.akita.jp */\n19981,  /* kyowa.akita.jp */\n19989,  /* misato.akita.jp */\n20000,  /* mitane.akita.jp */\n20007,  /* moriyoshi.akita.jp */\n20017,  /* nikaho.akita.jp */\n20024,  /* noshiro.akita.jp */\n 2239,  /* odate.akita.jp */\n10600,  /* oga.akita.jp */\n19893,  /* ogata.akita.jp */\n20044,  /* semboku.akita.jp */\n20052,  /* yokote.akita.jp */\n19920,  /* yurihonjo.akita.jp */\n18591,  /* aomori.aomori.jp */\n20059,  /* gonohe.aomori.jp */\n20066,  /* hachinohe.aomori.jp */\n20076,  /* hashikami.aomori.jp */\n20086,  /* hiranai.aomori.jp */\n20094,  /* hirosaki.aomori.jp */\n20103,  /* itayanagi.aomori.jp */\n20113,  /* kuroishi.aomori.jp */\n20122,  /* misawa.aomori.jp */\n20129,  /* mutsu.aomori.jp */\n20135,  /* nakadomari.aomori.jp */\n20146,  /* noheji.aomori.jp */\n20153,  /* oirase.aomori.jp */\n20160,  /* owani.aomori.jp */\n20166,  /* rokunohe.aomori.jp */\n20175,  /* sannohe.aomori.jp */\n20183,  /* shichinohe.aomori.jp */\n20194,  /* shingo.aomori.jp */\n20201,  /* takko.aomori.jp */\n20207,  /* towada.aomori.jp */\n20214,  /* tsugaru.aomori.jp */\n20222,  /* tsuruta.aomori.jp */\n20230,  /* abiko.chiba.jp */\n19734,  /* asahi.chiba.jp */\n20236,  /* chonan.chiba.jp */\n20243,  /* chosei.chiba.jp */\n20250,  /* choshi.chiba.jp */\n20261,  /* chuo.chiba.jp */\n20266,  /* funabashi.chiba.jp */\n20276,  /* futtsu.chiba.jp */\n20283,  /* hanamigawa.chiba.jp */\n20294,  /* ichihara.chiba.jp */\n20303,  /* ichikawa.chiba.jp */\n19573,  /* ichinomiya.chiba.jp */\n20312,  /* inzai.chiba.jp */\n17288,  /* isumi.chiba.jp */\n20318,  /* kamagaya.chiba.jp */\n20327,  /* kamogawa.chiba.jp */\n20336,  /* kashiwa.chiba.jp */\n20346,  /* katori.chiba.jp */\n20358,  /* katsuura.chiba.jp */\n20367,  /* kimitsu.chiba.jp */\n20375,  /* kisarazu.chiba.jp */\n20384,  /* kozaki.chiba.jp */\n20391,  /* kujukuri.chiba.jp */\n20400,  /* kyonan.chiba.jp */\n20407,  /* matsudo.chiba.jp */\n20415,  /* midori.chiba.jp */\n19662,  /* mihama.chiba.jp */\n20422,  /* minamiboso.chiba.jp */\n20433,  /* mobara.chiba.jp */\n20440,  /* mutsuzawa.chiba.jp */\n20450,  /* nagara.chiba.jp */\n20457,  /* nagareyama.chiba.jp */\n20468,  /* narashino.chiba.jp */\n20478,  /* narita.chiba.jp */\n20485,  /* noda.chiba.jp */\n20490,  /* oamishirasato.chiba.jp */\n20504,  /* omigawa.chiba.jp */\n20512,  /* onjuku.chiba.jp */\n20522,  /* otaki.chiba.jp */\n  154,  /* sakae.chiba.jp */\n 6909,  /* sakura.chiba.jp */\n20528,  /* shimofusa.chiba.jp */\n20538,  /* shirako.chiba.jp */\n20546,  /* shiroi.chiba.jp */\n20553,  /* shisui.chiba.jp */\n20560,  /* sodegaura.chiba.jp */\n20570,  /* sosa.chiba.jp */\n20576,  /* tako.chiba.jp */\n20581,  /* tateyama.chiba.jp */\n20590,  /* togane.chiba.jp */\n20597,  /* tohnosho.chiba.jp */\n19987,  /* tomisato.chiba.jp */\n20606,  /* urayasu.chiba.jp */\n20614,  /* yachimata.chiba.jp */\n20624,  /* yachiyo.chiba.jp */\n18598,  /* yokaichiba.chiba.jp */\n20632,  /* yokoshibahikari.chiba.jp */\n20648,  /* yotsukaido.chiba.jp */\n20660,  /* ainan.ehime.jp */\n20667,  /* honai.ehime.jp */\n20676,  /* ikata.ehime.jp */\n20682,  /* imabari.ehime.jp */\n20628,  /* iyo.ehime.jp */\n20701,  /* kamijima.ehime.jp */\n20710,  /* kihoku.ehime.jp */\n20717,  /* kumakogen.ehime.jp */\n20727,  /* masaki.ehime.jp */\n20734,  /* matsuno.ehime.jp */\n20749,  /* matsuyama.ehime.jp */\n20673,  /* namikata.ehime.jp */\n20759,  /* niihama.ehime.jp */\n20768,  /* ozu.ehime.jp */\n20772,  /* saijo.ehime.jp */\n20690,  /* seiyo.ehime.jp */\n20778,  /* shikokuchuo.ehime.jp */\n20791,  /* tobe.ehime.jp */\n11758,  /* toon.ehime.jp */\n20805,  /* uchiko.ehime.jp */\n20812,  /* uwajima.ehime.jp */\n20820,  /* yawatahama.ehime.jp */\n20837,  /* echizen.fukui.jp */\n20845,  /* eiheiji.fukui.jp */\n18615,  /* fukui.fukui.jp */\n20853,  /* ikeda.fukui.jp */\n20859,  /* katsuyama.fukui.jp */\n19662,  /* mihama.fukui.jp */\n20831,  /* minamiechizen.fukui.jp */\n20869,  /* obama.fukui.jp */\n11893,  /* ohi.fukui.jp */\n20876,  /* ono.fukui.jp */\n20880,  /* sabae.fukui.jp */\n20886,  /* sakai.fukui.jp */\n19780,  /* takahama.fukui.jp */\n20892,  /* tsuruga.fukui.jp */\n20900,  /* wakasa.fukui.jp */\n20907,  /* ashiya.fukuoka.jp */\n20914,  /* buzen.fukuoka.jp */\n20920,  /* chikugo.fukuoka.jp */\n20928,  /* chikuho.fukuoka.jp */\n20936,  /* chikujo.fukuoka.jp */\n20944,  /* chikushino.fukuoka.jp */\n20955,  /* chikuzen.fukuoka.jp */\n20261,  /* chuo.fukuoka.jp */\n20964,  /* dazaifu.fukuoka.jp */\n20972,  /* fukuchi.fukuoka.jp */\n20980,  /* hakata.fukuoka.jp */\n20987,  /* higashi.fukuoka.jp */\n20995,  /* hirokawa.fukuoka.jp */\n21004,  /* hisayama.fukuoka.jp */\n21013,  /* iizuka.fukuoka.jp */\n21020,  /* inatsuki.fukuoka.jp */\n20019,  /* kaho.fukuoka.jp */\n21029,  /* kasuga.fukuoka.jp */\n21036,  /* kasuya.fukuoka.jp */\n21043,  /* kawara.fukuoka.jp */\n21050,  /* keisen.fukuoka.jp */\n20032,  /* koga.fukuoka.jp */\n21057,  /* kurate.fukuoka.jp */\n21064,  /* kurogi.fukuoka.jp */\n21078,  /* kurume.fukuoka.jp */\n21088,  /* minami.fukuoka.jp */\n21095,  /* miyako.fukuoka.jp */\n21104,  /* miyama.fukuoka.jp */\n21111,  /* miyawaka.fukuoka.jp */\n21120,  /* mizumaki.fukuoka.jp */\n21129,  /* munakata.fukuoka.jp */\n18707,  /* nakagawa.fukuoka.jp */\n21138,  /* nakama.fukuoka.jp */\n21149,  /* nishi.fukuoka.jp */\n20037,  /* nogata.fukuoka.jp */\n21155,  /* ogori.fukuoka.jp */\n21161,  /* okagaki.fukuoka.jp */\n19831,  /* okawa.fukuoka.jp */\n21170,  /* oki.fukuoka.jp */\n21174,  /* omuta.fukuoka.jp */\n21180,  /* onga.fukuoka.jp */\n21190,  /* onojo.fukuoka.jp */\n 4710,  /* oto.fukuoka.jp */\n21201,  /* saigawa.fukuoka.jp */\n21209,  /* sasaguri.fukuoka.jp */\n21218,  /* shingu.fukuoka.jp */\n21225,  /* shinyoshitomi.fukuoka.jp */\n20666,  /* shonai.fukuoka.jp */\n21239,  /* soeda.fukuoka.jp */\n21248,  /* sue.fukuoka.jp */\n21252,  /* tachiarai.fukuoka.jp */\n21264,  /* tagawa.fukuoka.jp */\n21273,  /* takata.fukuoka.jp */\n21280,  /* toho.fukuoka.jp */\n21285,  /* toyotsu.fukuoka.jp */\n21293,  /* tsuiki.fukuoka.jp */\n21300,  /* ukiha.fukuoka.jp */\n17290,  /* umi.fukuoka.jp */\n21307,  /* usui.fukuoka.jp */\n21312,  /* yamada.fukuoka.jp */\n21319,  /* yame.fukuoka.jp */\n21324,  /* yanagawa.fukuoka.jp */\n21333,  /* yukuhashi.fukuoka.jp */\n21343,  /* aizubange.fukushima.jp */\n21353,  /* aizumisato.fukushima.jp */\n21364,  /* aizuwakamatsu.fukushima.jp */\n21378,  /* asakawa.fukushima.jp */\n21386,  /* bandai.fukushima.jp */\n 2240,  /* date.fukushima.jp */\n18633,  /* fukushima.fukushima.jp */\n21393,  /* furudono.fukushima.jp */\n21402,  /* futaba.fukushima.jp */\n21409,  /* hanawa.fukushima.jp */\n20987,  /* higashi.fukushima.jp */\n21416,  /* hirata.fukushima.jp */\n21423,  /* hirono.fukushima.jp */\n21430,  /* iitate.fukushima.jp */\n21437,  /* inawashiro.fukushima.jp */\n18692,  /* ishikawa.fukushima.jp */\n21452,  /* iwaki.fukushima.jp */\n21458,  /* izumizaki.fukushima.jp */\n21468,  /* kagamiishi.fukushima.jp */\n21479,  /* kaneyama.fukushima.jp */\n21488,  /* kawamata.fukushima.jp */\n21271,  /* kitakata.fukushima.jp */\n21497,  /* kitashiobara.fukushima.jp */\n21510,  /* koori.fukushima.jp */\n21522,  /* koriyama.fukushima.jp */\n21531,  /* kunimi.fukushima.jp */\n21538,  /* miharu.fukushima.jp */\n21545,  /* mishima.fukushima.jp */\n18761,  /* namie.fukushima.jp */\n 5836,  /* nango.fukushima.jp */\n21553,  /* nishiaizu.fukushima.jp */\n21563,  /* nishigo.fukushima.jp */\n21571,  /* okuma.fukushima.jp */\n21577,  /* omotego.fukushima.jp */\n20876,  /* ono.fukushima.jp */\n21585,  /* otama.fukushima.jp */\n21591,  /* samegawa.fukushima.jp */\n21600,  /* shimogo.fukushima.jp */\n21615,  /* shirakawa.fukushima.jp */\n21625,  /* showa.fukushima.jp */\n21631,  /* soma.fukushima.jp */\n21636,  /* sukagawa.fukushima.jp */\n21645,  /* taishin.fukushima.jp */\n21653,  /* tamakawa.fukushima.jp */\n21662,  /* tanagura.fukushima.jp */\n21671,  /* tenei.fukushima.jp */\n21677,  /* yabuki.fukushima.jp */\n21691,  /* yamato.fukushima.jp */\n21698,  /* yamatsuri.fukushima.jp */\n21708,  /* yanaizu.fukushima.jp */\n21716,  /* yugawa.fukushima.jp */\n21723,  /* anpachi.gifu.jp */\n16776,  /* ena.gifu.jp */\n18643,  /* gifu.gifu.jp */\n21731,  /* ginan.gifu.jp */\n 2481,  /* godo.gifu.jp */\n 4470,  /* gujo.gifu.jp */\n21737,  /* hashima.gifu.jp */\n21745,  /* hichiso.gifu.jp */\n21756,  /* hida.gifu.jp */\n21608,  /* higashishirakawa.gifu.jp */\n21761,  /* ibigawa.gifu.jp */\n20853,  /* ikeda.gifu.jp */\n21769,  /* kakamigahara.gifu.jp */\n21782,  /* kani.gifu.jp */\n21787,  /* kasahara.gifu.jp */\n21796,  /* kasamatsu.gifu.jp */\n21806,  /* kawaue.gifu.jp */\n21813,  /* kitagata.gifu.jp */\n21824,  /* mino.gifu.jp */\n21829,  /* minokamo.gifu.jp */\n21838,  /* mitake.gifu.jp */\n21845,  /* mizunami.gifu.jp */\n21854,  /* motosu.gifu.jp */\n21861,  /* nakatsugawa.gifu.jp */\n21874,  /* ogaki.gifu.jp */\n21880,  /* sakahogi.gifu.jp */\n21895,  /* seki.gifu.jp */\n21900,  /* sekigahara.gifu.jp */\n21615,  /* shirakawa.gifu.jp */\n21911,  /* tajimi.gifu.jp */\n21918,  /* takayama.gifu.jp */\n21927,  /* tarui.gifu.jp */\n21169,  /* toki.gifu.jp */\n21933,  /* tomika.gifu.jp */\n21940,  /* wanouchi.gifu.jp */\n19470,  /* yamagata.gifu.jp */\n21949,  /* yaotsu.gifu.jp */\n21958,  /* yoro.gifu.jp */\n21963,  /* annaka.gunma.jp */\n21970,  /* chiyoda.gunma.jp */\n21978,  /* fujioka.gunma.jp */\n21986,  /* higashiagatsuma.gunma.jp */\n22002,  /* isesaki.gunma.jp */\n22010,  /* itakura.gunma.jp */\n22018,  /* kanna.gunma.jp */\n 5915,  /* kanra.gunma.jp */\n22024,  /* katashina.gunma.jp */\n22034,  /* kawaba.gunma.jp */\n22041,  /* kiryu.gunma.jp */\n22047,  /* kusatsu.gunma.jp */\n22055,  /* maebashi.gunma.jp */\n22064,  /* meiwa.gunma.jp */\n20415,  /* midori.gunma.jp */\n22070,  /* minakami.gunma.jp */\n22079,  /* naganohara.gunma.jp */\n22090,  /* nakanojo.gunma.jp */\n22099,  /* nanmoku.gunma.jp */\n22107,  /* numata.gunma.jp */\n22114,  /* oizumi.gunma.jp */\n22123,  /* ora.gunma.jp */\n 7969,  /* ota.gunma.jp */\n22127,  /* shibukawa.gunma.jp */\n22137,  /* shimonita.gunma.jp */\n22147,  /* shinto.gunma.jp */\n21625,  /* showa.gunma.jp */\n22154,  /* takasaki.gunma.jp */\n21918,  /* takayama.gunma.jp */\n22163,  /* tamamura.gunma.jp */\n22172,  /* tatebayashi.gunma.jp */\n22184,  /* tomioka.gunma.jp */\n22192,  /* tsukiyono.gunma.jp */\n22202,  /* tsumagoi.gunma.jp */\n 5882,  /* ueno.gunma.jp */\n22211,  /* yoshioka.gunma.jp */\n21085,  /* asaminami.hiroshima.jp */\n22220,  /* daiwa.hiroshima.jp */\n22226,  /* etajima.hiroshima.jp */\n22234,  /* fuchu.hiroshima.jp */\n22240,  /* fukuyama.hiroshima.jp */\n22249,  /* hatsukaichi.hiroshima.jp */\n22261,  /* higashihiroshima.hiroshima.jp */\n22278,  /* hongo.hiroshima.jp */\n22284,  /* jinsekikogen.hiroshima.jp */\n22297,  /* kaita.hiroshima.jp */\n18617,  /* kui.hiroshima.jp */\n22303,  /* kumano.hiroshima.jp */\n 6582,  /* kure.hiroshima.jp */\n22314,  /* mihara.hiroshima.jp */\n19678,  /* miyoshi.hiroshima.jp */\n21965,  /* naka.hiroshima.jp */\n22321,  /* onomichi.hiroshima.jp */\n20696,  /* osakikamijima.hiroshima.jp */\n22330,  /* otake.hiroshima.jp */\n 6099,  /* saka.hiroshima.jp */\n22336,  /* sera.hiroshima.jp */\n21145,  /* seranishi.hiroshima.jp */\n22341,  /* shinichi.hiroshima.jp */\n22350,  /* shobara.hiroshima.jp */\n22358,  /* takehara.hiroshima.jp */\n22367,  /* abashiri.hokkaido.jp */\n22378,  /* abira.hokkaido.jp */\n22384,  /* aibetsu.hokkaido.jp */\n22376,  /* akabira.hokkaido.jp */\n22392,  /* akkeshi.hokkaido.jp */\n22400,  /* asahikawa.hokkaido.jp */\n22410,  /* ashibetsu.hokkaido.jp */\n22420,  /* ashoro.hokkaido.jp */\n22427,  /* assabu.hokkaido.jp */\n21995,  /* atsuma.hokkaido.jp */\n22434,  /* bibai.hokkaido.jp */\n22440,  /* biei.hokkaido.jp */\n22445,  /* bifuka.hokkaido.jp */\n22452,  /* bihoro.hokkaido.jp */\n22459,  /* biratori.hokkaido.jp */\n22468,  /* chippubetsu.hokkaido.jp */\n22480,  /* chitose.hokkaido.jp */\n 2240,  /* date.hokkaido.jp */\n22488,  /* ebetsu.hokkaido.jp */\n22495,  /* embetsu.hokkaido.jp */\n22503,  /* eniwa.hokkaido.jp */\n22509,  /* erimo.hokkaido.jp */\n16076,  /* esan.hokkaido.jp */\n22515,  /* esashi.hokkaido.jp */\n22522,  /* fukagawa.hokkaido.jp */\n18633,  /* fukushima.hokkaido.jp */\n22535,  /* furano.hokkaido.jp */\n22542,  /* furubira.hokkaido.jp */\n22551,  /* haboro.hokkaido.jp */\n 2236,  /* hakodate.hokkaido.jp */\n22558,  /* hamatonbetsu.hokkaido.jp */\n22571,  /* hidaka.hokkaido.jp */\n22578,  /* higashikagura.hokkaido.jp */\n22592,  /* higashikawa.hokkaido.jp */\n22604,  /* hiroo.hokkaido.jp */\n22610,  /* hokuryu.hokkaido.jp */\n22618,  /* hokuto.hokkaido.jp */\n22625,  /* honbetsu.hokkaido.jp */\n22634,  /* horokanai.hokkaido.jp */\n22644,  /* horonobe.hokkaido.jp */\n20853,  /* ikeda.hokkaido.jp */\n22653,  /* imakane.hokkaido.jp */\n22661,  /* ishikari.hokkaido.jp */\n22670,  /* iwamizawa.hokkaido.jp */\n22680,  /* iwanai.hokkaido.jp */\n22531,  /* kamifurano.hokkaido.jp */\n22687,  /* kamikawa.hokkaido.jp */\n22696,  /* kamishihoro.hokkaido.jp */\n22708,  /* kamisunagawa.hokkaido.jp */\n22721,  /* kamoenai.hokkaido.jp */\n22730,  /* kayabe.hokkaido.jp */\n22737,  /* kembuchi.hokkaido.jp */\n22746,  /* kikonai.hokkaido.jp */\n22754,  /* kimobetsu.hokkaido.jp */\n18654,  /* kitahiroshima.hokkaido.jp */\n22764,  /* kitami.hokkaido.jp */\n22771,  /* kiyosato.hokkaido.jp */\n22780,  /* koshimizu.hokkaido.jp */\n22790,  /* kunneppu.hokkaido.jp */\n22799,  /* kuriyama.hokkaido.jp */\n22808,  /* kuromatsunai.hokkaido.jp */\n22821,  /* kushiro.hokkaido.jp */\n22829,  /* kutchan.hokkaido.jp */\n19981,  /* kyowa.hokkaido.jp */\n22837,  /* mashike.hokkaido.jp */\n22845,  /* matsumae.hokkaido.jp */\n22854,  /* mikasa.hokkaido.jp */\n22861,  /* minamifurano.hokkaido.jp */\n22874,  /* mombetsu.hokkaido.jp */\n22883,  /* moseushi.hokkaido.jp */\n22894,  /* mukawa.hokkaido.jp */\n22901,  /* muroran.hokkaido.jp */\n22909,  /* naie.hokkaido.jp */\n18707,  /* nakagawa.hokkaido.jp */\n22914,  /* nakasatsunai.hokkaido.jp */\n22927,  /* nakatombetsu.hokkaido.jp */\n22940,  /* nanae.hokkaido.jp */\n22946,  /* nanporo.hokkaido.jp */\n21956,  /* nayoro.hokkaido.jp */\n22954,  /* nemuro.hokkaido.jp */\n22961,  /* niikappu.hokkaido.jp */\n15267,  /* niki.hokkaido.jp */\n22970,  /* nishiokoppe.hokkaido.jp */\n22982,  /* noboribetsu.hokkaido.jp */\n22107,  /* numata.hokkaido.jp */\n22994,  /* obihiro.hokkaido.jp */\n23002,  /* obira.hokkaido.jp */\n23008,  /* oketo.hokkaido.jp */\n22975,  /* okoppe.hokkaido.jp */\n23014,  /* otaru.hokkaido.jp */\n20790,  /* otobe.hokkaido.jp */\n23020,  /* otofuke.hokkaido.jp */\n23028,  /* otoineppu.hokkaido.jp */\n 5625,  /* oumu.hokkaido.jp */\n22121,  /* ozora.hokkaido.jp */\n17616,  /* pippu.hokkaido.jp */\n23038,  /* rankoshi.hokkaido.jp */\n23047,  /* rebun.hokkaido.jp */\n23053,  /* rikubetsu.hokkaido.jp */\n23063,  /* rishiri.hokkaido.jp */\n23071,  /* rishirifuji.hokkaido.jp */\n17697,  /* saroma.hokkaido.jp */\n23083,  /* sarufutsu.hokkaido.jp */\n23093,  /* shakotan.hokkaido.jp */\n23102,  /* shari.hokkaido.jp */\n23108,  /* shibecha.hokkaido.jp */\n22411,  /* shibetsu.hokkaido.jp */\n23117,  /* shikabe.hokkaido.jp */\n23125,  /* shikaoi.hokkaido.jp */\n23133,  /* shimamaki.hokkaido.jp */\n22782,  /* shimizu.hokkaido.jp */\n23143,  /* shimokawa.hokkaido.jp */\n23153,  /* shinshinotsu.hokkaido.jp */\n23166,  /* shintoku.hokkaido.jp */\n23175,  /* shiranuka.hokkaido.jp */\n23185,  /* shiraoi.hokkaido.jp */\n23193,  /* shiriuchi.hokkaido.jp */\n23203,  /* sobetsu.hokkaido.jp */\n22712,  /* sunagawa.hokkaido.jp */\n23211,  /* taiki.hokkaido.jp */\n23217,  /* takasu.hokkaido.jp */\n23224,  /* takikawa.hokkaido.jp */\n23233,  /* takinoue.hokkaido.jp */\n23242,  /* teshikaga.hokkaido.jp */\n23252,  /* tobetsu.hokkaido.jp */\n23260,  /* tohma.hokkaido.jp */\n23266,  /* tomakomai.hokkaido.jp */\n23276,  /* tomari.hokkaido.jp */\n23283,  /* toya.hokkaido.jp */\n23288,  /* toyako.hokkaido.jp */\n23295,  /* toyotomi.hokkaido.jp */\n23304,  /* toyoura.hokkaido.jp */\n23312,  /* tsubetsu.hokkaido.jp */\n23321,  /* tsukigata.hokkaido.jp */\n23331,  /* urakawa.hokkaido.jp */\n23339,  /* urausu.hokkaido.jp */\n22613,  /* uryu.hokkaido.jp */\n23346,  /* utashinai.hokkaido.jp */\n23356,  /* wakkanai.hokkaido.jp */\n23365,  /* wassamu.hokkaido.jp */\n23373,  /* yakumo.hokkaido.jp */\n23380,  /* yoichi.hokkaido.jp */\n23387,  /* aioi.hyogo.jp */\n23392,  /* akashi.hyogo.jp */\n20542,  /* ako.hyogo.jp */\n23399,  /* amagasaki.hyogo.jp */\n21873,  /* aogaki.hyogo.jp */\n23412,  /* asago.hyogo.jp */\n20907,  /* ashiya.hyogo.jp */\n23424,  /* awaji.hyogo.jp */\n23430,  /* fukusaki.hyogo.jp */\n23439,  /* goshiki.hyogo.jp */\n23447,  /* harima.hyogo.jp */\n23454,  /* himeji.hyogo.jp */\n20303,  /* ichikawa.hyogo.jp */\n23463,  /* inagawa.hyogo.jp */\n22765,  /* itami.hyogo.jp */\n23471,  /* kakogawa.hyogo.jp */\n23480,  /* kamigori.hyogo.jp */\n22687,  /* kamikawa.hyogo.jp */\n23489,  /* kasai.hyogo.jp */\n21029,  /* kasuga.hyogo.jp */\n23495,  /* kawanishi.hyogo.jp */\n23505,  /* miki.hyogo.jp */\n23418,  /* minamiawaji.hyogo.jp */\n23510,  /* nishinomiya.hyogo.jp */\n21448,  /* nishiwaki.hyogo.jp */\n20876,  /* ono.hyogo.jp */\n23522,  /* sanda.hyogo.jp */\n23528,  /* sannan.hyogo.jp */\n23535,  /* sasayama.hyogo.jp */\n23544,  /* sayo.hyogo.jp */\n21218,  /* shingu.hyogo.jp */\n23549,  /* shinonsen.hyogo.jp */\n23559,  /* shiso.hyogo.jp */\n23568,  /* sumoto.hyogo.jp */\n23575,  /* taishi.hyogo.jp */\n23584,  /* taka.hyogo.jp */\n23589,  /* takarazuka.hyogo.jp */\n23409,  /* takasago.hyogo.jp */\n23600,  /* takino.hyogo.jp */\n23610,  /* tamba.hyogo.jp */\n23616,  /* tatsuno.hyogo.jp */\n23624,  /* toyooka.hyogo.jp */\n23632,  /* yabu.hyogo.jp */\n23639,  /* yashiro.hyogo.jp */\n23647,  /* yoka.hyogo.jp */\n19830,  /* yokawa.hyogo.jp */\n 5396,  /* ami.ibaraki.jp */\n19734,  /* asahi.ibaraki.jp */\n23658,  /* bando.ibaraki.jp */\n23664,  /* chikusei.ibaraki.jp */\n  254,  /* daigo.ibaraki.jp */\n23673,  /* fujishiro.ibaraki.jp */\n 3921,  /* hitachi.ibaraki.jp */\n23683,  /* hitachinaka.ibaraki.jp */\n23695,  /* hitachiomiya.ibaraki.jp */\n23708,  /* hitachiota.ibaraki.jp */\n18683,  /* ibaraki.ibaraki.jp */\n 7287,  /* ina.ibaraki.jp */\n23725,  /* inashiki.ibaraki.jp */\n20575,  /* itako.ibaraki.jp */\n23734,  /* iwama.ibaraki.jp */\n23740,  /* joso.ibaraki.jp */\n23745,  /* kamisu.ibaraki.jp */\n23752,  /* kasama.ibaraki.jp */\n23761,  /* kashima.ibaraki.jp */\n23769,  /* kasumigaura.ibaraki.jp */\n20032,  /* koga.ibaraki.jp */\n23781,  /* miho.ibaraki.jp */\n 7919,  /* mito.ibaraki.jp */\n23786,  /* moriya.ibaraki.jp */\n21965,  /* naka.ibaraki.jp */\n23793,  /* namegata.ibaraki.jp */\n23802,  /* oarai.ibaraki.jp */\n20330,  /* ogawa.ibaraki.jp */\n23816,  /* omitama.ibaraki.jp */\n23824,  /* ryugasaki.ibaraki.jp */\n20886,  /* sakai.ibaraki.jp */\n23834,  /* sakuragawa.ibaraki.jp */\n23845,  /* shimodate.ibaraki.jp */\n23855,  /* shimotsuma.ibaraki.jp */\n23866,  /* shirosato.ibaraki.jp */\n11439,  /* sowa.ibaraki.jp */\n23876,  /* suifu.ibaraki.jp */\n23882,  /* takahagi.ibaraki.jp */\n23891,  /* tamatsukuri.ibaraki.jp */\n19804,  /* tokai.ibaraki.jp */\n23903,  /* tomobe.ibaraki.jp */\n 1201,  /* tone.ibaraki.jp */\n23910,  /* toride.ibaraki.jp */\n23917,  /* tsuchiura.ibaraki.jp */\n23927,  /* tsukuba.ibaraki.jp */\n23935,  /* uchihara.ibaraki.jp */\n23944,  /* ushiku.ibaraki.jp */\n20624,  /* yachiyo.ibaraki.jp */\n19470,  /* yamagata.ibaraki.jp */\n23951,  /* yawara.ibaraki.jp */\n23958,  /* yuki.ibaraki.jp */\n23963,  /* anamizu.ishikawa.jp */\n23971,  /* hakui.ishikawa.jp */\n23977,  /* hakusan.ishikawa.jp */\n23247,  /* kaga.ishikawa.jp */\n23994,  /* kahoku.ishikawa.jp */\n24001,  /* kanazawa.ishikawa.jp */\n18582,  /* kawakita.ishikawa.jp */\n 4642,  /* komatsu.ishikawa.jp */\n24010,  /* nakanoto.ishikawa.jp */\n24019,  /* nanao.ishikawa.jp */\n24029,  /* nomi.ishikawa.jp */\n24034,  /* nonoichi.ishikawa.jp */\n24014,  /* noto.ishikawa.jp */\n24045,  /* shika.ishikawa.jp */\n24051,  /* suzu.ishikawa.jp */\n24056,  /* tsubata.ishikawa.jp */\n24064,  /* tsurugi.ishikawa.jp */\n24072,  /* uchinada.ishikawa.jp */\n20813,  /* wajima.ishikawa.jp */\n24081,  /* fudai.iwate.jp */\n24087,  /* fujisawa.iwate.jp */\n24096,  /* hanamaki.iwate.jp */\n24105,  /* hiraizumi.iwate.jp */\n21423,  /* hirono.iwate.jp */\n20185,  /* ichinohe.iwate.jp */\n21889,  /* ichinoseki.iwate.jp */\n24115,  /* iwaizumi.iwate.jp */\n18701,  /* iwate.iwate.jp */\n24124,  /* joboji.iwate.jp */\n24131,  /* kamaishi.iwate.jp */\n24140,  /* kanegasaki.iwate.jp */\n24151,  /* karumai.iwate.jp */\n24159,  /* kawai.iwate.jp */\n24165,  /* kitakami.iwate.jp */\n24174,  /* kuji.iwate.jp */\n20168,  /* kunohe.iwate.jp */\n24179,  /* kuzumaki.iwate.jp */\n21095,  /* miyako.iwate.jp */\n24188,  /* mizusawa.iwate.jp */\n24197,  /* morioka.iwate.jp */\n24205,  /* ninohe.iwate.jp */\n20485,  /* noda.iwate.jp */\n24212,  /* ofunato.iwate.jp */\n24221,  /* oshu.iwate.jp */\n24226,  /* otsuchi.iwate.jp */\n24234,  /* rikuzentakata.iwate.jp */\n20338,  /* shiwa.iwate.jp */\n24248,  /* shizukuishi.iwate.jp */\n24260,  /* sumita.iwate.jp */\n24267,  /* tanohata.iwate.jp */\n20875,  /* tono.iwate.jp */\n24276,  /* yahaba.iwate.jp */\n21312,  /* yamada.iwate.jp */\n24283,  /* ayagawa.kagawa.jp */\n24291,  /* higashikagawa.kagawa.jp */\n24305,  /* kanonji.kagawa.jp */\n24313,  /* kotohira.kagawa.jp */\n24322,  /* manno.kagawa.jp */\n 3388,  /* marugame.kagawa.jp */\n24328,  /* mitoyo.kagawa.jp */\n24335,  /* naoshima.kagawa.jp */\n24344,  /* sanuki.kagawa.jp */\n24351,  /* tadotsu.kagawa.jp */\n24359,  /* takamatsu.kagawa.jp */\n24369,  /* tonosho.kagawa.jp */\n24025,  /* uchinomi.kagawa.jp */\n24377,  /* utazu.kagawa.jp */\n24383,  /* zentsuji.kagawa.jp */\n24392,  /* akune.kagoshima.jp */\n24399,  /* amami.kagoshima.jp */\n24405,  /* hioki.kagoshima.jp */\n 8291,  /* isa.kagoshima.jp */\n 6657,  /* isen.kagoshima.jp */\n22115,  /* izumi.kagoshima.jp */\n18716,  /* kagoshima.kagoshima.jp */\n24411,  /* kanoya.kagoshima.jp */\n24418,  /* kawanabe.kagoshima.jp */\n24427,  /* kinko.kagoshima.jp */\n24433,  /* kouyama.kagoshima.jp */\n24441,  /* makurazaki.kagoshima.jp */\n23565,  /* matsumoto.kagoshima.jp */\n19996,  /* minamitane.kagoshima.jp */\n24452,  /* nakatane.kagoshima.jp */\n24461,  /* nishinoomote.kagoshima.jp */\n18844,  /* satsumasendai.kagoshima.jp */\n24474,  /* soo.kagoshima.jp */\n24478,  /* tarumizu.kagoshima.jp */\n21306,  /* yusui.kagoshima.jp */\n19937,  /* aikawa.kanagawa.jp */\n24487,  /* atsugi.kanagawa.jp */\n24494,  /* ayase.kanagawa.jp */\n24500,  /* chigasaki.kanagawa.jp */\n23719,  /* ebina.kanagawa.jp */\n24087,  /* fujisawa.kanagawa.jp */\n24510,  /* hadano.kanagawa.jp */\n24517,  /* hakone.kanagawa.jp */\n24524,  /* hiratsuka.kanagawa.jp */\n24534,  /* isehara.kanagawa.jp */\n24542,  /* kaisei.kanagawa.jp */\n24549,  /* kamakura.kanagawa.jp */\n24558,  /* kiyokawa.kanagawa.jp */\n24567,  /* matsuda.kanagawa.jp */\n24575,  /* minamiashigara.kanagawa.jp */\n24590,  /* miura.kanagawa.jp */\n24596,  /* nakai.kanagawa.jp */\n24602,  /* ninomiya.kanagawa.jp */\n24611,  /* odawara.kanagawa.jp */\n 5486,  /* oi.kanagawa.jp */\n24622,  /* oiso.kanagawa.jp */\n22310,  /* sagamihara.kanagawa.jp */\n22892,  /* samukawa.kanagawa.jp */\n24627,  /* tsukui.kanagawa.jp */\n24634,  /* yamakita.kanagawa.jp */\n21691,  /* yamato.kanagawa.jp */\n24643,  /* yokosuka.kanagawa.jp */\n24652,  /* yugawara.kanagawa.jp */\n19499,  /* zama.kanagawa.jp */\n24661,  /* zushi.kanagawa.jp */\n 1764,  /* !city.kawasaki.jp */\n11410,  /* *.kawasaki.jp */\n18687,  /* aki.kochi.jp */\n24667,  /* geisei.kochi.jp */\n22571,  /* hidaka.kochi.jp */\n24674,  /* higashitsuno.kochi.jp */\n 1516,  /* ino.kochi.jp */\n24693,  /* kagami.kochi.jp */\n20081,  /* kami.kochi.jp */\n21262,  /* kitagawa.kochi.jp */\n18755,  /* kochi.kochi.jp */\n22314,  /* mihara.kochi.jp */\n18907,  /* motoyama.kochi.jp */\n24708,  /* muroto.kochi.jp */\n24715,  /* nahari.kochi.jp */\n24722,  /* nakamura.kochi.jp */\n24731,  /* nankoku.kochi.jp */\n24739,  /* nishitosa.kochi.jp */\n24749,  /* niyodogawa.kochi.jp */\n18756,  /* ochi.kochi.jp */\n19831,  /* okawa.kochi.jp */\n24760,  /* otoyo.kochi.jp */\n24766,  /* otsuki.kochi.jp */\n21379,  /* sakawa.kochi.jp */\n24773,  /* sukumo.kochi.jp */\n24780,  /* susaki.kochi.jp */\n24744,  /* tosa.kochi.jp */\n24787,  /* tosashimizu.kochi.jp */\n24330,  /* toyo.kochi.jp */\n20736,  /* tsuno.kochi.jp */\n24799,  /* umaji.kochi.jp */\n24805,  /* yasuda.kochi.jp */\n24812,  /* yusuhara.kochi.jp */\n24825,  /* amakusa.kumamoto.jp */\n24833,  /* arao.kumamoto.jp */\n 7344,  /* aso.kumamoto.jp */\n24838,  /* choyo.kumamoto.jp */\n24844,  /* gyokuto.kumamoto.jp */\n24821,  /* kamiamakusa.kumamoto.jp */\n24852,  /* kikuchi.kumamoto.jp */\n 5553,  /* kumamoto.kumamoto.jp */\n24860,  /* mashiki.kumamoto.jp */\n24868,  /* mifune.kumamoto.jp */\n24875,  /* minamata.kumamoto.jp */\n24884,  /* minamioguni.kumamoto.jp */\n24896,  /* nagasu.kumamoto.jp */\n24903,  /* nishihara.kumamoto.jp */\n24890,  /* oguni.kumamoto.jp */\n20768,  /* ozu.kumamoto.jp */\n23568,  /* sumoto.kumamoto.jp */\n24913,  /* takamori.kumamoto.jp */\n 7591,  /* uki.kumamoto.jp */\n  630,  /* uto.kumamoto.jp */\n24922,  /* yamaga.kumamoto.jp */\n21691,  /* yamato.kumamoto.jp */\n24929,  /* yatsushiro.kumamoto.jp */\n22731,  /* ayabe.kyoto.jp */\n24940,  /* fukuchiyama.kyoto.jp */\n24952,  /* higashiyama.kyoto.jp */\n 2275,  /* ide.kyoto.jp */\n 6026,  /* ine.kyoto.jp */\n24964,  /* joyo.kyoto.jp */\n24969,  /* kameoka.kyoto.jp */\n21833,  /* kamo.kyoto.jp */\n18586,  /* kita.kyoto.jp */\n24977,  /* kizu.kyoto.jp */\n21102,  /* kumiyama.kyoto.jp */\n23607,  /* kyotamba.kyoto.jp */\n24982,  /* kyotanabe.kyoto.jp */\n24992,  /* kyotango.kyoto.jp */\n25001,  /* maizuru.kyoto.jp */\n21088,  /* minami.kyoto.jp */\n25009,  /* minamiyamashiro.kyoto.jp */\n25025,  /* miyazu.kyoto.jp */\n25032,  /* muko.kyoto.jp */\n25037,  /* nagaokakyo.kyoto.jp */\n25048,  /* nakagyo.kyoto.jp */\n25056,  /* nantan.kyoto.jp */\n25063,  /* oyamazaki.kyoto.jp */\n25073,  /* sakyo.kyoto.jp */\n25079,  /* seika.kyoto.jp */\n24985,  /* tanabe.kyoto.jp */\n 7253,  /* uji.kyoto.jp */\n25085,  /* ujitawara.kyoto.jp */\n25095,  /* wazuka.kyoto.jp */\n25102,  /* yamashina.kyoto.jp */\n25112,  /* yawata.kyoto.jp */\n19734,  /* asahi.mie.jp */\n25119,  /* inabe.mie.jp */\n 2145,  /* ise.mie.jp */\n25125,  /* kameyama.mie.jp */\n25134,  /* kawagoe.mie.jp */\n25142,  /* kiho.mie.jp */\n25147,  /* kisosaki.mie.jp */\n25156,  /* kiwa.mie.jp */\n25161,  /* komono.mie.jp */\n22303,  /* kumano.mie.jp */\n25168,  /* kuwana.mie.jp */\n25175,  /* matsusaka.mie.jp */\n22064,  /* meiwa.mie.jp */\n19662,  /* mihama.mie.jp */\n25185,  /* minamiise.mie.jp */\n25195,  /* misugi.mie.jp */\n21104,  /* miyama.mie.jp */\n16285,  /* nabari.mie.jp */\n18637,  /* shima.mie.jp */\n25202,  /* suzuka.mie.jp */\n25209,  /* tado.mie.jp */\n23211,  /* taiki.mie.jp */\n20523,  /* taki.mie.jp */\n25214,  /* tamaki.mie.jp */\n25221,  /* toba.mie.jp */\n 3309,  /* tsu.mie.jp */\n21396,  /* udono.mie.jp */\n25226,  /* ureshino.mie.jp */\n25235,  /* watarai.mie.jp */\n18572,  /* yokkaichi.mie.jp */\n25243,  /* furukawa.miyagi.jp */\n25252,  /* higashimatsushima.miyagi.jp */\n25270,  /* ishinomaki.miyagi.jp */\n25281,  /* iwanuma.miyagi.jp */\n25289,  /* kakuda.miyagi.jp */\n20081,  /* kami.miyagi.jp */\n18735,  /* kawasaki.miyagi.jp */\n25296,  /* marumori.miyagi.jp */\n19846,  /* matsushima.miyagi.jp */\n25305,  /* minamisanriku.miyagi.jp */\n19989,  /* misato.miyagi.jp */\n25319,  /* murata.miyagi.jp */\n25326,  /* natori.miyagi.jp */\n25333,  /* ogawara.miyagi.jp */\n24316,  /* ohira.miyagi.jp */\n25341,  /* onagawa.miyagi.jp */\n20097,  /* osaki.miyagi.jp */\n25349,  /* rifu.miyagi.jp */\n25354,  /* semine.miyagi.jp */\n25361,  /* shibata.miyagi.jp */\n25369,  /* shichikashuku.miyagi.jp */\n25383,  /* shikama.miyagi.jp */\n25391,  /* shiogama.miyagi.jp */\n25400,  /* shiroishi.miyagi.jp */\n25410,  /* tagajo.miyagi.jp */\n25417,  /* taiwa.miyagi.jp */\n25426,  /* tome.miyagi.jp */\n25431,  /* tomiya.miyagi.jp */\n25438,  /* wakuya.miyagi.jp */\n25445,  /* watari.miyagi.jp */\n25452,  /* yamamoto.miyagi.jp */\n25461,  /* zao.miyagi.jp */\n20323,  /* aya.miyazaki.jp */\n24687,  /* ebino.miyazaki.jp */\n25471,  /* gokase.miyazaki.jp */\n25478,  /* hyuga.miyazaki.jp */\n25484,  /* kadogawa.miyazaki.jp */\n25493,  /* kawaminami.miyazaki.jp */\n25504,  /* kijo.miyazaki.jp */\n21262,  /* kitagawa.miyazaki.jp */\n21271,  /* kitakata.miyazaki.jp */\n25509,  /* kitaura.miyazaki.jp */\n25517,  /* kobayashi.miyazaki.jp */\n25527,  /* kunitomi.miyazaki.jp */\n18635,  /* kushima.miyazaki.jp */\n25536,  /* mimata.miyazaki.jp */\n21185,  /* miyakonojo.miyazaki.jp */\n18774,  /* miyazaki.miyazaki.jp */\n 6104,  /* morotsuka.miyazaki.jp */\n25543,  /* nichinan.miyazaki.jp */\n25552,  /* nishimera.miyazaki.jp */\n25562,  /* nobeoka.miyazaki.jp */\n25570,  /* saito.miyazaki.jp */\n25576,  /* shiiba.miyazaki.jp */\n25583,  /* shintomi.miyazaki.jp */\n25592,  /* takaharu.miyazaki.jp */\n25601,  /* takanabe.miyazaki.jp */\n25610,  /* takazaki.miyazaki.jp */\n20736,  /* tsuno.miyazaki.jp */\n 3924,  /* achi.nagano.jp */\n25626,  /* agematsu.nagano.jp */\n25636,  /* anan.nagano.jp */\n25641,  /* aoki.nagano.jp */\n19734,  /* asahi.nagano.jp */\n25646,  /* azumino.nagano.jp */\n25654,  /* chikuhoku.nagano.jp */\n25664,  /* chikuma.nagano.jp */\n25672,  /* chino.nagano.jp */\n25678,  /* fujimi.nagano.jp */\n25685,  /* hakuba.nagano.jp */\n19775,  /* hara.nagano.jp */\n25692,  /* hiraya.nagano.jp */\n25705,  /* iida.nagano.jp */\n25710,  /* iijima.nagano.jp */\n25717,  /* iiyama.nagano.jp */\n25724,  /* iizuna.nagano.jp */\n20853,  /* ikeda.nagano.jp */\n25731,  /* ikusaka.nagano.jp */\n 7287,  /* ina.nagano.jp */\n25739,  /* karuizawa.nagano.jp */\n25749,  /* kawakami.nagano.jp */\n25758,  /* kiso.nagano.jp */\n18629,  /* kisofukushima.nagano.jp */\n25763,  /* kitaaiki.nagano.jp */\n25772,  /* komagane.nagano.jp */\n25781,  /* komoro.nagano.jp */\n25788,  /* matsukawa.nagano.jp */\n23565,  /* matsumoto.nagano.jp */\n25798,  /* miasa.nagano.jp */\n25804,  /* minamiaiki.nagano.jp */\n25815,  /* minamimaki.nagano.jp */\n25826,  /* minamiminowa.nagano.jp */\n25832,  /* minowa.nagano.jp */\n25839,  /* miyada.nagano.jp */\n25846,  /* miyota.nagano.jp */\n25853,  /* mochizuki.nagano.jp */\n18790,  /* nagano.nagano.jp */\n18728,  /* nagawa.nagano.jp */\n25863,  /* nagiso.nagano.jp */\n18707,  /* nakagawa.nagano.jp */\n25870,  /* nakano.nagano.jp */\n25877,  /* nozawaonsen.nagano.jp */\n25889,  /* obuse.nagano.jp */\n20330,  /* ogawa.nagano.jp */\n25465,  /* okaya.nagano.jp */\n25901,  /* omachi.nagano.jp */\n19860,  /* omi.nagano.jp */\n25908,  /* ookuwa.nagano.jp */\n24043,  /* ooshika.nagano.jp */\n20522,  /* otaki.nagano.jp */\n25915,  /* otari.nagano.jp */\n  154,  /* sakae.nagano.jp */\n25921,  /* sakaki.nagano.jp */\n25928,  /* saku.nagano.jp */\n25933,  /* sakuho.nagano.jp */\n25940,  /* shimosuwa.nagano.jp */\n25895,  /* shinanomachi.nagano.jp */\n25950,  /* shiojiri.nagano.jp */\n25945,  /* suwa.nagano.jp */\n25959,  /* suzaka.nagano.jp */\n25966,  /* takagi.nagano.jp */\n24913,  /* takamori.nagano.jp */\n21918,  /* takayama.nagano.jp */\n25973,  /* tateshina.nagano.jp */\n23616,  /* tatsuno.nagano.jp */\n25983,  /* togakushi.nagano.jp */\n25993,  /* togura.nagano.jp */\n19859,  /* tomi.nagano.jp */\n26000,  /* ueda.nagano.jp */\n20209,  /* wada.nagano.jp */\n19470,  /* yamagata.nagano.jp */\n26005,  /* yamanouchi.nagano.jp */\n26016,  /* yasaka.nagano.jp */\n26023,  /* yasuoka.nagano.jp */\n26031,  /* chijiwa.nagasaki.jp */\n23087,  /* futsu.nagasaki.jp */\n26047,  /* goto.nagasaki.jp */\n26052,  /* hasami.nagasaki.jp */\n26059,  /* hirado.nagasaki.jp */\n 8548,  /* iki.nagasaki.jp */\n26066,  /* isahaya.nagasaki.jp */\n26074,  /* kawatana.nagasaki.jp */\n26083,  /* kuchinotsu.nagasaki.jp */\n26094,  /* matsuura.nagasaki.jp */\n18797,  /* nagasaki.nagasaki.jp */\n20869,  /* obama.nagasaki.jp */\n26103,  /* omura.nagasaki.jp */\n19740,  /* oseto.nagasaki.jp */\n26109,  /* saikai.nagasaki.jp */\n26116,  /* sasebo.nagasaki.jp */\n26123,  /* seihi.nagasaki.jp */\n26129,  /* shimabara.nagasaki.jp */\n26039,  /* shinkamigoto.nagasaki.jp */\n26139,  /* togitsu.nagasaki.jp */\n19848,  /* tsushima.nagasaki.jp */\n26147,  /* unzen.nagasaki.jp */\n23659,  /* ando.nara.jp */\n26154,  /* gose.nara.jp */\n11356,  /* heguri.nara.jp */\n26159,  /* higashiyoshino.nara.jp */\n26174,  /* ikaruga.nara.jp */\n26182,  /* ikoma.nara.jp */\n26188,  /* kamikitayama.nara.jp */\n26201,  /* kanmaki.nara.jp */\n26209,  /* kashiba.nara.jp */\n26217,  /* kashihara.nara.jp */\n26227,  /* katsuragi.nara.jp */\n24159,  /* kawai.nara.jp */\n25749,  /* kawakami.nara.jp */\n23495,  /* kawanishi.nara.jp */\n26237,  /* koryo.nara.jp */\n20519,  /* kurotaki.nara.jp */\n26245,  /* mitsue.nara.jp */\n26252,  /* miyake.nara.jp */\n17635,  /* nara.nara.jp */\n26259,  /* nosegawa.nara.jp */\n24127,  /* oji.nara.jp */\n26268,  /* ouda.nara.jp */\n26273,  /* oyodo.nara.jp */\n26279,  /* sakurai.nara.jp */\n26287,  /* sango.nara.jp */\n26293,  /* shimoichi.nara.jp */\n26303,  /* shimokitayama.nara.jp */\n26317,  /* shinjo.nara.jp */\n26324,  /* soni.nara.jp */\n20344,  /* takatori.nara.jp */\n26329,  /* tawaramoto.nara.jp */\n26340,  /* tenkawa.nara.jp */\n26348,  /* tenri.nara.jp */\n24571,  /* uda.nara.jp */\n21516,  /* yamatokoriyama.nara.jp */\n26354,  /* yamatotakada.nara.jp */\n26367,  /* yamazoe.nara.jp */\n26166,  /* yoshino.nara.jp */\n 3354,  /* aga.niigata.jp */\n18791,  /* agano.niigata.jp */\n26375,  /* gosen.niigata.jp */\n26381,  /* itoigawa.niigata.jp */\n26390,  /* izumozaki.niigata.jp */\n26400,  /* joetsu.niigata.jp */\n21833,  /* kamo.niigata.jp */\n26407,  /* kariwa.niigata.jp */\n26414,  /* kashiwazaki.niigata.jp */\n26426,  /* minamiuonuma.niigata.jp */\n26439,  /* mitsuke.niigata.jp */\n26447,  /* muika.niigata.jp */\n26453,  /* murakami.niigata.jp */\n26462,  /* myoko.niigata.jp */\n26468,  /* nagaoka.niigata.jp */\n18806,  /* niigata.niigata.jp */\n26476,  /* ojiya.niigata.jp */\n19860,  /* omi.niigata.jp */\n26482,  /* sado.niigata.jp */\n19504,  /* sanjo.niigata.jp */\n26487,  /* seiro.niigata.jp */\n26493,  /* seirou.niigata.jp */\n26500,  /* sekikawa.niigata.jp */\n25361,  /* shibata.niigata.jp */\n19964,  /* tagami.niigata.jp */\n26509,  /* tainai.niigata.jp */\n26516,  /* tochio.niigata.jp */\n26523,  /* tokamachi.niigata.jp */\n26533,  /* tsubame.niigata.jp */\n26541,  /* tsunan.niigata.jp */\n26432,  /* uonuma.niigata.jp */\n26548,  /* yahiko.niigata.jp */\n18814,  /* yoita.niigata.jp */\n26555,  /* yuzawa.niigata.jp */\n26562,  /* beppu.oita.jp */\n26568,  /* bungoono.oita.jp */\n26577,  /* bungotakada.oita.jp */\n26589,  /* hasama.oita.jp */\n26596,  /* hiji.oita.jp */\n26601,  /* himeshima.oita.jp */\n19524,  /* hita.oita.jp */\n26243,  /* kamitsue.oita.jp */\n26611,  /* kokonoe.oita.jp */\n26619,  /* kuju.oita.jp */\n26624,  /* kunisaki.oita.jp */\n 7540,  /* kusu.oita.jp */\n18815,  /* oita.oita.jp */\n26633,  /* saiki.oita.jp */\n26639,  /* taketa.oita.jp */\n26646,  /* tsukumi.oita.jp */\n17643,  /* usa.oita.jp */\n26654,  /* usuki.oita.jp */\n26660,  /* yufu.oita.jp */\n26665,  /* akaiwa.okayama.jp */\n26672,  /* asakuchi.okayama.jp */\n26681,  /* bizen.okayama.jp */\n26687,  /* hayashima.okayama.jp */\n26699,  /* ibara.okayama.jp */\n26705,  /* kagamino.okayama.jp */\n26714,  /* kasaoka.okayama.jp */\n20257,  /* kibichuo.okayama.jp */\n26722,  /* kumenan.okayama.jp */\n26730,  /* kurashiki.okayama.jp */\n26740,  /* maniwa.okayama.jp */\n26747,  /* misaki.okayama.jp */\n20108,  /* nagi.okayama.jp */\n26760,  /* niimi.okayama.jp */\n26766,  /* nishiawakura.okayama.jp */\n18820,  /* okayama.okayama.jp */\n26779,  /* satosho.okayama.jp */\n26787,  /* setouchi.okayama.jp */\n26317,  /* shinjo.okayama.jp */\n26796,  /* shoo.okayama.jp */\n26801,  /* soja.okayama.jp */\n26806,  /* takahashi.okayama.jp */\n26816,  /* tamano.okayama.jp */\n20751,  /* tsuyama.okayama.jp */\n 4539,  /* wake.okayama.jp */\n26823,  /* yakage.okayama.jp */\n26833,  /* aguni.okinawa.jp */\n26839,  /* ginowan.okinawa.jp */\n26847,  /* ginoza.okinawa.jp */\n26854,  /* gushikami.okinawa.jp */\n26864,  /* haebaru.okinawa.jp */\n20987,  /* higashi.okinawa.jp */\n26872,  /* hirara.okinawa.jp */\n26879,  /* iheya.okinawa.jp */\n26885,  /* ishigaki.okinawa.jp */\n18692,  /* ishikawa.okinawa.jp */\n 5195,  /* itoman.okinawa.jp */\n26894,  /* izena.okinawa.jp */\n26900,  /* kadena.okinawa.jp */\n 7316,  /* kin.okinawa.jp */\n26907,  /* kitadaito.okinawa.jp */\n26917,  /* kitanakagusuku.okinawa.jp */\n26932,  /* kumejima.okinawa.jp */\n26941,  /* kunigami.okinawa.jp */\n26950,  /* minamidaito.okinawa.jp */\n19701,  /* motobu.okinawa.jp */\n26964,  /* nago.okinawa.jp */\n11881,  /* naha.okinawa.jp */\n26921,  /* nakagusuku.okinawa.jp */\n26969,  /* nakijin.okinawa.jp */\n26977,  /* nanjo.okinawa.jp */\n24903,  /* nishihara.okinawa.jp */\n26983,  /* ogimi.okinawa.jp */\n 5966,  /* okinawa.okinawa.jp */\n26990,  /* onna.okinawa.jp */\n26995,  /* shimoji.okinawa.jp */\n27003,  /* taketomi.okinawa.jp */\n27012,  /* tarama.okinawa.jp */\n27019,  /* tokashiki.okinawa.jp */\n27029,  /* tomigusuku.okinawa.jp */\n27040,  /* tonaki.okinawa.jp */\n27047,  /* urasoe.okinawa.jp */\n27054,  /* uruma.okinawa.jp */\n27060,  /* yaese.okinawa.jp */\n27066,  /* yomitan.okinawa.jp */\n27074,  /* yonabaru.okinawa.jp */\n26830,  /* yonaguni.okinawa.jp */\n24398,  /* zamami.okinawa.jp */\n27083,  /* abeno.osaka.jp */\n27089,  /* chihayaakasaka.osaka.jp */\n20261,  /* chuo.osaka.jp */\n26911,  /* daito.osaka.jp */\n27104,  /* fujiidera.osaka.jp */\n27114,  /* habikino.osaka.jp */\n27123,  /* hannan.osaka.jp */\n27130,  /* higashiosaka.osaka.jp */\n19669,  /* higashisumiyoshi.osaka.jp */\n27143,  /* higashiyodogawa.osaka.jp */\n27159,  /* hirakata.osaka.jp */\n18683,  /* ibaraki.osaka.jp */\n20853,  /* ikeda.osaka.jp */\n22115,  /* izumi.osaka.jp */\n27168,  /* izumiotsu.osaka.jp */\n27178,  /* izumisano.osaka.jp */\n27188,  /* kadoma.osaka.jp */\n27195,  /* kaizuka.osaka.jp */\n25635,  /* kanan.osaka.jp */\n27203,  /* kashiwara.osaka.jp */\n27213,  /* katano.osaka.jp */\n18783,  /* kawachinagano.osaka.jp */\n27220,  /* kishiwada.osaka.jp */\n18586,  /* kita.osaka.jp */\n27230,  /* kumatori.osaka.jp */\n27239,  /* matsubara.osaka.jp */\n27254,  /* minato.osaka.jp */\n27261,  /* minoh.osaka.jp */\n26747,  /* misaki.osaka.jp */\n27267,  /* moriguchi.osaka.jp */\n27277,  /* neyagawa.osaka.jp */\n21149,  /* nishi.osaka.jp */\n 7109,  /* nose.osaka.jp */\n27286,  /* osakasayama.osaka.jp */\n20886,  /* sakai.osaka.jp */\n21006,  /* sayama.osaka.jp */\n27298,  /* sennan.osaka.jp */\n27305,  /* settsu.osaka.jp */\n27312,  /* shijonawate.osaka.jp */\n27324,  /* shimamoto.osaka.jp */\n27334,  /* suita.osaka.jp */\n27340,  /* tadaoka.osaka.jp */\n23575,  /* taishi.osaka.jp */\n27348,  /* tajiri.osaka.jp */\n27355,  /* takaishi.osaka.jp */\n27364,  /* takatsuki.osaka.jp */\n27374,  /* tondabayashi.osaka.jp */\n27387,  /* toyonaka.osaka.jp */\n27396,  /* toyono.osaka.jp */\n27403,  /* yao.osaka.jp */\n27407,  /* ariake.saga.jp */\n20479,  /* arita.saga.jp */\n27414,  /* fukudomi.saga.jp */\n27423,  /* genkai.saga.jp */\n27430,  /* hamatama.saga.jp */\n20839,  /* hizen.saga.jp */\n27439,  /* imari.saga.jp */\n27445,  /* kamimine.saga.jp */\n27454,  /* kanzaki.saga.jp */\n27462,  /* karatsu.saga.jp */\n23761,  /* kashima.saga.jp */\n21813,  /* kitagata.saga.jp */\n27470,  /* kitahata.saga.jp */\n27479,  /* kiyama.saga.jp */\n27486,  /* kouhoku.saga.jp */\n27494,  /* kyuragi.saga.jp */\n27502,  /* nishiarita.saga.jp */\n 3509,  /* ogi.saga.jp */\n25901,  /* omachi.saga.jp */\n21943,  /* ouchi.saga.jp */\n 3353,  /* saga.saga.jp */\n25400,  /* shiroishi.saga.jp */\n27513,  /* taku.saga.jp */\n19768,  /* tara.saga.jp */\n21856,  /* tosu.saga.jp */\n27518,  /* yoshinogari.saga.jp */\n27530,  /* arakawa.saitama.jp */\n26017,  /* asaka.saitama.jp */\n27545,  /* chichibu.saitama.jp */\n25678,  /* fujimi.saitama.jp */\n27554,  /* fujimino.saitama.jp */\n27563,  /* fukaya.saitama.jp */\n27570,  /* hanno.saitama.jp */\n27576,  /* hanyu.saitama.jp */\n27582,  /* hasuda.saitama.jp */\n27589,  /* hatogaya.saitama.jp */\n27598,  /* hatoyama.saitama.jp */\n22571,  /* hidaka.saitama.jp */\n27538,  /* higashichichibu.saitama.jp */\n20742,  /* higashimatsuyama.saitama.jp */\n19924,  /* honjo.saitama.jp */\n 7287,  /* ina.saitama.jp */\n27607,  /* iruma.saitama.jp */\n27613,  /* iwatsuki.saitama.jp */\n27622,  /* kamiizumi.saitama.jp */\n22687,  /* kamikawa.saitama.jp */\n27632,  /* kamisato.saitama.jp */\n27641,  /* kasukabe.saitama.jp */\n25134,  /* kawagoe.saitama.jp */\n27650,  /* kawaguchi.saitama.jp */\n27660,  /* kawajima.saitama.jp */\n27669,  /* kazo.saitama.jp */\n27674,  /* kitamoto.saitama.jp */\n27683,  /* koshigaya.saitama.jp */\n27693,  /* kounosu.saitama.jp */\n27701,  /* kuki.saitama.jp */\n27706,  /* kumagaya.saitama.jp */\n27715,  /* matsubushi.saitama.jp */\n27726,  /* minano.saitama.jp */\n19989,  /* misato.saitama.jp */\n23637,  /* miyashiro.saitama.jp */\n19678,  /* miyoshi.saitama.jp */\n27733,  /* moroyama.saitama.jp */\n27742,  /* nagatoro.saitama.jp */\n27751,  /* namegawa.saitama.jp */\n27760,  /* niiza.saitama.jp */\n27766,  /* ogano.saitama.jp */\n20330,  /* ogawa.saitama.jp */\n26153,  /* ogose.saitama.jp */\n27772,  /* okegawa.saitama.jp */\n19578,  /* omiya.saitama.jp */\n20522,  /* otaki.saitama.jp */\n27780,  /* ranzan.saitama.jp */\n24700,  /* ryokami.saitama.jp */\n18828,  /* saitama.saitama.jp */\n27787,  /* sakado.saitama.jp */\n27794,  /* satte.saitama.jp */\n21006,  /* sayama.saitama.jp */\n19602,  /* shiki.saitama.jp */\n27800,  /* shiraoka.saitama.jp */\n27809,  /* soka.saitama.jp */\n27814,  /* sugito.saitama.jp */\n27821,  /* toda.saitama.jp */\n27826,  /* tokigawa.saitama.jp */\n27835,  /* tokorozawa.saitama.jp */\n27846,  /* tsurugashima.saitama.jp */\n27859,  /* urawa.saitama.jp */\n27865,  /* warabi.saitama.jp */\n27872,  /* yashio.saitama.jp */\n27879,  /* yokoze.saitama.jp */\n22197,  /* yono.saitama.jp */\n27886,  /* yorii.saitama.jp */\n27896,  /* yoshida.saitama.jp */\n27904,  /* yoshikawa.saitama.jp */\n27914,  /* yoshimi.saitama.jp */\n27922,  /* aisho.shiga.jp */\n16366,  /* gamo.shiga.jp */\n27928,  /* higashiomi.shiga.jp */\n27939,  /* hikone.shiga.jp */\n27946,  /* koka.shiga.jp */\n19656,  /* konan.shiga.jp */\n27951,  /* kosei.shiga.jp */\n21196,  /* koto.shiga.jp */\n22047,  /* kusatsu.shiga.jp */\n26697,  /* maibara.shiga.jp */\n27957,  /* moriyama.shiga.jp */\n27966,  /* nagahama.shiga.jp */\n27975,  /* nishiazai.shiga.jp */\n27985,  /* notogawa.shiga.jp */\n27994,  /* omihachiman.shiga.jp */\n21288,  /* otsu.shiga.jp */\n28012,  /* ritto.shiga.jp */\n28018,  /* ryuoh.shiga.jp */\n23759,  /* takashima.shiga.jp */\n27364,  /* takatsuki.shiga.jp */\n28024,  /* torahime.shiga.jp */\n28033,  /* toyosato.shiga.jp */\n20609,  /* yasu.shiga.jp */\n25967,  /* akagi.shimane.jp */\n10609,  /* ama.shimane.jp */\n28006,  /* gotsu.shimane.jp */\n28042,  /* hamada.shimane.jp */\n28049,  /* higashiizumo.shimane.jp */\n18694,  /* hikawa.shimane.jp */\n28062,  /* hikimi.shimane.jp */\n28056,  /* izumo.shimane.jp */\n28078,  /* kakinoki.shimane.jp */\n28087,  /* masuda.shimane.jp */\n21245,  /* matsue.shimane.jp */\n19989,  /* misato.shimane.jp */\n28094,  /* nishinoshima.shimane.jp */\n28107,  /* ohda.shimane.jp */\n28112,  /* okinoshima.shimane.jp */\n28069,  /* okuizumo.shimane.jp */\n18864,  /* shimane.shimane.jp */\n28123,  /* tamayu.shimane.jp */\n28130,  /* tsuwano.shimane.jp */\n28138,  /* unnan.shimane.jp */\n23373,  /* yakumo.shimane.jp */\n28144,  /* yasugi.shimane.jp */\n28151,  /* yatsuka.shimane.jp */\n21257,  /* arai.shizuoka.jp */\n23652,  /* atami.shizuoka.jp */\n23078,  /* fuji.shizuoka.jp */\n28159,  /* fujieda.shizuoka.jp */\n28167,  /* fujikawa.shizuoka.jp */\n28176,  /* fujinomiya.shizuoka.jp */\n28187,  /* fukuroi.shizuoka.jp */\n 5289,  /* gotemba.shizuoka.jp */\n28195,  /* haibara.shizuoka.jp */\n28203,  /* hamamatsu.shizuoka.jp */\n28213,  /* higashiizu.shizuoka.jp */\n 7920,  /* ito.shizuoka.jp */\n28224,  /* iwata.shizuoka.jp */\n21559,  /* izu.shizuoka.jp */\n28230,  /* izunokuni.shizuoka.jp */\n28240,  /* kakegawa.shizuoka.jp */\n28249,  /* kannami.shizuoka.jp */\n28257,  /* kawanehon.shizuoka.jp */\n28267,  /* kawazu.shizuoka.jp */\n28274,  /* kikugawa.shizuoka.jp */\n28283,  /* kosai.shizuoka.jp */\n28289,  /* makinohara.shizuoka.jp */\n28300,  /* matsuzaki.shizuoka.jp */\n28310,  /* minamiizu.shizuoka.jp */\n21545,  /* mishima.shizuoka.jp */\n28320,  /* morimachi.shizuoka.jp */\n28330,  /* nishiizu.shizuoka.jp */\n28339,  /* numazu.shizuoka.jp */\n28346,  /* omaezaki.shizuoka.jp */\n28355,  /* shimada.shizuoka.jp */\n22782,  /* shimizu.shizuoka.jp */\n 5473,  /* shimoda.shizuoka.jp */\n18872,  /* shizuoka.shizuoka.jp */\n28363,  /* susono.shizuoka.jp */\n28370,  /* yaizu.shizuoka.jp */\n27896,  /* yoshida.shizuoka.jp */\n23985,  /* ashikaga.tochigi.jp */\n11640,  /* bato.tochigi.jp */\n28376,  /* haga.tochigi.jp */\n28381,  /* ichikai.tochigi.jp */\n28389,  /* iwafune.tochigi.jp */\n28397,  /* kaminokawa.tochigi.jp */\n28408,  /* kanuma.tochigi.jp */\n28415,  /* karasuyama.tochigi.jp */\n24619,  /* kuroiso.tochigi.jp */\n28426,  /* mashiko.tochigi.jp */\n28434,  /* mibu.tochigi.jp */\n28439,  /* moka.tochigi.jp */\n28444,  /* motegi.tochigi.jp */\n28451,  /* nasu.tochigi.jp */\n28456,  /* nasushiobara.tochigi.jp */\n28469,  /* nikko.tochigi.jp */\n28475,  /* nishikata.tochigi.jp */\n 3508,  /* nogi.tochigi.jp */\n24316,  /* ohira.tochigi.jp */\n28485,  /* ohtawara.tochigi.jp */\n18910,  /* oyama.tochigi.jp */\n 6909,  /* sakura.tochigi.jp */\n27183,  /* sano.tochigi.jp */\n28494,  /* shimotsuke.tochigi.jp */\n28505,  /* shioya.tochigi.jp */\n28512,  /* takanezawa.tochigi.jp */\n18881,  /* tochigi.tochigi.jp */\n28523,  /* tsuga.tochigi.jp */\n28529,  /* ujiie.tochigi.jp */\n28535,  /* utsunomiya.tochigi.jp */\n28546,  /* yaita.tochigi.jp */\n24108,  /* aizumi.tokushima.jp */\n25636,  /* anan.tokushima.jp */\n18602,  /* ichiba.tokushima.jp */\n28552,  /* itano.tokushima.jp */\n20659,  /* kainan.tokushima.jp */\n19844,  /* komatsushima.tokushima.jp */\n28558,  /* matsushige.tokushima.jp */\n28569,  /* mima.tokushima.jp */\n21088,  /* minami.tokushima.jp */\n19678,  /* miyoshi.tokushima.jp */\n28574,  /* mugi.tokushima.jp */\n18707,  /* nakagawa.tokushima.jp */\n28579,  /* naruto.tokushima.jp */\n28586,  /* sanagochi.tokushima.jp */\n28596,  /* shishikui.tokushima.jp */\n18889,  /* tokushima.tokushima.jp */\n28606,  /* wajiki.tokushima.jp */\n25619,  /* adachi.tokyo.jp */\n28613,  /* akiruno.tokyo.jp */\n28621,  /* akishima.tokyo.jp */\n28630,  /* aogashima.tokyo.jp */\n27530,  /* arakawa.tokyo.jp */\n28640,  /* bunkyo.tokyo.jp */\n21970,  /* chiyoda.tokyo.jp */\n28647,  /* chofu.tokyo.jp */\n20261,  /* chuo.tokyo.jp */\n23808,  /* edogawa.tokyo.jp */\n22234,  /* fuchu.tokyo.jp */\n28653,  /* fussa.tokyo.jp */\n28659,  /* hachijo.tokyo.jp */\n28667,  /* hachioji.tokyo.jp */\n28676,  /* hamura.tokyo.jp */\n21071,  /* higashikurume.tokyo.jp */\n28683,  /* higashimurayama.tokyo.jp */\n21684,  /* higashiyamato.tokyo.jp */\n20473,  /* hino.tokyo.jp */\n28699,  /* hinode.tokyo.jp */\n28706,  /* hinohara.tokyo.jp */\n26754,  /* inagi.tokyo.jp */\n28715,  /* itabashi.tokyo.jp */\n28724,  /* katsushika.tokyo.jp */\n18586,  /* kita.tokyo.jp */\n28735,  /* kiyose.tokyo.jp */\n28742,  /* kodaira.tokyo.jp */\n28750,  /* koganei.tokyo.jp */\n28758,  /* kokubunji.tokyo.jp */\n28768,  /* komae.tokyo.jp */\n21196,  /* koto.tokyo.jp */\n28774,  /* kouzushima.tokyo.jp */\n28785,  /* kunitachi.tokyo.jp */\n21753,  /* machida.tokyo.jp */\n28795,  /* meguro.tokyo.jp */\n27254,  /* minato.tokyo.jp */\n23582,  /* mitaka.tokyo.jp */\n28802,  /* mizuho.tokyo.jp */\n28809,  /* musashimurayama.tokyo.jp */\n28825,  /* musashino.tokyo.jp */\n25870,  /* nakano.tokyo.jp */\n28835,  /* nerima.tokyo.jp */\n28842,  /* ogasawara.tokyo.jp */\n28852,  /* okutama.tokyo.jp */\n 1692,  /* ome.tokyo.jp */\n18661,  /* oshima.tokyo.jp */\n 7969,  /* ota.tokyo.jp */\n28873,  /* setagaya.tokyo.jp */\n28882,  /* shibuya.tokyo.jp */\n23461,  /* shinagawa.tokyo.jp */\n28890,  /* shinjuku.tokyo.jp */\n28899,  /* suginami.tokyo.jp */\n28908,  /* sumida.tokyo.jp */\n28915,  /* tachikawa.tokyo.jp */\n28925,  /* taito.tokyo.jp */\n18831,  /* tama.tokyo.jp */\n28865,  /* toshima.tokyo.jp */\n28931,  /* chizu.tottori.jp */\n20473,  /* hino.tottori.jp */\n28937,  /* kawahara.tottori.jp */\n 3456,  /* koge.tottori.jp */\n28946,  /* kotoura.tottori.jp */\n28954,  /* misasa.tottori.jp */\n28961,  /* nanbu.tottori.jp */\n25543,  /* nichinan.tottori.jp */\n27249,  /* sakaiminato.tottori.jp */\n18899,  /* tottori.tottori.jp */\n20900,  /* wakasa.tottori.jp */\n25027,  /* yazu.tottori.jp */\n26962,  /* yonago.tottori.jp */\n19734,  /* asahi.toyama.jp */\n22234,  /* fuchu.toyama.jp */\n28967,  /* fukumitsu.toyama.jp */\n28977,  /* funahashi.toyama.jp */\n27917,  /* himi.toyama.jp */\n22784,  /* imizu.toyama.jp */\n21089,  /* inami.toyama.jp */\n28987,  /* johana.toyama.jp */\n28994,  /* kamiichi.toyama.jp */\n29003,  /* kurobe.toyama.jp */\n29010,  /* nakaniikawa.toyama.jp */\n29022,  /* namerikawa.toyama.jp */\n29033,  /* nanto.toyama.jp */\n29039,  /* nyuzen.toyama.jp */\n29046,  /* oyabe.toyama.jp */\n29052,  /* taira.toyama.jp */\n29058,  /* takaoka.toyama.jp */\n20581,  /* tateyama.toyama.jp */\n29066,  /* toga.toyama.jp */\n29071,  /* tonami.toyama.jp */\n18909,  /* toyama.toyama.jp */\n29078,  /* unazuki.toyama.jp */\n20767,  /* uozu.toyama.jp */\n21312,  /* yamada.toyama.jp */\n29086,  /* arida.wakayama.jp */\n29092,  /* aridagawa.wakayama.jp */\n29102,  /* gobo.wakayama.jp */\n29107,  /* hashimoto.wakayama.jp */\n22571,  /* hidaka.wakayama.jp */\n29117,  /* hirogawa.wakayama.jp */\n21089,  /* inami.wakayama.jp */\n29126,  /* iwade.wakayama.jp */\n20659,  /* kainan.wakayama.jp */\n29132,  /* kamitonda.wakayama.jp */\n26227,  /* katsuragi.wakayama.jp */\n21822,  /* kimino.wakayama.jp */\n29142,  /* kinokawa.wakayama.jp */\n26192,  /* kitayama.wakayama.jp */\n29151,  /* koya.wakayama.jp */\n10620,  /* koza.wakayama.jp */\n29156,  /* kozagawa.wakayama.jp */\n29165,  /* kudoyama.wakayama.jp */\n29174,  /* kushimoto.wakayama.jp */\n19662,  /* mihama.wakayama.jp */\n19989,  /* misato.wakayama.jp */\n20353,  /* nachikatsuura.wakayama.jp */\n21218,  /* shingu.wakayama.jp */\n29184,  /* shirahama.wakayama.jp */\n29194,  /* taiji.wakayama.jp */\n24985,  /* tanabe.wakayama.jp */\n18916,  /* wakayama.wakayama.jp */\n29200,  /* yuasa.wakayama.jp */\n29206,  /* yura.wakayama.jp */\n19734,  /* asahi.yamagata.jp */\n29211,  /* funagata.yamagata.jp */\n29220,  /* higashine.yamagata.jp */\n 2274,  /* iide.yamagata.jp */\n23994,  /* kahoku.yamagata.jp */\n29230,  /* kaminoyama.yamagata.jp */\n21479,  /* kaneyama.yamagata.jp */\n23495,  /* kawanishi.yamagata.jp */\n29241,  /* mamurogawa.yamagata.jp */\n22689,  /* mikawa.yamagata.jp */\n28690,  /* murayama.yamagata.jp */\n29252,  /* nagai.yamagata.jp */\n29258,  /* nakayama.yamagata.jp */\n29267,  /* nanyo.yamagata.jp */\n18691,  /* nishikawa.yamagata.jp */\n29273,  /* obanazawa.yamagata.jp */\n 1676,  /* oe.yamagata.jp */\n24890,  /* oguni.yamagata.jp */\n29283,  /* ohkura.yamagata.jp */\n29290,  /* oishida.yamagata.jp */\n29298,  /* sagae.yamagata.jp */\n29304,  /* sakata.yamagata.jp */\n29311,  /* sakegawa.yamagata.jp */\n26317,  /* shinjo.yamagata.jp */\n29320,  /* shirataka.yamagata.jp */\n20666,  /* shonai.yamagata.jp */\n29330,  /* takahata.yamagata.jp */\n29339,  /* tendo.yamagata.jp */\n29345,  /* tozawa.yamagata.jp */\n29352,  /* tsuruoka.yamagata.jp */\n19470,  /* yamagata.yamagata.jp */\n29361,  /* yamanobe.yamagata.jp */\n29370,  /* yonezawa.yamagata.jp */\n29379,  /* yuza.yamagata.jp */\n22430,  /* abu.yamaguchi.jp */\n23886,  /* hagi.yamaguchi.jp */\n20641,  /* hikari.yamaguchi.jp */\n28648,  /* hofu.yamaguchi.jp */\n29384,  /* iwakuni.yamaguchi.jp */\n29392,  /* kudamatsu.yamaguchi.jp */\n29402,  /* mitou.yamaguchi.jp */\n29408,  /* nagato.yamaguchi.jp */\n18661,  /* oshima.yamaguchi.jp */\n29415,  /* shimonoseki.yamaguchi.jp */\n29427,  /* shunan.yamaguchi.jp */\n29434,  /* tabuse.yamaguchi.jp */\n29441,  /* tokuyama.yamaguchi.jp */\n 7966,  /* toyota.yamaguchi.jp */\n 8059,  /* ube.yamaguchi.jp */\n29450,  /* yuu.yamaguchi.jp */\n20261,  /* chuo.yamanashi.jp */\n29454,  /* doshi.yamanashi.jp */\n29460,  /* fuefuki.yamanashi.jp */\n28167,  /* fujikawa.yamanashi.jp */\n20796,  /* fujikawaguchiko.yamanashi.jp */\n27892,  /* fujiyoshida.yamanashi.jp */\n29468,  /* hayakawa.yamanashi.jp */\n22618,  /* hokuto.yamanashi.jp */\n29477,  /* ichikawamisato.yamanashi.jp */\n19806,  /* kai.yamanashi.jp */\n29492,  /* kofu.yamanashi.jp */\n24220,  /* koshu.yamanashi.jp */\n29497,  /* kosuge.yamanashi.jp */\n29504,  /* minami-alps.yamanashi.jp */\n29516,  /* minobu.yamanashi.jp */\n29523,  /* nakamichi.yamanashi.jp */\n28961,  /* nanbu.yamanashi.jp */\n29533,  /* narusawa.yamanashi.jp */\n29542,  /* nirasaki.yamanashi.jp */\n29551,  /* nishikatsura.yamanashi.jp */\n26167,  /* oshino.yamanashi.jp */\n24766,  /* otsuki.yamanashi.jp */\n21625,  /* showa.yamanashi.jp */\n29564,  /* tabayama.yamanashi.jp */\n29573,  /* tsuru.yamanashi.jp */\n29579,  /* uenohara.yamanashi.jp */\n29588,  /* yamanakako.yamanashi.jp */\n19489,  /* yamanashi.yamanashi.jp */\n  985,  /* biz.ki */\n 1913,  /* com.ki */\n 2624,  /* edu.ki */\n 3686,  /* gov.ki */\n 3167,  /* info.ki */\n 4185,  /* net.ki */\n 6070,  /* org.ki */\n 3548,  /* ass.km */\n11614,  /* asso.km */\n 1913,  /* com.km */\n 2047,  /* coop.km */\n 2624,  /* edu.km */\n11627,  /* gouv.km */\n 3686,  /* gov.km */\n15415,  /* medecin.km */\n 4195,  /* mil.km */\n 5998,  /* nom.km */\n15423,  /* notaires.km */\n 6070,  /* org.km */\n29599,  /* pharmaciens.km */\n15443,  /* prd.km */\n11816,  /* presse.km */\n 7910,  /* tm.km */\n15447,  /* veterinaire.km */\n 2624,  /* edu.kn */\n 3686,  /* gov.kn */\n 4185,  /* net.kn */\n 6070,  /* org.kn */\n 1913,  /* com.kp */\n 2624,  /* edu.kp */\n 3686,  /* gov.kp */\n 6070,  /* org.kp */\n29611,  /* rep.kp */\n16671,  /* tra.kp */\n   62,  /* ac.kr */\n10666,  /* blogspot.kr */\n29621,  /* busan.kr */\n29627,  /* chungbuk.kr */\n29636,  /* chungnam.kr */\n  113,  /* co.kr */\n29645,  /* daegu.kr */\n29651,  /* daejeon.kr */\n  558,  /* es.kr */\n29659,  /* gangwon.kr */\n  257,  /* go.kr */\n29667,  /* gwangju.kr */\n29675,  /* gyeongbuk.kr */\n29685,  /* gyeonggi.kr */\n29694,  /* gyeongnam.kr */\n 9270,  /* hs.kr */\n29708,  /* incheon.kr */\n29716,  /* jeju.kr */\n 8117,  /* jeonbuk.kr */\n29721,  /* jeonnam.kr */\n 4579,  /* kg.kr */\n 4195,  /* mil.kr */\n 1059,  /* ms.kr */\n 1203,  /* ne.kr */\n  137,  /* or.kr */\n 3739,  /* pe.kr */\n   80,  /* re.kr */\n 2158,  /* sc.kr */\n29729,  /* seoul.kr */\n29735,  /* ulsan.kr */\n  113,  /* co.krd */\n 2624,  /* edu.krd */\n 5911,  /* bnr.la */\n   36,  /* c.la */\n 1913,  /* com.la */\n 2624,  /* edu.la */\n 3686,  /* gov.la */\n 3167,  /* info.la */\n 3632,  /* int.la */\n 4185,  /* net.la */\n 6070,  /* org.la */\n 4523,  /* per.la */\n 2380,  /* dev.static.land */\n29756,  /* sites.static.land */\n  113,  /* co.lc */\n 1913,  /* com.lc */\n 2624,  /* edu.lc */\n 3686,  /* gov.lc */\n 4185,  /* net.lc */\n 6070,  /* org.lc */\n 4492,  /* oy.lc */\n29762,  /* cyon.link */\n29767,  /* mypep.link */\n   62,  /* ac.lk */\n29773,  /* assn.lk */\n 1913,  /* com.lk */\n 2624,  /* edu.lk */\n 3686,  /* gov.lk */\n29778,  /* grp.lk */\n 7749,  /* hotel.lk */\n 3632,  /* int.lk */\n 5103,  /* ltd.lk */\n 4185,  /* net.lk */\n  976,  /* ngo.lk */\n 6070,  /* org.lk */\n 1145,  /* sch.lk */\n29782,  /* soc.lk */\n11967,  /* web.lk */\n 7340,  /* asn.lv */\n 1913,  /* com.lv */\n11412,  /* conf.lv */\n 2624,  /* edu.lv */\n 3686,  /* gov.lv */\n  437,  /* id.lv */\n 4195,  /* mil.lv */\n 4185,  /* net.lv */\n 6070,  /* org.lv */\n 1913,  /* com.ly */\n 2624,  /* edu.ly */\n 3686,  /* gov.ly */\n  437,  /* id.ly */\n 1858,  /* med.ly */\n 4185,  /* net.ly */\n 6070,  /* org.ly */\n 4860,  /* plc.ly */\n 1145,  /* sch.ly */\n   62,  /* ac.ma */\n  113,  /* co.ma */\n 3686,  /* gov.ma */\n 4185,  /* net.ma */\n 6070,  /* org.ma */\n  371,  /* press.ma */\n15043,  /* router.management */\n11614,  /* asso.mc */\n 7910,  /* tm.mc */\n   62,  /* ac.me */\n29786,  /* brasilia.me */\n  113,  /* co.me */\n29795,  /* daplie.me */\n29802,  /* ddns.me */\n15103,  /* diskstation.me */\n29807,  /* dnsfor.me */\n11518,  /* dscloud.me */\n 2624,  /* edu.me */\n 3686,  /* gov.me */\n29814,  /* hopto.me */\n29820,  /* i234.me */\n18288,  /* its.me */\n29825,  /* loginto.me */\n29833,  /* myds.me */\n 4185,  /* net.me */\n29838,  /* noip.me */\n 6070,  /* org.me */\n11393,  /* priv.me */\n29843,  /* synology.me */\n11601,  /* webhop.me */\n29852,  /* yombo.me */\n  113,  /* co.mg */\n 1913,  /* com.mg */\n 2624,  /* edu.mg */\n 3686,  /* gov.mg */\n 4195,  /* mil.mg */\n 5998,  /* nom.mg */\n 6070,  /* org.mg */\n15443,  /* prd.mg */\n 7910,  /* tm.mg */\n10666,  /* blogspot.mk */\n 1913,  /* com.mk */\n 2624,  /* edu.mk */\n 3686,  /* gov.mk */\n 5824,  /* inf.mk */\n 5725,  /* name.mk */\n 4185,  /* net.mk */\n 6070,  /* org.mk */\n 1913,  /* com.ml */\n 2624,  /* edu.ml */\n11627,  /* gouv.ml */\n 3686,  /* gov.ml */\n 4185,  /* net.ml */\n 6070,  /* org.ml */\n11816,  /* presse.ml */\n 2624,  /* edu.mn */\n 3686,  /* gov.mn */\n 5933,  /* nyc.mn */\n 6070,  /* org.mn */\n11518,  /* dscloud.mobi */\n   62,  /* ac.mu */\n  113,  /* co.mu */\n 1913,  /* com.mu */\n 3686,  /* gov.mu */\n 4185,  /* net.mu */\n  137,  /* or.mu */\n 6070,  /* org.mu */\n   65,  /* academy.museum */\n29858,  /* agriculture.museum */\n 3824,  /* air.museum */\n29870,  /* airguard.museum */\n29879,  /* alabama.museum */\n29887,  /* alaska.museum */\n29894,  /* amber.museum */\n10818,  /* ambulance.museum */\n29906,  /* american.museum */\n29915,  /* americana.museum */\n29925,  /* americanantiques.museum */\n29942,  /* americanart.museum */\n  412,  /* amsterdam.museum */\n  726,  /* and.museum */\n29960,  /* annefrank.museum */\n29970,  /* anthro.museum */\n29977,  /* anthropology.museum */\n29933,  /* antiques.museum */\n30001,  /* aquarium.museum */\n30010,  /* arboretum.museum */\n30020,  /* archaeological.museum */\n30035,  /* archaeology.museum */\n30047,  /* architecture.museum */\n  527,  /* art.museum */\n 2367,  /* artanddesign.museum */\n 1590,  /* artcenter.museum */\n30060,  /* artdeco.museum */\n 2628,  /* arteducation.museum */\n 3364,  /* artgallery.museum */\n 6175,  /* arts.museum */\n30068,  /* artsandcrafts.museum */\n30082,  /* asmatart.museum */\n30091,  /* assassination.museum */\n30105,  /* assisi.museum */\n10848,  /* association.museum */\n30112,  /* astronomy.museum */\n30122,  /* atlanta.museum */\n30130,  /* austin.museum */\n30137,  /* australia.museum */\n30147,  /* automotive.museum */\n10921,  /* aviation.museum */\n30158,  /* axis.museum */\n30163,  /* badajoz.museum */\n 2211,  /* baghdad.museum */\n30176,  /* bahn.museum */\n30181,  /* bale.museum */\n30186,  /* baltimore.museum */\n  740,  /* barcelona.museum */\n  789,  /* baseball.museum */\n30196,  /* basel.museum */\n30202,  /* baths.museum */\n30208,  /* bauern.museum */\n30215,  /* beauxarts.museum */\n30225,  /* beeldengeluid.museum */\n30239,  /* bellevue.museum */\n30248,  /* bergbau.museum */\n30256,  /* berkeley.museum */\n  894,  /* berlin.museum */\n30265,  /* bern.museum */\n  950,  /* bible.museum */\n30270,  /* bilbao.museum */\n30277,  /* bill.museum */\n30282,  /* birdart.museum */\n 6335,  /* birthplace.museum */\n30290,  /* bonn.museum */\n 1156,  /* boston.museum */\n30295,  /* botanical.museum */\n30305,  /* botanicalgarden.museum */\n30321,  /* botanicgarden.museum */\n30335,  /* botany.museum */\n30342,  /* brandywinevalley.museum */\n30359,  /* brasil.museum */\n30366,  /* bristol.museum */\n30374,  /* british.museum */\n30382,  /* britishcolumbia.museum */\n30398,  /* broadcast.museum */\n30408,  /* brunel.museum */\n30415,  /* brussel.museum */\n 1230,  /* brussels.museum */\n30423,  /* bruxelles.museum */\n30433,  /* building.museum */\n30442,  /* burghof.museum */\n  263,  /* bus.museum */\n30450,  /* bushey.museum */\n30457,  /* cadaques.museum */\n30466,  /* california.museum */\n30477,  /* cambridge.museum */\n 6730,  /* can.museum */\n30487,  /* canada.museum */\n30494,  /* capebreton.museum */\n30505,  /* carrier.museum */\n30513,  /* cartoonart.museum */\n30524,  /* casadelamoneda.museum */\n30539,  /* castle.museum */\n30546,  /* castres.museum */\n30554,  /* celtic.museum */\n 1593,  /* center.museum */\n30561,  /* chattanooga.museum */\n30573,  /* cheltenham.museum */\n30584,  /* chesapeakebay.museum */\n30598,  /* chicago.museum */\n30606,  /* children.museum */\n30615,  /* childrens.museum */\n30625,  /* childrensgarden.museum */\n30641,  /* chiropractic.museum */\n30654,  /* chocolate.museum */\n30664,  /* christiansburg.museum */\n30679,  /* cincinnati.museum */\n30690,  /* cinema.museum */\n30697,  /* circus.museum */\n30704,  /* civilisation.museum */\n30717,  /* civilization.museum */\n30730,  /* civilwar.museum */\n30739,  /* clinton.museum */\n30755,  /* clock.museum */\n  288,  /* coal.museum */\n30761,  /* coastaldefence.museum */\n15262,  /* cody.museum */\n30776,  /* coldwar.museum */\n30784,  /* collection.museum */\n30795,  /* colonialwilliamsburg.museum */\n30816,  /* coloradoplateau.museum */\n30389,  /* columbia.museum */\n30832,  /* columbus.museum */\n30841,  /* communication.museum */\n30869,  /* communications.museum */\n 1934,  /* community.museum */\n 1952,  /* computer.museum */\n30884,  /* computerhistory.museum */\n30900,  /* contemporary.museum */\n30913,  /* contemporaryart.museum */\n30929,  /* convent.museum */\n30937,  /* copenhagen.museum */\n30948,  /* corporation.museum */\n30960,  /* corvette.museum */\n30969,  /* costume.museum */\n30979,  /* countryestate.museum */\n30993,  /* county.museum */\n30075,  /* crafts.museum */\n31000,  /* cranbrook.museum */\n11212,  /* creation.museum */\n31010,  /* cultural.museum */\n31019,  /* culturalcenter.museum */\n29862,  /* culture.museum */\n31044,  /* cyber.museum */\n 2187,  /* cymru.museum */\n31058,  /* dali.museum */\n31063,  /* dallas.museum */\n31070,  /* database.museum */\n11348,  /* ddr.museum */\n31081,  /* decorativearts.museum */\n31103,  /* delaware.museum */\n31112,  /* delmenhorst.museum */\n31124,  /* denmark.museum */\n 3985,  /* depot.museum */\n 2373,  /* design.museum */\n31132,  /* detroit.museum */\n31140,  /* dinosaur.museum */\n31149,  /* discovery.museum */\n31159,  /* dolls.museum */\n31165,  /* donostia.museum */\n31174,  /* durham.museum */\n  213,  /* eastafrica.museum */\n31181,  /* eastcoast.museum */\n 2631,  /* education.museum */\n31191,  /* educational.museum */\n31203,  /* egyptian.museum */\n30171,  /* eisenbahn.museum */\n17690,  /* elburg.museum */\n31212,  /* elvendrell.museum */\n31223,  /* embroidery.museum */\n31234,  /* encyclopedic.museum */\n31247,  /* england.museum */\n31255,  /* entomology.museum */\n31266,  /* environment.museum */\n31278,  /* environmentalconservation.museum */\n31304,  /* epilepsy.museum */\n 7166,  /* essex.museum */\n 2769,  /* estate.museum */\n31313,  /* ethnology.museum */\n31323,  /* exeter.museum */\n31330,  /* exhibition.museum */\n  385,  /* family.museum */\n 2948,  /* farm.museum */\n 2721,  /* farmequipment.museum */\n 2953,  /* farmers.museum */\n31341,  /* farmstead.museum */\n31351,  /* field.museum */\n31357,  /* figueres.museum */\n31366,  /* filatelia.museum */\n 3031,  /* film.museum */\n31376,  /* fineart.museum */\n31384,  /* finearts.museum */\n31393,  /* finland.museum */\n31401,  /* flanders.museum */\n31410,  /* florida.museum */\n  270,  /* force.museum */\n31418,  /* fortmissoula.museum */\n31431,  /* fortworth.museum */\n 3229,  /* foundation.museum */\n31441,  /* francaise.museum */\n31451,  /* frankfurt.museum */\n31461,  /* franziskaner.museum */\n31474,  /* freemasonry.museum */\n31486,  /* freiburg.museum */\n31495,  /* fribourg.museum */\n31504,  /* frog.museum */\n31509,  /* fundacio.museum */\n 3332,  /* furniture.museum */\n 3367,  /* gallery.museum */\n 3417,  /* garden.museum */\n12529,  /* gateway.museum */\n31518,  /* geelvinck.museum */\n31528,  /* gemological.museum */\n31540,  /* geology.museum */\n31548,  /* georgia.museum */\n31556,  /* giessen.museum */\n31564,  /* glas.museum */\n 3546,  /* glass.museum */\n31569,  /* gorge.museum */\n31575,  /* grandrapids.museum */\n31587,  /* graz.museum */\n31592,  /* guernsey.museum */\n31601,  /* halloffame.museum */\n 3828,  /* hamburg.museum */\n31612,  /* handson.museum */\n31620,  /* harvestcelebration.museum */\n31639,  /* hawaii.museum */\n 3862,  /* health.museum */\n31646,  /* heimatunduhren.museum */\n31661,  /* hellas.museum */\n 3874,  /* helsinki.museum */\n31668,  /* hembygdsforbund.museum */\n31692,  /* heritage.museum */\n31701,  /* histoire.museum */\n31710,  /* historical.museum */\n31721,  /* historicalsociety.museum */\n31739,  /* historichouses.museum */\n31754,  /* historisch.museum */\n31770,  /* historisches.museum */\n30892,  /* history.museum */\n 7064,  /* historyofscience.museum */\n31793,  /* horology.museum */\n 4105,  /* house.museum */\n31802,  /* humanities.museum */\n31813,  /* illustration.museum */\n31826,  /* imageandsound.museum */\n31840,  /* indian.museum */\n31847,  /* indiana.museum */\n31855,  /* indianapolis.museum */\n 5223,  /* indianmarket.museum */\n31868,  /* intelligence.museum */\n  116,  /* interactive.museum */\n  478,  /* iraq.museum */\n31881,  /* iron.museum */\n31886,  /* isleofman.museum */\n31896,  /* jamison.museum */\n31904,  /* jefferson.museum */\n31914,  /* jerusalem.museum */\n 4439,  /* jewelry.museum */\n31924,  /* jewish.museum */\n31931,  /* jewishart.museum */\n 3115,  /* jfk.museum */\n31941,  /* journalism.museum */\n31952,  /* judaica.museum */\n31960,  /* judygarland.museum */\n31972,  /* juedisches.museum */\n31983,  /* juif.museum */\n31988,  /* karate.museum */\n11329,  /* karikatur.museum */\n31995,  /* kids.museum */\n 8344,  /* koebenhavn.museum */\n 4636,  /* koeln.museum */\n32000,  /* kunst.museum */\n32006,  /* kunstsammlung.museum */\n32020,  /* kunstunddesign.museum */\n32035,  /* labor.museum */\n32041,  /* labour.museum */\n32048,  /* lajolla.museum */\n32056,  /* lancashire.museum */\n32067,  /* landes.museum */\n32074,  /* lans.museum */\n32079,  /* larsson.museum */\n32087,  /* lewismiller.museum */\n 4980,  /* lincoln.museum */\n 5937,  /* linz.museum */\n 5014,  /* living.museum */\n32101,  /* livinghistory.museum */\n32115,  /* localhistory.museum */\n 5064,  /* london.museum */\n32128,  /* losangeles.museum */\n32139,  /* louvre.museum */\n32146,  /* loyalist.museum */\n32155,  /* lucerne.museum */\n32163,  /* luxembourg.museum */\n32174,  /* luzern.museum */\n  140,  /* mad.museum */\n 5160,  /* madrid.museum */\n32181,  /* mallorca.museum */\n32190,  /* manchester.museum */\n32201,  /* mansion.museum */\n32209,  /* mansions.museum */\n11905,  /* manx.museum */\n32218,  /* marburg.museum */\n32226,  /* maritime.museum */\n32235,  /* maritimo.museum */\n32244,  /* maryland.museum */\n32253,  /* marylhurst.museum */\n 5327,  /* media.museum */\n 1315,  /* medical.museum */\n32264,  /* medizinhistorisches.museum */\n32284,  /* meeres.museum */\n 5353,  /* memorial.museum */\n32291,  /* mesaverde.museum */\n32301,  /* michigan.museum */\n32310,  /* midatlantic.museum */\n32322,  /* military.museum */\n32335,  /* mill.museum */\n32340,  /* miners.museum */\n32347,  /* mining.museum */\n32354,  /* minnesota.museum */\n32364,  /* missile.museum */\n31422,  /* missoula.museum */\n32372,  /* modern.museum */\n32379,  /* moma.museum */\n 5500,  /* money.museum */\n32384,  /* monmouth.museum */\n32393,  /* monticello.museum */\n32404,  /* montreal.museum */\n 5546,  /* moscow.museum */\n32413,  /* motorcycle.museum */\n32424,  /* muenchen.museum */\n32433,  /* muenster.museum */\n 4102,  /* mulhouse.museum */\n32442,  /* muncie.museum */\n32449,  /* museet.museum */\n32456,  /* museumcenter.museum */\n32469,  /* museumvereniging.museum */\n17756,  /* music.museum */\n 4313,  /* national.museum */\n32486,  /* nationalfirearms.museum */\n31684,  /* nationalheritage.museum */\n29900,  /* nativeamerican.museum */\n32503,  /* naturalhistory.museum */\n 5630,  /* naturalhistorymuseum.museum */\n32518,  /* naturalsciences.museum */\n32534,  /* nature.museum */\n31765,  /* naturhistorisches.museum */\n32541,  /* natuurwetenschappen.museum */\n32561,  /* naumburg.museum */\n32570,  /* naval.museum */\n32576,  /* nebraska.museum */\n 2755,  /* neues.museum */\n32585,  /* newhampshire.museum */\n32598,  /* newjersey.museum */\n32608,  /* newmexico.museum */\n32618,  /* newport.museum */\n32626,  /* newspaper.museum */\n32636,  /* newyork.museum */\n32644,  /* niepce.museum */\n32651,  /* norfolk.museum */\n32659,  /* north.museum */\n 5921,  /* nrw.museum */\n32665,  /* nuernberg.museum */\n32675,  /* nuremberg.museum */\n 5933,  /* nyc.museum */\n32685,  /* nyny.museum */\n32690,  /* oceanographic.museum */\n32704,  /* oceanographique.museum */\n32720,  /* omaha.museum */\n 6023,  /* online.museum */\n32726,  /* ontario.museum */\n32734,  /* openair.museum */\n32742,  /* oregon.museum */\n32749,  /* oregontrail.museum */\n32761,  /* otago.museum */\n 3202,  /* oxford.museum */\n32767,  /* pacific.museum */\n32775,  /* paderborn.museum */\n32785,  /* palace.museum */\n32792,  /* paleo.museum */\n32798,  /* palmsprings.museum */\n32810,  /* panama.museum */\n 6154,  /* paris.museum */\n32817,  /* pasadena.museum */\n 6217,  /* pharmacy.museum */\n32826,  /* philadelphia.museum */\n32839,  /* philadelphiaarea.museum */\n32856,  /* philately.museum */\n32866,  /* phoenix.museum */\n 6244,  /* photography.museum */\n32874,  /* pilots.museum */\n 3497,  /* pittsburgh.museum */\n32881,  /* planetarium.museum */\n32893,  /* plantation.museum */\n32904,  /* plants.museum */\n32911,  /* plaza.museum */\n32917,  /* portal.museum */\n32924,  /* portland.museum */\n32933,  /* portlligat.museum */\n30855,  /* posts-and-telecommunications.museum */\n32944,  /* preservation.museum */\n32957,  /* presidio.museum */\n  371,  /* press.museum */\n32966,  /* project.museum */\n  711,  /* public.museum */\n32974,  /* pubol.museum */\n 6547,  /* quebec.museum */\n32980,  /* railroad.museum */\n32989,  /* railway.museum */\n 1383,  /* research.museum */\n32997,  /* resistance.museum */\n33008,  /* riodejaneiro.museum */\n33021,  /* rochester.museum */\n33031,  /* rockart.museum */\n17699,  /* roma.museum */\n33039,  /* russia.museum */\n33046,  /* saintlouis.museum */\n31918,  /* salem.museum */\n31050,  /* salvadordali.museum */\n33057,  /* salzburg.museum */\n33066,  /* sandiego.museum */\n 1732,  /* sanfrancisco.museum */\n33075,  /* santabarbara.museum */\n33088,  /* santacruz.museum */\n33098,  /* santafe.museum */\n33106,  /* saskatchewan.museum */\n33119,  /* satx.museum */\n33124,  /* savannahga.museum */\n33135,  /* schlesisches.museum */\n33148,  /* schoenbrunn.museum */\n33160,  /* schokoladen.museum */\n 7042,  /* school.museum */\n33172,  /* schweiz.museum */\n 7073,  /* science.museum */\n33180,  /* science-fiction.museum */\n33196,  /* scienceandhistory.museum */\n33214,  /* scienceandindustry.museum */\n33233,  /* sciencecenter.museum */\n33247,  /* sciencecenters.museum */\n33262,  /* sciencehistory.museum */\n32525,  /* sciences.museum */\n33277,  /* sciencesnaturelles.museum */\n33296,  /* scotland.museum */\n33305,  /* seaport.museum */\n33313,  /* settlement.museum */\n33324,  /* settlers.museum */\n 7216,  /* shell.museum */\n33333,  /* sherbrooke.museum */\n33344,  /* sibenik.museum */\n 7278,  /* silk.museum */\n 4585,  /* ski.museum */\n33352,  /* skole.museum */\n31731,  /* society.museum */\n33358,  /* sologne.museum */\n33366,  /* soundandvision.museum */\n33381,  /* southcarolina.museum */\n33395,  /* southwest.museum */\n 2889,  /* space.museum */\n 6524,  /* spy.museum */\n33405,  /* square.museum */\n33412,  /* stadt.museum */\n33418,  /* stalbans.museum */\n33427,  /* starnberg.museum */\n  331,  /* state.museum */\n31096,  /* stateofdelaware.museum */\n 6355,  /* station.museum */\n 7732,  /* steam.museum */\n33437,  /* steiermark.museum */\n 3950,  /* stjohn.museum */\n 7496,  /* stockholm.museum */\n33448,  /* stpetersburg.museum */\n33461,  /* stuttgart.museum */\n33471,  /* suisse.museum */\n33478,  /* surgeonshall.museum */\n33491,  /* surrey.museum */\n33498,  /* svizzera.museum */\n33507,  /* sweden.museum */\n 7628,  /* sydney.museum */\n33514,  /* tank.museum */\n 1862,  /* tcm.museum */\n 7738,  /* technology.museum */\n33519,  /* telekommunikation.museum */\n 8295,  /* television.museum */\n33537,  /* texas.museum */\n33543,  /* textile.museum */\n 7810,  /* theater.museum */\n 7261,  /* time.museum */\n33551,  /* timekeeping.museum */\n33563,  /* topology.museum */\n17867,  /* torino.museum */\n33572,  /* touch.museum */\n 1402,  /* town.museum */\n15689,  /* transport.museum */\n 2641,  /* tree.museum */\n33578,  /* trolley.museum */\n 8041,  /* trust.museum */\n33586,  /* trustee.museum */\n31655,  /* uhren.museum */\n33594,  /* ulm.museum */\n33598,  /* undersea.museum */\n 8132,  /* university.museum */\n17643,  /* usa.museum */\n29990,  /* usantiques.museum */\n33607,  /* usarts.museum */\n30977,  /* uscountryestate.museum */\n31034,  /* usculture.museum */\n31079,  /* usdecorativearts.museum */\n 3415,  /* usgarden.museum */\n31783,  /* ushistory.museum */\n33614,  /* ushuaia.museum */\n32099,  /* uslivinghistory.museum */\n11873,  /* utah.museum */\n11434,  /* uvic.museum */\n16188,  /* valley.museum */\n17820,  /* vantaa.museum */\n33622,  /* versailles.museum */\n 8257,  /* viking.museum */\n33633,  /* village.museum */\n33641,  /* virginia.museum */\n33650,  /* virtual.museum */\n33658,  /* virtuel.museum */\n 8333,  /* vlaanderen.museum */\n33666,  /* volkenkunde.museum */\n 8412,  /* wales.museum */\n33678,  /* wallonie.museum */\n30735,  /* war.museum */\n33687,  /* washingtondc.museum */\n33700,  /* watch-and-clock.museum */\n30747,  /* watchandclock.museum */\n33716,  /* western.museum */\n33724,  /* westfalen.museum */\n33734,  /* whaling.museum */\n33742,  /* wildlife.museum */\n30803,  /* williamsburg.museum */\n32331,  /* windmill.museum */\n 7241,  /* workshop.museum */\n33751,  /* xn--9dbhblg6di.museum */\n33766,  /* xn--comunicaes-v6a2o.museum */\n33787,  /* xn--correios-e-telecomunicaes-ghc29a.museum */\n33824,  /* xn--h1aegh.museum */\n33835,  /* xn--lns-qla.museum */\n32639,  /* york.museum */\n33847,  /* yorkshire.museum */\n33857,  /* yosemite.museum */\n33866,  /* youth.museum */\n33872,  /* zoological.museum */\n33883,  /* zoology.museum */\n  164,  /* aero.mv */\n  985,  /* biz.mv */\n 1913,  /* com.mv */\n 2047,  /* coop.mv */\n 2624,  /* edu.mv */\n 3686,  /* gov.mv */\n 3167,  /* info.mv */\n 3632,  /* int.mv */\n 4195,  /* mil.mv */\n 5644,  /* museum.mv */\n 5725,  /* name.mv */\n 4185,  /* net.mv */\n 6070,  /* org.mv */\n 6427,  /* pro.mv */\n   62,  /* ac.mw */\n  985,  /* biz.mw */\n  113,  /* co.mw */\n 1913,  /* com.mw */\n 2047,  /* coop.mw */\n 2624,  /* edu.mw */\n 3686,  /* gov.mw */\n 3632,  /* int.mw */\n 5644,  /* museum.mw */\n 4185,  /* net.mw */\n 6070,  /* org.mw */\n10666,  /* blogspot.mx */\n 1913,  /* com.mx */\n 2624,  /* edu.mx */\n11325,  /* gob.mx */\n 4185,  /* net.mx */\n 6070,  /* org.mx */\n10666,  /* blogspot.my */\n 1913,  /* com.my */\n 2624,  /* edu.my */\n 3686,  /* gov.my */\n 4195,  /* mil.my */\n 5725,  /* name.my */\n 4185,  /* net.my */\n 6070,  /* org.my */\n   62,  /* ac.mz */\n11632,  /* adv.mz */\n  113,  /* co.mz */\n 2624,  /* edu.mz */\n 3686,  /* gov.mz */\n 4195,  /* mil.mz */\n 4185,  /* net.mz */\n 6070,  /* org.mz */\n  221,  /* ca.na */\n 1579,  /* cc.na */\n  113,  /* co.na */\n 1913,  /* com.na */\n11349,  /* dr.na */\n  898,  /* in.na */\n 3167,  /* info.na */\n 5448,  /* mobi.na */\n 3604,  /* mx.na */\n 5725,  /* name.na */\n  137,  /* or.na */\n 6070,  /* org.na */\n 6427,  /* pro.na */\n 7042,  /* school.na */\n 2546,  /* tv.na */\n  264,  /* us.na */\n  659,  /* ws.na */\n 3673,  /* forgot.her.name */\n11614,  /* asso.nc */\n  138,  /* r.cdn77.net */\n    2,  /* a.prod.fastly.net */\n 3563,  /* global.prod.fastly.net */\n    2,  /* a.ssl.fastly.net */\n   18,  /* b.ssl.fastly.net */\n 3563,  /* global.ssl.fastly.net */\n 6175,  /* arts.nf */\n 1913,  /* com.nf */\n11959,  /* firm.nf */\n 3167,  /* info.nf */\n 4185,  /* net.nf */\n 1224,  /* other.nf */\n 4523,  /* per.nf */\n 2608,  /* rec.nf */\n 7514,  /* store.nf */\n11967,  /* web.nf */\n   62,  /* ac.ni */\n  985,  /* biz.ni */\n  113,  /* co.ni */\n 1913,  /* com.ni */\n 2624,  /* edu.ni */\n11325,  /* gob.ni */\n  898,  /* in.ni */\n 3167,  /* info.ni */\n 3632,  /* int.ni */\n 4195,  /* mil.ni */\n 4185,  /* net.ni */\n 5998,  /* nom.ni */\n 6070,  /* org.ni */\n11967,  /* web.ni */\n 3760,  /* gs.aa.no */\n 8069,  /* nes.akershus.no */\n  637,  /* os.hedmark.no */\n35773,  /* valer.hedmark.no */\n40788,  /* xn--vler-qoa.hedmark.no */\n  637,  /* os.hordaland.no */\n40801,  /* heroy.more-og-romsdal.no */\n40807,  /* sande.more-og-romsdal.no */\n 1086,  /* bo.nordland.no */\n40801,  /* heroy.nordland.no */\n40813,  /* xn--b-5ga.nordland.no */\n40823,  /* xn--hery-ira.nordland.no */\n35773,  /* valer.ostfold.no */\n 1086,  /* bo.telemark.no */\n40813,  /* xn--b-5ga.telemark.no */\n40807,  /* sande.vestfold.no */\n40807,  /* sande.xn--mre-og-romsdal-qqb.no */\n40823,  /* xn--hery-ira.xn--mre-og-romsdal-qqb.no */\n40788,  /* xn--vler-qoa.xn--stfold-9xa.no */\n40836,  /* merseine.nu */\n25356,  /* mine.nu */\n40845,  /* shacknet.nu */\n  113,  /* co.om */\n 1913,  /* com.om */\n 2624,  /* edu.om */\n 3686,  /* gov.om */\n 1858,  /* med.om */\n 5644,  /* museum.om */\n 4185,  /* net.om */\n 6070,  /* org.om */\n 6427,  /* pro.om */\n 4994,  /* homelink.one */\n17123,  /* tele.amune.org */\n   36,  /* c.cdn77.org */\n41365,  /* rsc.cdn77.org */\n13051,  /* ssl.origin.cdn77-secure.org */\n  257,  /* go.dyndns.org */\n 6804,  /* home.dyndns.org */\n  290,  /* al.eu.org */\n11614,  /* asso.eu.org */\n  562,  /* at.eu.org */\n  584,  /* au.eu.org */\n  860,  /* be.eu.org */\n  931,  /* bg.eu.org */\n  221,  /* ca.eu.org */\n 1583,  /* cd.eu.org */\n 1146,  /* ch.eu.org */\n  842,  /* cn.eu.org */\n  241,  /* cy.eu.org */\n 2202,  /* cz.eu.org */\n 2276,  /* de.eu.org */\n 2470,  /* dk.eu.org */\n 2624,  /* edu.eu.org */\n 1886,  /* ee.eu.org */\n  558,  /* es.eu.org */\n 3009,  /* fi.eu.org */\n 3245,  /* fr.eu.org */\n 3697,  /* gr.eu.org */\n 4118,  /* hr.eu.org */\n 4138,  /* hu.eu.org */\n   31,  /* ie.eu.org */\n 2653,  /* il.eu.org */\n  898,  /* in.eu.org */\n 3632,  /* int.eu.org */\n 3722,  /* is.eu.org */\n 2098,  /* it.eu.org */\n 4495,  /* jp.eu.org */\n 3123,  /* kr.eu.org */\n  151,  /* lt.eu.org */\n 5112,  /* lu.eu.org */\n 5147,  /* lv.eu.org */\n 5307,  /* mc.eu.org */\n 1693,  /* me.eu.org */\n 5433,  /* mk.eu.org */\n 5609,  /* mt.eu.org */\n   70,  /* my.eu.org */\n 4185,  /* net.eu.org */\n  971,  /* ng.eu.org */\n 1071,  /* nl.eu.org */\n 1517,  /* no.eu.org */\n  325,  /* nz.eu.org */\n 6154,  /* paris.eu.org */\n 5089,  /* pl.eu.org */\n 6510,  /* pt.eu.org */\n41376,  /* q-a.eu.org */\n  166,  /* ro.eu.org */\n 2190,  /* ru.eu.org */\n 1498,  /* se.eu.org */\n 2364,  /* si.eu.org */\n 7312,  /* sk.eu.org */\n 3302,  /* tr.eu.org */\n 8122,  /* uk.eu.org */\n  264,  /* us.eu.org */\n15166,  /* nerdpol.ovh */\n 1085,  /* abo.pa */\n   62,  /* ac.pa */\n 1913,  /* com.pa */\n 2624,  /* edu.pa */\n11325,  /* gob.pa */\n  970,  /* ing.pa */\n 1858,  /* med.pa */\n 4185,  /* net.pa */\n 5998,  /* nom.pa */\n 6070,  /* org.pa */\n15162,  /* sld.pa */\n10666,  /* blogspot.pe */\n 1913,  /* com.pe */\n 2624,  /* edu.pe */\n11325,  /* gob.pe */\n 4195,  /* mil.pe */\n 4185,  /* net.pe */\n 5998,  /* nom.pe */\n 6070,  /* org.pe */\n 1913,  /* com.pf */\n 2624,  /* edu.pf */\n 6070,  /* org.pf */\n 1913,  /* com.ph */\n 2624,  /* edu.ph */\n 3686,  /* gov.ph */\n   58,  /* i.ph */\n 4195,  /* mil.ph */\n 4185,  /* net.ph */\n  976,  /* ngo.ph */\n 6070,  /* org.ph */\n  985,  /* biz.pk */\n 1913,  /* com.pk */\n 2624,  /* edu.pk */\n  402,  /* fam.pk */\n11325,  /* gob.pk */\n41380,  /* gok.pk */\n32745,  /* gon.pk */\n 3669,  /* gop.pk */\n 4515,  /* gos.pk */\n 3686,  /* gov.pk */\n 3167,  /* info.pk */\n 4185,  /* net.pk */\n 6070,  /* org.pk */\n11967,  /* web.pk */\n 1662,  /* ap.gov.pl */\n42422,  /* griw.gov.pl */\n  715,  /* ic.gov.pl */\n 3722,  /* is.gov.pl */\n42427,  /* kmpsp.gov.pl */\n42433,  /* konsulat.gov.pl */\n42442,  /* kppsp.gov.pl */\n42448,  /* kwp.gov.pl */\n42452,  /* kwpsp.gov.pl */\n42458,  /* mup.gov.pl */\n 1063,  /* mw.gov.pl */\n42462,  /* oirm.gov.pl */\n42467,  /* oum.gov.pl */\n  522,  /* pa.gov.pl */\n42471,  /* pinb.gov.pl */\n42476,  /* piw.gov.pl */\n 6969,  /* po.gov.pl */\n42429,  /* psp.gov.pl */\n42480,  /* psse.gov.pl */\n42485,  /* pup.gov.pl */\n 3818,  /* rzgw.gov.pl */\n 1493,  /* sa.gov.pl */\n42489,  /* sdn.gov.pl */\n35272,  /* sko.gov.pl */\n 7345,  /* so.gov.pl */\n 7437,  /* sr.gov.pl */\n42493,  /* starostwo.gov.pl */\n 8114,  /* ug.gov.pl */\n42503,  /* ugim.gov.pl */\n 3226,  /* um.gov.pl */\n42508,  /* umig.gov.pl */\n42513,  /* upow.gov.pl */\n17587,  /* uppo.gov.pl */\n  264,  /* us.gov.pl */\n42522,  /* uw.gov.pl */\n42525,  /* uzs.gov.pl */\n42529,  /* wif.gov.pl */\n42533,  /* wiih.gov.pl */\n11749,  /* winb.gov.pl */\n40783,  /* wios.gov.pl */\n42538,  /* witd.gov.pl */\n42543,  /* wiw.gov.pl */\n 6884,  /* wsa.gov.pl */\n 4677,  /* wskr.gov.pl */\n11425,  /* wuoz.gov.pl */\n42518,  /* wzmiuw.gov.pl */\n42547,  /* zp.gov.pl */\n  113,  /* co.pn */\n 2624,  /* edu.pn */\n 3686,  /* gov.pn */\n 4185,  /* net.pn */\n 6070,  /* org.pn */\n   62,  /* ac.pr */\n  985,  /* biz.pr */\n 1913,  /* com.pr */\n 2624,  /* edu.pr */\n  902,  /* est.pr */\n 3686,  /* gov.pr */\n 3167,  /* info.pr */\n42555,  /* isla.pr */\n 5725,  /* name.pr */\n 4185,  /* net.pr */\n 6070,  /* org.pr */\n 6427,  /* pro.pr */\n 6448,  /* prof.pr */\n    0,  /* aaa.pro */\n 1302,  /* aca.pro */\n16649,  /* acct.pro */\n 1520,  /* avocat.pro */\n  736,  /* bar.pro */\n11367,  /* cloudns.pro */\n13231,  /* cpa.pro */\n11645,  /* eng.pro */\n42560,  /* jur.pro */\n 4840,  /* law.pro */\n 1858,  /* med.pro */\n 4126,  /* recht.pro */\n 1913,  /* com.ps */\n 2624,  /* edu.ps */\n 3686,  /* gov.ps */\n 4185,  /* net.ps */\n 6070,  /* org.ps */\n17154,  /* plo.ps */\n 1964,  /* sec.ps */\n10666,  /* blogspot.pt */\n 1913,  /* com.pt */\n 2624,  /* edu.pt */\n 3686,  /* gov.pt */\n 3632,  /* int.pt */\n 4185,  /* net.pt */\n28860,  /* nome.pt */\n 6070,  /* org.pt */\n16378,  /* publ.pt */\n42564,  /* belau.pw */\n11367,  /* cloudns.pw */\n  113,  /* co.pw */\n 1859,  /* ed.pw */\n  257,  /* go.pw */\n 1203,  /* ne.pw */\n  137,  /* or.pw */\n 1913,  /* com.py */\n 2047,  /* coop.py */\n 2624,  /* edu.py */\n 3686,  /* gov.py */\n 4195,  /* mil.py */\n 4185,  /* net.py */\n 6070,  /* org.py */\n10666,  /* blogspot.qa */\n 1913,  /* com.qa */\n 2624,  /* edu.qa */\n 3686,  /* gov.qa */\n 4195,  /* mil.qa */\n 5725,  /* name.qa */\n 4185,  /* net.qa */\n 6070,  /* org.qa */\n 1145,  /* sch.qa */\n11614,  /* asso.re */\n10666,  /* blogspot.re */\n 1913,  /* com.re */\n 5998,  /* nom.re */\n 6175,  /* arts.ro */\n10666,  /* blogspot.ro */\n 1913,  /* com.ro */\n11959,  /* firm.ro */\n 3167,  /* info.ro */\n 5998,  /* nom.ro */\n   97,  /* nt.ro */\n 6070,  /* org.ro */\n 2608,  /* rec.ro */\n 7245,  /* shop.ro */\n 7514,  /* store.ro */\n 7910,  /* tm.ro */\n11840,  /* www.ro */\n   62,  /* ac.rs */\n10666,  /* blogspot.rs */\n  113,  /* co.rs */\n 2624,  /* edu.rs */\n 3686,  /* gov.rs */\n  898,  /* in.rs */\n 6070,  /* org.rs */\n   62,  /* ac.ru */\n10666,  /* blogspot.ru */\n 2624,  /* edu.ru */\n 3686,  /* gov.ru */\n 3632,  /* int.ru */\n 4195,  /* mil.ru */\n42550,  /* test.ru */\n   62,  /* ac.rw */\n  113,  /* co.rw */\n 1913,  /* com.rw */\n 2624,  /* edu.rw */\n11627,  /* gouv.rw */\n 3686,  /* gov.rw */\n 3632,  /* int.rw */\n 4195,  /* mil.rw */\n 4185,  /* net.rw */\n 1913,  /* com.sa */\n 2624,  /* edu.sa */\n 3686,  /* gov.sa */\n 1858,  /* med.sa */\n 4185,  /* net.sa */\n 6070,  /* org.sa */\n 6513,  /* pub.sa */\n 1145,  /* sch.sa */\n 1913,  /* com.sd */\n 2624,  /* edu.sd */\n 3686,  /* gov.sd */\n 3167,  /* info.sd */\n 1858,  /* med.sd */\n 4185,  /* net.sd */\n 6070,  /* org.sd */\n 2546,  /* tv.sd */\n    2,  /* a.se */\n   62,  /* ac.se */\n   18,  /* b.se */\n  855,  /* bd.se */\n10666,  /* blogspot.se */\n29954,  /* brand.se */\n   36,  /* c.se */\n 1913,  /* com.se */\n  142,  /* d.se */\n   32,  /* e.se */\n  192,  /* f.se */\n 4576,  /* fh.se */\n42570,  /* fhsk.se */\n42575,  /* fhv.se */\n  162,  /* g.se */\n   14,  /* h.se */\n   58,  /* i.se */\n  734,  /* k.se */\n42579,  /* komforb.se */\n42587,  /* kommunalforbund.se */\n42603,  /* komvux.se */\n  211,  /* l.se */\n42610,  /* lanbib.se */\n  354,  /* m.se */\n  235,  /* n.se */\n42617,  /* naturbruksgymn.se */\n   49,  /* o.se */\n 6070,  /* org.se */\n    7,  /* p.se */\n42632,  /* parti.se */\n  469,  /* pp.se */\n  371,  /* press.se */\n  138,  /* r.se */\n  110,  /* s.se */\n   25,  /* t.se */\n 7910,  /* tm.se */\n  585,  /* u.se */\n  650,  /* w.se */\n  398,  /* x.se */\n   71,  /* y.se */\n  326,  /* z.se */\n10666,  /* blogspot.sg */\n 1913,  /* com.sg */\n 2624,  /* edu.sg */\n 3686,  /* gov.sg */\n 4185,  /* net.sg */\n 6070,  /* org.sg */\n 4523,  /* per.sg */\n29762,  /* cyon.site */\n  527,  /* art.sn */\n10666,  /* blogspot.sn */\n 1913,  /* com.sn */\n 2624,  /* edu.sn */\n11627,  /* gouv.sn */\n 6070,  /* org.sn */\n15614,  /* perso.sn */\n42656,  /* univ.sn */\n 1913,  /* com.so */\n 4185,  /* net.so */\n 6070,  /* org.so */\n42661,  /* stackspace.space */\n  113,  /* co.st */\n 1913,  /* com.st */\n42672,  /* consulado.st */\n 2624,  /* edu.st */\n42682,  /* embaixada.st */\n 3686,  /* gov.st */\n 4195,  /* mil.st */\n 4185,  /* net.st */\n 6070,  /* org.st */\n42692,  /* principe.st */\n25423,  /* saotome.st */\n 7514,  /* store.st */\n42701,  /* adygeya.su */\n42709,  /* arkhangelsk.su */\n42721,  /* balashov.su */\n42730,  /* bashkiria.su */\n42740,  /* bryansk.su */\n42748,  /* dagestan.su */\n42757,  /* grozny.su */\n42764,  /* ivanovo.su */\n42772,  /* kalmykia.su */\n42781,  /* kaluga.su */\n42788,  /* karelia.su */\n42796,  /* khakassia.su */\n42806,  /* krasnodar.su */\n42816,  /* kurgan.su */\n42823,  /* lenug.su */\n42829,  /* mordovia.su */\n 7311,  /* msk.su */\n42838,  /* murmansk.su */\n42847,  /* nalchik.su */\n42855,  /* nov.su */\n42859,  /* obninsk.su */\n42867,  /* penza.su */\n42873,  /* pokrovsk.su */\n42882,  /* sochi.su */\n11321,  /* spb.su */\n42888,  /* togliatti.su */\n42898,  /* troitsk.su */\n42906,  /* tula.su */\n 8158,  /* tuva.su */\n42911,  /* vladikavkaz.su */\n42923,  /* vladimir.su */\n41518,  /* vologda.su */\n 1913,  /* com.sv */\n 2624,  /* edu.sv */\n11325,  /* gob.sv */\n 6070,  /* org.sv */\n 4687,  /* red.sv */\n42932,  /* knightpoint.systems */\n   62,  /* ac.sz */\n  113,  /* co.sz */\n 6070,  /* org.sz */\n   62,  /* ac.th */\n  113,  /* co.th */\n  257,  /* go.th */\n  898,  /* in.th */\n 5397,  /* mi.th */\n 4185,  /* net.th */\n  137,  /* or.th */\n   62,  /* ac.tj */\n  985,  /* biz.tj */\n  113,  /* co.tj */\n 1913,  /* com.tj */\n 2624,  /* edu.tj */\n  257,  /* go.tj */\n 3686,  /* gov.tj */\n 3632,  /* int.tj */\n 4195,  /* mil.tj */\n 5725,  /* name.tj */\n 4185,  /* net.tj */\n 1815,  /* nic.tj */\n 6070,  /* org.tj */\n42550,  /* test.tj */\n11967,  /* web.tj */\n  113,  /* co.tm */\n 1913,  /* com.tm */\n 2624,  /* edu.tm */\n 3686,  /* gov.tm */\n 4195,  /* mil.tm */\n 4185,  /* net.tm */\n 5998,  /* nom.tm */\n 6070,  /* org.tm */\n42944,  /* agrinet.tn */\n 1913,  /* com.tn */\n42952,  /* defense.tn */\n42960,  /* edunet.tn */\n 6192,  /* ens.tn */\n 4231,  /* fin.tn */\n 3686,  /* gov.tn */\n11676,  /* ind.tn */\n 3167,  /* info.tn */\n 7904,  /* intl.tn */\n 1910,  /* mincom.tn */\n  561,  /* nat.tn */\n 4185,  /* net.tn */\n 6070,  /* org.tn */\n15614,  /* perso.tn */\n42967,  /* rnrt.tn */\n11754,  /* rns.tn */\n 5929,  /* rnu.tn */\n42266,  /* tourism.tn */\n 6676,  /* turen.tn */\n  164,  /* aero.tt */\n  985,  /* biz.tt */\n  113,  /* co.tt */\n 1913,  /* com.tt */\n 2047,  /* coop.tt */\n 2624,  /* edu.tt */\n 3686,  /* gov.tt */\n 3167,  /* info.tt */\n 3632,  /* int.tt */\n 4475,  /* jobs.tt */\n 5448,  /* mobi.tt */\n 5644,  /* museum.tt */\n 5725,  /* name.tt */\n 4185,  /* net.tt */\n 6070,  /* org.tt */\n 6427,  /* pro.tt */\n 8005,  /* travel.tt */\n42980,  /* better-than.tv */\n11526,  /* dyndns.tv */\n42992,  /* on-the-web.tv */\n43003,  /* worse-than.tv */\n10666,  /* blogspot.tw */\n 1849,  /* club.tw */\n 1913,  /* com.tw */\n  984,  /* ebiz.tw */\n 2624,  /* edu.tw */\n 3392,  /* game.tw */\n 3686,  /* gov.tw */\n15467,  /* idv.tw */\n 4195,  /* mil.tw */\n 4185,  /* net.tw */\n 6070,  /* org.tw */\n43014,  /* xn--czrw28b.tw */\n15553,  /* xn--uc0atv.tw */\n43026,  /* xn--zf0ao64a.tw */\n   62,  /* ac.tz */\n  113,  /* co.tz */\n  257,  /* go.tz */\n 7749,  /* hotel.tz */\n 3167,  /* info.tz */\n 1693,  /* me.tz */\n 4195,  /* mil.tz */\n 5448,  /* mobi.tz */\n 1203,  /* ne.tz */\n  137,  /* or.tz */\n 2158,  /* sc.tz */\n 2546,  /* tv.tz */\n  985,  /* biz.ua */\n 1579,  /* cc.ua */\n43039,  /* cherkassy.ua */\n43049,  /* cherkasy.ua */\n 3680,  /* chernigov.ua */\n 3929,  /* chernihiv.ua */\n43058,  /* chernivtsi.ua */\n43069,  /* chernovtsy.ua */\n  995,  /* ck.ua */\n  842,  /* cn.ua */\n  113,  /* co.ua */\n 1913,  /* com.ua */\n 2091,  /* cr.ua */\n43080,  /* crimea.ua */\n 2176,  /* cv.ua */\n  285,  /* dn.ua */\n43087,  /* dnepropetrovsk.ua */\n43102,  /* dnipropetrovsk.ua */\n43117,  /* dominic.ua */\n43125,  /* donetsk.ua */\n43133,  /* dp.ua */\n 2624,  /* edu.ua */\n 3686,  /* gov.ua */\n 5169,  /* if.ua */\n  898,  /* in.ua */\n 5824,  /* inf.ua */\n43136,  /* ivano-frankivsk.ua */\n 4582,  /* kh.ua */\n43152,  /* kharkiv.ua */\n43160,  /* kharkov.ua */\n43168,  /* kherson.ua */\n43176,  /* khmelnitskiy.ua */\n43189,  /* khmelnytskyi.ua */\n43202,  /* kiev.ua */\n43207,  /* kirovograd.ua */\n 4628,  /* km.ua */\n 3123,  /* kr.ua */\n43218,  /* krym.ua */\n 6843,  /* ks.ua */\n43223,  /* kv.ua */\n43226,  /* kyiv.ua */\n11693,  /* lg.ua */\n  151,  /* lt.ua */\n 5103,  /* ltd.ua */\n43231,  /* lugansk.ua */\n43239,  /* lutsk.ua */\n 5147,  /* lv.ua */\n43245,  /* lviv.ua */\n 5433,  /* mk.ua */\n43250,  /* mykolaiv.ua */\n 4185,  /* net.ua */\n43259,  /* nikolaev.ua */\n 3178,  /* od.ua */\n15713,  /* odesa.ua */\n43268,  /* odessa.ua */\n 6070,  /* org.ua */\n 5089,  /* pl.ua */\n43275,  /* poltava.ua */\n  469,  /* pp.ua */\n43283,  /* rivne.ua */\n43289,  /* rovno.ua */\n 8048,  /* rv.ua */\n 6991,  /* sb.ua */\n43295,  /* sebastopol.ua */\n43306,  /* sevastopol.ua */\n 7331,  /* sm.ua */\n 5682,  /* sumy.ua */\n  334,  /* te.ua */\n43317,  /* ternopil.ua */\n 5902,  /* uz.ua */\n43326,  /* uzhgorod.ua */\n43335,  /* vinnica.ua */\n43343,  /* vinnytsia.ua */\n 8352,  /* vn.ua */\n43353,  /* volyn.ua */\n34391,  /* yalta.ua */\n43359,  /* zaporizhzhe.ua */\n43371,  /* zaporizhzhia.ua */\n43384,  /* zhitomir.ua */\n43393,  /* zhytomyr.ua */\n42547,  /* zp.ua */\n 4436,  /* zt.ua */\n   62,  /* ac.ug */\n10666,  /* blogspot.ug */\n  113,  /* co.ug */\n 1913,  /* com.ug */\n  257,  /* go.ug */\n 1203,  /* ne.ug */\n  137,  /* or.ug */\n 6070,  /* org.ug */\n 2158,  /* sc.ug */\n10666,  /* blogspot.co.uk */\n11588,  /* no-ip.co.uk */\n15218,  /* wellbeingzone.co.uk */\n 5955,  /* homeoffice.gov.uk */\n43413,  /* service.gov.uk */\n 1579,  /* cc.ak.us */\n15174,  /* k12.ak.us */\n15182,  /* lib.ak.us */\n 1579,  /* cc.hi.us */\n15182,  /* lib.hi.us */\n43459,  /* chtr.k12.ma.us */\n43464,  /* paroch.k12.ma.us */\n15459,  /* pvt.k12.ma.us */\n 1579,  /* cc.wv.us */\n  113,  /* co.uz */\n 1913,  /* com.uz */\n 4185,  /* net.uz */\n 6070,  /* org.uz */\n 6175,  /* arts.ve */\n  113,  /* co.ve */\n 1913,  /* com.ve */\n43475,  /* e12.ve */\n 2624,  /* edu.ve */\n11959,  /* firm.ve */\n11325,  /* gob.ve */\n 3686,  /* gov.ve */\n 3167,  /* info.ve */\n 3632,  /* int.ve */\n 4195,  /* mil.ve */\n 4185,  /* net.ve */\n 6070,  /* org.ve */\n 2608,  /* rec.ve */\n 7514,  /* store.ve */\n 7640,  /* tec.ve */\n11967,  /* web.ve */\n  113,  /* co.vi */\n 1913,  /* com.vi */\n15174,  /* k12.vi */\n 4185,  /* net.vi */\n 6070,  /* org.vi */\n   62,  /* ac.vn */\n  985,  /* biz.vn */\n10666,  /* blogspot.vn */\n 1913,  /* com.vn */\n 2624,  /* edu.vn */\n 3686,  /* gov.vn */\n 3862,  /* health.vn */\n 3167,  /* info.vn */\n 3632,  /* int.vn */\n 5725,  /* name.vn */\n 4185,  /* net.vn */\n 6070,  /* org.vn */\n 6427,  /* pro.vn */\n 1913,  /* com.ws */\n11526,  /* dyndns.ws */\n 2624,  /* edu.ws */\n 3686,  /* gov.ws */\n43479,  /* mypets.ws */\n 4185,  /* net.ws */\n 6070,  /* org.ws */\n43486,  /* xn--80au.xn--90a3ac */\n43495,  /* xn--90azh.xn--90a3ac */\n 9065,  /* xn--c1avg.xn--90a3ac */\n43505,  /* xn--d1at.xn--90a3ac */\n43514,  /* xn--o1ac.xn--90a3ac */\n43523,  /* xn--o1ach.xn--90a3ac */\n  466,  /* fhapp.xyz */\n   62,  /* ac.zm */\n  985,  /* biz.zm */\n  113,  /* co.zm */\n 1913,  /* com.zm */\n 2624,  /* edu.zm */\n 3686,  /* gov.zm */\n 3167,  /* info.zm */\n 4195,  /* mil.zm */\n 4185,  /* net.zm */\n 6070,  /* org.zm */\n 1145,  /* sch.zm */\n};\n\nstatic const size_t kLeafChildOffset = 3549;\nstatic const size_t kNumRootChildren = 1553;\n"
  },
  {
    "path": "TrustKit/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>$(PRODUCT_BUNDLE_IDENTIFIER)</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>FMWK</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>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>NSPrincipalClass</key>\n\t<string></string>\n</dict>\n</plist>\n"
  },
  {
    "path": "TrustKit/Pinning/public_key_utils.h",
    "content": "/*\n \n public_key_utils.h\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#ifndef TrustKit_subjectPublicKeyHash_h\n#define TrustKit_subjectPublicKeyHash_h\n\n#import <Foundation/Foundation.h>\n@import Security;\n\n\ntypedef NS_ENUM(NSInteger, TSKPublicKeyAlgorithm)\n{\n    // Some assumptions are made about this specific ordering in public_key_utils.m\n    TSKPublicKeyAlgorithmRsa2048 = 0,\n    TSKPublicKeyAlgorithmRsa4096 = 1,\n    TSKPublicKeyAlgorithmEcDsaSecp256r1 = 2,\n    TSKPublicKeyAlgorithmEcDsaSecp384r1 = 3,\n    \n    TSKPublicKeyAlgorithmLast = TSKPublicKeyAlgorithmEcDsaSecp384r1\n};\n\n\nvoid initializeSubjectPublicKeyInfoCache(void);\n\nNSData *hashSubjectPublicKeyInfoFromCertificate(SecCertificateRef certificate, TSKPublicKeyAlgorithm publicKeyAlgorithm);\n\n\n// For tests\nvoid resetSubjectPublicKeyInfoCache(void);\n\n// Each key is a raw certificate data (for easy lookup) and each value is the certificate's raw SPKI data\ntypedef NSMutableDictionary<NSData *, NSData *> SpkiCacheDictionnary;\n\nNSMutableDictionary<NSNumber *, SpkiCacheDictionnary *> *getSpkiCache(void);\nNSMutableDictionary<NSNumber *, SpkiCacheDictionnary *> *getSpkiCacheFromFileSystem(void);\n\n\n#endif\n"
  },
  {
    "path": "TrustKit/Pinning/public_key_utils.m",
    "content": "/*\n \n public_key_utils.m\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n\n#import \"public_key_utils.h\"\n#include <pthread.h>\n#import <CommonCrypto/CommonDigest.h>\n#import \"../TrustKit+Private.h\"\n\n\n#pragma mark Global Cache for SPKI Hashes\n\n// Dictionnary to cache SPKI hashes instead of having to compute them on every connection\n// We store one cache dictionnary per TSKPublicKeyAlgorithm we support\nNSMutableDictionary<NSNumber *, SpkiCacheDictionnary *> *_subjectPublicKeyInfoHashesCache;\n\n// Used to lock access to our SPKI cache\nstatic pthread_mutex_t _spkiCacheLock;\n\n// File name for persisting the cache in the filesystem\nstatic NSString *_spkiCacheFilename = @\"TrustKitSpkiCache.plist\";\n\n#pragma mark Missing ASN1 SPKI Headers\n\n// These are the ASN1 headers for the Subject Public Key Info section of a certificate\nstatic unsigned char rsa2048Asn1Header[] = {\n    0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,\n    0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00\n};\n\nstatic unsigned char rsa4096Asn1Header[] = {\n    0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,\n    0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00\n};\n\nstatic unsigned char ecDsaSecp256r1Asn1Header[] = {\n    0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,\n    0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,\n    0x42, 0x00\n};\n\nstatic unsigned char ecDsaSecp384r1Asn1Header[] = {\n    0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,\n    0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00\n};\n\n// Careful with the order... must match how TSKPublicKeyAlgorithm is defined\nstatic unsigned char *asn1HeaderBytes[4] = { rsa2048Asn1Header, rsa4096Asn1Header,\n    ecDsaSecp256r1Asn1Header, ecDsaSecp384r1Asn1Header };\nstatic unsigned int asn1HeaderSizes[4] = { sizeof(rsa2048Asn1Header), sizeof(rsa4096Asn1Header),\n    sizeof(ecDsaSecp256r1Asn1Header), sizeof(ecDsaSecp384r1Asn1Header) };\n\n\n#if TARGET_OS_WATCH || TARGET_OS_TV || (TARGET_OS_IOS &&__IPHONE_OS_VERSION_MAX_ALLOWED >= 100000) || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200)\n\n#pragma mark Public Key Converter - iOS 10.0+, macOS 10.12+, watchOS 3.0, tvOS 10.0\n\n// Use the unified SecKey API (specifically SecKeyCopyExternalRepresentation())\nstatic NSData *getPublicKeyDataFromCertificate_unified(SecCertificateRef certificate)\n{\n    SecKeyRef publicKey;\n    SecTrustRef tempTrust;\n    SecPolicyRef policy = SecPolicyCreateBasicX509();\n    SecTrustResultType result;\n    \n    // Get a public key reference from the certificate\n    SecTrustCreateWithCertificates(certificate, policy, &tempTrust);\n    SecTrustEvaluate(tempTrust, &result);\n    publicKey = SecTrustCopyPublicKey(tempTrust);\n    CFRelease(policy);\n    CFRelease(tempTrust);\n    \n    CFDataRef publicKeyData = SecKeyCopyExternalRepresentation(publicKey, NULL);\n    CFRelease(publicKey);\n    return (NSData *)CFBridgingRelease(publicKeyData);\n}\n#endif\n\n\n#if TARGET_OS_IOS\n\n#pragma mark Public Key Converter - iOS before 10.0\n\n// Need to support iOS before 10.0\n// The one and only way to get a key's data in a buffer on iOS is to put it in the Keychain and then ask for the data back...\n#define LEGACY_IOS_KEY_EXTRACTION 1\n\nstatic const NSString *kTSKKeychainPublicKeyTag = @\"TSKKeychainPublicKeyTag\"; // Used to add and find the public key in the Keychain\n\nstatic pthread_mutex_t _keychainLock; // Used to lock access to our Keychain item\n\n\nstatic NSData *getPublicKeyDataFromCertificate_legacy_ios(SecCertificateRef certificate)\n{\n    NSData *publicKeyData = nil;\n    OSStatus resultAdd, resultDel = noErr;\n    SecKeyRef publicKey;\n    SecTrustRef tempTrust;\n    SecPolicyRef policy = SecPolicyCreateBasicX509();\n    SecTrustResultType result;\n\n    // Get a public key reference from the certificate\n    SecTrustCreateWithCertificates(certificate, policy, &tempTrust);\n    SecTrustEvaluate(tempTrust, &result);\n    publicKey = SecTrustCopyPublicKey(tempTrust);\n    CFRelease(policy);\n    CFRelease(tempTrust);\n    \n    \n    // Extract the actual bytes from the key reference using the Keychain\n    // Prepare the dictionary to add the key\n    NSMutableDictionary *peerPublicKeyAdd = [[NSMutableDictionary alloc] init];\n    [peerPublicKeyAdd setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];\n    [peerPublicKeyAdd setObject:kTSKKeychainPublicKeyTag forKey:(__bridge id)kSecAttrApplicationTag];\n    [peerPublicKeyAdd setObject:(__bridge id)(publicKey) forKey:(__bridge id)kSecValueRef];\n    \n    // Avoid issues with background fetching while the device is locked\n    [peerPublicKeyAdd setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly forKey:(__bridge id)kSecAttrAccessible];\n    \n    // Request the key's data to be returned\n    [peerPublicKeyAdd setObject:(__bridge id)(kCFBooleanTrue) forKey:(__bridge id)kSecReturnData];\n    \n    // Prepare the dictionary to retrieve and delete the key\n    NSMutableDictionary * publicKeyGet = [[NSMutableDictionary alloc] init];\n    [publicKeyGet setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];\n    [publicKeyGet setObject:(kTSKKeychainPublicKeyTag) forKey:(__bridge id)kSecAttrApplicationTag];\n    [publicKeyGet setObject:(__bridge id)(kCFBooleanTrue) forKey:(__bridge id)kSecReturnData];\n    \n    \n    // Get the key bytes from the Keychain atomically\n    pthread_mutex_lock(&_keychainLock);\n    {\n        resultAdd = SecItemAdd((__bridge CFDictionaryRef) peerPublicKeyAdd, (void *)&publicKeyData);\n        resultDel = SecItemDelete((__bridge CFDictionaryRef)(publicKeyGet));\n    }\n    pthread_mutex_unlock(&_keychainLock);\n    \n    CFRelease(publicKey);\n    if ((resultAdd != errSecSuccess) || (resultDel != errSecSuccess))\n    {\n        // Something went wrong with the Keychain we won't know if we did get the right key data\n        TSKLog(@\"Keychain error\");\n        publicKeyData = nil;\n    }\n    \n    return publicKeyData;\n}\n#endif\n\n\n#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200\n\n#pragma mark Public Key Converter - macOS before 10.12\n\n// Need to support macOS before 10.12\n\nstatic NSData *getPublicKeyDataFromCertificate_legacy_macos(SecCertificateRef certificate)\n{\n    NSData *publicKeyData = nil;\n    CFErrorRef error = NULL;\n    \n    // SecCertificateCopyValues() is macOS only\n    NSArray *oids = [NSArray arrayWithObject:(__bridge id)(kSecOIDX509V1SubjectPublicKey)];\n    CFDictionaryRef certificateValues = SecCertificateCopyValues(certificate, (__bridge CFArrayRef)(oids), &error);\n    if (certificateValues == NULL)\n    {\n        CFStringRef errorDescription = CFErrorCopyDescription(error);\n        TSKLog(@\"SecCertificateCopyValues() error: %@\", errorDescription);\n        CFRelease(errorDescription);\n        CFRelease(error);\n        return nil;\n    }\n    \n    for (NSString* fieldName in (__bridge NSDictionary *)certificateValues)\n    {\n        NSDictionary *fieldDict = CFDictionaryGetValue(certificateValues, (__bridge const void *)(fieldName));\n        if ([fieldDict[(__bridge __strong id)(kSecPropertyKeyLabel)] isEqualToString:@\"Public Key Data\"])\n        {\n            publicKeyData = fieldDict[(__bridge __strong id)(kSecPropertyKeyValue)];\n        }\n    }\n    CFRelease(certificateValues);\n    return publicKeyData;\n}\n#endif\n\n\nstatic NSData *getPublicKeyDataFromCertificate(SecCertificateRef certificate)\n{\n#if TARGET_OS_WATCH || TARGET_OS_TV\n    // watchOS 3+ or tvOS 10+\n    return getPublicKeyDataFromCertificate_unified(certificate);\n#elif TARGET_OS_IOS\n    // iOS 7+\n#if __IPHONE_OS_VERSION_MAX_ALLOWED < 100000\n    // Base SDK is iOS 7, 8 or 9\n    return getPublicKeyDataFromCertificate_legacy_ios(certificate);\n#else\n    // Base SDK is iOS 10+ - try to use the unified Security APIs if available\n    NSProcessInfo *processInfo = [NSProcessInfo processInfo];\n    if ([processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && [processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){10, 0, 0}])\n    {\n        // iOS 10+\n        return getPublicKeyDataFromCertificate_unified(certificate);\n    }\n    else\n    {\n        // iOS 7, 8, 9\n        return getPublicKeyDataFromCertificate_legacy_ios(certificate);\n    }\n#endif\n#else\n    // macOS 10.9+\n#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101200\n    // Base SDK is macOS 10.9, 10.10 or 10.11\n    return getPublicKeyDataFromCertificate_legacy_macos(certificate);\n#else\n    // Base SDK is macOS 10.12 - try to use the unified Security APIs if available\n    NSProcessInfo *processInfo = [NSProcessInfo processInfo];\n    if ([processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && [processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){10, 12, 0}])\n    {\n        // macOS 10.12+\n        return getPublicKeyDataFromCertificate_unified(certificate);\n    }\n    else\n    {\n        // macOS 10.9, 10.10, 10.11\n        return getPublicKeyDataFromCertificate_legacy_macos(certificate);\n    }\n#endif\n#endif\n}\n\n\n#pragma mark SPKI Hashing Function\n\nNSData *hashSubjectPublicKeyInfoFromCertificate(SecCertificateRef certificate, TSKPublicKeyAlgorithm publicKeyAlgorithm)\n{\n    NSData *cachedSubjectPublicKeyInfo = NULL;\n    NSNumber *algorithmKey = [NSNumber numberWithInt:(int)publicKeyAlgorithm];\n    \n    // Have we seen this certificate before? Look for the SPKI in the cache\n    NSData *certificateData = (__bridge NSData *)(SecCertificateCopyData(certificate));\n\n    pthread_mutex_lock(&_spkiCacheLock);\n    {\n        cachedSubjectPublicKeyInfo = _subjectPublicKeyInfoHashesCache[algorithmKey][certificateData];\n    }\n    pthread_mutex_unlock(&_spkiCacheLock);\n    \n    if (cachedSubjectPublicKeyInfo)\n    {\n        TSKLog(@\"Subject Public Key Info hash was found in the cache\");\n        CFRelease((__bridge CFTypeRef)(certificateData));\n        return cachedSubjectPublicKeyInfo;\n    }\n    \n    // We didn't this certificate in the cache so we need to generate its SPKI hash\n    TSKLog(@\"Generating Subject Public Key Info hash...\");\n    \n    // First extract the public key bytes\n    NSData *publicKeyData = getPublicKeyDataFromCertificate(certificate);\n    if (publicKeyData == nil)\n    {\n        TSKLog(@\"Error - could not extract the public key bytes\");\n        CFRelease((__bridge CFTypeRef)(certificateData));\n        return nil;\n    }\n    \n    \n    // Generate a hash of the subject public key info\n    NSMutableData *subjectPublicKeyInfoHash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];\n    CC_SHA256_CTX shaCtx;\n    CC_SHA256_Init(&shaCtx);\n    \n    // Add the missing ASN1 header for public keys to re-create the subject public key info\n    CC_SHA256_Update(&shaCtx, asn1HeaderBytes[publicKeyAlgorithm], asn1HeaderSizes[publicKeyAlgorithm]);\n    \n    // Add the public key\n    CC_SHA256_Update(&shaCtx, [publicKeyData bytes], (unsigned int)[publicKeyData length]);\n    CC_SHA256_Final((unsigned char *)[subjectPublicKeyInfoHash bytes], &shaCtx);\n    \n\n    // Store the hash in our memory cache\n    pthread_mutex_lock(&_spkiCacheLock);\n    {\n        _subjectPublicKeyInfoHashesCache[algorithmKey][certificateData] = subjectPublicKeyInfoHash;\n    }\n    pthread_mutex_unlock(&_spkiCacheLock);\n    \n    // Update the cache on the filesystem\n    NSString *spkiCachePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:_spkiCacheFilename];\n    NSData *serializedSpkiCache = [NSKeyedArchiver archivedDataWithRootObject:_subjectPublicKeyInfoHashesCache];\n    if ([serializedSpkiCache writeToFile:spkiCachePath atomically:YES] == NO)\n    {\n        TSKLog(@\"Could not persist SPKI cache to the filesystem\");\n    }\n    \n    CFRelease((__bridge CFTypeRef)(certificateData));\n    return subjectPublicKeyInfoHash;\n}\n\n\nvoid initializeSubjectPublicKeyInfoCache(void)\n{\n    // Initialize our cache of SPKI hashes\n    // First try to load a cached version from the filesystem\n    _subjectPublicKeyInfoHashesCache = getSpkiCacheFromFileSystem();\n    TSKLog(@\"Loaded %d SPKI cache entries from the filesystem\", [_subjectPublicKeyInfoHashesCache count]);\n    \n    if (_subjectPublicKeyInfoHashesCache == nil)\n    {\n        _subjectPublicKeyInfoHashesCache = [[NSMutableDictionary alloc]init];\n    }\n    \n    // Initialize any sub-dictionnary that hasn't been initialized\n    for (int i=0; i<=TSKPublicKeyAlgorithmLast; i++)\n    {\n        NSNumber *algorithmKey = [NSNumber numberWithInt:i];\n        if (_subjectPublicKeyInfoHashesCache[algorithmKey] == nil)\n        {\n            _subjectPublicKeyInfoHashesCache[algorithmKey] = [[NSMutableDictionary alloc]init];\n        }\n        \n    }\n    \n    // Initialize our locks\n    pthread_mutex_init(&_spkiCacheLock, NULL);\n    \n#if LEGACY_IOS_KEY_EXTRACTION\n    pthread_mutex_init(&_keychainLock, NULL);\n    // Cleanup the Keychain in case the App previously crashed\n    NSMutableDictionary * publicKeyGet = [[NSMutableDictionary alloc] init];\n    [publicKeyGet setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];\n    [publicKeyGet setObject:(kTSKKeychainPublicKeyTag) forKey:(__bridge id)kSecAttrApplicationTag];\n    [publicKeyGet setObject:(__bridge id)(kCFBooleanTrue) forKey:(__bridge id)kSecReturnData];\n    pthread_mutex_lock(&_keychainLock);\n    {\n        SecItemDelete((__bridge CFDictionaryRef)(publicKeyGet));\n    }\n    pthread_mutex_unlock(&_keychainLock);\n#endif\n}\n\n\n#pragma mark Functions used by the Test Suite\n\nvoid resetSubjectPublicKeyInfoCache(void)\n{\n    // This is only used for tests\n    // Destroy our locks\n    pthread_mutex_destroy(&_spkiCacheLock);\n    \n#if LEGACY_IOS_KEY_EXTRACTION\n    pthread_mutex_destroy(&_keychainLock);\n#endif\n    \n    // Discard SPKI cache\n    _subjectPublicKeyInfoHashesCache = nil;\n    \n    NSFileManager *fileManager = [NSFileManager defaultManager];\n    NSString *spkiCachePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:_spkiCacheFilename];\n    [fileManager removeItemAtPath:spkiCachePath error:nil];\n}\n\n\nNSMutableDictionary<NSNumber *, SpkiCacheDictionnary *> *getSpkiCacheFromFileSystem(void)\n{\n    NSMutableDictionary *spkiCache = nil;\n    NSString *spkiCachePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:_spkiCacheFilename];\n    NSData *serializedSpkiCache = [NSData dataWithContentsOfFile:spkiCachePath];\n    if (serializedSpkiCache) {\n        spkiCache = [NSKeyedUnarchiver unarchiveObjectWithData:serializedSpkiCache];\n    }\n    return spkiCache;\n}\n\n\nNSMutableDictionary<NSNumber *, SpkiCacheDictionnary *> *getSpkiCache(void)\n{\n    return _subjectPublicKeyInfoHashesCache;\n}\n"
  },
  {
    "path": "TrustKit/Pinning/ssl_pin_verifier.h",
    "content": "/*\n \n ssl_pin_verifier.h\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n\n#import <Foundation/Foundation.h>\n\n\n/**\n Possible return values when verifying a server's identity. \n */\ntypedef NS_ENUM(NSInteger, TSKPinValidationResult)\n{\n    /**\n     The server trust was succesfully evaluated and contained at least one of the configured pins.\n     */\n    TSKPinValidationResultSuccess,\n    \n    /**\n     The server trust was succesfully evaluated but did not contain any of the configured pins.\n     */\n    TSKPinValidationResultFailed,\n    \n    /**\n     The server trust's evaluation failed: the server's certificate chain is not trusted.\n     */\n    TSKPinValidationResultFailedCertificateChainNotTrusted,\n    \n    /**\n     The server trust could not be evaluated due to invalid parameters.\n     */\n    TSKPinValidationResultErrorInvalidParameters,\n\n    /**\n     The server trust was succesfully evaluated but did not contain any of the configured pins. However, the certificate chain terminates at a user-defined trust anchor (ie. a custom/private CA that was manually added to OS X's trust store). Only available on OS X.\n     */\n    TSKPinValidationResultFailedUserDefinedTrustAnchor NS_AVAILABLE_MAC(10_9),\n    \n    /**\n     The server trust could not be evaluated due to an error when trying to generate the certificate's subject public key info hash. On iOS, this could be caused by a Keychain failure when trying to extract the certificate's public key bytes.\n     */\n    TSKPinValidationResultErrorCouldNotGenerateSpkiHash,\n};\n\n\n// Figure out if a specific domain is pinned and retrieve this domain's configuration key; returns nil if no configuration was found\nNSString *getPinningConfigurationKeyForDomain(NSString *hostname, NSDictionary *trustKitConfiguration);\n\n// Validate that the server trust contains at least one of the know/expected pins\nTSKPinValidationResult verifyPublicKeyPin(SecTrustRef serverTrust, NSString *serverHostname, NSArray<NSNumber *> *supportedAlgorithms, NSSet<NSData *> *knownPins);\n\n"
  },
  {
    "path": "TrustKit/Pinning/ssl_pin_verifier.m",
    "content": "/*\n \n ssl_pin_verifier.m\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import \"ssl_pin_verifier.h\"\n#import \"../Dependencies/domain_registry/domain_registry.h\"\n#import \"public_key_utils.h\"\n#import \"../TrustKit+Private.h\"\n#import \"../configuration_utils.h\"\n\n\n#pragma mark SSL Pin Verifier\n\nTSKPinValidationResult verifyPublicKeyPin(SecTrustRef serverTrust, NSString *serverHostname, NSArray<NSNumber *> *supportedAlgorithms, NSSet<NSData *> *knownPins)\n{\n    if ((serverTrust == NULL) || (supportedAlgorithms == nil) || (knownPins == nil))\n    {\n        TSKLog(@\"Invalid pinning parameters for %@\", serverHostname);\n        return TSKPinValidationResultErrorInvalidParameters;\n    }\n\n    // First re-check the certificate chain using the default SSL validation in case it was disabled\n    // This gives us revocation (only for EV certs I think?) and also ensures the certificate chain is sane\n    // And also gives us the exact path that successfully validated the chain\n    CFRetain(serverTrust);\n    \n    // Create and use a sane SSL policy to force hostname validation, even if the supplied trust has a bad\n    // policy configured (such as one from SecPolicyCreateBasicX509())\n    SecPolicyRef SslPolicy = SecPolicyCreateSSL(YES, (__bridge CFStringRef)(serverHostname));\n    SecTrustSetPolicies(serverTrust, SslPolicy);\n    CFRelease(SslPolicy);\n    \n    SecTrustResultType trustResult = 0;\n    if (SecTrustEvaluate(serverTrust, &trustResult) != errSecSuccess)\n    {\n        TSKLog(@\"SecTrustEvaluate error for %@\", serverHostname);\n        CFRelease(serverTrust);\n        return TSKPinValidationResultErrorInvalidParameters;\n    }\n    \n    if ((trustResult != kSecTrustResultUnspecified) && (trustResult != kSecTrustResultProceed))\n    {\n        // Default SSL validation failed\n        CFDictionaryRef evaluationDetails = SecTrustCopyResult(serverTrust);\n        TSKLog(@\"Error: default SSL validation failed for %@: %@\", serverHostname, evaluationDetails);\n        CFRelease(evaluationDetails);\n        CFRelease(serverTrust);\n        return TSKPinValidationResultFailedCertificateChainNotTrusted;\n    }\n    \n    // Check each certificate in the server's certificate chain (the trust object); start with the CA all the way down to the leaf\n    CFIndex certificateChainLen = SecTrustGetCertificateCount(serverTrust);\n    for(int i=(int)certificateChainLen-1;i>=0;i--)\n    {\n        // Extract the certificate\n        SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i);\n        CFStringRef certificateSubject = SecCertificateCopySubjectSummary(certificate);\n        TSKLog(@\"Checking certificate with CN: %@\", certificateSubject);\n        CFRelease(certificateSubject);\n        \n        // For each public key algorithm flagged as supported in the config, generate the subject public key info hash\n        for (NSNumber *savedAlgorithm in supportedAlgorithms)\n        {\n            TSKPublicKeyAlgorithm algorithm = [savedAlgorithm integerValue];\n            NSData *subjectPublicKeyInfoHash = hashSubjectPublicKeyInfoFromCertificate(certificate, algorithm);\n            if (subjectPublicKeyInfoHash == nil)\n            {\n                TSKLog(@\"Error - could not generate the SPKI hash for %@\", serverHostname);\n                CFRelease(serverTrust);\n                return TSKPinValidationResultErrorCouldNotGenerateSpkiHash;\n            }\n            \n            // Is the generated hash in our set of pinned hashes ?\n            if ([knownPins containsObject:subjectPublicKeyInfoHash])\n            {\n                TSKLog(@\"SSL Pin found for %@\", serverHostname);\n                CFRelease(serverTrust);\n                return TSKPinValidationResultSuccess;\n            }\n        }\n    }\n    \n#if !TARGET_OS_IPHONE\n    // OS X only: if user-defined anchors are whitelisted, allow the App to not enforce pin validation\n    NSMutableArray *customRootCerts = [NSMutableArray array];\n    \n    // Retrieve the OS X host's list of user-defined CA certificates\n    CFArrayRef userRootCerts;\n    OSStatus status = SecTrustSettingsCopyCertificates(kSecTrustSettingsDomainUser, &userRootCerts);\n    if (status == errSecSuccess)\n    {\n        [customRootCerts addObjectsFromArray:(__bridge NSArray *)(userRootCerts)];\n        CFRelease(userRootCerts);\n    }\n    CFArrayRef adminRootCerts;\n    status = SecTrustSettingsCopyCertificates(kSecTrustSettingsDomainAdmin, &adminRootCerts);\n    if (status == errSecSuccess)\n    {\n        [customRootCerts addObjectsFromArray:(__bridge NSArray *)(adminRootCerts)];\n        CFRelease(adminRootCerts);\n    }\n    \n    // Is any certificate in the chain a custom anchor that was manually added to the OS' trust store ?\n    // If we get there, we shouldn't have to check the custom certificates' trust setting (trusted / not trusted)\n    // as the chain validation was successful right before\n    if ([customRootCerts count] > 0)\n    {\n        for(int i=0;i<certificateChainLen;i++)\n        {\n            SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i);\n            \n            // Is the certificate chain's anchor a user-defined anchor ?\n            if ([customRootCerts containsObject:(__bridge id)(certificate)])\n            {\n                TSKLog(@\"Detected user-defined trust anchor in the certificate chain\");\n                CFRelease(serverTrust);\n                return TSKPinValidationResultFailedUserDefinedTrustAnchor;\n            }\n        }\n    }\n#endif\n    \n    // If we get here, we didn't find any matching SPKI hash in the chain\n    TSKLog(@\"Error: SSL Pin not found for %@\", serverHostname);\n    CFRelease(serverTrust);\n    return TSKPinValidationResultFailed;\n}\n"
  },
  {
    "path": "TrustKit/Reporting/TSKBackgroundReporter.h",
    "content": "/*\n \n TSKBackgroundReporter.h\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import <Foundation/Foundation.h>\n#import \"../Pinning/ssl_pin_verifier.h\"\n\n/**\n `TSKSimpleBackgroundReporter` is a class for uploading pin failure reports using the background transfer service.\n \n */\n@interface TSKBackgroundReporter : NSObject <NSURLSessionTaskDelegate>\n\n///---------------------\n/// @name Initialization\n///---------------------\n\n/**\n Initializes a background reporter.\n \n @param shouldRateLimitReports Prevent identical pin failure reports from being sent more than once per day.\n @exception NSException Thrown when the App does not have a bundle ID, meaning we're running in unit tests where the background transfer service can't be used.\n \n */\n- (nonnull instancetype)initAndRateLimitReports:(BOOL)shouldRateLimitReports;\n\n///----------------------\n/// @name Sending Reports\n///----------------------\n\n/**\n Send a pin validation failure report; each argument is described section 3. of RFC 7469.\n */\n- (void) pinValidationFailedForHostname:(nonnull NSString *) serverHostname\n                                   port:(nullable NSNumber *) serverPort\n                                  certificateChain:(nonnull NSArray *) certificateChain\n                          notedHostname:(nonnull NSString *) notedHostname\n                             reportURIs:(nonnull NSArray<NSURL *> *) reportURIs\n                      includeSubdomains:(BOOL) includeSubdomains\n                         enforcePinning:(BOOL) enforcePinning\n                              knownPins:(nonnull NSSet<NSData *> *) knownPins\n                       validationResult:(TSKPinValidationResult) validationResult\n                         expirationDate:(nullable NSDate *)knownPinsExpirationDate;\n\n- (void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error;\n\n@end\n\n"
  },
  {
    "path": "TrustKit/Reporting/TSKBackgroundReporter.m",
    "content": "/*\n \n TSKBackgroundReporter.m\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import \"TSKBackgroundReporter.h\"\n#import \"../TrustKit+Private.h\"\n#import \"TSKPinFailureReport.h\"\n#import \"reporting_utils.h\"\n#import \"TSKReportsRateLimiter.h\"\n#import \"vendor_identifier.h\"\n#import <Foundation/NSObjCRuntime.h>\n\n\n// Session identifier for background uploads: <bundle_id>.TSKBackgroundReporter\nstatic NSString *kTSKBackgroundSessionIdentifierFormat = @\"%@.TSKBackgroundReporter\";\nstatic NSURLSession *_backgroundSession = nil;\nstatic dispatch_once_t dispatchOnceBackgroundSession;\n\n\n@interface TSKBackgroundReporter()\n\n@property (nonatomic, strong, nonnull) NSString *appBundleId;\n@property (nonatomic, strong, nonnull) NSString *appVersion;\n@property (nonatomic, strong, nonnull) NSString *appVendorId;\n@property (nonatomic, strong, nonnull) NSString *appPlatform;\n@property (nonatomic, strong, nonnull) NSString *appPlatformVersion;\n@property BOOL shouldRateLimitReports;\n\n@end\n\n\n@implementation TSKBackgroundReporter\n\n#pragma mark Public methods\n\n- (nonnull instancetype)initAndRateLimitReports:(BOOL)shouldRateLimitReports;\n{\n    self = [super init];\n    if (self)\n    {\n        _shouldRateLimitReports = shouldRateLimitReports;\n        \n        // Retrieve the App and device's information\n#if TARGET_OS_IPHONE\n#if TARGET_OS_TV\n        _appPlatform = @\"TVOS\";\n#elif TARGET_OS_WATCH\n        _appPlatform = @\"WATCHOS\";\n#else\n        _appPlatform = @\"IOS\";\n        \n        // Before iOS 8 we need to build the OS version manually\n        // The number will not be perfectly accurate as we can't detect the patch version\n        if (NSFoundationVersionNumber == NSFoundationVersionNumber_iOS_7_0)\n        {\n            _appPlatformVersion = @\"7.0.0\";\n        }\n        else if (NSFoundationVersionNumber == NSFoundationVersionNumber_iOS_7_1)\n        {\n            _appPlatformVersion = @\"7.1.0\";\n        }\n#endif\n#else\n        _appPlatform = @\"MACOS\";\n        \n        // Before macOS 10.10 we need to build the OS version manually\n        // The number will not be perfectly accurate as we can't detect the patch version\n        if (NSFoundationVersionNumber == NSFoundationVersionNumber10_9)\n        {\n            _appPlatformVersion = @\"10.9.0\";\n        }\n        else if (NSFoundationVersionNumber == NSFoundationVersionNumber10_9_2)\n        {\n            _appPlatformVersion = @\"10.9.2\";\n        }\n#endif\n        \n        // If we don't have the OS version yet, we are on a device that provides the operatingSystemVersion method\n        if (_appPlatformVersion == nil)\n        {\n            NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];\n            _appPlatformVersion = [NSString stringWithFormat:@\"%ld.%ld.%ld\", (long)version.majorVersion, (long)version.minorVersion, (long)version.patchVersion];\n        }\n        \n        \n        CFBundleRef appBundle = CFBundleGetMainBundle();\n        _appVersion =  (__bridge NSString *)CFBundleGetValueForInfoDictionaryKey(appBundle, (CFStringRef) @\"CFBundleShortVersionString\");\n        if (_appVersion == nil)\n        {\n            _appVersion = @\"\";\n        }\n        \n        _appBundleId = (__bridge NSString *)CFBundleGetIdentifier(appBundle);\n        if (_appBundleId == nil)\n        {\n            // The bundle ID we get is nil if we're running tests on Travis. If the bundle ID is nil, background sessions can't be used\n            // backgroundSessionConfigurationWithIdentifier: will throw an exception within dispatch_once() which can't be handled\n            // Use a regular session instead\n            TSKLog(@\"Null bundle ID: we are running the test suite; falling back to a normal session.\");\n            _appBundleId = @\"N/A\";\n            _appVendorId = @\"unit-tests\";\n            \n            dispatch_once(&dispatchOnceBackgroundSession, ^{\n                _backgroundSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]\n                                                                   delegate:self\n                                                              delegateQueue:nil];\n            });\n        }\n        else\n        {\n            // Get the vendor identifier\n            _appVendorId = identifier_for_vendor();\n\n            \n            // We're not running unit tests - use a background session\n            /*\n             Using dispatch_once here ensures that multiple background sessions with the same identifier are not created\n             in this instance of the application. If you want to support multiple background sessions within a single process,\n             you should create each session with its own identifier.\n             */\n            dispatch_once(&dispatchOnceBackgroundSession, ^{\n                NSURLSessionConfiguration *backgroundConfiguration = nil;\n                \n                // The API for creating background sessions changed between iOS 7 and iOS 8 and OS X 10.9 and 10.10\n#if (TARGET_OS_IPHONE &&__IPHONE_OS_VERSION_MAX_ALLOWED < 80000) || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MAX_ALLOWED < 1100)\n                // iOS 7 or OS X 10.9 as the max SDK: awlays use the deprecated/iOS 7 API\n                backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:[NSString stringWithFormat:kTSKBackgroundSessionIdentifierFormat, _appBundleId]];\n#else\n                // iOS 8+ or OS X 10.10+ as the max SDK\n#if (TARGET_OS_IPHONE &&__IPHONE_OS_VERSION_MIN_REQUIRED < 80000) || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED < 1100)\n                // iOS 7 or OS X 10.9 as the min SDK\n                // Try to use the new API if available at runtime\n                if (![NSURLSessionConfiguration respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)])\n                {\n                    // Device runs on iOS 7 or OS X 10.9\n                    backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:[NSString stringWithFormat:kTSKBackgroundSessionIdentifierFormat, _appBundleId]];\n                }\n                else\n#endif\n                {\n                    // Device runs on iOS 8+ or OS X 10.10+ or min SDK is iOS 8+ or OS X 10.10+\n                    backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: [NSString stringWithFormat:kTSKBackgroundSessionIdentifierFormat, self->_appBundleId]];\n                }\n#endif\n                \n                \n                \n#if TARGET_OS_IPHONE\n                // iOS-only settings\n                // Do not wake up the App after completing the upload\n                backgroundConfiguration.sessionSendsLaunchEvents = NO;\n#endif\n                \n#if (TARGET_OS_IPHONE) || ((!TARGET_OS_IPHONE) && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1100))\n                // On OS X discretionary is only available on 10.10\n                backgroundConfiguration.discretionary = YES;\n#endif\n                // We have to use a delegate as background sessions can't use completion handlers\n                _backgroundSession = [NSURLSession sessionWithConfiguration:backgroundConfiguration\n                                                                   delegate:self\n                                                              delegateQueue:nil];\n            });\n        }\n    }\n    return self;\n}\n\n\n- (void) pinValidationFailedForHostname:(nonnull NSString *) serverHostname\n                                   port:(nullable NSNumber *) serverPort\n                       certificateChain:(nonnull NSArray *) certificateChain\n                          notedHostname:(nonnull NSString *) notedHostname\n                             reportURIs:(nonnull NSArray<NSURL *> *) reportURIs\n                      includeSubdomains:(BOOL) includeSubdomains\n                         enforcePinning:(BOOL) enforcePinning\n                              knownPins:(nonnull NSSet<NSData *> *) knownPins\n                       validationResult:(TSKPinValidationResult) validationResult\n                         expirationDate:(nullable NSDate *)knownPinsExpirationDate\n{\n    // Default port to 0 if not specified\n    if (serverPort == nil)\n    {\n        serverPort = [NSNumber numberWithInt:0];\n    }\n    \n    if (reportURIs == nil)\n    {\n        [NSException raise:@\"TSKBackgroundReporter configuration invalid\"\n                    format:@\"Reporter was given an invalid value for reportURIs: %@ for domain %@\",\n         reportURIs, notedHostname];\n    }\n    \n    // Create the pin validation failure report\n    NSArray *formattedPins = convertPinsToHpkpPins(knownPins);\n    TSKPinFailureReport *report = [[TSKPinFailureReport alloc]initWithAppBundleId:_appBundleId\n                                                                       appVersion:_appVersion\n                                                                      appPlatform:_appPlatform\n                                                               appPlatformVersion:_appPlatformVersion\n                                                                      appVendorId:_appVendorId\n                                                                  trustkitVersion:TrustKitVersion\n                                                                         hostname:serverHostname\n                                                                             port:serverPort\n                                                                         dateTime:[NSDate date] // Use the current time\n                                                                    notedHostname:notedHostname\n                                                                includeSubdomains:includeSubdomains\n                                                                   enforcePinning:enforcePinning\n                                                        validatedCertificateChain:certificateChain\n                                                                        knownPins:formattedPins\n                                                                 validationResult:validationResult\n                                                                   expirationDate:knownPinsExpirationDate];\n    \n    // Should we rate-limit this report?\n    if (_shouldRateLimitReports && [TSKReportsRateLimiter shouldRateLimitReport:report])\n    {\n        // We recently sent the exact same report; do not send this report\n        TSKLog(@\"Pin failure report for %@ was not sent due to rate-limiting\", serverHostname);\n        return;\n    }\n    \n    // Create a temporary file for storing the JSON data in ~/tmp\n    NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];\n    NSURL *tmpFileURL = [[tmpDirURL URLByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]] URLByAppendingPathExtension:@\"tsk-report\"];\n    \n    // Write the JSON report data to the temporary file\n    NSError *error;\n    NSUInteger writeOptions = NSDataWritingAtomic;\n#if TARGET_OS_IPHONE\n    // Ensure the report is accessible when locked on iOS, in case the App has the NSFileProtectionComplete entitlement\n    writeOptions = writeOptions | NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication;\n#endif\n    \n    if (!([[report json] writeToURL:tmpFileURL options:writeOptions error:&error]))\n    {\n#if DEBUG\n        // Only raise this exception for debug as not being able to save the report would crash a prod App\n        // https://github.com/datatheorem/TrustKit/issues/32\n        // This might happen when the device's storage is full?\n        [NSException raise:@\"TSKBackgroundReporter runtime error\"\n                    format:@\"Report cannot be saved to file: %@\", [error description]];\n#endif\n    }\n    TSKLog(@\"Report for %@ created at: %@\", serverHostname, [tmpFileURL path]);\n    \n    \n    // Create the HTTP request for all the configured report URIs and send it\n    for (NSURL *reportUri in reportURIs)\n    {\n        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:reportUri];\n        [request setHTTPMethod:@\"POST\"];\n        [request setValue:@\"application/json\" forHTTPHeaderField:@\"Content-Type\"];\n        \n        // Pass the URL and the temporary file to the background upload task and start uploading\n        NSURLSessionUploadTask *uploadTask = [_backgroundSession uploadTaskWithRequest:request\n                                                                              fromFile:tmpFileURL];\n        \n        [uploadTask resume];\n    }\n}\n\n\n\n- (void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error\n{\n    if (error == nil)\n    {\n        TSKLog(@\"Background upload - task completed successfully: pinning failure report sent\");\n    }\n    else\n    {\n        TSKLog(@\"Background upload - task completed with error: %@ (code %ld)\", [error localizedDescription], (long)error.code);\n    }\n}\n\n\n@end\n\n"
  },
  {
    "path": "TrustKit/Reporting/TSKPinFailureReport.h",
    "content": "/*\n \n TSKPinFailureReport.h\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import <Foundation/Foundation.h>\n#import \"../Pinning/ssl_pin_verifier.h\"\n\n\n@interface TSKPinFailureReport : NSObject\n\n@property (readonly, nonatomic, nonnull) NSString *appBundleId; // Not part of the HPKP spec\n@property (readonly, nonatomic, nonnull) NSString *appVersion; // Not part of the HPKP spec\n@property (readonly, nonatomic, nonnull) NSString *appPlatform; // Not part of the HPKP spec\n@property (readonly, nonatomic, nonnull) NSString *appPlatformVersion; // Not part of the HPKP spec\n@property (readonly, nonatomic, nonnull) NSString *appVendorId; // Not part of the HPKP spec\n@property (readonly, nonatomic, nonnull) NSString *trustkitVersion; // Not part of the HPKP spec\n@property (readonly, nonatomic, nonnull) NSString *notedHostname;\n@property (readonly, nonatomic, nonnull) NSString *hostname;\n@property (readonly, nonatomic, nonnull) NSNumber *port;\n@property (readonly, nonatomic, nonnull) NSDate *dateTime;\n@property (readonly, nonatomic) BOOL includeSubdomains;\n@property (readonly, nonatomic, nonnull) NSArray *validatedCertificateChain;\n@property (readonly, nonatomic, nonnull) NSArray *knownPins;\n@property (readonly, nonatomic) TSKPinValidationResult validationResult; // Not part of the HPKP spec\n@property (readonly, nonatomic) BOOL enforcePinning; // Not part of the HPKP spec\n@property (readonly, nonatomic, nullable) NSDate *knownPinsExpirationDate; // Not part of the HPKP spec\n\n\n// Init with default bundle ID and current time as the date-time\n- (nonnull instancetype) initWithAppBundleId:(nonnull NSString *)appBundleId\n                                  appVersion:(nonnull NSString *)appVersion\n                                 appPlatform:(nonnull NSString *)appPlatform\n                          appPlatformVersion:(nonnull NSString *)appPlatformVersion\n                                 appVendorId:(nonnull NSString *)appVendorId\n                             trustkitVersion:(nonnull NSString *)trustkitVersion\n                                    hostname:(nonnull NSString *)serverHostname\n                                        port:(nonnull NSNumber *)serverPort\n                                    dateTime:(nonnull NSDate *)dateTime\n                               notedHostname:(nonnull NSString *)notedHostname\n                           includeSubdomains:(BOOL)includeSubdomains\n                              enforcePinning:(BOOL)enforcePinning\n                   validatedCertificateChain:(nonnull NSArray<NSString *> *)validatedCertificateChain\n                                   knownPins:(nonnull NSArray<NSString *> *)knownPins\n                            validationResult:(TSKPinValidationResult)validationResult\n                              expirationDate:(nullable NSDate *)knownPinsExpirationDate;\n\n// Return the report in JSON format for POSTing it\n- (nonnull NSData *)json;\n\n// Return a request ready to be sent with the report in JSON format in the response's body\n- (nonnull NSMutableURLRequest *)requestToUri:(nonnull NSURL *)reportUri;\n\n\n@end\n"
  },
  {
    "path": "TrustKit/Reporting/TSKPinFailureReport.m",
    "content": "/*\n \n TSKPinFailureReport.m\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import \"TSKPinFailureReport.h\"\n\n@implementation TSKPinFailureReport\n\n\n- (nonnull instancetype) initWithAppBundleId:(nonnull NSString *)appBundleId\n                                  appVersion:(nonnull NSString *)appVersion\n                                 appPlatform:(nonnull NSString *)appPlatform\n                          appPlatformVersion:(nonnull NSString *)appPlatformVersion\n                                 appVendorId:(nonnull NSString *)appVendorId\n                             trustkitVersion:(nonnull NSString *)trustkitVersion\n                                    hostname:(nonnull NSString *)serverHostname\n                                        port:(nonnull NSNumber *)serverPort\n                                    dateTime:(nonnull NSDate *)dateTime\n                               notedHostname:(nonnull NSString *)notedHostname\n                           includeSubdomains:(BOOL)includeSubdomains\n                              enforcePinning:(BOOL)enforcePinning\n                   validatedCertificateChain:(nonnull NSArray<NSString *> *)validatedCertificateChain\n                                   knownPins:(nonnull NSArray<NSString *> *)knownPins\n                            validationResult:(TSKPinValidationResult)validationResult\n                              expirationDate:(nullable NSDate *)knownPinsExpirationDate\n{\n    self = [super init];\n    if (self)\n    {\n        _appBundleId = appBundleId;\n        _appVersion = appVersion;\n        _appPlatform = appPlatform;\n        _appVendorId = appVendorId;\n        _trustkitVersion = trustkitVersion;\n        _appPlatformVersion = appPlatformVersion;\n        _hostname = serverHostname;\n        _port = serverPort;\n        _dateTime = dateTime;\n        _notedHostname = notedHostname;\n        _includeSubdomains = includeSubdomains;\n        _enforcePinning = enforcePinning;\n        _validatedCertificateChain = validatedCertificateChain;\n        _knownPins = knownPins;\n        _validationResult = validationResult;\n        _knownPinsExpirationDate = knownPinsExpirationDate;\n    }\n    return self;\n}\n\n\n- (nonnull NSData *)json;\n{\n    // Convert the date to a string\n    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];\n    \n    // Explicitely set the locale to avoid an iOS 8 bug\n    // http://stackoverflow.com/questions/29374181/nsdateformatter-hh-returning-am-pm-on-ios-8-device\n    [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@\"en_US_POSIX\"]];\n    \n    [dateFormatter setDateFormat:@\"yyyy-MM-dd'T'HH:mm:ss'Z'\"];\n    [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@\"UTC\"]];\n    NSString *currentTimeStr = [dateFormatter stringFromDate: self.dateTime];\n    \n    id expirationDateStr = [NSNull null];\n    if (self.knownPinsExpirationDate)\n    {\n        // For the expiration date, only return the expiration day, as specified in the pinning policy\n        [dateFormatter setDateFormat:@\"yyyy-MM-dd\"];\n        expirationDateStr = [dateFormatter stringFromDate:self.knownPinsExpirationDate];\n    }\n    \n    // Create the dictionary\n    NSDictionary *requestData = @{\n        @\"app-bundle-id\" : self.appBundleId,\n        @\"app-version\" : self.appVersion,\n        @\"app-platform\" : self.appPlatform,\n        @\"app-platform-version\" : self.appPlatformVersion,\n        @\"app-vendor-id\" : self.appVendorId,\n        @\"trustkit-version\" : self.trustkitVersion,\n        @\"date-time\" : currentTimeStr,\n        @\"hostname\" : self.hostname,\n        @\"port\" : self.port,\n        @\"noted-hostname\" : self.notedHostname,\n        @\"include-subdomains\" : [NSNumber numberWithBool:self.includeSubdomains],\n        @\"enforce-pinning\" : [NSNumber numberWithBool:self.enforcePinning],\n        @\"validated-certificate-chain\" : self.validatedCertificateChain,\n        @\"known-pins\" : self.knownPins,\n        @\"validation-result\": [NSNumber numberWithInt:(int)self.validationResult],\n        @\"known-pins-expiration-date\": expirationDateStr\n    };\n    \n    NSError *error;\n    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:requestData options:(NSJSONWritingOptions)0 error:&error];\n    return jsonData;\n}\n\n\n- (nonnull NSMutableURLRequest *)requestToUri:(NSURL *)reportUri\n{\n    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:reportUri];\n    [request setHTTPMethod:@\"POST\"];\n    [request setValue:@\"application/json\" forHTTPHeaderField:@\"Content-Type\"];\n    [request setHTTPBody:[self json]];\n    return request;\n}\n\n\n@end\n"
  },
  {
    "path": "TrustKit/Reporting/TSKReportsRateLimiter.h",
    "content": "/*\n \n TSKReportsRateLimiter.h\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import \"TSKPinFailureReport.h\"\n#import <Foundation/Foundation.h>\n\n\n/*\n * Simple helper class which caches reports for 24 hours to prevent identical reports from being sent twice\n * during this 24 hour period.\n * This is best-effort as the class doesn't persist state across App restarts, so if the App\n * gets killed, it will start sending reports again.\n */\n@interface TSKReportsRateLimiter : NSObject\n\n+ (BOOL) shouldRateLimitReport:(TSKPinFailureReport *)report;\n\n@end\n\n\n\n@interface TSKReportsRateLimiter(Private)\n// Helper method for running tests\n+ (void) setLastReportsCacheResetDate:(NSDate *)date;\n@end\n"
  },
  {
    "path": "TrustKit/Reporting/TSKReportsRateLimiter.m",
    "content": "/*\n \n TSKReportsRateLimiter.m\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import \"TSKReportsRateLimiter.h\"\n#include <pthread.h>\n#import \"reporting_utils.h\"\n\n\n// Variables to rate-limit the number of pin failure reports that get sent\nstatic dispatch_once_t _dispatchOnceInit;\nstatic NSMutableSet *_reportsCache = nil;\nstatic pthread_mutex_t _reportsCacheLock;\n// We reset the reports cache every 24 hours to ensure identical reports are only sent once per day\n#define INTERVAL_BETWEEN_REPORTS_CACHE_RESET 3600*24\nstatic NSDate *_lastReportsCacheResetDate = nil;\n\n\n\n\n@implementation TSKReportsRateLimiter\n\n+ (BOOL) shouldRateLimitReport:(TSKPinFailureReport *)report\n{\n    // Initialize all the internal state for rate-limiting report uploads\n    dispatch_once(&_dispatchOnceInit, ^\n                  {\n                      // Initialize state for rate-limiting\n                      pthread_mutex_init(&_reportsCacheLock, NULL);\n                      _lastReportsCacheResetDate = [NSDate date];\n                      _reportsCache = [NSMutableSet set];\n                  });\n    \n    \n    // Check if we need to clear the reports cache for rate-limiting\n    NSDate *currentDate = [NSDate date];\n    NSTimeInterval secondsSinceCacheReset = [currentDate timeIntervalSinceDate:_lastReportsCacheResetDate];\n    if (secondsSinceCacheReset > INTERVAL_BETWEEN_REPORTS_CACHE_RESET)\n    {\n        // Reset the cache\n        pthread_mutex_lock(&_reportsCacheLock);\n        {\n            [_reportsCache removeAllObjects];\n            _lastReportsCacheResetDate = currentDate;\n        }\n        pthread_mutex_unlock(&_reportsCacheLock);\n    }\n    \n    \n    // Create an array containg the gist of the pin failure report; do not include the dates\n    NSArray *pinFailureInfo = @[report.notedHostname, report.hostname, report.port, report.validatedCertificateChain, report.knownPins, [NSNumber numberWithInt:(int)report.validationResult]];\n    \n    \n    // Check if the exact same report has already been sent recently\n    BOOL shouldRateLimitReport = NO;\n    pthread_mutex_lock(&_reportsCacheLock);\n    {\n        shouldRateLimitReport = [_reportsCache containsObject:pinFailureInfo];\n    }\n    pthread_mutex_unlock(&_reportsCacheLock);\n    \n    if (shouldRateLimitReport == NO)\n    {\n        // An identical report has NOT been sent recently\n        // Add this report to the cache for rate-limiting\n        pthread_mutex_lock(&_reportsCacheLock);\n        {\n            [_reportsCache addObject:pinFailureInfo];\n        }\n        pthread_mutex_unlock(&_reportsCacheLock);\n    }\n    return shouldRateLimitReport;\n}\n\n\n+ (void) setLastReportsCacheResetDate:(NSDate *)date\n{\n    pthread_mutex_lock(&_reportsCacheLock);\n    {\n        _lastReportsCacheResetDate = date;\n    }\n    pthread_mutex_unlock(&_reportsCacheLock);\n}\n\n@end\n\n"
  },
  {
    "path": "TrustKit/Reporting/reporting_utils.h",
    "content": "/*\n \n reporting_utils.h\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#ifndef TrustKit_reporting_utils_h\n#define TrustKit_reporting_utils_h\n\nNSArray<NSString *> *convertTrustToPemArray(SecTrustRef serverTrust);\nNSArray<NSString *> *convertPinsToHpkpPins(NSSet<NSData *> *knownPins);\n\n#endif\n"
  },
  {
    "path": "TrustKit/Reporting/reporting_utils.m",
    "content": "/*\n \n reporting_utils.m\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import <Foundation/Foundation.h>\n\n#import \"reporting_utils.h\"\n\n\nNSArray<NSString *> *convertTrustToPemArray(SecTrustRef serverTrust)\n{\n    // Convert the trust object into an array of PEM certificates\n    // Warning: SecTrustEvaluate() always needs to be called first on the serverTrust to be able to extract the certificates\n    NSMutableArray *certificateChain = [NSMutableArray array];\n    CFIndex chainLen = SecTrustGetCertificateCount(serverTrust);\n    for (CFIndex i=0;i<chainLen;i++)\n    {\n        SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i);\n        CFDataRef certificateData = SecCertificateCopyData(certificate);\n        \n        // Craft the PEM certificate\n        NSString *certificatePem = [NSString\n                                    stringWithFormat:@\"-----BEGIN CERTIFICATE-----\\n%@\\n-----END CERTIFICATE-----\",\n                                    [(__bridge NSData *)certificateData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]];\n        [certificateChain addObject:certificatePem];\n        CFRelease(certificateData);\n    }\n    return certificateChain;\n}\n\n\nNSArray<NSString *> *convertPinsToHpkpPins(NSSet<NSData *> *knownPins)\n{\n    // Convert the know pins from a set of data to an array of strings as described in the HPKP spec\n    NSMutableArray *formattedPins = [NSMutableArray array];\n    for (NSData *pin in knownPins)\n    {\n        [formattedPins addObject:[NSString stringWithFormat:@\"pin-sha256=\\\"%@\\\"\", [pin base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]]];\n    }\n    return formattedPins;\n}\n\n"
  },
  {
    "path": "TrustKit/Reporting/vendor_identifier.h",
    "content": "//\n//  vendor_identifier.h\n//  TrustKit\n//\n//  Created by Alban Diquet on 8/24/16.\n//  Copyright © 2016 TrustKit. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n\n// Will return the IDFV on platforms that support it (iOS, tvOS) and a randomly generated UUID on other platforms (macOS, watchOS)\nNSString *identifier_for_vendor(void);\n"
  },
  {
    "path": "TrustKit/Reporting/vendor_identifier.m",
    "content": "//\n//  vendor_identifier.m\n//  TrustKit\n//\n//  Created by Alban Diquet on 8/24/16.\n//  Copyright © 2016 TrustKit. All rights reserved.\n//\n\n#import \"vendor_identifier.h\"\n\n\n#if TARGET_OS_IPHONE && !TARGET_OS_WATCH\n\n#pragma mark Vendor identifier - macOS, tvOS\n\n@import UIKit; // For accessing the IDFV\n\nNSString *identifier_for_vendor(void)\n{\n    return [[[UIDevice currentDevice] identifierForVendor]UUIDString];\n}\n\n#else\n\n#pragma mark Vendor identifier - macOS, watchOS\n\n#include <pthread.h>\n\nstatic NSString * const kTSKVendorIdentifierKey = @\"TSKVendorIdentifier\";\n\n\nNSString *identifier_for_vendor(void)\n{\n    // Try to retrieve the vendor ID from the preferences\n    NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];\n    NSString *vendorId = [preferences stringForKey:kTSKVendorIdentifierKey];\n    if (vendorId == nil)\n    {\n        // Generate and store a new UUID\n        vendorId = [[NSUUID UUID] UUIDString];\n        \n        [preferences setObject:vendorId forKey:kTSKVendorIdentifierKey];\n        [preferences synchronize];\n    }\n    return vendorId;\n}\n\n#endif\n\n"
  },
  {
    "path": "TrustKit/Swizzling/TSKNSURLConnectionDelegateProxy.h",
    "content": "//\n//  TSKNSURLConnectionDelegateProxy.h\n//  TrustKit\n//\n//  Created by Alban Diquet on 10/7/15.\n//  Copyright © 2015 TrustKit. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n\n@interface TSKNSURLConnectionDelegateProxy : NSObject<NSURLConnectionDelegate>\n{\n    id<NSURLConnectionDelegate> originalDelegate; // The NSURLConnectionDelegate we're going to proxy\n}\n\n// Initalize our hooks\n+ (void)swizzleNSURLConnectionConstructors;\n\n- (instancetype)initWithDelegate:(id)delegate;\n\n// Mirror the original delegate's list of implemented methods\n- (BOOL)respondsToSelector:(SEL)aSelector ;\n\n// Forward messages to the original delegate if the proxy doesn't implement the method\n- (id)forwardingTargetForSelector:(SEL)sel;\n\n- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;\n\n\n@end\n"
  },
  {
    "path": "TrustKit/Swizzling/TSKNSURLConnectionDelegateProxy.m",
    "content": "//\n//  TSKNSURLConnectionDelegateProxy.m\n//  TrustKit\n//\n//  Created by Alban Diquet on 10/7/15.\n//  Copyright © 2015 TrustKit. All rights reserved.\n//\n\n#import \"TSKNSURLConnectionDelegateProxy.h\"\n#import \"../TrustKit+Private.h\"\n#import \"../Dependencies/RSSwizzle/RSSwizzle.h\"\n\n\n\ntypedef void (^AsyncCompletionHandler)(NSURLResponse *response, NSData *data, NSError *connectionError);\n\n\n@interface TSKNSURLConnectionDelegateProxy(Private)\n-(BOOL)forwardToOriginalDelegateAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge forConnection:(NSURLConnection *)connection;\n@end\n\n\n@implementation TSKNSURLConnectionDelegateProxy\n\n\n#pragma mark Private methods used for tests\n\nstatic TSKTrustDecision _lastTrustDecision = (TSKTrustDecision)-1;\n\n+(void)resetLastTrustDecision\n{\n    _lastTrustDecision = (TSKTrustDecision)-1;\n}\n\n+(TSKTrustDecision)getLastTrustDecision\n{\n    return _lastTrustDecision;\n}\n\n\n#pragma mark Public methods\n\n+ (void)swizzleNSURLConnectionConstructors\n{\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wshadow\"\n    // - initWithRequest:delegate:\n    RSSwizzleInstanceMethod(NSClassFromString(@\"NSURLConnection\"),\n                            @selector(initWithRequest:delegate:),\n                            RSSWReturnType(NSURLConnection*),\n                            RSSWArguments(NSURLRequest *request, id<NSURLConnectionDelegate> delegate),\n                            RSSWReplacement(\n                                            {\n                                                NSURLConnection *connection;\n                                                \n                                                if ([NSStringFromClass([delegate class]) hasPrefix:@\"TSK\"])\n                                                {\n                                                    // Don't proxy ourselves\n                                                    connection = RSSWCallOriginal(request, delegate);\n                                                }\n                                                else\n                                                {\n                                                    // Replace the delegate with our own so we can intercept and handle authentication challenges\n                                                    TSKNSURLConnectionDelegateProxy *swizzledDelegate = [[TSKNSURLConnectionDelegateProxy alloc]initWithDelegate:delegate];\n                                                     connection = RSSWCallOriginal(request, swizzledDelegate);\n                                                }\n                                                return connection;\n                                            }), RSSwizzleModeAlways, NULL);\n    \n    \n    \n    // - initWithRequest:delegate:startImmediately:\n    RSSwizzleInstanceMethod(NSClassFromString(@\"NSURLConnection\"),\n                            @selector(initWithRequest:delegate:startImmediately:),\n                            RSSWReturnType(NSURLConnection*),\n                            RSSWArguments(NSURLRequest *request, id<NSURLConnectionDelegate> delegate, BOOL startImmediately),\n                            RSSWReplacement(\n                                            {\n                                                NSURLConnection *connection;\n                                                \n                                                if ([NSStringFromClass([delegate class]) hasPrefix:@\"TSK\"])\n                                                {\n                                                    // Don't proxy ourselves\n                                                    connection = RSSWCallOriginal(request, delegate, startImmediately);\n                                                }\n                                                else\n                                                {\n                                                    // Replace the delegate with our own so we can intercept and handle authentication challenges\n                                                    TSKNSURLConnectionDelegateProxy *swizzledDelegate = [[TSKNSURLConnectionDelegateProxy alloc]initWithDelegate:delegate];\n                                                    connection = RSSWCallOriginal(request, swizzledDelegate, startImmediately);\n                                                }\n                                                return connection;\n                                            }), RSSwizzleModeAlways, NULL);\n    \n    \n    // Not hooking + connectionWithRequest:delegate: as it ends up calling initWithRequest:delegate:\n    \n    // Log a warning for methods that do not have a delegate (ie. we can't protect these connections)\n    // + sendAsynchronousRequest:queue:completionHandler:\n    \n    RSSwizzleClassMethod(NSClassFromString(@\"NSURLConnection\"),\n                         @selector(sendAsynchronousRequest:queue:completionHandler:),\n                         RSSWReturnType(void),\n                         RSSWArguments(NSURLRequest *request, NSOperationQueue *queue, AsyncCompletionHandler handler),\n                         RSSWReplacement(\n                                         {\n                                             // Just display a warning\n                                             TSKLog(@\"WARNING: +sendAsynchronousRequest:queue:completionHandler: was called to connect to %@. This method does not expose a delegate argument for handling authentication challenges; TrustKit cannot enforce SSL pinning for these connections\", [[request URL]host]);\n                                             RSSWCallOriginal(request, queue, handler);\n                                         }));\n     \n    \n    // + sendSynchronousRequest:returningResponse:error:\n    RSSwizzleClassMethod(NSClassFromString(@\"NSURLConnection\"),\n                         @selector(sendSynchronousRequest:returningResponse:error:),\n                         RSSWReturnType(NSData *),\n                         RSSWArguments(NSURLRequest *request, NSURLResponse * _Nullable *response, NSError * _Nullable *error),\n                         RSSWReplacement(\n                                         {\n                                             // Just display a warning\n                                             TSKLog(@\"WARNING: +sendSynchronousRequest:returningResponse:error: was called to connect to %@. This method does not expose a delegate argument for handling authentication challenges; TrustKit cannot enforce SSL pinning for these connections\", [[request URL]host]);\n                                             NSData *data = RSSWCallOriginal(request, response, error);\n                                             return data;\n                                         }));\n#pragma clang diagnostic pop\n}\n\n\n- (instancetype)initWithDelegate:(id)delegate\n{\n    self = [super init];\n    if (self)\n    {\n        originalDelegate = delegate;\n    }\n    TSKLog(@\"Proxy-ing NSURLConnectionDelegate: %@\", NSStringFromClass([delegate class]));\n    return self;\n}\n\n\n#pragma mark Delegate methods\n\n- (BOOL)respondsToSelector:(SEL)aSelector\n{\n    if (aSelector == @selector(connection:willSendRequestForAuthenticationChallenge:))\n    {\n        // The delegate proxy should always receive authentication challenges\n        return YES;\n    }\n    else\n    {\n        // The delegate proxy should mirror the original delegate's methods so that it doesn't change the app flow\n        return [originalDelegate respondsToSelector:aSelector];\n    }\n}\n\n\n- (id)forwardingTargetForSelector:(SEL)sel\n{\n    // Forward messages to the original delegate if the proxy doesn't implement the method\n    return originalDelegate;\n}\n\n\n// NSURLConnection is deprecated in iOS 9\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n-(BOOL)forwardToOriginalDelegateAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge forConnection:(NSURLConnection *)connection\n{\n    BOOL wasChallengeHandled = NO;\n    \n    // Can the original delegate handle this challenge ?\n    if  ([originalDelegate respondsToSelector:@selector(connection:willSendRequestForAuthenticationChallenge:)])\n    {\n        // Yes - forward the challenge to the original delegate\n        wasChallengeHandled = YES;\n        [originalDelegate connection:connection willSendRequestForAuthenticationChallenge:challenge];\n    }\n    else if ([originalDelegate respondsToSelector:@selector(connection:canAuthenticateAgainstProtectionSpace:)])\n    {\n        if ([originalDelegate connection:connection canAuthenticateAgainstProtectionSpace:challenge.protectionSpace])\n        {\n            // Yes - forward the challenge to the original delegate\n            wasChallengeHandled = YES;\n            [originalDelegate connection:connection didReceiveAuthenticationChallenge:challenge];\n        }\n    }\n\n    return wasChallengeHandled;\n}\n#pragma GCC diagnostic pop\n\n\n- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge\n{\n    BOOL wasChallengeHandled = NO;\n    \n    // For SSL pinning we only care about server authentication\n    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])\n    {\n        TSKTrustDecision trustDecision = TSKTrustDecisionShouldBlockConnection;\n        SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;\n        NSString *serverHostname = challenge.protectionSpace.host;\n    \n        // Check the trust object against the pinning policy\n        trustDecision = [TSKPinningValidator evaluateTrust:serverTrust forHostname:serverHostname];\n        _lastTrustDecision = trustDecision;\n        if (trustDecision == TSKTrustDecisionShouldBlockConnection)\n        {\n            // Pinning validation failed - block the connection\n            wasChallengeHandled = YES;\n            [challenge.sender cancelAuthenticationChallenge:challenge];\n        }\n    }\n    \n    // Forward all challenges (including client auth challenges) to the original delegate\n    if (wasChallengeHandled == NO)\n    {\n        // We will also get here if the pinning validation succeeded or the domain was not pinned\n        if ([self forwardToOriginalDelegateAuthenticationChallenge:challenge forConnection:connection] == NO)\n        {\n            // The original delegate could not handle the challenge; use the default handler\n            [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];\n        }\n    }\n}\n\n\n@end\n"
  },
  {
    "path": "TrustKit/Swizzling/TSKNSURLSessionDelegateProxy.h",
    "content": "//\n//  TSKNSURLSessionDelegateProxy.h\n//  TrustKit\n//\n//  Created by Alban Diquet on 10/11/15.\n//  Copyright © 2015 TrustKit. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n\n@interface TSKNSURLSessionDelegateProxy : NSObject\n{\n    id<NSURLSessionDelegate, NSURLSessionTaskDelegate> originalDelegate; // The NSURLSessionDelegate we're going to proxy\n}\n\n+ (void)swizzleNSURLSessionConstructors;\n\n- (_Nullable instancetype)initWithDelegate:(_Nonnull id)delegate;\n\n// Mirror the original delegate's list of implemented methods\n- (BOOL)respondsToSelector:(_Nonnull SEL)aSelector;\n\n// Forward messages to the original delegate if the proxy doesn't implement the method\n- (_Nonnull id)forwardingTargetForSelector:(_Nonnull SEL)sel;\n\n- (void)URLSession:(NSURLSession * _Nonnull)session\ndidReceiveChallenge:(NSURLAuthenticationChallenge * _Nonnull)challenge\n completionHandler:(void (^ _Nonnull)(NSURLSessionAuthChallengeDisposition disposition,\n                                      NSURLCredential * _Nullable credential))completionHandler;\n\n- (void)URLSession:(NSURLSession * _Nonnull)session\n              task:(NSURLSessionTask * _Nonnull)task\ndidReceiveChallenge:(NSURLAuthenticationChallenge * _Nonnull)challenge\n completionHandler:(void (^ _Nonnull)(NSURLSessionAuthChallengeDisposition disposition,\n                                      NSURLCredential * _Nullable credential))completionHandler;\n\n@end\n"
  },
  {
    "path": "TrustKit/Swizzling/TSKNSURLSessionDelegateProxy.m",
    "content": "//\n//  TSKNSURLSessionDelegateProxy.m\n//  TrustKit\n//\n//  Created by Alban Diquet on 10/11/15.\n//  Copyright © 2015 TrustKit. All rights reserved.\n//\n\n#import \"TSKNSURLSessionDelegateProxy.h\"\n#import \"../Dependencies/RSSwizzle/RSSwizzle.h\"\n#import \"../TrustKit+Private.h\"\n\n\n@implementation TSKNSURLSessionDelegateProxy\n\n\n#pragma mark Private methods used for tests\n\nstatic TSKTrustDecision _lastTrustDecision = (TSKTrustDecision)-1;\n\n+(void)resetLastTrustDecision\n{\n    _lastTrustDecision = (TSKTrustDecision)-1;\n}\n\n+(TSKTrustDecision)getLastTrustDecision\n{\n    return _lastTrustDecision;\n}\n\n\n#pragma mark Public methods\n\n+ (void)swizzleNSURLSessionConstructors\n{\n    // Figure out NSURLSession's \"real\" class\n    NSString *NSURLSessionClass;\n    if (NSClassFromString(@\"NSURLSession\") != nil)\n    {\n        // iOS 8+\n        NSURLSessionClass = @\"NSURLSession\";\n    }\n    else if (NSClassFromString(@\"__NSCFURLSession\") != nil)\n    {\n        // Pre iOS 8, for some reason hooking NSURLSession doesn't work. We need to use the real/private class __NSCFURLSession\n        NSURLSessionClass = @\"__NSCFURLSession\";\n    }\n    else\n    {\n        TSKLog(@\"ERROR: Could not find NSURLSession's class\");\n        return;\n    }\n\n\n    // + sessionWithConfiguration:delegate:delegateQueue:\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wshadow\"\n    RSSwizzleClassMethod(NSClassFromString(NSURLSessionClass),\n                         @selector(sessionWithConfiguration:delegate:delegateQueue:),\n                         RSSWReturnType(NSURLSession *),\n                         RSSWArguments(NSURLSessionConfiguration * _Nonnull configuration, id _Nullable delegate, NSOperationQueue * _Nullable queue),\n                         RSSWReplacement(\n                                         {\n                                             NSURLSession *session;\n\n                                             if (delegate == nil)\n                                             {\n                                                 // Just display a warning\n                                                 //TSKLog(@\"WARNING: +sessionWithConfiguration:delegate:delegateQueue: was called with a nil delegate; TrustKit cannot enforce SSL pinning for any connection initiated by this session\");\n                                                 session = RSSWCallOriginal(configuration, delegate, queue);\n                                             }\n\n                                             // Do not swizzle TrustKit objects (such as the reporter)\n                                             else if ([NSStringFromClass([delegate class]) hasPrefix:@\"TSK\"])\n                                             {\n                                                 session = RSSWCallOriginal(configuration, delegate, queue);\n                                             }\n                                             else\n                                             {\n                                                 // Replace the delegate with our own so we can intercept and handle authentication challenges\n                                                 TSKNSURLSessionDelegateProxy *swizzledDelegate = [[TSKNSURLSessionDelegateProxy alloc]initWithDelegate:delegate];\n                                                 session = RSSWCallOriginal(configuration, swizzledDelegate, queue);\n                                             }\n\n                                             return session;\n                                         }));\n    // Not hooking the following methods as they end up calling +sessionWithConfiguration:delegate:delegateQueue:\n    // +sessionWithConfiguration:\n    // +sharedSession\n\n#pragma clang diagnostic pop\n}\n\n\n\n- (instancetype)initWithDelegate:(id)delegate\n{\n    self = [super init];\n    if (self)\n    {\n        originalDelegate = delegate;\n    }\n    TSKLog(@\"Proxy-ing NSURLSessionDelegate: %@\", NSStringFromClass([delegate class]));\n    return self;\n}\n\n\n#pragma mark Delegate methods\n\n- (BOOL)respondsToSelector:(SEL)aSelector\n{\n    if (aSelector == @selector(URLSession:task:didReceiveChallenge:completionHandler:))\n    {\n        // For the task-level handler, mirror the delegate\n        return [originalDelegate respondsToSelector:@selector(URLSession:task:didReceiveChallenge:completionHandler:)];\n    }\n    else if (aSelector == @selector(URLSession:didReceiveChallenge:completionHandler:))\n    {\n        if ([originalDelegate respondsToSelector:@selector(URLSession:didReceiveChallenge:completionHandler:)] == YES)\n        {\n            return YES;\n        }\n        else\n        {\n            if ([originalDelegate respondsToSelector:@selector(URLSession:task:didReceiveChallenge:completionHandler:)] == NO)\n            {\n                // If the task-level handler is not implemented in the delegate, we need to implement the session-level handler\n                // regardless of what the delegate implements, to ensure we get to handle auth challenges so we can do pinning validation\n                return YES;\n            }\n            else\n            {\n                // Let the task-level handler handle auth challenges\n                return NO;\n            }\n        }\n    }\n    else\n    {\n        // The delegate proxy should mirror the original delegate's methods so that it doesn't change the app flow\n        return [originalDelegate respondsToSelector:aSelector];\n    }\n}\n\n\n- (id)forwardingTargetForSelector:(SEL)sel\n{\n    // Forward messages to the original delegate if the proxy doesn't implement the method\n    return originalDelegate;\n}\n\n\n-(BOOL)forwardToOriginalDelegateAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge\n                                      completionHandler:(void (^ _Nonnull) (NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler\n                                             forSession:(NSURLSession * _Nonnull)session\n{\n    BOOL wasChallengeHandled = NO;\n\n    // Can the original delegate handle this challenge ?\n    if  ([originalDelegate respondsToSelector:@selector(URLSession:didReceiveChallenge:completionHandler:)])\n    {\n        // Yes - forward the challenge to the original delegate\n        wasChallengeHandled = YES;\n        [originalDelegate URLSession:session didReceiveChallenge:challenge completionHandler:completionHandler];\n    }\n    return wasChallengeHandled;\n}\n\n\n- (void)URLSession:(NSURLSession * _Nonnull)session\ndidReceiveChallenge:(NSURLAuthenticationChallenge * _Nonnull)challenge\n completionHandler:(void (^ _Nonnull)(NSURLSessionAuthChallengeDisposition disposition,\n                                      NSURLCredential * _Nullable credential))completionHandler\n{\n    BOOL wasChallengeHandled = NO;\n\n    // For SSL pinning we only care about server authentication\n    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])\n    {\n        TSKTrustDecision trustDecision = TSKTrustDecisionShouldBlockConnection;\n        SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;\n        NSString *serverHostname = challenge.protectionSpace.host;\n\n        // Check the trust object against the pinning policy\n        trustDecision = [TSKPinningValidator evaluateTrust:serverTrust forHostname:serverHostname];\n        _lastTrustDecision = trustDecision;\n        if (trustDecision == TSKTrustDecisionShouldBlockConnection)\n        {\n            // Pinning validation failed - block the connection\n            wasChallengeHandled = YES;\n            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL);\n        }\n    }\n\n    // Forward all challenges (including client auth challenges) to the original delegate\n    if (wasChallengeHandled == NO)\n    {\n        // We will also get here if the pinning validation succeeded or the domain was not pinned\n        if ([self forwardToOriginalDelegateAuthenticationChallenge:challenge completionHandler:completionHandler forSession:session] == NO)\n        {\n            // The original delegate could not handle the challenge; use the default handler\n            completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, NULL);\n        }\n    }\n}\n\n- (void)URLSession:(NSURLSession * _Nonnull)session\n              task:(NSURLSessionTask * _Nonnull)task\ndidReceiveChallenge:(NSURLAuthenticationChallenge * _Nonnull)challenge\n completionHandler:(void (^ _Nonnull)(NSURLSessionAuthChallengeDisposition disposition,\n                                      NSURLCredential * _Nullable credential))completionHandler\n{\n    BOOL wasChallengeHandled = NO;\n\n    // For SSL pinning we only care about server authentication\n    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])\n    {\n        TSKTrustDecision trustDecision = TSKTrustDecisionShouldBlockConnection;\n\n        // Check the trust object against the pinning policy\n        trustDecision = [TSKPinningValidator evaluateTrust:challenge.protectionSpace.serverTrust\n                                               forHostname:challenge.protectionSpace.host];\n        _lastTrustDecision = trustDecision;\n        if (trustDecision == TSKTrustDecisionShouldBlockConnection)\n        {\n            // Pinning validation failed - block the connection\n            wasChallengeHandled = YES;\n            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL);\n        }\n    }\n\n    // Forward all challenges (including client auth challenges) to the original delegate\n    if (wasChallengeHandled == NO)\n    {\n        // We will also get here if the pinning validation succeeded or the domain was not pinned\n        // If we're in this delegate method (and not URLSession:didReceiveChallenge:completionHandler:)\n        // it means the delegate definitely implements the handler method so we can call it directly\n        [originalDelegate URLSession:session task:task didReceiveChallenge:challenge completionHandler:completionHandler];\n    }\n}\n\n@end\n"
  },
  {
    "path": "TrustKit/TSKPinningValidator.h",
    "content": "/*\n \n TSKPinningValidator.h\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import <Foundation/Foundation.h>\n\n\n\n/**\n Possible return values when verifying a server's identity against the global SSL pinning policy using `TSKPinningValidator`.\n \n */\ntypedef NS_ENUM(NSInteger, TSKTrustDecision)\n{\n/**\n Based on the server's certificate chain and the global pinning policy for this domain, the SSL connection should be allowed.\n This return value does not necessarily mean that the pinning validation succeded (for example if `kTSKEnforcePinning` was set to `NO` for this domain). If a pinning validation failure occured and if a report URI was configured, a pin failure report was sent.\n */\n    TSKTrustDecisionShouldAllowConnection,\n    \n/**\n Based on the server's certificate chain and the global pinning policy for this domain, the SSL connection should be blocked.\n A pinning validation failure occured and if a report URI was configured, a pin failure report was sent.\n */\n    TSKTrustDecisionShouldBlockConnection,\n    \n/**\n No pinning policy was configured for this domain and TrustKit did not validate the server's identity.\n Because this will happen in an authentication handler, it means that the server's _serverTrust_ object __needs__ to be verified against the device's trust store using `SecTrustEvaluate()`. Failing to do so will __disable SSL certificate validation__.\n */\n    TSKTrustDecisionDomainNotPinned,\n};\n\n\n/**\n `TSKPinningValidator` is a class for manually verifying a server's identity against the global SSL pinning policy.\n \n In specific scenarios, TrustKit cannot intercept outgoing SSL connections and automatically validate the server's identity against the pinning policy:\n \n * All connections within an App that disables TrustKit's network delegate swizzling by setting the `kTSKSwizzleNetworkDelegates` configuration key to `NO`.\n * Connections that do not rely on the `NSURLConnection` or `NSURLSession` APIs:\n     * `WKWebView` connections.\n     * Connections leveraging low-level network APIs (such as `NSStream`).\n     * Connections initiated using a third-party SSL library such as OpenSSL.\n \n For these connections, pin validation must be manually triggered using one of the two available methods:\n \n * `evaluateTrust:forHostname:` which evaluates the server's certificate chain against the global SSL pinning policy.\n * `handleChallenge:completionHandler:` a helper method to be used for implementing pinning validation in challenge handler methods within `NSURLSession` and `WKWebView` delegates.\n \n */\n\n@interface TSKPinningValidator : NSObject\n\n///------------------------------------\n/// @name Manual SSL Pinning Validation\n///------------------------------------\n\n/**\n Evaluate the supplied server trust against the global SSL pinning policy previously configured. If the validation fails, a pin failure report will be sent.\n \n When using the `NSURLSession` or `WKWebView` network APIs, the `handleChallenge:completionHandler:` method should be called instead, as it is simpler to use.\n \n When using low-level network APIs (such as `NSStream`), instructions on how to retrieve the connection's `serverTrust` are available at https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html .\n \n @param serverTrust The trust object representing the server's certificate chain. The trust's evaluation policy is always overridden using `SecTrustSetPolicies()` to ensure all the proper SSL checks (expiration, hostname validation, etc.) are enabled.\n \n @param serverHostname The hostname of the server whose identity is being validated.\n \n @return A `TSKTrustDecision` which describes whether the SSL connection should be allowed or blocked, based on the global pinning policy.\n \n @warning If no SSL pinning policy was configured for the supplied _serverHostname_, this method has no effect and will return `TSKTrustDecisionDomainNotPinned` without validating the supplied _serverTrust_ at all. This means that the server's _serverTrust_ object __must__ be verified against the device's trust store using `SecTrustEvaluate()`. Failing to do so will __disable SSL certificate validation__.\n \n @exception NSException Thrown when TrustKit has not been initialized with a pinning policy.\n */\n+ (TSKTrustDecision) evaluateTrust:(SecTrustRef _Nonnull)serverTrust forHostname:(NSString * _Nonnull)serverHostname;\n\n\n/**\n Helper method for handling authentication challenges received within a `NSURLSessionDelegate`, `NSURLSessionTaskDelegate` or `WKNavigationDelegate`.\n \n This method will evaluate the server trust within the authentication challenge against the global SSL pinning policy previously configured, and then call the `completionHandler` with the corresponding `disposition` and `credential`. For example, this method can be leveraged in a `WKNavigationDelegate` challenge handler method:\n     \n     - (void)webView:(WKWebView *)webView\n     didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge\n     completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,\n     NSURLCredential *credential))completionHandler\n     {\n         if (![TSKPinningValidator handleChallenge:challenge completionHandler:completionHandler]) \n         {\n             // TrustKit did not handle this challenge: perhaps it was not for server trust\n             // or the domain was not pinned. Fall back to the default behavior\n             completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);\n         }\n     }\n \n @param challenge The authentication challenge, supplied by the URL loading system to the delegate's challenge handler method.\n \n @param completionHandler A block to invoke to respond to the challenge, supplied by the URL loading system to the delegate's challenge handler method.\n \n @return `YES` if the challenge was handled and the `completionHandler` was successfuly invoked. `NO` if the challenge could not be handled because it was not for server certificate validation (ie. the challenge's `authenticationMethod` was not `NSURLAuthenticationMethodServerTrust`).\n \n @exception NSException Thrown when TrustKit has not been initialized with a pinning policy.\n */\n+ (BOOL) handleChallenge:(NSURLAuthenticationChallenge * _Nonnull)challenge\n       completionHandler:(void (^ _Nonnull)(NSURLSessionAuthChallengeDisposition disposition,\n                                            NSURLCredential * _Nullable credential))completionHandler;\n@end\n"
  },
  {
    "path": "TrustKit/TSKPinningValidator.m",
    "content": "/*\n \n TSKPinningValidator.m\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import \"TrustKit+Private.h\"\n\n\n@implementation TSKPinningValidator\n\n+ (TSKTrustDecision) evaluateTrust:(SecTrustRef _Nonnull)serverTrust forHostname:(NSString * _Nonnull)serverHostname\n{\n    TSKTrustDecision finalTrustDecision = TSKTrustDecisionShouldBlockConnection;\n    \n    if ([TrustKit wasTrustKitInitialized] == NO)\n    {\n        [NSException raise:@\"TrustKit not initialized\"\n                    format:@\"TrustKit has not been initialized with a pinning configuration\"];\n    }\n    \n    if ((serverTrust == NULL) || (serverHostname == nil))\n    {\n        TSKLog(@\"Pin validation error - invalid parameters for %@\", serverHostname);\n        return finalTrustDecision;\n    }\n    CFRetain(serverTrust);\n    \n    // Register start time for duration computations\n    NSTimeInterval validationStartTime = [NSDate timeIntervalSinceReferenceDate];\n    \n    // Retrieve the pinning configuration for this specific domain, if there is one\n    NSDictionary *trustKitConfig = [TrustKit configuration];\n    NSString *domainConfigKey = getPinningConfigurationKeyForDomain(serverHostname, trustKitConfig);\n    if (domainConfigKey == nil)\n    {\n        // The domain has no pinning policy: nothing to do/validate\n        finalTrustDecision = TSKTrustDecisionDomainNotPinned;\n    }\n    else\n    {\n        // This domain has a pinning policy\n        NSDictionary *domainConfig = trustKitConfig[kTSKPinnedDomains][domainConfigKey];\n        \n        // Has the pinning policy expired?\n        NSDate *expirationDate = domainConfig[kTSKExpirationDate];\n        if ((expirationDate != nil) && ([expirationDate compare:[NSDate date]] == NSOrderedAscending))\n        {\n            // Yes the policy has expired\n            finalTrustDecision = TSKTrustDecisionDomainNotPinned;\n            \n        }\n        else if ([domainConfig[kTSKExcludeSubdomainFromParentPolicy] boolValue])\n        {\n            // This is a subdomain that was explicitely excluded from the parent domain's policy\n            finalTrustDecision = TSKTrustDecisionDomainNotPinned;\n        }\n        else\n        {\n            // The domain has a pinning policy that has not expired\n            // Look for one the configured public key pins in the server's evaluated certificate chain\n            TSKPinValidationResult validationResult = verifyPublicKeyPin(serverTrust, serverHostname, domainConfig[kTSKPublicKeyAlgorithms], domainConfig[kTSKPublicKeyHashes]);\n            if (validationResult == TSKPinValidationResultSuccess)\n            {\n                // Pin validation was successful\n                TSKLog(@\"Pin validation succeeded for %@\", serverHostname);\n                finalTrustDecision = TSKTrustDecisionShouldAllowConnection;\n            }\n            else\n            {\n                // Pin validation failed\n                TSKLog(@\"Pin validation failed for %@\", serverHostname);\n#if !TARGET_OS_IPHONE\n                if ((validationResult == TSKPinValidationResultFailedUserDefinedTrustAnchor)\n                    && ([trustKitConfig[kTSKIgnorePinningForUserDefinedTrustAnchors] boolValue] == YES))\n                {\n                    // OS-X only: user-defined trust anchors can be whitelisted (for corporate proxies, etc.) so don't send reports\n                    TSKLog(@\"Ignoring pinning failure due to user-defined trust anchor for %@\", serverHostname);\n                    finalTrustDecision = TSKTrustDecisionShouldAllowConnection;\n                }\n                else\n#endif\n                {\n                    if (validationResult == TSKPinValidationResultFailed)\n                    {\n                        // Is pinning enforced?\n                        if ([domainConfig[kTSKEnforcePinning] boolValue] == YES)\n                        {\n                            // Yes - Block the connection\n                            finalTrustDecision = TSKTrustDecisionShouldBlockConnection;\n                        }\n                        else\n                        {\n                            finalTrustDecision = TSKTrustDecisionShouldAllowConnection;\n                        }\n                    }\n                    else\n                    {\n                        // Misc pinning errors (such as invalid certificate chain) - block the connection\n                        finalTrustDecision = TSKTrustDecisionShouldBlockConnection;\n                    }\n                }\n            }\n            // Send a notification after all validation is done; this will also trigger a report if pin validation failed\n            NSTimeInterval validationDuration = [NSDate timeIntervalSinceReferenceDate] - validationStartTime;\n            sendValidationNotification_async(serverHostname, serverTrust, domainConfigKey, validationResult, finalTrustDecision, validationDuration);\n        }\n    }\n    CFRelease(serverTrust);\n    \n    return finalTrustDecision;\n}\n\n\n+ (BOOL) handleChallenge:(NSURLAuthenticationChallenge * _Nonnull)challenge completionHandler:(void (^ _Nonnull)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler\n{\n    BOOL wasChallengeHandled = NO;\n    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])\n    {\n        // Check the trust object against the pinning policy\n        SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;\n        NSString *serverHostname = challenge.protectionSpace.host;\n        \n        TSKTrustDecision trustDecision = [TSKPinningValidator evaluateTrust:serverTrust forHostname:serverHostname];\n        if (trustDecision == TSKTrustDecisionShouldAllowConnection)\n        {\n            // Success\n            wasChallengeHandled = YES;\n            completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:serverTrust]);\n        }\n        else if (trustDecision == TSKTrustDecisionDomainNotPinned)\n        {\n            // Domain was not pinned; we need to do the default validation to avoid disabling SSL validation for all non-pinned domains\n            wasChallengeHandled = YES;\n            completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, NULL);\n        }\n        else\n        {\n            // Pinning validation failed - block the connection\n            wasChallengeHandled = YES;\n            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL);\n        }\n    }\n    return wasChallengeHandled;\n}\n\n@end\n"
  },
  {
    "path": "TrustKit/TrustKit+Private.h",
    "content": "/*\n \n TrustKit+Private.h\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#ifndef TrustKit_TrustKit_Private____FILEEXTENSION___\n#define TrustKit_TrustKit_Private____FILEEXTENSION___\n\n#import \"TrustKit.h\"\n#import \"Pinning/ssl_pin_verifier.h\"\n#import \"Reporting/TSKBackgroundReporter.h\"\n\n\n#pragma mark Utility functions\n\nvoid TSKLog(NSString *format, ...);\n\nvoid sendValidationNotification_async(NSString *serverHostname, SecTrustRef serverTrust, NSString *notedHostname, TSKPinValidationResult validationResult, TSKTrustDecision finalTrustDecision, NSTimeInterval validationDuration);\n\n#pragma mark Methods for the unit tests\n\n@interface TrustKit(Private)\n\n+ (void) resetConfiguration;\n+ (BOOL) wasTrustKitInitialized;\n+ (NSString *) getDefaultReportUri;\n+ (TSKBackgroundReporter *) getGlobalPinFailureReporter;\n+ (void) setGlobalPinFailureReporter:(TSKBackgroundReporter *) reporter;\n\n@end\n\n\n#endif\n"
  },
  {
    "path": "TrustKit/TrustKit.h",
    "content": "/*\n \n TrustKit.h\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n\n#import <Foundation/Foundation.h>\n#import \"TSKPinningValidator.h\"\n\nNS_ASSUME_NONNULL_BEGIN\n\n\n#pragma mark TrustKit Version Number\n\n/**\n The version of TrustKit, such as \"1.4.0\".\n */\nFOUNDATION_EXPORT NSString * const TrustKitVersion;\n\n\n#pragma mark Configuration Keys\n\n\n/**\n A global, App-wide configuration key that can be set in the pinning policy.\n */\ntypedef NSString *TSKGlobalConfigurationKey;\n\n\n/**\n A domain-specific configuration key (to defined for a domain under the `kTSKPinnedDomains` key) that can be set in the pinning policy.\n */\ntypedef NSString *TSKDomainConfigurationKey;\n\n\n#pragma mark Global Configuration Keys - Required\n\n\n/**\n A boolean. If set to `YES`, TrustKit will perform method swizzling on the App's `NSURLConnection` and `NSURLSession` delegates in order to automatically add SSL pinning validation to the App's connections.\n \n Swizzling allows enabling pinning within an App without having to find and modify each and every instance of `NSURLConnection` or `NSURLSession` delegates.\n However, it should only be enabled for simple Apps, as it may not work properly in several scenarios including:\n \n * Apps with complex connection delegates, for example to handle client authentication via certificates or basic authentication.\n * Apps where method swizzling of the connection delegates is already performed by another module or library (such as Analytics SDKs).\n * Apps that do no use `NSURLSession` or `NSURLConnection` for their connections.\n \n In such scenarios or if the developer wants a tigher control on the App's networking behavior, `kTSKSwizzleNetworkDelegates` should be set to `NO`; the developer should then manually add pinning validation to the App's authentication handlers.\n \n See the `TSKPinningValidator` class for instructions on how to do so.\n */\nFOUNDATION_EXPORT const TSKGlobalConfigurationKey kTSKSwizzleNetworkDelegates;\n\n\n/**\n A dictionary with domains (such as _www.domain.com_) as keys and dictionaries as values.\n \n Each entry should contain domain-specific settings for performing pinning validation when connecting to the domain, including for example the domain's public key hashes. A list of all domain-specific keys is available in the \"Domain-specific Keys\" sections.\n */\nFOUNDATION_EXPORT const TSKGlobalConfigurationKey kTSKPinnedDomains;\n\n\n\n#pragma mark Global Configuration Keys - Optional\n\n\n/**\n A boolean. If set to `YES`, pinning validation will be skipped if the server's certificate chain terminates at a user-defined trust anchor (such as a root CA that isn't part of OS X's default trust store) and no pin failure reports will be sent; default value is `YES`.\n \n This is useful for allowing SSL connections through corporate proxies or firewalls. See \"How does key pinning interact with local proxies and filters?\" within the Chromium security FAQ at https://www.chromium.org/Home/chromium-security/security-faq for more information.\n \n Only available on macOS.\n */\nFOUNDATION_EXPORT const TSKGlobalConfigurationKey kTSKIgnorePinningForUserDefinedTrustAnchors NS_AVAILABLE_MAC(10_9);\n\n\n#pragma mark Domain-Specific Configuration Keys - Required\n\n/**\n An array of SSL pins, where each pin is the base64-encoded SHA-256 hash of a certificate's Subject Public Key Info.\n \n TrustKit will verify that at least one of the specified pins is found in the server's evaluated certificate chain.\n */\nFOUNDATION_EXPORT const TSKDomainConfigurationKey kTSKPublicKeyHashes;\n\n\n/**\n An array of `TSKSupportedAlgorithm` constants to specify the public key algorithms for the keys to be pinned.\n \n TrustKit requires this information in order to compute SSL pins when validating a server's certificate chain, because the `Security` framework does not provide APIs to extract the key's algorithm from an SSL certificate. To minimize the performance impact of Trustkit, only one algorithm should be enabled.\n*/\nFOUNDATION_EXPORT const TSKDomainConfigurationKey kTSKPublicKeyAlgorithms;\n\n\n#pragma mark Domain-Specific Configuration Keys - Optional\n\n/**\n A boolean. If set to `NO`, TrustKit will not block SSL connections that caused a pin or certificate validation error; default value is `YES`.\n \n When a pinning failure occurs, pin failure reports will always be sent to the configured report URIs regardless of the value of `kTSKEnforcePinning`.\n */\nFOUNDATION_EXPORT const TSKDomainConfigurationKey kTSKEnforcePinning;\n\n\n/**\n A boolean. If set to `YES`, also pin all the subdomains of the specified domain; default value is `NO`.\n */\nFOUNDATION_EXPORT const TSKDomainConfigurationKey kTSKIncludeSubdomains;\n\n\n/**\n A boolean. If set to `YES`, TrustKit will not pin this specific domain if `kTSKIncludeSubdomains` was set for this domain's parent domain.\n \n This allows excluding specific subdomains from a pinning policy that was applied to a parent domain.\n */\nFOUNDATION_EXPORT const TSKDomainConfigurationKey kTSKExcludeSubdomainFromParentPolicy;\n\n\n/**\n An array of URLs to which pin validation failures should be reported.\n \n To minimize the performance impact of sending reports on each validation failure, the reports are uploaded using the background transfer service and are also rate-limited to one per day and per type of failure. For HTTPS report URLs, the HTTPS connections will ignore the SSL pinning policy and use the default certificate validation mechanisms, in order to maximize the chance of the reports reaching the server. The format of the reports is similar to the one described in RFC 7469 for the HPKP specification:\n \n    {\n        \"app-bundle-id\": \"com.datatheorem.testtrustkit2\",\n        \"app-version\": \"1\",\n        \"app-vendor-id\": \"599F9C00-92DC-4B5C-9464-7971F01F8370\",\n        \"app-platform\": \"IOS\",\n        \"app-platform-version\": \"10.2.0\",\n        \"trustkit-version\": \"1.3.1\",\n        \"hostname\": \"www.datatheorem.com\",\n        \"port\": 0,\n        \"noted-hostname\": \"datatheorem.com\",\n        \"include-subdomains\": true,\n        \"enforce-pinning\": true,\n        \"validated-certificate-chain\": [\n            pem1, ... pemN\n        ],\n        \"known-pins\": [\n            \"pin-sha256=\\\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\\\"\",\n            \"pin-sha256=\\\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\\\"\"\n        ],\n        \"validation-result\":1\n    }\n */\nFOUNDATION_EXPORT const TSKDomainConfigurationKey kTSKReportUris;\n\n\n/**\n A boolean. If set to `YES`, the default report URL for sending pin failure reports will be disabled; default value is `NO`.\n \n By default, pin failure reports are sent to a report server hosted by Data Theorem, for detecting potential CA compromises and man-in-the-middle attacks, as well as providing a free dashboard for developers; email info@datatheorem.com if you'd like a dashboard for your App. Only pin failure reports are sent, which contain the App's bundle ID, the IDFV, and the server's hostname and certificate chain that failed validation.\n */\nFOUNDATION_EXPORT const TSKDomainConfigurationKey kTSKDisableDefaultReportUri;\n\n\n/**\n A string containing the date, in yyyy-MM-dd format, on which the domain's configured SSL pins expire, thus disabling pinning validation. If the key is not set, then the pins do not expire.\n \n Expiration helps prevent connectivity issues in Apps which do not get updates to their pin set, such as when the user disables App updates.\n */\nFOUNDATION_EXPORT const TSKDomainConfigurationKey kTSKExpirationDate;\n\n\n\n#pragma mark Supported Public Key Algorithm Keys\n\n\n/**\n A public key algorithm supported by TrustKit for computing SSL pins: \n \n * `kTSKAlgorithmRsa2048`\n * `kTSKAlgorithmRsa4096`\n * `kTSKAlgorithmEcDsaSecp256r1`\n * `kTSKAlgorithmEcDsaSecp384r1`\n \n */\ntypedef NSString *TSKSupportedAlgorithm;\n\n\n/**\n RSA 2048.\n */\nFOUNDATION_EXPORT const TSKSupportedAlgorithm kTSKAlgorithmRsa2048;\n\n\n/**\n RSA 4096.\n */\nFOUNDATION_EXPORT const TSKSupportedAlgorithm kTSKAlgorithmRsa4096;\n\n\n/**\n ECDSA with secp256r1 curve.\n */\nFOUNDATION_EXPORT const TSKSupportedAlgorithm kTSKAlgorithmEcDsaSecp256r1;\n\n\n/**\n ECDSA with secp384r1 curve.\n */\nFOUNDATION_EXPORT const TSKSupportedAlgorithm kTSKAlgorithmEcDsaSecp384r1;\n\n\n#pragma mark Pinning Validation Notification Name\n\n/**\n The `name` of the notification to be posted for every request that is going through TrustKit's pinning validation mechanism.\n \n Once TrustKit has been initialized, notifications will be posted with this `name` every time TrustKit validates the certificate chain for a server configured in the SSL pinning policy; if the server's hostname does not have an entry in the pinning policy, no notifications get posted as no pinning validation was performed.\n \n These notifications can be used for performance measurement or to act upon any pinning validation performed by TrustKit (for example to customize the reporting mechanism). The notifications provide details about TrustKit's inner-workings which most Apps should not need to process. Hence, these notifications can be ignored unless the App requires some advanced customization in regards to pinning validation.\n */\nFOUNDATION_EXPORT NSString *kTSKValidationCompletedNotification;\n\n\n#pragma mark Pinning Validation Notification UserInfo Keys\n\n/**\n A key to be used to retrieve data about the pinning validation that occured, from the `userInfo` dictionary attached to a `kTSKValidationCompletedNotification` notification.\n */\ntypedef NSString *TSKNotificationUserInfoKey;\n\n\n/**\n The time in seconds it took for the SSL pinning validation to be performed.\n */\nFOUNDATION_EXPORT const TSKNotificationUserInfoKey kTSKValidationDurationNotificationKey;\n\n\n/**\n The `TSKPinningValidationResult` returned when validating the server's certificate chain, which represents the result of evaluating the certificate chain against the configured SSL pins for this server.\n */\nFOUNDATION_EXPORT const TSKNotificationUserInfoKey kTSKValidationResultNotificationKey;\n\n/**\n The `TSKTrustDecision` returned when validating the certificate's chain, which describes whether the connection should be blocked or allowed, based on the `TSKPinningValidationResult` returned when evaluating the server's certificate chain and the SSL pining policy configured for this server.\n \n For example, the pinning validation could have failed (returning `TSKPinningValidationFailed`) but the policy might be set to ignore pinning validation failures for this server, thereby returning `TSKTrustDecisionShouldAllowConnection`.\n */\nFOUNDATION_EXPORT const TSKNotificationUserInfoKey kTSKValidationDecisionNotificationKey;\n\n/**\n The certificate chain returned by the server as an array of PEM-formatted certificates.\n */\nFOUNDATION_EXPORT const TSKNotificationUserInfoKey kTSKValidationCertificateChainNotificationKey;\n\n/**\n The entry within the SSL pinning configuration that was used as the pinning policy for the server being validated. It will be the same as the `kTSKValidationServerHostnameNotificationKey` entry unless the server is a subdomain of a domain configured in the pinning policy with `kTSKIncludeSubdomains` enabled. The corresponding pinning configuration that was used for validation can be retrieved using:\n    \n     NSString *notedHostname = userInfo[kTSKValidationNotedHostnameNotificationKey];\n     NSDictionary *hostnameConfiguration = [TrustKit configuration][kTSKPinnedDomains][notedHostname];\n */\nFOUNDATION_EXPORT const TSKNotificationUserInfoKey kTSKValidationNotedHostnameNotificationKey;\n\n/**\n The hostname of the server SSL pinning validation was performed against.\n */\nFOUNDATION_EXPORT const TSKNotificationUserInfoKey kTSKValidationServerHostnameNotificationKey;\n\n\n/**\n `TrustKit` is a class for programmatically configuring the global SSL pinning policy within an App.\n \n  The policy can be set either by adding it to the App's _Info.plist_ under the `TSKConfiguration` key, or by programmatically supplying it using the `TrustKit` class described here. Throughout the App's lifecycle, TrustKit can only be initialized once so only one of the two techniques should be used.\n \n A TrustKit pinning policy is a dictionary which contains some global, App-wide settings (of type `TSKGlobalConfigurationKey`) as well as domain-specific configuration keys (of type `TSKDomainConfigurationKey`) to be defined under the `kTSKPinnedDomains` entry. The following table shows the keys and the types of the corresponding values, and uses indentation to indicate structure:\n \n ```\n | Key                                          | Type       |\n |----------------------------------------------|------------|\n | TSKSwizzleNetworkDelegates                   | Boolean    |\n | TSKIgnorePinningForUserDefinedTrustAnchors   | Boolean    |\n | TSKPinnedDomains                             | Dictionary |\n | __ <domain-name-to-pin-as-string>            | Dictionary |\n | ____ TSKPublicKeyHashes                      | Array      |\n | ____ TSKPublicKeyAlgorithms                  | Array      |\n | ____ TSKIncludeSubdomains                    | Boolean    |\n | ____ TSKExcludeSubdomainFromParentPolicy     | Boolean    |\n | ____ TSKEnforcePinning                       | Boolean    |\n | ____ TSKReportUris                           | Array      |\n | ____ TSKDisableDefaultReportUri              | Boolean    |\n ```\n \n When setting the pinning policy programmatically, it has to be supplied to the `initializeWithConfiguration:` method as a dictionary. For example:\n \n ```\n    NSDictionary *trustKitConfig =\n  @{\n    kTSKSwizzleNetworkDelegates: @NO,\n    kTSKPinnedDomains : @{\n            @\"www.datatheorem.com\" : @{\n                    kTSKExpirationDate: @\"2017-12-01\",\n                    kTSKPublicKeyAlgorithms : @[kTSKAlgorithmRsa2048],\n                    kTSKPublicKeyHashes : @[\n                            @\"HXXQgxueCIU5TTLHob/bPbwcKOKw6DkfsTWYHbxbqTY=\",\n                            @\"0SDf3cRToyZJaMsoS17oF72VMavLxj/N7WBNasNuiR8=\"\n                            ],\n                    kTSKEnforcePinning : @NO,\n                    kTSKReportUris : @[@\"http://report.datatheorem.com/log_report\"],\n                    },\n            @\"yahoo.com\" : @{\n                    kTSKPublicKeyAlgorithms : @[kTSKAlgorithmRsa4096],\n                    kTSKPublicKeyHashes : @[\n                            @\"TQEtdMbmwFgYUifM4LDF+xgEtd0z69mPGmkp014d6ZY=\",\n                            @\"rFjc3wG7lTZe43zeYTvPq8k4xdDEutCmIhI5dn4oCeE=\",\n                            ],\n                    kTSKIncludeSubdomains : @YES\n                    }\n            }};\n    \n    [TrustKit initializeWithConfiguration:trustKitConfig];\n ```\n \n Similarly, TrustKit can be initialized in Swift:\n \n ```\n        let trustKitConfig = [\n            kTSKSwizzleNetworkDelegates: false,\n            kTSKPinnedDomains: [\n                \"yahoo.com\": [\n                    kTSKExpirationDate: \"2017-12-01\",\n                    kTSKPublicKeyAlgorithms: [kTSKAlgorithmRsa2048],\n                    kTSKPublicKeyHashes: [\n                        \"JbQbUG5JMJUoI6brnx0x3vZF6jilxsapbXGVfjhN8Fg=\",\n                        \"WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=\"\n                    ],]]] as [String : Any]\n        \n        TrustKit.initialize(withConfiguration:trustKitConfig)\n ```\n \n The various configuration keys that can be specified in the policy are described in the \"Constants\" section of the documentation.\n \n Lastly, once TrustKit has been initialized, `kTSKValidationCompletedNotification` notifications will be posted every time TrustKit validates the certificate chain of a server; these notifications provide some information about the validation that was done and can be used for example for performance measurement.\n \n */\n@interface TrustKit : NSObject\n\n///---------------------\n/// @name Initialization\n///---------------------\n\n/**\n Initialize the global SSL pinning policy with the supplied configuration.\n \n This method should be called as early as possible in the App's lifecycle to ensure that the App's very first SSL connections are validated by TrustKit. Once TrustKit has been initialized, notifications will be posted for any SSL pinning validation performed.\n \n @param trustKitConfig A dictionary containing various keys for configuring the global SSL pinning policy.\n @exception NSException Thrown when the supplied configuration is invalid or TrustKit has already been initialized.\n \n */\n+ (void) initializeWithConfiguration:(NSDictionary *)trustKitConfig;\n\n\n///----------------------------\n/// @name Current Configuration\n///----------------------------\n\n/**\n Retrieve a copy of the global SSL pinning policy.\n \n @return A dictionary with a copy of the current TrustKit configuration, or `nil` if TrustKit has not been initialized.\n */\n+ (nullable NSDictionary *) configuration;\n\n/**\n Set the global logger.\n \n This method sets the global logger, used when TrustKit needs to display a message to the developer. \n \n If a global logger is not set, the default logger will be used, which will print TrustKit log messages (using `NSLog()`) when the App is built in Debug mode. If the App was built for Release, the default logger will not print any messages at all.\n */\n+ (void)setLoggerBlock:(void (^)(NSString *))block;\n\n@end\nNS_ASSUME_NONNULL_END\n"
  },
  {
    "path": "TrustKit/TrustKit.m",
    "content": "/*\n \n TrustKit.m\n TrustKit\n \n Copyright 2015 The TrustKit Project Authors\n Licensed under the MIT license, see associated LICENSE file for terms.\n See AUTHORS file for the list of project authors.\n \n */\n\n#import \"TrustKit+Private.h\"\n#import \"Pinning/public_key_utils.h\"\n#import \"Reporting/TSKBackgroundReporter.h\"\n#import \"Swizzling/TSKNSURLConnectionDelegateProxy.h\"\n#import \"Swizzling/TSKNSURLSessionDelegateProxy.h\"\n#import \"parse_configuration.h\"\n#import \"Reporting/reporting_utils.h\"\n\n\nNSString * const TrustKitVersion = @\"1.4.2\";\n\n#pragma mark Configuration Constants\n\n// Info.plist key we read the public key hashes from\nstatic const NSString *kTSKConfiguration = @\"TSKConfiguration\";\n\n// General keys\nconst TSKGlobalConfigurationKey kTSKSwizzleNetworkDelegates = @\"TSKSwizzleNetworkDelegates\";\nconst TSKGlobalConfigurationKey kTSKPinnedDomains = @\"TSKPinnedDomains\";\n\nconst TSKGlobalConfigurationKey kTSKIgnorePinningForUserDefinedTrustAnchors = @\"TSKIgnorePinningForUserDefinedTrustAnchors\";\n\n// Keys for each domain within the TSKPinnedDomains entry\nconst TSKDomainConfigurationKey kTSKPublicKeyHashes = @\"TSKPublicKeyHashes\";\nconst TSKDomainConfigurationKey kTSKEnforcePinning = @\"TSKEnforcePinning\";\nconst TSKDomainConfigurationKey kTSKExcludeSubdomainFromParentPolicy = @\"kSKExcludeSubdomainFromParentPolicy\";\n\nconst TSKDomainConfigurationKey kTSKIncludeSubdomains = @\"TSKIncludeSubdomains\";\nconst TSKDomainConfigurationKey kTSKPublicKeyAlgorithms = @\"TSKPublicKeyAlgorithms\";\nconst TSKDomainConfigurationKey kTSKReportUris = @\"TSKReportUris\";\nconst TSKDomainConfigurationKey kTSKDisableDefaultReportUri = @\"TSKDisableDefaultReportUri\";\nconst TSKDomainConfigurationKey kTSKExpirationDate = @\"TSKExpirationDate\";\n\n#pragma mark Public key Algorithms Constants\nconst TSKSupportedAlgorithm kTSKAlgorithmRsa2048 = @\"TSKAlgorithmRsa2048\";\nconst TSKSupportedAlgorithm kTSKAlgorithmRsa4096 = @\"TSKAlgorithmRsa4096\";\nconst TSKSupportedAlgorithm kTSKAlgorithmEcDsaSecp256r1 = @\"TSKAlgorithmEcDsaSecp256r1\";\nconst TSKSupportedAlgorithm kTSKAlgorithmEcDsaSecp384r1 = @\"TSKAlgorithmEcDsaSecp384r1\";\n\n#pragma mark Notification keys\nNSString *kTSKValidationCompletedNotification   = @\"TSKValidationCompletedNotification\";\n\nconst TSKNotificationUserInfoKey kTSKValidationDurationNotificationKey = @\"TSKValidationDurationNotificationKey\";\nconst TSKNotificationUserInfoKey kTSKValidationResultNotificationKey   = @\"TSKValidationResultNotificationKey\";\nconst TSKNotificationUserInfoKey kTSKValidationDecisionNotificationKey = @\"TSKValidationDecisionNotificationKey\";\nconst TSKNotificationUserInfoKey kTSKValidationCertificateChainNotificationKey = @\"TSKValidationCertificateChainNotificationKey\";\nconst TSKNotificationUserInfoKey kTSKValidationNotedHostnameNotificationKey = @\"TSKValidationNotedHostnameNotificationKey\";\nconst TSKNotificationUserInfoKey kTSKValidationServerHostnameNotificationKey = @\"TSKValidationServerHostnameNotificationKey\";\n\n\n#pragma mark TrustKit Global State\n// Global dictionary for storing the public key hashes and domains\nstatic NSDictionary *_trustKitGlobalConfiguration = nil;\n\n// Global preventing multiple initializations (double method swizzling, etc.)\nstatic BOOL _isTrustKitInitialized = NO;\nstatic dispatch_once_t dispatchOnceTrustKitInit;\n\n// Reporter for sending pin violation reports\nstatic TSKBackgroundReporter *_pinFailureReporter = nil;\nstatic char kTSKPinFailureReporterQueueLabel[] = \"com.datatheorem.trustkit.reporterqueue\";\nstatic dispatch_queue_t _pinFailureReporterQueue = NULL;\nstatic id _pinValidationObserver = nil;\n\n\n// Default report URI - can be disabled with TSKDisableDefaultReportUri\n// Email info@datatheorem.com if you need a free dashboard to see your App's reports\nstatic NSString * const kTSKDefaultReportUri = @\"https://overmind.datatheorem.com/trustkit/report\";\n\n\n#pragma mark Default Logging Block\n\n// Default logger block: only log in debug builds and add TrustKit at the beginning of the line\nvoid (^_loggerBlock)(NSString *) = ^void(NSString *message)\n{\n#if DEBUG\n    NSLog(@\"=== TrustKit: %@\", message);\n#endif\n};\n\n\n// The logging function we use within TrustKit\nvoid TSKLog(NSString *format, ...)\n{\n    va_list args;\n    va_start(args, format);\n    NSString *message = [[NSString alloc] initWithFormat: format arguments:args];\n    va_end(args);\n    _loggerBlock(message);\n}\n\n\n#pragma mark Helper Function to Send Notifications and Reports\n\n// Send a notification and release the serverTrust\nvoid sendValidationNotification_async(NSString *serverHostname, SecTrustRef serverTrust, NSString *notedHostname, TSKPinValidationResult validationResult, TSKTrustDecision finalTrustDecision, NSTimeInterval validationDuration)\n{\n    // Convert the server trust to a certificate chain\n    // This cannot be done in the dispatch_async() block as sometimes the serverTrust seems to become invalid once the block gets scheduled, even tho its retain count is still positive\n    CFRetain(serverTrust);\n    NSArray *certificateChain = convertTrustToPemArray(serverTrust);\n    CFRelease(serverTrust);\n    \n    // Send the notification to consumers that want to get notified about all validations performed\n    // We use the _pinFailureReporterQueue so our receving block sendReportFromNotificationBlock gets executed on this queue as well\n    dispatch_async(_pinFailureReporterQueue, ^(void)\n                   {\n                       [[NSNotificationCenter defaultCenter] postNotificationName:kTSKValidationCompletedNotification\n                                                                           object:nil\n                                                                         userInfo:@{kTSKValidationDurationNotificationKey: @(validationDuration),\n                                                                                    kTSKValidationDecisionNotificationKey: @(finalTrustDecision),\n                                                                                    kTSKValidationResultNotificationKey: @(validationResult),\n                                                                                    kTSKValidationCertificateChainNotificationKey: certificateChain,\n                                                                                    kTSKValidationNotedHostnameNotificationKey: notedHostname,\n                                                                                    kTSKValidationServerHostnameNotificationKey: serverHostname}];\n                   });\n}\n\n\n// The block which receives pin validation notification and turns them into pin validation reports\nstatic void (^sendReportFromNotificationBlock)(NSNotification *note) = ^void(NSNotification *note)\n{\n    NSDictionary *userInfo = [note userInfo];\n    TSKPinValidationResult validationResult = [userInfo[kTSKValidationResultNotificationKey] integerValue];\n    \n    // Send a report only if the there was a pinning failure\n    if (validationResult != TSKPinValidationResultSuccess)\n    {\n#if !TARGET_OS_IPHONE\n        if (validationResult != TSKPinValidationResultFailedUserDefinedTrustAnchor)\n#endif\n        {\n            NSString *notedHostname = userInfo[kTSKValidationNotedHostnameNotificationKey];\n            NSDictionary *notedHostnameConfig = _trustKitGlobalConfiguration[kTSKPinnedDomains][notedHostname];\n            \n            // Pin validation failed: retrieve the list of configured report URLs\n            NSMutableArray *reportUris = [NSMutableArray arrayWithArray:notedHostnameConfig[kTSKReportUris]];\n            \n            // Also enable the default reporting URL\n            if ([notedHostnameConfig[kTSKDisableDefaultReportUri] boolValue] == NO)\n            {\n                [reportUris addObject:[NSURL URLWithString:kTSKDefaultReportUri]];\n            }\n            \n            // If some report URLs have been defined, send the pin failure report\n            if ((reportUris != nil) && ([reportUris count] > 0))\n            {\n                [_pinFailureReporter pinValidationFailedForHostname:userInfo[kTSKValidationServerHostnameNotificationKey]\n                                                               port:nil\n                                                   certificateChain:userInfo[kTSKValidationCertificateChainNotificationKey]\n                                                      notedHostname:notedHostname\n                                                         reportURIs:reportUris\n                                                  includeSubdomains:[notedHostnameConfig[kTSKIncludeSubdomains] boolValue]\n                                                     enforcePinning:[notedHostnameConfig[kTSKEnforcePinning] boolValue]\n                                                          knownPins:notedHostnameConfig[kTSKPublicKeyHashes]\n                                                   validationResult:validationResult\n                                                     expirationDate:notedHostnameConfig[kTSKExpirationDate]];\n            }\n        }\n    }\n};\n\n\n#pragma mark TrustKit Initialization Helper Functions\n\nstatic void initializeTrustKit(NSDictionary *trustKitConfig)\n{\n    if (trustKitConfig == nil)\n    {\n        return;\n    }\n    \n    if (_isTrustKitInitialized == YES)\n    {\n        // TrustKit should only be initialized once so we don't double interpose SecureTransport or get into anything unexpected\n        [NSException raise:@\"TrustKit already initialized\"\n                    format:@\"TrustKit was already initialized with the following SSL pins: %@\", _trustKitGlobalConfiguration];\n    }\n    \n    if ([trustKitConfig count] > 0)\n    {\n        initializeSubjectPublicKeyInfoCache();\n        \n        // Convert and store the SSL pins in our global variable\n        _trustKitGlobalConfiguration = [[NSDictionary alloc]initWithDictionary:parseTrustKitConfiguration(trustKitConfig)];\n        \n        \n        // We use dispatch_once() here only so that unit tests don't reset the reporter\n        // or the swizzling logic when calling [TrustKit resetConfiguration]\n        dispatch_once(&dispatchOnceTrustKitInit, ^{\n            // Create our reporter for sending pin validation failures; do this before hooking NSURLSession so we don't hook ourselves\n            _pinFailureReporter = [[TSKBackgroundReporter alloc]initAndRateLimitReports:YES];\n            \n            \n            // Create a dispatch queue for activating the reporter\n            // We use a serial queue targetting the global default queue in order to ensure reports are sent one by one\n            // even when a lot of pin failures are occuring, instead of spamming the global queue with events to process\n            _pinFailureReporterQueue = dispatch_queue_create(kTSKPinFailureReporterQueueLabel, DISPATCH_QUEUE_SERIAL);\n            dispatch_set_target_queue(_pinFailureReporterQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));\n            \n            \n            // Register for pinning notifications in order to trigger reports\n            // Nil queue to run the block on the _pinFailureReporterQueue (where the notification is posted from)\n            _pinValidationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kTSKValidationCompletedNotification\n                                                                              object:nil\n                                                                               queue:nil\n                                                                          usingBlock:sendReportFromNotificationBlock];\n            \n            // Hook network APIs if needed\n            if ([_trustKitGlobalConfiguration[kTSKSwizzleNetworkDelegates] boolValue] == YES)\n            {\n                // NSURLConnection\n                [TSKNSURLConnectionDelegateProxy swizzleNSURLConnectionConstructors];\n                \n                // NSURLSession\n                [TSKNSURLSessionDelegateProxy swizzleNSURLSessionConstructors];\n            }\n        });\n        \n        // All done\n        _isTrustKitInitialized = YES;\n        TSKLog(@\"Successfully initialized with configuration %@\", _trustKitGlobalConfiguration);\n    }\n}\n\n\n@implementation TrustKit\n\n\n#pragma mark TrustKit Explicit Initialization\n\n+ (void) initializeWithConfiguration:(NSDictionary *)trustKitConfig\n{\n    TSKLog(@\"Configuration passed via explicit call to initializeWithConfiguration:\");\n    initializeTrustKit(trustKitConfig);\n}\n\n+ (void)setLoggerBlock:(void (^)(NSString *))block\n{\n    _loggerBlock = block;\n}\n\n\n# pragma mark Private / Test Methods\n\n+ (NSDictionary *) configuration\n{\n    return [_trustKitGlobalConfiguration copy];\n}\n\n\n+ (BOOL) wasTrustKitInitialized\n{\n    return _isTrustKitInitialized;\n}\n\n\n+ (void) resetConfiguration\n{\n    // Reset is only available/used for tests\n    resetSubjectPublicKeyInfoCache();\n    _trustKitGlobalConfiguration = nil;\n    _isTrustKitInitialized = NO;\n}\n\n\n+ (NSString *) getDefaultReportUri\n{\n    return kTSKDefaultReportUri;\n}\n\n\n+ (TSKBackgroundReporter *) getGlobalPinFailureReporter\n{\n    return _pinFailureReporter;\n}\n\n\n+ (void) setGlobalPinFailureReporter:(TSKBackgroundReporter *) reporter\n{\n    _pinFailureReporter = reporter;\n}\n\n@end\n\n\n#pragma mark TrustKit Implicit Initialization via Library Constructor\n\n// TRUSTKIT_SKIP_LIB_INITIALIZATION define allows consumers to opt out of the dylib constructor.\n// This might be useful to mitigate integration risks, if the consumer doens't wish to use\n// plist file, and wants to initialize lib manually later on.\n#ifndef TRUSTKIT_SKIP_LIB_INITIALIZATION\n\n__attribute__((constructor)) static void initializeWithInfoPlist(int argc, const char **argv)\n{\n    // TrustKit just got started in the App\n    CFBundleRef appBundle = CFBundleGetMainBundle();\n    \n    // Retrieve the configuration from the App's Info.plist file\n    NSDictionary *trustKitConfigFromInfoPlist = (__bridge NSDictionary *)CFBundleGetValueForInfoDictionaryKey(appBundle, (__bridge CFStringRef)kTSKConfiguration);\n    if (trustKitConfigFromInfoPlist)\n    {\n        TSKLog(@\"Configuration supplied via the App's Info.plist\");\n        initializeTrustKit(trustKitConfigFromInfoPlist);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "TrustKit/configuration_utils.h",
    "content": "//\n//  configuration_utils.h\n//  TrustKit\n//\n//  Created by Alban Diquet on 2/20/17.\n//  Copyright © 2017 TrustKit. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\nNSString *getPinningConfigurationKeyForDomain(NSString *hostname, NSDictionary *trustKitConfiguration);\n"
  },
  {
    "path": "TrustKit/configuration_utils.m",
    "content": "//\n//  configuration_utils.m\n//  TrustKit\n//\n//  Created by Alban Diquet on 2/20/17.\n//  Copyright © 2017 TrustKit. All rights reserved.\n//\n\n#import \"configuration_utils.h\"\n#import \"Dependencies/domain_registry/domain_registry.h\"\n#import \"TrustKit+Private.h\"\n\n\nstatic BOOL isSubdomain(NSString *domain, NSString *subdomain)\n{\n    size_t domainRegistryLength = GetRegistryLength([domain UTF8String]);\n    if (GetRegistryLength([subdomain UTF8String]) != domainRegistryLength)\n    {\n        // Different TLDs\n        return NO;\n    }\n    \n    // Retrieve the main domain without the TLD\n    // When initializing TrustKit, we check that [domain length] > domainRegistryLength\n    NSString *domainLabel = [domain substringToIndex:([domain length] - domainRegistryLength - 1)];\n    \n    // Retrieve the subdomain's domain without the TLD\n    NSString *subdomainLabel = [subdomain substringToIndex:([subdomain length] - domainRegistryLength - 1)];\n    \n    // Does the subdomain contain the domain\n    NSArray *subComponents = [subdomainLabel componentsSeparatedByString:domainLabel];\n    if ([[subComponents lastObject] isEqualToString:@\"\"])\n    {\n        // This is a subdomain\n        return YES;\n    }\n    return NO;\n}\n\n\nNSString *getPinningConfigurationKeyForDomain(NSString *hostname, NSDictionary *trustKitConfiguration)\n{\n    NSString *configHostname = nil;\n    NSDictionary *domainsPinningPolicy = trustKitConfiguration[kTSKPinnedDomains];\n    \n    if (domainsPinningPolicy[hostname] == nil)\n    {\n        // No pins explicitly configured for this domain\n        // Look for an includeSubdomain pin that applies\n        for (NSString *pinnedServerName in domainsPinningPolicy)\n        {\n            // Check each domain configured with the includeSubdomain flag\n            if ([domainsPinningPolicy[pinnedServerName][kTSKIncludeSubdomains] boolValue])\n            {\n                // Is the server a subdomain of this pinned server?\n                TSKLog(@\"Checking includeSubdomains configuration for %@\", pinnedServerName);\n                if (isSubdomain(pinnedServerName, hostname))\n                {\n                    // Yes; let's use the parent domain's pinning configuration\n                    TSKLog(@\"Applying includeSubdomains configuration from %@ to %@\", pinnedServerName, hostname);\n                    configHostname = pinnedServerName;\n                    break;\n                }\n            }\n        }\n    }\n    else\n    {\n        // This hostname has a pinnning configuration\n        configHostname = hostname;\n    }\n    \n    if (configHostname == nil)\n    {\n        TSKLog(@\"Domain %@ is not pinned\", hostname);\n    }\n    return configHostname;\n}\n"
  },
  {
    "path": "TrustKit/module.modulemap",
    "content": "framework module TrustKit {\n    umbrella header \"TrustKit.h\" \n    \n    export *\n    module * { export * }\n}\n"
  },
  {
    "path": "TrustKit/parse_configuration.h",
    "content": "//\n//  parse_configuration.h\n//  TrustKit\n//\n//  Created by Alban Diquet on 5/20/16.\n//  Copyright © 2016 TrustKit. All rights reserved.\n//\n\n#ifndef parse_configuration_h\n#define parse_configuration_h\n\nNSDictionary *parseTrustKitConfiguration(NSDictionary *TrustKitArguments);\n\n#endif /* parse_configuration_h */\n"
  },
  {
    "path": "TrustKit/parse_configuration.m",
    "content": "//\n//  parse_configuration.m\n//  TrustKit\n//\n//  Created by Alban Diquet on 5/20/16.\n//  Copyright © 2016 TrustKit. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"TrustKit.h\"\n#import \"Dependencies/domain_registry/domain_registry.h\"\n#import \"parse_configuration.h\"\n#import \"Pinning/public_key_utils.h\"\n#import <CommonCrypto/CommonDigest.h>\n#import \"configuration_utils.h\"\n\n\nNSDictionary *parseTrustKitConfiguration(NSDictionary *TrustKitArguments)\n{\n    // Convert settings supplied by the user to a configuration dictionary that can be used by TrustKit\n    // This includes checking the sanity of the settings and converting public key hashes/pins from an\n    // NSSArray of NSStrings (as provided by the user) to an NSSet of NSData (as needed by TrustKit)\n    \n    // Initialize domain registry library\n    InitializeDomainRegistry();\n    \n    NSMutableDictionary *finalConfiguration = [[NSMutableDictionary alloc]init];\n    finalConfiguration[kTSKPinnedDomains] = [[NSMutableDictionary alloc]init];\n    \n    \n    // Retrieve global settings\n    \n    // Should we auto-swizzle network delegates\n    NSNumber *shouldSwizzleNetworkDelegates = TrustKitArguments[kTSKSwizzleNetworkDelegates];\n    if (shouldSwizzleNetworkDelegates == nil)\n    {\n        // This is a required argument\n        [NSException raise:@\"TrustKit configuration invalid\"\n                    format:@\"TrustKit was initialized without specifying the kTSKSwizzleNetworkDelegates setting. Please add this boolean entry to the root of your TrustKit configuration in order to specify if auto-swizzling of the App's connection delegates should be enabled or not; see the documentation for more information.\"];\n        // Default setting is YES\n        finalConfiguration[kTSKSwizzleNetworkDelegates] = @(YES);\n    }\n    else\n    {\n        finalConfiguration[kTSKSwizzleNetworkDelegates] = shouldSwizzleNetworkDelegates;\n    }\n    \n    \n#if !TARGET_OS_IPHONE\n    // OS X only: extract the optional ignorePinningForUserDefinedTrustAnchors setting\n    NSNumber *shouldIgnorePinningForUserDefinedTrustAnchors = TrustKitArguments[kTSKIgnorePinningForUserDefinedTrustAnchors];\n    if (shouldIgnorePinningForUserDefinedTrustAnchors == nil)\n    {\n        // Default setting is YES\n        finalConfiguration[kTSKIgnorePinningForUserDefinedTrustAnchors] = @(YES);\n    }\n    else\n    {\n        finalConfiguration[kTSKIgnorePinningForUserDefinedTrustAnchors] = shouldIgnorePinningForUserDefinedTrustAnchors;\n    }\n#endif\n    \n    // Retrieve the pinning policy for each domains\n    if ((TrustKitArguments[kTSKPinnedDomains] == nil) || ([TrustKitArguments[kTSKPinnedDomains] count] < 1))\n    {\n        [NSException raise:@\"TrustKit configuration invalid\"\n                    format:@\"TrustKit was initialized with no pinned domains. The configuration format has changed: ensure your domain pinning policies are under the TSKPinnedDomains key within TSKConfiguration.\"];\n    }\n    \n    \n    for (NSString *domainName in TrustKitArguments[kTSKPinnedDomains])\n    {\n        // Sanity checks on the domain name\n        if (GetRegistryLength([domainName UTF8String]) == 0)\n        {\n            [NSException raise:@\"TrustKit configuration invalid\"\n                        format:@\"TrustKit was initialized with an invalid domain %@\", domainName];\n        }\n        \n        \n        // Retrieve the supplied arguments for this domain\n        NSDictionary *domainPinningPolicy = TrustKitArguments[kTSKPinnedDomains][domainName];\n        NSMutableDictionary *domainFinalConfiguration = [[NSMutableDictionary alloc]init];\n        \n        \n        // Always start with the optional excludeSubDomain setting; if it set, no other TSKDomainConfigurationKey can be set for this domain\n        NSNumber *shouldExcludeSubdomain = domainPinningPolicy[kTSKExcludeSubdomainFromParentPolicy];\n        if (shouldExcludeSubdomain)\n        {\n            // Confirm that no other TSKDomainConfigurationKeys were set for this domain\n            if ([[domainPinningPolicy allKeys] count] > 1)\n            {\n                [NSException raise:@\"TrustKit configuration invalid\"\n                            format:@\"TrustKit was initialized with TSKExcludeSubdomainFromParentPolicy for domain %@ but detected additional configuration keys\", domainName];\n            }\n            \n            // Store the whole configuration and continue to the next domain entry\n            domainFinalConfiguration[kTSKExcludeSubdomainFromParentPolicy] = @(YES);\n            finalConfiguration[kTSKPinnedDomains][domainName] = [NSDictionary dictionaryWithDictionary:domainFinalConfiguration];\n            continue;\n        }\n        else\n        {\n            // Default setting is NO\n            domainFinalConfiguration[kTSKExcludeSubdomainFromParentPolicy] = @(NO);\n        }\n        \n        \n        // Extract the optional includeSubdomains setting\n        NSNumber *shouldIncludeSubdomains = domainPinningPolicy[kTSKIncludeSubdomains];\n        if (shouldIncludeSubdomains == nil)\n        {\n            // Default setting is NO\n            domainFinalConfiguration[kTSKIncludeSubdomains] = @(NO);\n        }\n        else\n        {\n            if ([shouldIncludeSubdomains boolValue] == YES)\n            {\n                // Prevent pinning on *.com\n                // Ran into this issue with *.appspot.com which is part of the public suffix list\n                if (GetRegistryLength([domainName UTF8String]) == [domainName length])\n                {\n                    [NSException raise:@\"TrustKit configuration invalid\"\n                                format:@\"TrustKit was initialized with includeSubdomains for a domain suffix %@\", domainName];\n                }\n            }\n            \n            domainFinalConfiguration[kTSKIncludeSubdomains] = shouldIncludeSubdomains;\n        }\n        \n        \n        // Extract the optional expiration date setting\n        NSString *expirationDateStr = domainPinningPolicy[kTSKExpirationDate];\n        if (expirationDateStr != nil)\n        {\n            // Convert the string in the yyyy-MM-dd format into an actual date\n            NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];\n            [dateFormat setDateFormat:@\"yyyy-MM-dd\"];\n            NSDate *expirationDate = [dateFormat dateFromString:expirationDateStr];\n            domainFinalConfiguration[kTSKExpirationDate] = expirationDate;\n        }\n        \n        \n        // Extract the optional enforcePinning setting\n        NSNumber *shouldEnforcePinning = domainPinningPolicy[kTSKEnforcePinning];\n        if (shouldEnforcePinning)\n        {\n            domainFinalConfiguration[kTSKEnforcePinning] = shouldEnforcePinning;\n        }\n        else\n        {\n            // Default setting is YES\n            domainFinalConfiguration[kTSKEnforcePinning] = @(YES);\n        }\n\n        \n        // Extract the optional disableDefaultReportUri setting\n        NSNumber *shouldDisableDefaultReportUri = domainPinningPolicy[kTSKDisableDefaultReportUri];\n        if (shouldDisableDefaultReportUri)\n        {\n            domainFinalConfiguration[kTSKDisableDefaultReportUri] = shouldDisableDefaultReportUri;\n        }\n        else\n        {\n            // Default setting is NO\n            domainFinalConfiguration[kTSKDisableDefaultReportUri] = @(NO);\n        }\n        \n        \n        // Extract the list of public key algorithms to support and convert them from string to the TSKPublicKeyAlgorithm type\n        NSArray<NSString *> *publicKeyAlgsStr = domainPinningPolicy[kTSKPublicKeyAlgorithms];\n        if (publicKeyAlgsStr == nil)\n        {\n            [NSException raise:@\"TrustKit configuration invalid\"\n                        format:@\"TrustKit was initialized with an invalid value for %@ for domain %@\", kTSKPublicKeyAlgorithms, domainName];\n        }\n        NSMutableArray *publicKeyAlgs = [NSMutableArray array];\n        for (NSString *algorithm in publicKeyAlgsStr)\n        {\n            if ([kTSKAlgorithmRsa2048 isEqualToString:algorithm])\n            {\n                [publicKeyAlgs addObject:@(TSKPublicKeyAlgorithmRsa2048)];\n            }\n            else if ([kTSKAlgorithmRsa4096 isEqualToString:algorithm])\n            {\n                [publicKeyAlgs addObject:@(TSKPublicKeyAlgorithmRsa4096)];\n            }\n            else if ([kTSKAlgorithmEcDsaSecp256r1 isEqualToString:algorithm])\n            {\n                [publicKeyAlgs addObject:@(TSKPublicKeyAlgorithmEcDsaSecp256r1)];\n            }\n            else if ([kTSKAlgorithmEcDsaSecp384r1 isEqualToString:algorithm])\n            {\n                [publicKeyAlgs addObject:@(TSKPublicKeyAlgorithmEcDsaSecp384r1)];\n            }\n            else\n            {\n                [NSException raise:@\"TrustKit configuration invalid\"\n                            format:@\"TrustKit was initialized with an invalid value for %@ for domain %@\", kTSKPublicKeyAlgorithms, domainName];\n            }\n        }\n        domainFinalConfiguration[kTSKPublicKeyAlgorithms] = [NSArray arrayWithArray:publicKeyAlgs];\n        \n        \n        // Extract and convert the report URIs if defined\n        NSArray<NSString *> *reportUriList = domainPinningPolicy[kTSKReportUris];\n        if (reportUriList != nil)\n        {\n            NSMutableArray<NSURL *> *reportUriListFinal = [NSMutableArray array];\n            for (NSString *reportUriStr in reportUriList)\n            {\n                NSURL *reportUri = [NSURL URLWithString:reportUriStr];\n                if (reportUri == nil)\n                {\n                    [NSException raise:@\"TrustKit configuration invalid\"\n                                format:@\"TrustKit was initialized with an invalid value for %@ for domain %@\", kTSKReportUris, domainName];\n                }\n                [reportUriListFinal addObject:reportUri];\n            }\n            \n            domainFinalConfiguration[kTSKReportUris] = [NSArray arrayWithArray:reportUriListFinal];\n        }\n        \n        \n        // Extract and convert the subject public key info hashes\n        NSArray<NSString *> *serverSslPinsBase64 = domainPinningPolicy[kTSKPublicKeyHashes];\n        NSMutableSet<NSData *> *serverSslPinsSet = [NSMutableSet set];\n        \n        for (NSString *pinnedKeyHashBase64 in serverSslPinsBase64) {\n            NSData *pinnedKeyHash = [[NSData alloc] initWithBase64EncodedString:pinnedKeyHashBase64 options:(NSDataBase64DecodingOptions)0];\n            \n            if ([pinnedKeyHash length] != CC_SHA256_DIGEST_LENGTH)\n            {\n                // The subject public key info hash doesn't have a valid size\n                [NSException raise:@\"TrustKit configuration invalid\"\n                            format:@\"TrustKit was initialized with an invalid Pin %@ for domain %@\", pinnedKeyHashBase64, domainName];\n            }\n            \n            [serverSslPinsSet addObject:pinnedKeyHash];\n        }\n        \n        \n        NSUInteger requiredNumberOfPins = [domainFinalConfiguration[kTSKEnforcePinning] boolValue] ? 2 : 1;\n        if([serverSslPinsSet count] < requiredNumberOfPins)\n        {\n            [NSException raise:@\"TrustKit configuration invalid\"\n                        format:@\"TrustKit was initialized with less than %lu pins (ie. no backup pins) for domain %@. This might brick your App; please review the Getting Started guide in ./docs/getting-started.md\", (unsigned long)requiredNumberOfPins, domainName];\n        }\n        \n        // Save the hashes for this server as an NSSet for quick lookup\n        domainFinalConfiguration[kTSKPublicKeyHashes] = [NSSet setWithSet:serverSslPinsSet];\n        \n        // Store the whole configuration\n        finalConfiguration[kTSKPinnedDomains][domainName] = [NSDictionary dictionaryWithDictionary:domainFinalConfiguration];\n    }\n    \n    \n    // Lastly, ensure that we can find a parent policy for subdomains configured with TSKExcludeSubdomainFromParentPolicy\n    for (NSString *domainName in finalConfiguration[kTSKPinnedDomains])\n    {\n        if ([finalConfiguration[kTSKPinnedDomains][domainName][kTSKExcludeSubdomainFromParentPolicy] boolValue])\n        {\n            // To force the lookup of a parent domain, we append 'a' to this subdomain so we don't retrieve its policy\n            NSString *parentDomainConfigKey = getPinningConfigurationKeyForDomain([@\"a\" stringByAppendingString:domainName], finalConfiguration);\n            if (parentDomainConfigKey == nil)\n            {\n                [NSException raise:@\"TrustKit configuration invalid\"\n                            format:@\"TrustKit was initialized with TSKExcludeSubdomainFromParentPolicy for domain %@ but could not find a policy for a parent domain\", domainName];\n            }\n        }\n    }\n\n    return finalConfiguration;\n}\n\n\n"
  },
  {
    "path": "UITests/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>$(PRODUCT_BUNDLE_IDENTIFIER)</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>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>VERSION_STRING</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>GIT_VERSION</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "UITests/SnapshotHelper.swift",
    "content": "//\n//  SnapshotHelper.swift\n//  Example\n//\n//  Created by Felix Krause on 10/8/15.\n//\n\n// -----------------------------------------------------\n// IMPORTANT: When modifying this file, make sure to\n//            increment the version number at the very\n//            bottom of the file to notify users about\n//            the new SnapshotHelper.swift\n// -----------------------------------------------------\n\nimport Foundation\nimport XCTest\n\nvar deviceLanguage = \"\"\nvar locale = \"\"\n\nfunc setupSnapshot(_ app: XCUIApplication, waitForAnimations: Bool = true) {\n    Snapshot.setupSnapshot(app, waitForAnimations: waitForAnimations)\n}\n\nfunc snapshot(_ name: String, waitForLoadingIndicator: Bool) {\n    if waitForLoadingIndicator {\n        Snapshot.snapshot(name)\n    } else {\n        Snapshot.snapshot(name, timeWaitingForIdle: 0)\n    }\n}\n\n/// - Parameters:\n///   - name: The name of the snapshot\n///   - timeout: Amount of seconds to wait until the network loading indicator disappears. Pass `0` if you don't want to wait.\nfunc snapshot(_ name: String, timeWaitingForIdle timeout: TimeInterval = 20) {\n    Snapshot.snapshot(name, timeWaitingForIdle: timeout)\n}\n\nenum SnapshotError: Error, CustomDebugStringConvertible {\n    case cannotFindSimulatorHomeDirectory\n    case cannotRunOnPhysicalDevice\n\n    var debugDescription: String {\n        switch self {\n        case .cannotFindSimulatorHomeDirectory:\n            return \"Couldn't find simulator home location. Please, check SIMULATOR_HOST_HOME env variable.\"\n        case .cannotRunOnPhysicalDevice:\n            return \"Can't use Snapshot on a physical device.\"\n        }\n    }\n}\n\n@objcMembers\nopen class Snapshot: NSObject {\n    static var app: XCUIApplication?\n    static var waitForAnimations = true\n    static var cacheDirectory: URL?\n    static var screenshotsDirectory: URL? {\n        return cacheDirectory?.appendingPathComponent(\"screenshots\", isDirectory: true)\n    }\n\n    open class func setupSnapshot(_ app: XCUIApplication, waitForAnimations: Bool = true) {\n\n        Snapshot.app = app\n        Snapshot.waitForAnimations = waitForAnimations\n\n        do {\n            let cacheDir = try getCacheDirectory()\n            Snapshot.cacheDirectory = cacheDir\n            setLanguage(app)\n            setLocale(app)\n            setLaunchArguments(app)\n        } catch let error {\n            NSLog(error.localizedDescription)\n        }\n    }\n\n    class func setLanguage(_ app: XCUIApplication) {\n        guard let cacheDirectory = self.cacheDirectory else {\n            NSLog(\"CacheDirectory is not set - probably running on a physical device?\")\n            return\n        }\n\n        let path = cacheDirectory.appendingPathComponent(\"language.txt\")\n\n        do {\n            let trimCharacterSet = CharacterSet.whitespacesAndNewlines\n            deviceLanguage = try String(contentsOf: path, encoding: .utf8).trimmingCharacters(in: trimCharacterSet)\n            app.launchArguments += [\"-AppleLanguages\", \"(\\(deviceLanguage))\"]\n        } catch {\n            NSLog(\"Couldn't detect/set language...\")\n        }\n    }\n\n    class func setLocale(_ app: XCUIApplication) {\n        guard let cacheDirectory = self.cacheDirectory else {\n            NSLog(\"CacheDirectory is not set - probably running on a physical device?\")\n            return\n        }\n\n        let path = cacheDirectory.appendingPathComponent(\"locale.txt\")\n\n        do {\n            let trimCharacterSet = CharacterSet.whitespacesAndNewlines\n            locale = try String(contentsOf: path, encoding: .utf8).trimmingCharacters(in: trimCharacterSet)\n        } catch {\n            NSLog(\"Couldn't detect/set locale...\")\n        }\n\n        if locale.isEmpty && !deviceLanguage.isEmpty {\n            locale = Locale(identifier: deviceLanguage).identifier\n        }\n\n        if !locale.isEmpty {\n            app.launchArguments += [\"-AppleLocale\", \"\\\"\\(locale)\\\"\"]\n        }\n    }\n\n    class func setLaunchArguments(_ app: XCUIApplication) {\n        guard let cacheDirectory = self.cacheDirectory else {\n            NSLog(\"CacheDirectory is not set - probably running on a physical device?\")\n            return\n        }\n\n        let path = cacheDirectory.appendingPathComponent(\"snapshot-launch_arguments.txt\")\n        app.launchArguments += [\"-FASTLANE_SNAPSHOT\", \"YES\", \"-ui_testing\"]\n\n        do {\n            let launchArguments = try String(contentsOf: path, encoding: String.Encoding.utf8)\n            let regex = try NSRegularExpression(pattern: \"(\\\\\\\".+?\\\\\\\"|\\\\S+)\", options: [])\n            let matches = regex.matches(in: launchArguments, options: [], range: NSRange(location: 0, length: launchArguments.count))\n            let results = matches.map { result -> String in\n                (launchArguments as NSString).substring(with: result.range)\n            }\n            app.launchArguments += results\n        } catch {\n            NSLog(\"Couldn't detect/set launch_arguments...\")\n        }\n    }\n\n    open class func snapshot(_ name: String, timeWaitingForIdle timeout: TimeInterval = 20) {\n        if timeout > 0 {\n            waitForLoadingIndicatorToDisappear(within: timeout)\n        }\n\n        NSLog(\"snapshot: \\(name)\") // more information about this, check out https://docs.fastlane.tools/actions/snapshot/#how-does-it-work\n\n        if Snapshot.waitForAnimations {\n            sleep(1) // Waiting for the animation to be finished (kind of)\n        }\n\n        #if os(OSX)\n            guard let app = self.app else {\n                NSLog(\"XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().\")\n                return\n            }\n\n            app.typeKey(XCUIKeyboardKeySecondaryFn, modifierFlags: [])\n        #else\n\n            guard self.app != nil else {\n                NSLog(\"XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().\")\n                return\n            }\n\n            let screenshot = XCUIScreen.main.screenshot()\n            #if os(iOS) && !targetEnvironment(macCatalyst)\n            let image = XCUIDevice.shared.orientation.isLandscape ?  fixLandscapeOrientation(image: screenshot.image) : screenshot.image\n            #else\n            let image = screenshot.image\n            #endif\n\n            guard var simulator = ProcessInfo().environment[\"SIMULATOR_DEVICE_NAME\"], let screenshotsDir = screenshotsDirectory else { return }\n\n            do {\n                // The simulator name contains \"Clone X of \" inside the screenshot file when running parallelized UI Tests on concurrent devices\n                let regex = try NSRegularExpression(pattern: \"Clone [0-9]+ of \")\n                let range = NSRange(location: 0, length: simulator.count)\n                simulator = regex.stringByReplacingMatches(in: simulator, range: range, withTemplate: \"\")\n\n                let path = screenshotsDir.appendingPathComponent(\"\\(simulator)-\\(name).png\")\n                #if swift(<5.0)\n                    UIImagePNGRepresentation(image)?.write(to: path, options: .atomic)\n                #else\n                    try image.pngData()?.write(to: path, options: .atomic)\n                #endif\n            } catch let error {\n                NSLog(\"Problem writing screenshot: \\(name) to \\(screenshotsDir)/\\(simulator)-\\(name).png\")\n                NSLog(error.localizedDescription)\n            }\n        #endif\n    }\n\n    class func fixLandscapeOrientation(image: UIImage) -> UIImage {\n        #if os(watchOS)\n            return image\n        #else\n            if #available(iOS 10.0, *) {\n                let format = UIGraphicsImageRendererFormat()\n                format.scale = image.scale\n                let renderer = UIGraphicsImageRenderer(size: image.size, format: format)\n                return renderer.image { context in\n                    image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))\n                }\n            } else {\n                return image\n            }\n        #endif\n    }\n\n    class func waitForLoadingIndicatorToDisappear(within timeout: TimeInterval) {\n        #if os(tvOS)\n            return\n        #endif\n\n        guard let app = self.app else {\n            NSLog(\"XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().\")\n            return\n        }\n\n        let networkLoadingIndicator = app.otherElements.deviceStatusBars.networkLoadingIndicators.element\n        let networkLoadingIndicatorDisappeared = XCTNSPredicateExpectation(predicate: NSPredicate(format: \"exists == false\"), object: networkLoadingIndicator)\n        _ = XCTWaiter.wait(for: [networkLoadingIndicatorDisappeared], timeout: timeout)\n    }\n\n    class func getCacheDirectory() throws -> URL {\n        let cachePath = \"Library/Caches/tools.fastlane\"\n        // on OSX config is stored in /Users/<username>/Library\n        // and on iOS/tvOS/WatchOS it's in simulator's home dir\n        #if os(OSX)\n            let homeDir = URL(fileURLWithPath: NSHomeDirectory())\n            return homeDir.appendingPathComponent(cachePath)\n        #elseif arch(i386) || arch(x86_64) || arch(arm64)\n            guard let simulatorHostHome = ProcessInfo().environment[\"SIMULATOR_HOST_HOME\"] else {\n                throw SnapshotError.cannotFindSimulatorHomeDirectory\n            }\n            let homeDir = URL(fileURLWithPath: simulatorHostHome)\n            return homeDir.appendingPathComponent(cachePath)\n        #else\n            throw SnapshotError.cannotRunOnPhysicalDevice\n        #endif\n    }\n}\n\nprivate extension XCUIElementAttributes {\n    var isNetworkLoadingIndicator: Bool {\n        if hasAllowListedIdentifier { return false }\n\n        let hasOldLoadingIndicatorSize = frame.size == CGSize(width: 10, height: 20)\n        let hasNewLoadingIndicatorSize = frame.size.width.isBetween(46, and: 47) && frame.size.height.isBetween(2, and: 3)\n\n        return hasOldLoadingIndicatorSize || hasNewLoadingIndicatorSize\n    }\n\n    var hasAllowListedIdentifier: Bool {\n        let allowListedIdentifiers = [\"GeofenceLocationTrackingOn\", \"StandardLocationTrackingOn\"]\n\n        return allowListedIdentifiers.contains(identifier)\n    }\n\n    func isStatusBar(_ deviceWidth: CGFloat) -> Bool {\n        if elementType == .statusBar { return true }\n        guard frame.origin == .zero else { return false }\n\n        let oldStatusBarSize = CGSize(width: deviceWidth, height: 20)\n        let newStatusBarSize = CGSize(width: deviceWidth, height: 44)\n\n        return [oldStatusBarSize, newStatusBarSize].contains(frame.size)\n    }\n}\n\nprivate extension XCUIElementQuery {\n    var networkLoadingIndicators: XCUIElementQuery {\n        let isNetworkLoadingIndicator = NSPredicate { (evaluatedObject, _) in\n            guard let element = evaluatedObject as? XCUIElementAttributes else { return false }\n\n            return element.isNetworkLoadingIndicator\n        }\n\n        return self.containing(isNetworkLoadingIndicator)\n    }\n\n    var deviceStatusBars: XCUIElementQuery {\n        guard let app = Snapshot.app else {\n            fatalError(\"XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().\")\n        }\n\n        let deviceWidth = app.windows.firstMatch.frame.width\n\n        let isStatusBar = NSPredicate { (evaluatedObject, _) in\n            guard let element = evaluatedObject as? XCUIElementAttributes else { return false }\n\n            return element.isStatusBar(deviceWidth)\n        }\n\n        return self.containing(isStatusBar)\n    }\n}\n\nprivate extension CGFloat {\n    func isBetween(_ numberA: CGFloat, and numberB: CGFloat) -> Bool {\n        return numberA...numberB ~= self\n    }\n}\n\n// Please don't remove the lines below\n// They are used to detect outdated configuration files\n// SnapshotHelperVersion [1.28]\n"
  },
  {
    "path": "UITests/UITests-Bridging-Header.h",
    "content": "//\n//  Use this file to import your target's public headers that you would like to expose to Swift.\n//\n\n"
  },
  {
    "path": "UITests/UITests.swift",
    "content": "//\n//  UITests.swift\n//  UITests\n//\n//  Copyright © 2016 IRCCloud, Ltd. All rights reserved.\n//\n\nimport Foundation\nimport XCTest\n\nlet SCREENSHOT_DELAY:UInt32 = 5;\n\nclass UITests: XCTestCase {\n\n\noverride func setUp() {\n    super.setUp()\n    XCUIDevice().orientation = UIDeviceOrientation.portrait\n}\n\n  func takeScreenshotTheme(_ theme: String, mono: Bool = false, memberlist: Bool = false) {\n    let app = XCUIApplication()\n    app.launchArguments = [\"-theme\", theme]\n    if (mono) {\n        app.launchArguments += [\"-mono\"]\n    }\n    if (memberlist) {\n        app.launchArguments += [\"-memberlist\"]\n    }\n    setupSnapshot(app)\n    app.launch()\n    \n    let isPhone = UIDevice().userInterfaceIdiom == .phone\n    let isPad = UIDevice().userInterfaceIdiom == .pad\n    var isBigPhone = false\n    if (app.launchArguments.contains(\"-bigphone\")) {\n        isBigPhone = true\n    }\n    let isDawn = theme == \"dawn\"\n    \n    if (memberlist) {\n        sleep(SCREENSHOT_DELAY)\n        snapshot(\"\\(theme)-Portrait-Members\", waitForLoadingIndicator: false)\n    } else {\n        if (isDawn || isPhone) {\n            sleep(SCREENSHOT_DELAY)\n            snapshot(\"\\(theme)-Portrait\", waitForLoadingIndicator: false)\n        }\n        if (isPad || (isDawn && isBigPhone)) {\n            XCUIDevice().orientation = UIDeviceOrientation.landscapeLeft;\n            sleep(SCREENSHOT_DELAY)\n            snapshot(\"\\(theme)-Landscape\", waitForLoadingIndicator: false)\n        }\n    }\n}\n\nfunc testAshScreenshots () {\n    takeScreenshotTheme(\"ash\", mono: true)\n}\n    \nfunc testDawnScreenshots () {\n    takeScreenshotTheme(\"dawn\")\n}\n    \nfunc testDawnMembersScreenshots () {\n    if (UIDevice().userInterfaceIdiom == .phone) {\n        takeScreenshotTheme(\"dawn\", memberlist: true)\n    }\n}\n    \nfunc testDuskScreenshots () {\n    takeScreenshotTheme(\"dusk\")\n}\n\n}\n"
  },
  {
    "path": "WebP.framework/Headers/config.h",
    "content": "/* src/webp/config.h.  Generated from config.h.in by configure.  */\n/* src/webp/config.h.in.  Generated from configure.ac by autoheader.  */\n\n/* Define if building universal (internal helper macro) */\n/* #undef AC_APPLE_UNIVERSAL_BUILD */\n\n/* Set to 1 if __builtin_bswap16 is available */\n#define HAVE_BUILTIN_BSWAP16 1\n\n/* Set to 1 if __builtin_bswap32 is available */\n#define HAVE_BUILTIN_BSWAP32 1\n\n/* Set to 1 if __builtin_bswap64 is available */\n#define HAVE_BUILTIN_BSWAP64 1\n\n/* Define to 1 if you have the <dlfcn.h> header file. */\n#define HAVE_DLFCN_H 1\n\n/* Define to 1 if you have the <GLUT/glut.h> header file. */\n/* #undef HAVE_GLUT_GLUT_H */\n\n/* Define to 1 if you have the <GL/glut.h> header file. */\n/* #undef HAVE_GL_GLUT_H */\n\n/* Define to 1 if you have the <inttypes.h> header file. */\n#define HAVE_INTTYPES_H 1\n\n/* Define to 1 if you have the <memory.h> header file. */\n#define HAVE_MEMORY_H 1\n\n/* Define to 1 if you have the <OpenGL/glut.h> header file. */\n/* #undef HAVE_OPENGL_GLUT_H */\n\n/* Have PTHREAD_PRIO_INHERIT. */\n#define HAVE_PTHREAD_PRIO_INHERIT 1\n\n/* Define to 1 if you have the <shlwapi.h> header file. */\n/* #undef HAVE_SHLWAPI_H */\n\n/* Define to 1 if you have the <stdint.h> header file. */\n#define HAVE_STDINT_H 1\n\n/* Define to 1 if you have the <stdlib.h> header file. */\n#define HAVE_STDLIB_H 1\n\n/* Define to 1 if you have the <strings.h> header file. */\n#define HAVE_STRINGS_H 1\n\n/* Define to 1 if you have the <string.h> header file. */\n#define HAVE_STRING_H 1\n\n/* Define to 1 if you have the <sys/stat.h> header file. */\n#define HAVE_SYS_STAT_H 1\n\n/* Define to 1 if you have the <sys/types.h> header file. */\n#define HAVE_SYS_TYPES_H 1\n\n/* Define to 1 if you have the <unistd.h> header file. */\n#define HAVE_UNISTD_H 1\n\n/* Define to 1 if you have the <wincodec.h> header file. */\n/* #undef HAVE_WINCODEC_H */\n\n/* Define to 1 if you have the <windows.h> header file. */\n/* #undef HAVE_WINDOWS_H */\n\n/* Define to the sub-directory in which libtool stores uninstalled libraries.\n   */\n#define LT_OBJDIR \".libs/\"\n\n/* Name of package */\n#define PACKAGE \"libwebp\"\n\n/* Define to the address where bug reports for this package should be sent. */\n#define PACKAGE_BUGREPORT \"https://bugs.chromium.org/p/webp\"\n\n/* Define to the full name of this package. */\n#define PACKAGE_NAME \"libwebp\"\n\n/* Define to the full name and version of this package. */\n#define PACKAGE_STRING \"libwebp 0.6.0\"\n\n/* Define to the one symbol short name of this package. */\n#define PACKAGE_TARNAME \"libwebp\"\n\n/* Define to the home page for this package. */\n#define PACKAGE_URL \"http://developers.google.com/speed/webp\"\n\n/* Define to the version of this package. */\n#define PACKAGE_VERSION \"0.6.0\"\n\n/* Define to necessary symbol if this constant uses a non-standard name on\n   your system. */\n/* #undef PTHREAD_CREATE_JOINABLE */\n\n/* Define to 1 if you have the ANSI C header files. */\n#define STDC_HEADERS 1\n\n/* Version number of package */\n#define VERSION \"0.6.0\"\n\n/* Enable experimental code */\n/* #undef WEBP_EXPERIMENTAL_FEATURES */\n\n/* Set to 1 if AVX2 is supported */\n/* #undef WEBP_HAVE_AVX2 */\n\n/* Set to 1 if GIF library is installed */\n/* #undef WEBP_HAVE_GIF */\n\n/* Set to 1 if OpenGL is supported */\n/* #undef WEBP_HAVE_GL */\n\n/* Set to 1 if JPEG library is installed */\n/* #undef WEBP_HAVE_JPEG */\n\n/* Set to 1 if NEON is supported */\n/* #undef WEBP_HAVE_NEON */\n\n/* Set to 1 if runtime detection of NEON is enabled */\n/* #undef WEBP_HAVE_NEON_RTCD */\n\n/* Set to 1 if PNG library is installed */\n/* #undef WEBP_HAVE_PNG */\n\n/* Set to 1 if SSE2 is supported */\n/* #undef WEBP_HAVE_SSE2 */\n\n/* Set to 1 if SSE4.1 is supported */\n/* #undef WEBP_HAVE_SSE41 */\n\n/* Set to 1 if TIFF library is installed */\n/* #undef WEBP_HAVE_TIFF */\n\n/* Undefine this to disable thread support. */\n#define WEBP_USE_THREAD 1\n\n/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most\n   significant byte first (like Motorola and SPARC, unlike Intel). */\n#if defined AC_APPLE_UNIVERSAL_BUILD\n# if defined __BIG_ENDIAN__\n#  define WORDS_BIGENDIAN 1\n# endif\n#else\n# ifndef WORDS_BIGENDIAN\n/* #  undef WORDS_BIGENDIAN */\n# endif\n#endif\n"
  },
  {
    "path": "WebP.framework/Headers/decode.h",
    "content": "// Copyright 2010 Google Inc. All Rights Reserved.\n//\n// Use of this source code is governed by a BSD-style license\n// that can be found in the COPYING file in the root of the source\n// tree. An additional intellectual property rights grant can be found\n// in the file PATENTS. All contributing project authors may\n// be found in the AUTHORS file in the root of the source tree.\n// -----------------------------------------------------------------------------\n//\n//  Main decoding functions for WebP images.\n//\n// Author: Skal (pascal.massimino@gmail.com)\n\n#ifndef WEBP_WEBP_DECODE_H_\n#define WEBP_WEBP_DECODE_H_\n\n#include \"./types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define WEBP_DECODER_ABI_VERSION 0x0208    // MAJOR(8b) + MINOR(8b)\n\n// Note: forward declaring enumerations is not allowed in (strict) C and C++,\n// the types are left here for reference.\n// typedef enum VP8StatusCode VP8StatusCode;\n// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE;\ntypedef struct WebPRGBABuffer WebPRGBABuffer;\ntypedef struct WebPYUVABuffer WebPYUVABuffer;\ntypedef struct WebPDecBuffer WebPDecBuffer;\ntypedef struct WebPIDecoder WebPIDecoder;\ntypedef struct WebPBitstreamFeatures WebPBitstreamFeatures;\ntypedef struct WebPDecoderOptions WebPDecoderOptions;\ntypedef struct WebPDecoderConfig WebPDecoderConfig;\n\n// Return the decoder's version number, packed in hexadecimal using 8bits for\n// each of major/minor/revision. E.g: v2.5.7 is 0x020507.\nWEBP_EXTERN(int) WebPGetDecoderVersion(void);\n\n// Retrieve basic header information: width, height.\n// This function will also validate the header, returning true on success,\n// false otherwise. '*width' and '*height' are only valid on successful return.\n// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant.\nWEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size,\n                             int* width, int* height);\n\n// Decodes WebP images pointed to by 'data' and returns RGBA samples, along\n// with the dimensions in *width and *height. The ordering of samples in\n// memory is R, G, B, A, R, G, B, A... in scan order (endian-independent).\n// The returned pointer should be deleted calling WebPFree().\n// Returns NULL in case of error.\nWEBP_EXTERN(uint8_t*) WebPDecodeRGBA(const uint8_t* data, size_t data_size,\n                                     int* width, int* height);\n\n// Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data.\nWEBP_EXTERN(uint8_t*) WebPDecodeARGB(const uint8_t* data, size_t data_size,\n                                     int* width, int* height);\n\n// Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data.\nWEBP_EXTERN(uint8_t*) WebPDecodeBGRA(const uint8_t* data, size_t data_size,\n                                     int* width, int* height);\n\n// Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data.\n// If the bitstream contains transparency, it is ignored.\nWEBP_EXTERN(uint8_t*) WebPDecodeRGB(const uint8_t* data, size_t data_size,\n                                    int* width, int* height);\n\n// Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data.\nWEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size,\n                                    int* width, int* height);\n\n\n// Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer\n// returned is the Y samples buffer. Upon return, *u and *v will point to\n// the U and V chroma data. These U and V buffers need NOT be passed to\n// WebPFree(), unlike the returned Y luma one. The dimension of the U and V\n// planes are both (*width + 1) / 2 and (*height + 1)/ 2.\n// Upon return, the Y buffer has a stride returned as '*stride', while U and V\n// have a common stride returned as '*uv_stride'.\n// Return NULL in case of error.\n// (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr\nWEBP_EXTERN(uint8_t*) WebPDecodeYUV(const uint8_t* data, size_t data_size,\n                                    int* width, int* height,\n                                    uint8_t** u, uint8_t** v,\n                                    int* stride, int* uv_stride);\n\n// Releases memory returned by the WebPDecode*() functions above.\nWEBP_EXTERN(void) WebPFree(void* ptr);\n\n// These five functions are variants of the above ones, that decode the image\n// directly into a pre-allocated buffer 'output_buffer'. The maximum storage\n// available in this buffer is indicated by 'output_buffer_size'. If this\n// storage is not sufficient (or an error occurred), NULL is returned.\n// Otherwise, output_buffer is returned, for convenience.\n// The parameter 'output_stride' specifies the distance (in bytes)\n// between scanlines. Hence, output_buffer_size is expected to be at least\n// output_stride x picture-height.\nWEBP_EXTERN(uint8_t*) WebPDecodeRGBAInto(\n    const uint8_t* data, size_t data_size,\n    uint8_t* output_buffer, size_t output_buffer_size, int output_stride);\nWEBP_EXTERN(uint8_t*) WebPDecodeARGBInto(\n    const uint8_t* data, size_t data_size,\n    uint8_t* output_buffer, size_t output_buffer_size, int output_stride);\nWEBP_EXTERN(uint8_t*) WebPDecodeBGRAInto(\n    const uint8_t* data, size_t data_size,\n    uint8_t* output_buffer, size_t output_buffer_size, int output_stride);\n\n// RGB and BGR variants. Here too the transparency information, if present,\n// will be dropped and ignored.\nWEBP_EXTERN(uint8_t*) WebPDecodeRGBInto(\n    const uint8_t* data, size_t data_size,\n    uint8_t* output_buffer, size_t output_buffer_size, int output_stride);\nWEBP_EXTERN(uint8_t*) WebPDecodeBGRInto(\n    const uint8_t* data, size_t data_size,\n    uint8_t* output_buffer, size_t output_buffer_size, int output_stride);\n\n// WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly\n// into pre-allocated luma/chroma plane buffers. This function requires the\n// strides to be passed: one for the luma plane and one for each of the\n// chroma ones. The size of each plane buffer is passed as 'luma_size',\n// 'u_size' and 'v_size' respectively.\n// Pointer to the luma plane ('*luma') is returned or NULL if an error occurred\n// during decoding (or because some buffers were found to be too small).\nWEBP_EXTERN(uint8_t*) WebPDecodeYUVInto(\n    const uint8_t* data, size_t data_size,\n    uint8_t* luma, size_t luma_size, int luma_stride,\n    uint8_t* u, size_t u_size, int u_stride,\n    uint8_t* v, size_t v_size, int v_stride);\n\n//------------------------------------------------------------------------------\n// Output colorspaces and buffer\n\n// Colorspaces\n// Note: the naming describes the byte-ordering of packed samples in memory.\n// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,...\n// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels.\n// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order:\n// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ...\n// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ...\n// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for\n// these two modes:\n// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ...\n// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ...\n\ntypedef enum WEBP_CSP_MODE {\n  MODE_RGB = 0, MODE_RGBA = 1,\n  MODE_BGR = 2, MODE_BGRA = 3,\n  MODE_ARGB = 4, MODE_RGBA_4444 = 5,\n  MODE_RGB_565 = 6,\n  // RGB-premultiplied transparent modes (alpha value is preserved)\n  MODE_rgbA = 7,\n  MODE_bgrA = 8,\n  MODE_Argb = 9,\n  MODE_rgbA_4444 = 10,\n  // YUV modes must come after RGB ones.\n  MODE_YUV = 11, MODE_YUVA = 12,  // yuv 4:2:0\n  MODE_LAST = 13\n} WEBP_CSP_MODE;\n\n// Some useful macros:\nstatic WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) {\n  return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb ||\n          mode == MODE_rgbA_4444);\n}\n\nstatic WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) {\n  return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB ||\n          mode == MODE_RGBA_4444 || mode == MODE_YUVA ||\n          WebPIsPremultipliedMode(mode));\n}\n\nstatic WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) {\n  return (mode < MODE_YUV);\n}\n\n//------------------------------------------------------------------------------\n// WebPDecBuffer: Generic structure for describing the output sample buffer.\n\nstruct WebPRGBABuffer {    // view as RGBA\n  uint8_t* rgba;    // pointer to RGBA samples\n  int stride;       // stride in bytes from one scanline to the next.\n  size_t size;      // total size of the *rgba buffer.\n};\n\nstruct WebPYUVABuffer {              // view as YUVA\n  uint8_t* y, *u, *v, *a;     // pointer to luma, chroma U/V, alpha samples\n  int y_stride;               // luma stride\n  int u_stride, v_stride;     // chroma strides\n  int a_stride;               // alpha stride\n  size_t y_size;              // luma plane size\n  size_t u_size, v_size;      // chroma planes size\n  size_t a_size;              // alpha-plane size\n};\n\n// Output buffer\nstruct WebPDecBuffer {\n  WEBP_CSP_MODE colorspace;  // Colorspace.\n  int width, height;         // Dimensions.\n  int is_external_memory;    // If non-zero, 'internal_memory' pointer is not\n                             // used. If value is '2' or more, the external\n                             // memory is considered 'slow' and multiple\n                             // read/write will be avoided.\n  union {\n    WebPRGBABuffer RGBA;\n    WebPYUVABuffer YUVA;\n  } u;                       // Nameless union of buffer parameters.\n  uint32_t       pad[4];     // padding for later use\n\n  uint8_t* private_memory;   // Internally allocated memory (only when\n                             // is_external_memory is 0). Should not be used\n                             // externally, but accessed via the buffer union.\n};\n\n// Internal, version-checked, entry point\nWEBP_EXTERN(int) WebPInitDecBufferInternal(WebPDecBuffer*, int);\n\n// Initialize the structure as empty. Must be called before any other use.\n// Returns false in case of version mismatch\nstatic WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) {\n  return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION);\n}\n\n// Free any memory associated with the buffer. Must always be called last.\n// Note: doesn't free the 'buffer' structure itself.\nWEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer);\n\n//------------------------------------------------------------------------------\n// Enumeration of the status codes\n\ntypedef enum VP8StatusCode {\n  VP8_STATUS_OK = 0,\n  VP8_STATUS_OUT_OF_MEMORY,\n  VP8_STATUS_INVALID_PARAM,\n  VP8_STATUS_BITSTREAM_ERROR,\n  VP8_STATUS_UNSUPPORTED_FEATURE,\n  VP8_STATUS_SUSPENDED,\n  VP8_STATUS_USER_ABORT,\n  VP8_STATUS_NOT_ENOUGH_DATA\n} VP8StatusCode;\n\n//------------------------------------------------------------------------------\n// Incremental decoding\n//\n// This API allows streamlined decoding of partial data.\n// Picture can be incrementally decoded as data become available thanks to the\n// WebPIDecoder object. This object can be left in a SUSPENDED state if the\n// picture is only partially decoded, pending additional input.\n// Code example:\n//\n//   WebPInitDecBuffer(&output_buffer);\n//   output_buffer.colorspace = mode;\n//   ...\n//   WebPIDecoder* idec = WebPINewDecoder(&output_buffer);\n//   while (additional_data_is_available) {\n//     // ... (get additional data in some new_data[] buffer)\n//     status = WebPIAppend(idec, new_data, new_data_size);\n//     if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) {\n//       break;    // an error occurred.\n//     }\n//\n//     // The above call decodes the current available buffer.\n//     // Part of the image can now be refreshed by calling\n//     // WebPIDecGetRGB()/WebPIDecGetYUVA() etc.\n//   }\n//   WebPIDelete(idec);\n\n// Creates a new incremental decoder with the supplied buffer parameter.\n// This output_buffer can be passed NULL, in which case a default output buffer\n// is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer'\n// is kept, which means that the lifespan of 'output_buffer' must be larger than\n// that of the returned WebPIDecoder object.\n// The supplied 'output_buffer' content MUST NOT be changed between calls to\n// WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is\n// not set to 0. In such a case, it is allowed to modify the pointers, size and\n// stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain\n// within valid bounds.\n// All other fields of WebPDecBuffer MUST remain constant between calls.\n// Returns NULL if the allocation failed.\nWEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer);\n\n// This function allocates and initializes an incremental-decoder object, which\n// will output the RGB/A samples specified by 'csp' into a preallocated\n// buffer 'output_buffer'. The size of this buffer is at least\n// 'output_buffer_size' and the stride (distance in bytes between two scanlines)\n// is specified by 'output_stride'.\n// Additionally, output_buffer can be passed NULL in which case the output\n// buffer will be allocated automatically when the decoding starts. The\n// colorspace 'csp' is taken into account for allocating this buffer. All other\n// parameters are ignored.\n// Returns NULL if the allocation failed, or if some parameters are invalid.\nWEBP_EXTERN(WebPIDecoder*) WebPINewRGB(\n    WEBP_CSP_MODE csp,\n    uint8_t* output_buffer, size_t output_buffer_size, int output_stride);\n\n// This function allocates and initializes an incremental-decoder object, which\n// will output the raw luma/chroma samples into a preallocated planes if\n// supplied. The luma plane is specified by its pointer 'luma', its size\n// 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane\n// is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v\n// plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer\n// can be pass NULL in case one is not interested in the transparency plane.\n// Conversely, 'luma' can be passed NULL if no preallocated planes are supplied.\n// In this case, the output buffer will be automatically allocated (using\n// MODE_YUVA) when decoding starts. All parameters are then ignored.\n// Returns NULL if the allocation failed or if a parameter is invalid.\nWEBP_EXTERN(WebPIDecoder*) WebPINewYUVA(\n    uint8_t* luma, size_t luma_size, int luma_stride,\n    uint8_t* u, size_t u_size, int u_stride,\n    uint8_t* v, size_t v_size, int v_stride,\n    uint8_t* a, size_t a_size, int a_stride);\n\n// Deprecated version of the above, without the alpha plane.\n// Kept for backward compatibility.\nWEBP_EXTERN(WebPIDecoder*) WebPINewYUV(\n    uint8_t* luma, size_t luma_size, int luma_stride,\n    uint8_t* u, size_t u_size, int u_stride,\n    uint8_t* v, size_t v_size, int v_stride);\n\n// Deletes the WebPIDecoder object and associated memory. Must always be called\n// if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded.\nWEBP_EXTERN(void) WebPIDelete(WebPIDecoder* idec);\n\n// Copies and decodes the next available data. Returns VP8_STATUS_OK when\n// the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more\n// data is expected. Returns error in other cases.\nWEBP_EXTERN(VP8StatusCode) WebPIAppend(\n    WebPIDecoder* idec, const uint8_t* data, size_t data_size);\n\n// A variant of the above function to be used when data buffer contains\n// partial data from the beginning. In this case data buffer is not copied\n// to the internal memory.\n// Note that the value of the 'data' pointer can change between calls to\n// WebPIUpdate, for instance when the data buffer is resized to fit larger data.\nWEBP_EXTERN(VP8StatusCode) WebPIUpdate(\n    WebPIDecoder* idec, const uint8_t* data, size_t data_size);\n\n// Returns the RGB/A image decoded so far. Returns NULL if output params\n// are not initialized yet. The RGB/A output type corresponds to the colorspace\n// specified during call to WebPINewDecoder() or WebPINewRGB().\n// *last_y is the index of last decoded row in raster scan order. Some pointers\n// (*last_y, *width etc.) can be NULL if corresponding information is not\n// needed.\nWEBP_EXTERN(uint8_t*) WebPIDecGetRGB(\n    const WebPIDecoder* idec, int* last_y,\n    int* width, int* height, int* stride);\n\n// Same as above function to get a YUVA image. Returns pointer to the luma\n// plane or NULL in case of error. If there is no alpha information\n// the alpha pointer '*a' will be returned NULL.\nWEBP_EXTERN(uint8_t*) WebPIDecGetYUVA(\n    const WebPIDecoder* idec, int* last_y,\n    uint8_t** u, uint8_t** v, uint8_t** a,\n    int* width, int* height, int* stride, int* uv_stride, int* a_stride);\n\n// Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the\n// alpha information (if present). Kept for backward compatibility.\nstatic WEBP_INLINE uint8_t* WebPIDecGetYUV(\n    const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v,\n    int* width, int* height, int* stride, int* uv_stride) {\n  return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height,\n                         stride, uv_stride, NULL);\n}\n\n// Generic call to retrieve information about the displayable area.\n// If non NULL, the left/right/width/height pointers are filled with the visible\n// rectangular area so far.\n// Returns NULL in case the incremental decoder object is in an invalid state.\n// Otherwise returns the pointer to the internal representation. This structure\n// is read-only, tied to WebPIDecoder's lifespan and should not be modified.\nWEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea(\n    const WebPIDecoder* idec, int* left, int* top, int* width, int* height);\n\n//------------------------------------------------------------------------------\n// Advanced decoding parametrization\n//\n//  Code sample for using the advanced decoding API\n/*\n     // A) Init a configuration object\n     WebPDecoderConfig config;\n     CHECK(WebPInitDecoderConfig(&config));\n\n     // B) optional: retrieve the bitstream's features.\n     CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);\n\n     // C) Adjust 'config', if needed\n     config.no_fancy_upsampling = 1;\n     config.output.colorspace = MODE_BGRA;\n     // etc.\n\n     // Note that you can also make config.output point to an externally\n     // supplied memory buffer, provided it's big enough to store the decoded\n     // picture. Otherwise, config.output will just be used to allocate memory\n     // and store the decoded picture.\n\n     // D) Decode!\n     CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);\n\n     // E) Decoded image is now in config.output (and config.output.u.RGBA)\n\n     // F) Reclaim memory allocated in config's object. It's safe to call\n     // this function even if the memory is external and wasn't allocated\n     // by WebPDecode().\n     WebPFreeDecBuffer(&config.output);\n*/\n\n// Features gathered from the bitstream\nstruct WebPBitstreamFeatures {\n  int width;          // Width in pixels, as read from the bitstream.\n  int height;         // Height in pixels, as read from the bitstream.\n  int has_alpha;      // True if the bitstream contains an alpha channel.\n  int has_animation;  // True if the bitstream is an animation.\n  int format;         // 0 = undefined (/mixed), 1 = lossy, 2 = lossless\n\n  uint32_t pad[5];    // padding for later use\n};\n\n// Internal, version-checked, entry point\nWEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal(\n    const uint8_t*, size_t, WebPBitstreamFeatures*, int);\n\n// Retrieve features from the bitstream. The *features structure is filled\n// with information gathered from the bitstream.\n// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns\n// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the\n// features from headers. Returns error in other cases.\nstatic WEBP_INLINE VP8StatusCode WebPGetFeatures(\n    const uint8_t* data, size_t data_size,\n    WebPBitstreamFeatures* features) {\n  return WebPGetFeaturesInternal(data, data_size, features,\n                                 WEBP_DECODER_ABI_VERSION);\n}\n\n// Decoding options\nstruct WebPDecoderOptions {\n  int bypass_filtering;               // if true, skip the in-loop filtering\n  int no_fancy_upsampling;            // if true, use faster pointwise upsampler\n  int use_cropping;                   // if true, cropping is applied _first_\n  int crop_left, crop_top;            // top-left position for cropping.\n                                      // Will be snapped to even values.\n  int crop_width, crop_height;        // dimension of the cropping area\n  int use_scaling;                    // if true, scaling is applied _afterward_\n  int scaled_width, scaled_height;    // final resolution\n  int use_threads;                    // if true, use multi-threaded decoding\n  int dithering_strength;             // dithering strength (0=Off, 100=full)\n  int flip;                           // flip output vertically\n  int alpha_dithering_strength;       // alpha dithering strength in [0..100]\n\n  uint32_t pad[5];                    // padding for later use\n};\n\n// Main object storing the configuration for advanced decoding.\nstruct WebPDecoderConfig {\n  WebPBitstreamFeatures input;  // Immutable bitstream features (optional)\n  WebPDecBuffer output;         // Output buffer (can point to external mem)\n  WebPDecoderOptions options;   // Decoding options\n};\n\n// Internal, version-checked, entry point\nWEBP_EXTERN(int) WebPInitDecoderConfigInternal(WebPDecoderConfig*, int);\n\n// Initialize the configuration as empty. This function must always be\n// called first, unless WebPGetFeatures() is to be called.\n// Returns false in case of mismatched version.\nstatic WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) {\n  return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION);\n}\n\n// Instantiate a new incremental decoder object with the requested\n// configuration. The bitstream can be passed using 'data' and 'data_size'\n// parameter, in which case the features will be parsed and stored into\n// config->input. Otherwise, 'data' can be NULL and no parsing will occur.\n// Note that 'config' can be NULL too, in which case a default configuration\n// is used. If 'config' is not NULL, it must outlive the WebPIDecoder object\n// as some references to its fields will be used. No internal copy of 'config'\n// is made.\n// The return WebPIDecoder object must always be deleted calling WebPIDelete().\n// Returns NULL in case of error (and config->status will then reflect\n// the error condition, if available).\nWEBP_EXTERN(WebPIDecoder*) WebPIDecode(const uint8_t* data, size_t data_size,\n                                       WebPDecoderConfig* config);\n\n// Non-incremental version. This version decodes the full data at once, taking\n// 'config' into account. Returns decoding status (which should be VP8_STATUS_OK\n// if the decoding was successful). Note that 'config' cannot be NULL.\nWEBP_EXTERN(VP8StatusCode) WebPDecode(const uint8_t* data, size_t data_size,\n                                      WebPDecoderConfig* config);\n\n#ifdef __cplusplus\n}    // extern \"C\"\n#endif\n\n#endif  /* WEBP_WEBP_DECODE_H_ */\n"
  },
  {
    "path": "WebP.framework/Headers/demux.h",
    "content": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Use of this source code is governed by a BSD-style license\n// that can be found in the COPYING file in the root of the source\n// tree. An additional intellectual property rights grant can be found\n// in the file PATENTS. All contributing project authors may\n// be found in the AUTHORS file in the root of the source tree.\n// -----------------------------------------------------------------------------\n//\n// Demux API.\n// Enables extraction of image and extended format data from WebP files.\n\n// Code Example: Demuxing WebP data to extract all the frames, ICC profile\n// and EXIF/XMP metadata.\n/*\n  WebPDemuxer* demux = WebPDemux(&webp_data);\n\n  uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);\n  uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);\n  // ... (Get information about the features present in the WebP file).\n  uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);\n\n  // ... (Iterate over all frames).\n  WebPIterator iter;\n  if (WebPDemuxGetFrame(demux, 1, &iter)) {\n    do {\n      // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(),\n      // ... and get other frame properties like width, height, offsets etc.\n      // ... see 'struct WebPIterator' below for more info).\n    } while (WebPDemuxNextFrame(&iter));\n    WebPDemuxReleaseIterator(&iter);\n  }\n\n  // ... (Extract metadata).\n  WebPChunkIterator chunk_iter;\n  if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, \"ICCP\", 1, &chunk_iter);\n  // ... (Consume the ICC profile in 'chunk_iter.chunk').\n  WebPDemuxReleaseChunkIterator(&chunk_iter);\n  if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, \"EXIF\", 1, &chunk_iter);\n  // ... (Consume the EXIF metadata in 'chunk_iter.chunk').\n  WebPDemuxReleaseChunkIterator(&chunk_iter);\n  if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, \"XMP \", 1, &chunk_iter);\n  // ... (Consume the XMP metadata in 'chunk_iter.chunk').\n  WebPDemuxReleaseChunkIterator(&chunk_iter);\n  WebPDemuxDelete(demux);\n*/\n\n#ifndef WEBP_WEBP_DEMUX_H_\n#define WEBP_WEBP_DEMUX_H_\n\n#include \"./decode.h\"     // for WEBP_CSP_MODE\n#include \"./mux_types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define WEBP_DEMUX_ABI_VERSION 0x0107    // MAJOR(8b) + MINOR(8b)\n\n// Note: forward declaring enumerations is not allowed in (strict) C and C++,\n// the types are left here for reference.\n// typedef enum WebPDemuxState WebPDemuxState;\n// typedef enum WebPFormatFeature WebPFormatFeature;\ntypedef struct WebPDemuxer WebPDemuxer;\ntypedef struct WebPIterator WebPIterator;\ntypedef struct WebPChunkIterator WebPChunkIterator;\ntypedef struct WebPAnimInfo WebPAnimInfo;\ntypedef struct WebPAnimDecoderOptions WebPAnimDecoderOptions;\n\n//------------------------------------------------------------------------------\n\n// Returns the version number of the demux library, packed in hexadecimal using\n// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.\nWEBP_EXTERN(int) WebPGetDemuxVersion(void);\n\n//------------------------------------------------------------------------------\n// Life of a Demux object\n\ntypedef enum WebPDemuxState {\n  WEBP_DEMUX_PARSE_ERROR    = -1,  // An error occurred while parsing.\n  WEBP_DEMUX_PARSING_HEADER =  0,  // Not enough data to parse full header.\n  WEBP_DEMUX_PARSED_HEADER  =  1,  // Header parsing complete,\n                                   // data may be available.\n  WEBP_DEMUX_DONE           =  2   // Entire file has been parsed.\n} WebPDemuxState;\n\n// Internal, version-checked, entry point\nWEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal(\n    const WebPData*, int, WebPDemuxState*, int);\n\n// Parses the full WebP file given by 'data'. For single images the WebP file\n// header alone or the file header and the chunk header may be absent.\n// Returns a WebPDemuxer object on successful parse, NULL otherwise.\nstatic WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {\n  return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION);\n}\n\n// Parses the possibly incomplete WebP file given by 'data'.\n// If 'state' is non-NULL it will be set to indicate the status of the demuxer.\n// Returns NULL in case of error or if there isn't enough data to start parsing;\n// and a WebPDemuxer object on successful parse.\n// Note that WebPDemuxer keeps internal pointers to 'data' memory segment.\n// If this data is volatile, the demuxer object should be deleted (by calling\n// WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data.\n// This is usually an inexpensive operation.\nstatic WEBP_INLINE WebPDemuxer* WebPDemuxPartial(\n    const WebPData* data, WebPDemuxState* state) {\n  return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION);\n}\n\n// Frees memory associated with 'dmux'.\nWEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux);\n\n//------------------------------------------------------------------------------\n// Data/information extraction.\n\ntypedef enum WebPFormatFeature {\n  WEBP_FF_FORMAT_FLAGS,  // Extended format flags present in the 'VP8X' chunk.\n  WEBP_FF_CANVAS_WIDTH,\n  WEBP_FF_CANVAS_HEIGHT,\n  WEBP_FF_LOOP_COUNT,\n  WEBP_FF_BACKGROUND_COLOR,\n  WEBP_FF_FRAME_COUNT    // Number of frames present in the demux object.\n                         // In case of a partial demux, this is the number of\n                         // frames seen so far, with the last frame possibly\n                         // being partial.\n} WebPFormatFeature;\n\n// Get the 'feature' value from the 'dmux'.\n// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial()\n// returned a state > WEBP_DEMUX_PARSING_HEADER.\nWEBP_EXTERN(uint32_t) WebPDemuxGetI(\n    const WebPDemuxer* dmux, WebPFormatFeature feature);\n\n//------------------------------------------------------------------------------\n// Frame iteration.\n\nstruct WebPIterator {\n  int frame_num;\n  int num_frames;          // equivalent to WEBP_FF_FRAME_COUNT.\n  int x_offset, y_offset;  // offset relative to the canvas.\n  int width, height;       // dimensions of this frame.\n  int duration;            // display duration in milliseconds.\n  WebPMuxAnimDispose dispose_method;  // dispose method for the frame.\n  int complete;   // true if 'fragment' contains a full frame. partial images\n                  // may still be decoded with the WebP incremental decoder.\n  WebPData fragment;  // The frame given by 'frame_num'. Note for historical\n                      // reasons this is called a fragment.\n  int has_alpha;      // True if the frame contains transparency.\n  WebPMuxAnimBlend blend_method;  // Blend operation for the frame.\n\n  uint32_t pad[2];         // padding for later use.\n  void* private_;          // for internal use only.\n};\n\n// Retrieves frame 'frame_number' from 'dmux'.\n// 'iter->fragment' points to the frame on return from this function.\n// Setting 'frame_number' equal to 0 will return the last frame of the image.\n// Returns false if 'dmux' is NULL or frame 'frame_number' is not present.\n// Call WebPDemuxReleaseIterator() when use of the iterator is complete.\n// NOTE: 'dmux' must persist for the lifetime of 'iter'.\nWEBP_EXTERN(int) WebPDemuxGetFrame(\n    const WebPDemuxer* dmux, int frame_number, WebPIterator* iter);\n\n// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or\n// previous ('iter->frame_num' - 1) frame. These functions do not loop.\n// Returns true on success, false otherwise.\nWEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter);\nWEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter);\n\n// Releases any memory associated with 'iter'.\n// Must be called before any subsequent calls to WebPDemuxGetChunk() on the same\n// iter. Also, must be called before destroying the associated WebPDemuxer with\n// WebPDemuxDelete().\nWEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter);\n\n//------------------------------------------------------------------------------\n// Chunk iteration.\n\nstruct WebPChunkIterator {\n  // The current and total number of chunks with the fourcc given to\n  // WebPDemuxGetChunk().\n  int chunk_num;\n  int num_chunks;\n  WebPData chunk;    // The payload of the chunk.\n\n  uint32_t pad[6];   // padding for later use\n  void* private_;\n};\n\n// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from\n// 'dmux'.\n// 'fourcc' is a character array containing the fourcc of the chunk to return,\n// e.g., \"ICCP\", \"XMP \", \"EXIF\", etc.\n// Setting 'chunk_number' equal to 0 will return the last chunk in a set.\n// Returns true if the chunk is found, false otherwise. Image related chunk\n// payloads are accessed through WebPDemuxGetFrame() and related functions.\n// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete.\n// NOTE: 'dmux' must persist for the lifetime of the iterator.\nWEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux,\n                                   const char fourcc[4], int chunk_number,\n                                   WebPChunkIterator* iter);\n\n// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous\n// ('iter->chunk_num' - 1) chunk. These functions do not loop.\n// Returns true on success, false otherwise.\nWEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter);\nWEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter);\n\n// Releases any memory associated with 'iter'.\n// Must be called before destroying the associated WebPDemuxer with\n// WebPDemuxDelete().\nWEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter);\n\n//------------------------------------------------------------------------------\n// WebPAnimDecoder API\n//\n// This API allows decoding (possibly) animated WebP images.\n//\n// Code Example:\n/*\n  WebPAnimDecoderOptions dec_options;\n  WebPAnimDecoderOptionsInit(&dec_options);\n  // Tune 'dec_options' as needed.\n  WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);\n  WebPAnimInfo anim_info;\n  WebPAnimDecoderGetInfo(dec, &anim_info);\n  for (uint32_t i = 0; i < anim_info.loop_count; ++i) {\n    while (WebPAnimDecoderHasMoreFrames(dec)) {\n      uint8_t* buf;\n      int timestamp;\n      WebPAnimDecoderGetNext(dec, &buf, &timestamp);\n      // ... (Render 'buf' based on 'timestamp').\n      // ... (Do NOT free 'buf', as it is owned by 'dec').\n    }\n    WebPAnimDecoderReset(dec);\n  }\n  const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);\n  // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).\n  WebPAnimDecoderDelete(dec);\n*/\n\ntypedef struct WebPAnimDecoder WebPAnimDecoder;  // Main opaque object.\n\n// Global options.\nstruct WebPAnimDecoderOptions {\n  // Output colorspace. Only the following modes are supported:\n  // MODE_RGBA, MODE_BGRA, MODE_rgbA and MODE_bgrA.\n  WEBP_CSP_MODE color_mode;\n  int use_threads;           // If true, use multi-threaded decoding.\n  uint32_t padding[7];       // Padding for later use.\n};\n\n// Internal, version-checked, entry point.\nWEBP_EXTERN(int) WebPAnimDecoderOptionsInitInternal(\n    WebPAnimDecoderOptions*, int);\n\n// Should always be called, to initialize a fresh WebPAnimDecoderOptions\n// structure before modification. Returns false in case of version mismatch.\n// WebPAnimDecoderOptionsInit() must have succeeded before using the\n// 'dec_options' object.\nstatic WEBP_INLINE int WebPAnimDecoderOptionsInit(\n    WebPAnimDecoderOptions* dec_options) {\n  return WebPAnimDecoderOptionsInitInternal(dec_options,\n                                            WEBP_DEMUX_ABI_VERSION);\n}\n\n// Internal, version-checked, entry point.\nWEBP_EXTERN(WebPAnimDecoder*) WebPAnimDecoderNewInternal(\n    const WebPData*, const WebPAnimDecoderOptions*, int);\n\n// Creates and initializes a WebPAnimDecoder object.\n// Parameters:\n//   webp_data - (in) WebP bitstream. This should remain unchanged during the\n//                    lifetime of the output WebPAnimDecoder object.\n//   dec_options - (in) decoding options. Can be passed NULL to choose\n//                      reasonable defaults (in particular, color mode MODE_RGBA\n//                      will be picked).\n// Returns:\n//   A pointer to the newly created WebPAnimDecoder object, or NULL in case of\n//   parsing error, invalid option or memory error.\nstatic WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew(\n    const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) {\n  return WebPAnimDecoderNewInternal(webp_data, dec_options,\n                                    WEBP_DEMUX_ABI_VERSION);\n}\n\n// Global information about the animation..\nstruct WebPAnimInfo {\n  uint32_t canvas_width;\n  uint32_t canvas_height;\n  uint32_t loop_count;\n  uint32_t bgcolor;\n  uint32_t frame_count;\n  uint32_t pad[4];   // padding for later use\n};\n\n// Get global information about the animation.\n// Parameters:\n//   dec - (in) decoder instance to get information from.\n//   info - (out) global information fetched from the animation.\n// Returns:\n//   True on success.\nWEBP_EXTERN(int) WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec,\n                                        WebPAnimInfo* info);\n\n// Fetch the next frame from 'dec' based on options supplied to\n// WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size\n// 'canvas_width * 4 * canvas_height', and not just the frame sub-rectangle. The\n// returned buffer 'buf' is valid only until the next call to\n// WebPAnimDecoderGetNext(), WebPAnimDecoderReset() or WebPAnimDecoderDelete().\n// Parameters:\n//   dec - (in/out) decoder instance from which the next frame is to be fetched.\n//   buf - (out) decoded frame.\n//   timestamp - (out) timestamp of the frame in milliseconds.\n// Returns:\n//   False if any of the arguments are NULL, or if there is a parsing or\n//   decoding error, or if there are no more frames. Otherwise, returns true.\nWEBP_EXTERN(int) WebPAnimDecoderGetNext(WebPAnimDecoder* dec,\n                                        uint8_t** buf, int* timestamp);\n\n// Check if there are more frames left to decode.\n// Parameters:\n//   dec - (in) decoder instance to be checked.\n// Returns:\n//   True if 'dec' is not NULL and some frames are yet to be decoded.\n//   Otherwise, returns false.\nWEBP_EXTERN(int) WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec);\n\n// Resets the WebPAnimDecoder object, so that next call to\n// WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be\n// helpful when all frames need to be decoded multiple times (e.g.\n// info.loop_count times) without destroying and recreating the 'dec' object.\n// Parameters:\n//   dec - (in/out) decoder instance to be reset\nWEBP_EXTERN(void) WebPAnimDecoderReset(WebPAnimDecoder* dec);\n\n// Grab the internal demuxer object.\n// Getting the demuxer object can be useful if one wants to use operations only\n// available through demuxer; e.g. to get XMP/EXIF/ICC metadata. The returned\n// demuxer object is owned by 'dec' and is valid only until the next call to\n// WebPAnimDecoderDelete().\n//\n// Parameters:\n//   dec - (in) decoder instance from which the demuxer object is to be fetched.\nWEBP_EXTERN(const WebPDemuxer*) WebPAnimDecoderGetDemuxer(\n    const WebPAnimDecoder* dec);\n\n// Deletes the WebPAnimDecoder object.\n// Parameters:\n//   dec - (in/out) decoder instance to be deleted\nWEBP_EXTERN(void) WebPAnimDecoderDelete(WebPAnimDecoder* dec);\n\n#ifdef __cplusplus\n}    // extern \"C\"\n#endif\n\n#endif  /* WEBP_WEBP_DEMUX_H_ */\n"
  },
  {
    "path": "WebP.framework/Headers/encode.h",
    "content": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Use of this source code is governed by a BSD-style license\n// that can be found in the COPYING file in the root of the source\n// tree. An additional intellectual property rights grant can be found\n// in the file PATENTS. All contributing project authors may\n// be found in the AUTHORS file in the root of the source tree.\n// -----------------------------------------------------------------------------\n//\n//   WebP encoder: main interface\n//\n// Author: Skal (pascal.massimino@gmail.com)\n\n#ifndef WEBP_WEBP_ENCODE_H_\n#define WEBP_WEBP_ENCODE_H_\n\n#include \"./types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define WEBP_ENCODER_ABI_VERSION 0x020e    // MAJOR(8b) + MINOR(8b)\n\n// Note: forward declaring enumerations is not allowed in (strict) C and C++,\n// the types are left here for reference.\n// typedef enum WebPImageHint WebPImageHint;\n// typedef enum WebPEncCSP WebPEncCSP;\n// typedef enum WebPPreset WebPPreset;\n// typedef enum WebPEncodingError WebPEncodingError;\ntypedef struct WebPConfig WebPConfig;\ntypedef struct WebPPicture WebPPicture;   // main structure for I/O\ntypedef struct WebPAuxStats WebPAuxStats;\ntypedef struct WebPMemoryWriter WebPMemoryWriter;\n\n// Return the encoder's version number, packed in hexadecimal using 8bits for\n// each of major/minor/revision. E.g: v2.5.7 is 0x020507.\nWEBP_EXTERN(int) WebPGetEncoderVersion(void);\n\n//------------------------------------------------------------------------------\n// One-stop-shop call! No questions asked:\n\n// Returns the size of the compressed data (pointed to by *output), or 0 if\n// an error occurred. The compressed data must be released by the caller\n// using the call 'WebPFree(*output)'.\n// These functions compress using the lossy format, and the quality_factor\n// can go from 0 (smaller output, lower quality) to 100 (best quality,\n// larger output).\nWEBP_EXTERN(size_t) WebPEncodeRGB(const uint8_t* rgb,\n                                  int width, int height, int stride,\n                                  float quality_factor, uint8_t** output);\nWEBP_EXTERN(size_t) WebPEncodeBGR(const uint8_t* bgr,\n                                  int width, int height, int stride,\n                                  float quality_factor, uint8_t** output);\nWEBP_EXTERN(size_t) WebPEncodeRGBA(const uint8_t* rgba,\n                                   int width, int height, int stride,\n                                   float quality_factor, uint8_t** output);\nWEBP_EXTERN(size_t) WebPEncodeBGRA(const uint8_t* bgra,\n                                   int width, int height, int stride,\n                                   float quality_factor, uint8_t** output);\n\n// These functions are the equivalent of the above, but compressing in a\n// lossless manner. Files are usually larger than lossy format, but will\n// not suffer any compression loss.\nWEBP_EXTERN(size_t) WebPEncodeLosslessRGB(const uint8_t* rgb,\n                                          int width, int height, int stride,\n                                          uint8_t** output);\nWEBP_EXTERN(size_t) WebPEncodeLosslessBGR(const uint8_t* bgr,\n                                          int width, int height, int stride,\n                                          uint8_t** output);\nWEBP_EXTERN(size_t) WebPEncodeLosslessRGBA(const uint8_t* rgba,\n                                           int width, int height, int stride,\n                                           uint8_t** output);\nWEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra,\n                                           int width, int height, int stride,\n                                           uint8_t** output);\n\n// Releases memory returned by the WebPEncode*() functions above.\nWEBP_EXTERN(void) WebPFree(void* ptr);\n\n//------------------------------------------------------------------------------\n// Coding parameters\n\n// Image characteristics hint for the underlying encoder.\ntypedef enum WebPImageHint {\n  WEBP_HINT_DEFAULT = 0,  // default preset.\n  WEBP_HINT_PICTURE,      // digital picture, like portrait, inner shot\n  WEBP_HINT_PHOTO,        // outdoor photograph, with natural lighting\n  WEBP_HINT_GRAPH,        // Discrete tone image (graph, map-tile etc).\n  WEBP_HINT_LAST\n} WebPImageHint;\n\n// Compression parameters.\nstruct WebPConfig {\n  int lossless;           // Lossless encoding (0=lossy(default), 1=lossless).\n  float quality;          // between 0 (smallest file) and 100 (biggest)\n  int method;             // quality/speed trade-off (0=fast, 6=slower-better)\n\n  WebPImageHint image_hint;  // Hint for image type (lossless only for now).\n\n  // Parameters related to lossy compression only:\n  int target_size;        // if non-zero, set the desired target size in bytes.\n                          // Takes precedence over the 'compression' parameter.\n  float target_PSNR;      // if non-zero, specifies the minimal distortion to\n                          // try to achieve. Takes precedence over target_size.\n  int segments;           // maximum number of segments to use, in [1..4]\n  int sns_strength;       // Spatial Noise Shaping. 0=off, 100=maximum.\n  int filter_strength;    // range: [0 = off .. 100 = strongest]\n  int filter_sharpness;   // range: [0 = off .. 7 = least sharp]\n  int filter_type;        // filtering type: 0 = simple, 1 = strong (only used\n                          // if filter_strength > 0 or autofilter > 0)\n  int autofilter;         // Auto adjust filter's strength [0 = off, 1 = on]\n  int alpha_compression;  // Algorithm for encoding the alpha plane (0 = none,\n                          // 1 = compressed with WebP lossless). Default is 1.\n  int alpha_filtering;    // Predictive filtering method for alpha plane.\n                          //  0: none, 1: fast, 2: best. Default if 1.\n  int alpha_quality;      // Between 0 (smallest size) and 100 (lossless).\n                          // Default is 100.\n  int pass;               // number of entropy-analysis passes (in [1..10]).\n\n  int show_compressed;    // if true, export the compressed picture back.\n                          // In-loop filtering is not applied.\n  int preprocessing;      // preprocessing filter:\n                          // 0=none, 1=segment-smooth, 2=pseudo-random dithering\n  int partitions;         // log2(number of token partitions) in [0..3]. Default\n                          // is set to 0 for easier progressive decoding.\n  int partition_limit;    // quality degradation allowed to fit the 512k limit\n                          // on prediction modes coding (0: no degradation,\n                          // 100: maximum possible degradation).\n  int emulate_jpeg_size;  // If true, compression parameters will be remapped\n                          // to better match the expected output size from\n                          // JPEG compression. Generally, the output size will\n                          // be similar but the degradation will be lower.\n  int thread_level;       // If non-zero, try and use multi-threaded encoding.\n  int low_memory;         // If set, reduce memory usage (but increase CPU use).\n\n  int near_lossless;      // Near lossless encoding [0 = max loss .. 100 = off\n                          // (default)].\n  int exact;              // if non-zero, preserve the exact RGB values under\n                          // transparent area. Otherwise, discard this invisible\n                          // RGB information for better compression. The default\n                          // value is 0.\n\n  int use_delta_palette;  // reserved for future lossless feature\n  int use_sharp_yuv;      // if needed, use sharp (and slow) RGB->YUV conversion\n\n  uint32_t pad[2];        // padding for later use\n};\n\n// Enumerate some predefined settings for WebPConfig, depending on the type\n// of source picture. These presets are used when calling WebPConfigPreset().\ntypedef enum WebPPreset {\n  WEBP_PRESET_DEFAULT = 0,  // default preset.\n  WEBP_PRESET_PICTURE,      // digital picture, like portrait, inner shot\n  WEBP_PRESET_PHOTO,        // outdoor photograph, with natural lighting\n  WEBP_PRESET_DRAWING,      // hand or line drawing, with high-contrast details\n  WEBP_PRESET_ICON,         // small-sized colorful images\n  WEBP_PRESET_TEXT          // text-like\n} WebPPreset;\n\n// Internal, version-checked, entry point\nWEBP_EXTERN(int) WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int);\n\n// Should always be called, to initialize a fresh WebPConfig structure before\n// modification. Returns false in case of version mismatch. WebPConfigInit()\n// must have succeeded before using the 'config' object.\n// Note that the default values are lossless=0 and quality=75.\nstatic WEBP_INLINE int WebPConfigInit(WebPConfig* config) {\n  return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f,\n                                WEBP_ENCODER_ABI_VERSION);\n}\n\n// This function will initialize the configuration according to a predefined\n// set of parameters (referred to by 'preset') and a given quality factor.\n// This function can be called as a replacement to WebPConfigInit(). Will\n// return false in case of error.\nstatic WEBP_INLINE int WebPConfigPreset(WebPConfig* config,\n                                        WebPPreset preset, float quality) {\n  return WebPConfigInitInternal(config, preset, quality,\n                                WEBP_ENCODER_ABI_VERSION);\n}\n\n// Activate the lossless compression mode with the desired efficiency level\n// between 0 (fastest, lowest compression) and 9 (slower, best compression).\n// A good default level is '6', providing a fair tradeoff between compression\n// speed and final compressed size.\n// This function will overwrite several fields from config: 'method', 'quality'\n// and 'lossless'. Returns false in case of parameter error.\nWEBP_EXTERN(int) WebPConfigLosslessPreset(WebPConfig* config, int level);\n\n// Returns true if 'config' is non-NULL and all configuration parameters are\n// within their valid ranges.\nWEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config);\n\n//------------------------------------------------------------------------------\n// Input / Output\n// Structure for storing auxiliary statistics (mostly for lossy encoding).\n\nstruct WebPAuxStats {\n  int coded_size;         // final size\n\n  float PSNR[5];          // peak-signal-to-noise ratio for Y/U/V/All/Alpha\n  int block_count[3];     // number of intra4/intra16/skipped macroblocks\n  int header_bytes[2];    // approximate number of bytes spent for header\n                          // and mode-partition #0\n  int residual_bytes[3][4];  // approximate number of bytes spent for\n                             // DC/AC/uv coefficients for each (0..3) segments.\n  int segment_size[4];    // number of macroblocks in each segments\n  int segment_quant[4];   // quantizer values for each segments\n  int segment_level[4];   // filtering strength for each segments [0..63]\n\n  int alpha_data_size;    // size of the transparency data\n  int layer_data_size;    // size of the enhancement layer data\n\n  // lossless encoder statistics\n  uint32_t lossless_features;  // bit0:predictor bit1:cross-color transform\n                               // bit2:subtract-green bit3:color indexing\n  int histogram_bits;          // number of precision bits of histogram\n  int transform_bits;          // precision bits for transform\n  int cache_bits;              // number of bits for color cache lookup\n  int palette_size;            // number of color in palette, if used\n  int lossless_size;           // final lossless size\n  int lossless_hdr_size;       // lossless header (transform, huffman etc) size\n  int lossless_data_size;      // lossless image data size\n\n  uint32_t pad[2];        // padding for later use\n};\n\n// Signature for output function. Should return true if writing was successful.\n// data/data_size is the segment of data to write, and 'picture' is for\n// reference (and so one can make use of picture->custom_ptr).\ntypedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size,\n                                  const WebPPicture* picture);\n\n// WebPMemoryWrite: a special WebPWriterFunction that writes to memory using\n// the following WebPMemoryWriter object (to be set as a custom_ptr).\nstruct WebPMemoryWriter {\n  uint8_t* mem;       // final buffer (of size 'max_size', larger than 'size').\n  size_t   size;      // final size\n  size_t   max_size;  // total capacity\n  uint32_t pad[1];    // padding for later use\n};\n\n// The following must be called first before any use.\nWEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer);\n\n// The following must be called to deallocate writer->mem memory. The 'writer'\n// object itself is not deallocated.\nWEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer);\n// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon\n// completion, writer.mem and writer.size will hold the coded data.\n// writer.mem must be freed by calling WebPMemoryWriterClear.\nWEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size,\n                                 const WebPPicture* picture);\n\n// Progress hook, called from time to time to report progress. It can return\n// false to request an abort of the encoding process, or true otherwise if\n// everything is OK.\ntypedef int (*WebPProgressHook)(int percent, const WebPPicture* picture);\n\n// Color spaces.\ntypedef enum WebPEncCSP {\n  // chroma sampling\n  WEBP_YUV420  = 0,        // 4:2:0\n  WEBP_YUV420A = 4,        // alpha channel variant\n  WEBP_CSP_UV_MASK = 3,    // bit-mask to get the UV sampling factors\n  WEBP_CSP_ALPHA_BIT = 4   // bit that is set if alpha is present\n} WebPEncCSP;\n\n// Encoding error conditions.\ntypedef enum WebPEncodingError {\n  VP8_ENC_OK = 0,\n  VP8_ENC_ERROR_OUT_OF_MEMORY,            // memory error allocating objects\n  VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY,  // memory error while flushing bits\n  VP8_ENC_ERROR_NULL_PARAMETER,           // a pointer parameter is NULL\n  VP8_ENC_ERROR_INVALID_CONFIGURATION,    // configuration is invalid\n  VP8_ENC_ERROR_BAD_DIMENSION,            // picture has invalid width/height\n  VP8_ENC_ERROR_PARTITION0_OVERFLOW,      // partition is bigger than 512k\n  VP8_ENC_ERROR_PARTITION_OVERFLOW,       // partition is bigger than 16M\n  VP8_ENC_ERROR_BAD_WRITE,                // error while flushing bytes\n  VP8_ENC_ERROR_FILE_TOO_BIG,             // file is bigger than 4G\n  VP8_ENC_ERROR_USER_ABORT,               // abort request by user\n  VP8_ENC_ERROR_LAST                      // list terminator. always last.\n} WebPEncodingError;\n\n// maximum width/height allowed (inclusive), in pixels\n#define WEBP_MAX_DIMENSION 16383\n\n// Main exchange structure (input samples, output bytes, statistics)\nstruct WebPPicture {\n  //   INPUT\n  //////////////\n  // Main flag for encoder selecting between ARGB or YUV input.\n  // It is recommended to use ARGB input (*argb, argb_stride) for lossless\n  // compression, and YUV input (*y, *u, *v, etc.) for lossy compression\n  // since these are the respective native colorspace for these formats.\n  int use_argb;\n\n  // YUV input (mostly used for input to lossy compression)\n  WebPEncCSP colorspace;     // colorspace: should be YUV420 for now (=Y'CbCr).\n  int width, height;         // dimensions (less or equal to WEBP_MAX_DIMENSION)\n  uint8_t *y, *u, *v;        // pointers to luma/chroma planes.\n  int y_stride, uv_stride;   // luma/chroma strides.\n  uint8_t* a;                // pointer to the alpha plane\n  int a_stride;              // stride of the alpha plane\n  uint32_t pad1[2];          // padding for later use\n\n  // ARGB input (mostly used for input to lossless compression)\n  uint32_t* argb;            // Pointer to argb (32 bit) plane.\n  int argb_stride;           // This is stride in pixels units, not bytes.\n  uint32_t pad2[3];          // padding for later use\n\n  //   OUTPUT\n  ///////////////\n  // Byte-emission hook, to store compressed bytes as they are ready.\n  WebPWriterFunction writer;  // can be NULL\n  void* custom_ptr;           // can be used by the writer.\n\n  // map for extra information (only for lossy compression mode)\n  int extra_info_type;    // 1: intra type, 2: segment, 3: quant\n                          // 4: intra-16 prediction mode,\n                          // 5: chroma prediction mode,\n                          // 6: bit cost, 7: distortion\n  uint8_t* extra_info;    // if not NULL, points to an array of size\n                          // ((width + 15) / 16) * ((height + 15) / 16) that\n                          // will be filled with a macroblock map, depending\n                          // on extra_info_type.\n\n  //   STATS AND REPORTS\n  ///////////////////////////\n  // Pointer to side statistics (updated only if not NULL)\n  WebPAuxStats* stats;\n\n  // Error code for the latest error encountered during encoding\n  WebPEncodingError error_code;\n\n  // If not NULL, report progress during encoding.\n  WebPProgressHook progress_hook;\n\n  void* user_data;        // this field is free to be set to any value and\n                          // used during callbacks (like progress-report e.g.).\n\n  uint32_t pad3[3];       // padding for later use\n\n  // Unused for now\n  uint8_t *pad4, *pad5;\n  uint32_t pad6[8];       // padding for later use\n\n  // PRIVATE FIELDS\n  ////////////////////\n  void* memory_;          // row chunk of memory for yuva planes\n  void* memory_argb_;     // and for argb too.\n  void* pad7[2];          // padding for later use\n};\n\n// Internal, version-checked, entry point\nWEBP_EXTERN(int) WebPPictureInitInternal(WebPPicture*, int);\n\n// Should always be called, to initialize the structure. Returns false in case\n// of version mismatch. WebPPictureInit() must have succeeded before using the\n// 'picture' object.\n// Note that, by default, use_argb is false and colorspace is WEBP_YUV420.\nstatic WEBP_INLINE int WebPPictureInit(WebPPicture* picture) {\n  return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION);\n}\n\n//------------------------------------------------------------------------------\n// WebPPicture utils\n\n// Convenience allocation / deallocation based on picture->width/height:\n// Allocate y/u/v buffers as per colorspace/width/height specification.\n// Note! This function will free the previous buffer if needed.\n// Returns false in case of memory error.\nWEBP_EXTERN(int) WebPPictureAlloc(WebPPicture* picture);\n\n// Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*().\n// Note that this function does _not_ free the memory used by the 'picture'\n// object itself.\n// Besides memory (which is reclaimed) all other fields of 'picture' are\n// preserved.\nWEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture);\n\n// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst\n// will fully own the copied pixels (this is not a view). The 'dst' picture need\n// not be initialized as its content is overwritten.\n// Returns false in case of memory allocation error.\nWEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst);\n\n// Compute the single distortion for packed planes of samples.\n// 'src' will be compared to 'ref', and the raw distortion stored into\n// '*distortion'. The refined metric (log(MSE), log(1 - ssim),...' will be\n// stored in '*result'.\n// 'x_step' is the horizontal stride (in bytes) between samples.\n// 'src/ref_stride' is the byte distance between rows.\n// Returns false in case of error (bad parameter, memory allocation error, ...).\nWEBP_EXTERN(int) WebPPlaneDistortion(const uint8_t* src, size_t src_stride,\n                                     const uint8_t* ref, size_t ref_stride,\n                                     int width, int height,\n                                     size_t x_step,\n                                     int type,   // 0 = PSNR, 1 = SSIM, 2 = LSIM\n                                     float* distortion, float* result);\n\n// Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results\n// are in dB, stored in result[] in the B/G/R/A/All order. The distortion is\n// always performed using ARGB samples. Hence if the input is YUV(A), the\n// picture will be internally converted to ARGB (just for the measurement).\n// Warning: this function is rather CPU-intensive.\nWEBP_EXTERN(int) WebPPictureDistortion(\n    const WebPPicture* src, const WebPPicture* ref,\n    int metric_type,           // 0 = PSNR, 1 = SSIM, 2 = LSIM\n    float result[5]);\n\n// self-crops a picture to the rectangle defined by top/left/width/height.\n// Returns false in case of memory allocation error, or if the rectangle is\n// outside of the source picture.\n// The rectangle for the view is defined by the top-left corner pixel\n// coordinates (left, top) as well as its width and height. This rectangle\n// must be fully be comprised inside the 'src' source picture. If the source\n// picture uses the YUV420 colorspace, the top and left coordinates will be\n// snapped to even values.\nWEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture,\n                                 int left, int top, int width, int height);\n\n// Extracts a view from 'src' picture into 'dst'. The rectangle for the view\n// is defined by the top-left corner pixel coordinates (left, top) as well\n// as its width and height. This rectangle must be fully be comprised inside\n// the 'src' source picture. If the source picture uses the YUV420 colorspace,\n// the top and left coordinates will be snapped to even values.\n// Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed\n// ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so,\n// the original dimension will be lost). Picture 'dst' need not be initialized\n// with WebPPictureInit() if it is different from 'src', since its content will\n// be overwritten.\n// Returns false in case of memory allocation error or invalid parameters.\nWEBP_EXTERN(int) WebPPictureView(const WebPPicture* src,\n                                 int left, int top, int width, int height,\n                                 WebPPicture* dst);\n\n// Returns true if the 'picture' is actually a view and therefore does\n// not own the memory for pixels.\nWEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture);\n\n// Rescale a picture to new dimension width x height.\n// If either 'width' or 'height' (but not both) is 0 the corresponding\n// dimension will be calculated preserving the aspect ratio.\n// No gamma correction is applied.\n// Returns false in case of error (invalid parameter or insufficient memory).\nWEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height);\n\n// Colorspace conversion function to import RGB samples.\n// Previous buffer will be free'd, if any.\n// *rgb buffer should have a size of at least height * rgb_stride.\n// Returns false in case of memory error.\nWEBP_EXTERN(int) WebPPictureImportRGB(\n    WebPPicture* picture, const uint8_t* rgb, int rgb_stride);\n// Same, but for RGBA buffer.\nWEBP_EXTERN(int) WebPPictureImportRGBA(\n    WebPPicture* picture, const uint8_t* rgba, int rgba_stride);\n// Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format\n// input buffer ignoring the alpha channel. Avoids needing to copy the data\n// to a temporary 24-bit RGB buffer to import the RGB only.\nWEBP_EXTERN(int) WebPPictureImportRGBX(\n    WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride);\n\n// Variants of the above, but taking BGR(A|X) input.\nWEBP_EXTERN(int) WebPPictureImportBGR(\n    WebPPicture* picture, const uint8_t* bgr, int bgr_stride);\nWEBP_EXTERN(int) WebPPictureImportBGRA(\n    WebPPicture* picture, const uint8_t* bgra, int bgra_stride);\nWEBP_EXTERN(int) WebPPictureImportBGRX(\n    WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride);\n\n// Converts picture->argb data to the YUV420A format. The 'colorspace'\n// parameter is deprecated and should be equal to WEBP_YUV420.\n// Upon return, picture->use_argb is set to false. The presence of real\n// non-opaque transparent values is detected, and 'colorspace' will be\n// adjusted accordingly. Note that this method is lossy.\n// Returns false in case of error.\nWEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,\n                                       WebPEncCSP /*colorspace = WEBP_YUV420*/);\n\n// Same as WebPPictureARGBToYUVA(), but the conversion is done using\n// pseudo-random dithering with a strength 'dithering' between\n// 0.0 (no dithering) and 1.0 (maximum dithering). This is useful\n// for photographic picture.\nWEBP_EXTERN(int) WebPPictureARGBToYUVADithered(\n    WebPPicture* picture, WebPEncCSP colorspace, float dithering);\n\n// Performs 'sharp' RGBA->YUVA420 downsampling and colorspace conversion.\n// Downsampling is handled with extra care in case of color clipping. This\n// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better\n// and sharper YUV representation.\n// Returns false in case of error.\nWEBP_EXTERN(int) WebPPictureSharpARGBToYUVA(WebPPicture* picture);\n// kept for backward compatibility:\nWEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture);\n\n// Converts picture->yuv to picture->argb and sets picture->use_argb to true.\n// The input format must be YUV_420 or YUV_420A. The conversion from YUV420 to\n// ARGB incurs a small loss too.\n// Note that the use of this colorspace is discouraged if one has access to the\n// raw ARGB samples, since using YUV420 is comparatively lossy.\n// Returns false in case of error.\nWEBP_EXTERN(int) WebPPictureYUVAToARGB(WebPPicture* picture);\n\n// Helper function: given a width x height plane of RGBA or YUV(A) samples\n// clean-up the YUV or RGB samples under fully transparent area, to help\n// compressibility (no guarantee, though).\nWEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* picture);\n\n// Scan the picture 'picture' for the presence of non fully opaque alpha values.\n// Returns true in such case. Otherwise returns false (indicating that the\n// alpha plane can be ignored altogether e.g.).\nWEBP_EXTERN(int) WebPPictureHasTransparency(const WebPPicture* picture);\n\n// Remove the transparency information (if present) by blending the color with\n// the background color 'background_rgb' (specified as 24bit RGB triplet).\n// After this call, all alpha values are reset to 0xff.\nWEBP_EXTERN(void) WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb);\n\n//------------------------------------------------------------------------------\n// Main call\n\n// Main encoding call, after config and picture have been initialized.\n// 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION),\n// and the 'config' object must be a valid one.\n// Returns false in case of error, true otherwise.\n// In case of error, picture->error_code is updated accordingly.\n// 'picture' can hold the source samples in both YUV(A) or ARGB input, depending\n// on the value of 'picture->use_argb'. It is highly recommended to use\n// the former for lossy encoding, and the latter for lossless encoding\n// (when config.lossless is true). Automatic conversion from one format to\n// another is provided but they both incur some loss.\nWEBP_EXTERN(int) WebPEncode(const WebPConfig* config, WebPPicture* picture);\n\n//------------------------------------------------------------------------------\n\n#ifdef __cplusplus\n}    // extern \"C\"\n#endif\n\n#endif  /* WEBP_WEBP_ENCODE_H_ */\n"
  },
  {
    "path": "WebP.framework/Headers/format_constants.h",
    "content": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Use of this source code is governed by a BSD-style license\n// that can be found in the COPYING file in the root of the source\n// tree. An additional intellectual property rights grant can be found\n// in the file PATENTS. All contributing project authors may\n// be found in the AUTHORS file in the root of the source tree.\n// -----------------------------------------------------------------------------\n//\n//  Internal header for constants related to WebP file format.\n//\n// Author: Urvang (urvang@google.com)\n\n#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_\n#define WEBP_WEBP_FORMAT_CONSTANTS_H_\n\n// Create fourcc of the chunk from the chunk tag characters.\n#define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24)\n\n// VP8 related constants.\n#define VP8_SIGNATURE 0x9d012a              // Signature in VP8 data.\n#define VP8_MAX_PARTITION0_SIZE (1 << 19)   // max size of mode partition\n#define VP8_MAX_PARTITION_SIZE  (1 << 24)   // max size for token partition\n#define VP8_FRAME_HEADER_SIZE 10  // Size of the frame header within VP8 data.\n\n// VP8L related constants.\n#define VP8L_SIGNATURE_SIZE          1      // VP8L signature size.\n#define VP8L_MAGIC_BYTE              0x2f   // VP8L signature byte.\n#define VP8L_IMAGE_SIZE_BITS         14     // Number of bits used to store\n                                            // width and height.\n#define VP8L_VERSION_BITS            3      // 3 bits reserved for version.\n#define VP8L_VERSION                 0      // version 0\n#define VP8L_FRAME_HEADER_SIZE       5      // Size of the VP8L frame header.\n\n#define MAX_PALETTE_SIZE             256\n#define MAX_CACHE_BITS               11\n#define HUFFMAN_CODES_PER_META_CODE  5\n#define ARGB_BLACK                   0xff000000\n\n#define DEFAULT_CODE_LENGTH          8\n#define MAX_ALLOWED_CODE_LENGTH      15\n\n#define NUM_LITERAL_CODES            256\n#define NUM_LENGTH_CODES             24\n#define NUM_DISTANCE_CODES           40\n#define CODE_LENGTH_CODES            19\n\n#define MIN_HUFFMAN_BITS             2  // min number of Huffman bits\n#define MAX_HUFFMAN_BITS             9  // max number of Huffman bits\n\n#define TRANSFORM_PRESENT            1  // The bit to be written when next data\n                                        // to be read is a transform.\n#define NUM_TRANSFORMS               4  // Maximum number of allowed transform\n                                        // in a bitstream.\ntypedef enum {\n  PREDICTOR_TRANSFORM      = 0,\n  CROSS_COLOR_TRANSFORM    = 1,\n  SUBTRACT_GREEN           = 2,\n  COLOR_INDEXING_TRANSFORM = 3\n} VP8LImageTransformType;\n\n// Alpha related constants.\n#define ALPHA_HEADER_LEN            1\n#define ALPHA_NO_COMPRESSION        0\n#define ALPHA_LOSSLESS_COMPRESSION  1\n#define ALPHA_PREPROCESSED_LEVELS   1\n\n// Mux related constants.\n#define TAG_SIZE           4     // Size of a chunk tag (e.g. \"VP8L\").\n#define CHUNK_SIZE_BYTES   4     // Size needed to store chunk's size.\n#define CHUNK_HEADER_SIZE  8     // Size of a chunk header.\n#define RIFF_HEADER_SIZE   12    // Size of the RIFF header (\"RIFFnnnnWEBP\").\n#define ANMF_CHUNK_SIZE    16    // Size of an ANMF chunk.\n#define ANIM_CHUNK_SIZE    6     // Size of an ANIM chunk.\n#define VP8X_CHUNK_SIZE    10    // Size of a VP8X chunk.\n\n#define MAX_CANVAS_SIZE     (1 << 24)     // 24-bit max for VP8X width/height.\n#define MAX_IMAGE_AREA      (1ULL << 32)  // 32-bit max for width x height.\n#define MAX_LOOP_COUNT      (1 << 16)     // maximum value for loop-count\n#define MAX_DURATION        (1 << 24)     // maximum duration\n#define MAX_POSITION_OFFSET (1 << 24)     // maximum frame x/y offset\n\n// Maximum chunk payload is such that adding the header and padding won't\n// overflow a uint32_t.\n#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1)\n\n#endif  /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */\n"
  },
  {
    "path": "WebP.framework/Headers/mux.h",
    "content": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Use of this source code is governed by a BSD-style license\n// that can be found in the COPYING file in the root of the source\n// tree. An additional intellectual property rights grant can be found\n// in the file PATENTS. All contributing project authors may\n// be found in the AUTHORS file in the root of the source tree.\n// -----------------------------------------------------------------------------\n//\n//  RIFF container manipulation and encoding for WebP images.\n//\n// Authors: Urvang (urvang@google.com)\n//          Vikas (vikasa@google.com)\n\n#ifndef WEBP_WEBP_MUX_H_\n#define WEBP_WEBP_MUX_H_\n\n#include \"./mux_types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define WEBP_MUX_ABI_VERSION 0x0108        // MAJOR(8b) + MINOR(8b)\n\n//------------------------------------------------------------------------------\n// Mux API\n//\n// This API allows manipulation of WebP container images containing features\n// like color profile, metadata, animation.\n//\n// Code Example#1: Create a WebPMux object with image data, color profile and\n// XMP metadata.\n/*\n  int copy_data = 0;\n  WebPMux* mux = WebPMuxNew();\n  // ... (Prepare image data).\n  WebPMuxSetImage(mux, &image, copy_data);\n  // ... (Prepare ICCP color profile data).\n  WebPMuxSetChunk(mux, \"ICCP\", &icc_profile, copy_data);\n  // ... (Prepare XMP metadata).\n  WebPMuxSetChunk(mux, \"XMP \", &xmp, copy_data);\n  // Get data from mux in WebP RIFF format.\n  WebPMuxAssemble(mux, &output_data);\n  WebPMuxDelete(mux);\n  // ... (Consume output_data; e.g. write output_data.bytes to file).\n  WebPDataClear(&output_data);\n*/\n\n// Code Example#2: Get image and color profile data from a WebP file.\n/*\n  int copy_data = 0;\n  // ... (Read data from file).\n  WebPMux* mux = WebPMuxCreate(&data, copy_data);\n  WebPMuxGetFrame(mux, 1, &image);\n  // ... (Consume image; e.g. call WebPDecode() to decode the data).\n  WebPMuxGetChunk(mux, \"ICCP\", &icc_profile);\n  // ... (Consume icc_data).\n  WebPMuxDelete(mux);\n  free(data);\n*/\n\n// Note: forward declaring enumerations is not allowed in (strict) C and C++,\n// the types are left here for reference.\n// typedef enum WebPMuxError WebPMuxError;\n// typedef enum WebPChunkId WebPChunkId;\ntypedef struct WebPMux WebPMux;   // main opaque object.\ntypedef struct WebPMuxFrameInfo WebPMuxFrameInfo;\ntypedef struct WebPMuxAnimParams WebPMuxAnimParams;\ntypedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions;\n\n// Error codes\ntypedef enum WebPMuxError {\n  WEBP_MUX_OK                 =  1,\n  WEBP_MUX_NOT_FOUND          =  0,\n  WEBP_MUX_INVALID_ARGUMENT   = -1,\n  WEBP_MUX_BAD_DATA           = -2,\n  WEBP_MUX_MEMORY_ERROR       = -3,\n  WEBP_MUX_NOT_ENOUGH_DATA    = -4\n} WebPMuxError;\n\n// IDs for different types of chunks.\ntypedef enum WebPChunkId {\n  WEBP_CHUNK_VP8X,        // VP8X\n  WEBP_CHUNK_ICCP,        // ICCP\n  WEBP_CHUNK_ANIM,        // ANIM\n  WEBP_CHUNK_ANMF,        // ANMF\n  WEBP_CHUNK_DEPRECATED,  // (deprecated from FRGM)\n  WEBP_CHUNK_ALPHA,       // ALPH\n  WEBP_CHUNK_IMAGE,       // VP8/VP8L\n  WEBP_CHUNK_EXIF,        // EXIF\n  WEBP_CHUNK_XMP,         // XMP\n  WEBP_CHUNK_UNKNOWN,     // Other chunks.\n  WEBP_CHUNK_NIL\n} WebPChunkId;\n\n//------------------------------------------------------------------------------\n\n// Returns the version number of the mux library, packed in hexadecimal using\n// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.\nWEBP_EXTERN(int) WebPGetMuxVersion(void);\n\n//------------------------------------------------------------------------------\n// Life of a Mux object\n\n// Internal, version-checked, entry point\nWEBP_EXTERN(WebPMux*) WebPNewInternal(int);\n\n// Creates an empty mux object.\n// Returns:\n//   A pointer to the newly created empty mux object.\n//   Or NULL in case of memory error.\nstatic WEBP_INLINE WebPMux* WebPMuxNew(void) {\n  return WebPNewInternal(WEBP_MUX_ABI_VERSION);\n}\n\n// Deletes the mux object.\n// Parameters:\n//   mux - (in/out) object to be deleted\nWEBP_EXTERN(void) WebPMuxDelete(WebPMux* mux);\n\n//------------------------------------------------------------------------------\n// Mux creation.\n\n// Internal, version-checked, entry point\nWEBP_EXTERN(WebPMux*) WebPMuxCreateInternal(const WebPData*, int, int);\n\n// Creates a mux object from raw data given in WebP RIFF format.\n// Parameters:\n//   bitstream - (in) the bitstream data in WebP RIFF format\n//   copy_data - (in) value 1 indicates given data WILL be copied to the mux\n//               object and value 0 indicates data will NOT be copied.\n// Returns:\n//   A pointer to the mux object created from given data - on success.\n//   NULL - In case of invalid data or memory error.\nstatic WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream,\n                                          int copy_data) {\n  return WebPMuxCreateInternal(bitstream, copy_data, WEBP_MUX_ABI_VERSION);\n}\n\n//------------------------------------------------------------------------------\n// Non-image chunks.\n\n// Note: Only non-image related chunks should be managed through chunk APIs.\n// (Image related chunks are: \"ANMF\", \"VP8 \", \"VP8L\" and \"ALPH\").\n// To add, get and delete images, use WebPMuxSetImage(), WebPMuxPushFrame(),\n// WebPMuxGetFrame() and WebPMuxDeleteFrame().\n\n// Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object.\n// Any existing chunk(s) with the same id will be removed.\n// Parameters:\n//   mux - (in/out) object to which the chunk is to be added\n//   fourcc - (in) a character array containing the fourcc of the given chunk;\n//                 e.g., \"ICCP\", \"XMP \", \"EXIF\" etc.\n//   chunk_data - (in) the chunk data to be added\n//   copy_data - (in) value 1 indicates given data WILL be copied to the mux\n//               object and value 0 indicates data will NOT be copied.\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL\n//                               or if fourcc corresponds to an image chunk.\n//   WEBP_MUX_MEMORY_ERROR - on memory allocation error.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxSetChunk(\n    WebPMux* mux, const char fourcc[4], const WebPData* chunk_data,\n    int copy_data);\n\n// Gets a reference to the data of the chunk with id 'fourcc' in the mux object.\n// The caller should NOT free the returned data.\n// Parameters:\n//   mux - (in) object from which the chunk data is to be fetched\n//   fourcc - (in) a character array containing the fourcc of the chunk;\n//                 e.g., \"ICCP\", \"XMP \", \"EXIF\" etc.\n//   chunk_data - (out) returned chunk data\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL\n//                               or if fourcc corresponds to an image chunk.\n//   WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxGetChunk(\n    const WebPMux* mux, const char fourcc[4], WebPData* chunk_data);\n\n// Deletes the chunk with the given 'fourcc' from the mux object.\n// Parameters:\n//   mux - (in/out) object from which the chunk is to be deleted\n//   fourcc - (in) a character array containing the fourcc of the chunk;\n//                 e.g., \"ICCP\", \"XMP \", \"EXIF\" etc.\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux or fourcc is NULL\n//                               or if fourcc corresponds to an image chunk.\n//   WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk(\n    WebPMux* mux, const char fourcc[4]);\n\n//------------------------------------------------------------------------------\n// Images.\n\n// Encapsulates data about a single frame.\nstruct WebPMuxFrameInfo {\n  WebPData    bitstream;  // image data: can be a raw VP8/VP8L bitstream\n                          // or a single-image WebP file.\n  int         x_offset;   // x-offset of the frame.\n  int         y_offset;   // y-offset of the frame.\n  int         duration;   // duration of the frame (in milliseconds).\n\n  WebPChunkId id;         // frame type: should be one of WEBP_CHUNK_ANMF\n                          // or WEBP_CHUNK_IMAGE\n  WebPMuxAnimDispose dispose_method;  // Disposal method for the frame.\n  WebPMuxAnimBlend   blend_method;    // Blend operation for the frame.\n  uint32_t    pad[1];     // padding for later use\n};\n\n// Sets the (non-animated) image in the mux object.\n// Note: Any existing images (including frames) will be removed.\n// Parameters:\n//   mux - (in/out) object in which the image is to be set\n//   bitstream - (in) can be a raw VP8/VP8L bitstream or a single-image\n//               WebP file (non-animated)\n//   copy_data - (in) value 1 indicates given data WILL be copied to the mux\n//               object and value 0 indicates data will NOT be copied.\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL.\n//   WEBP_MUX_MEMORY_ERROR - on memory allocation error.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxSetImage(\n    WebPMux* mux, const WebPData* bitstream, int copy_data);\n\n// Adds a frame at the end of the mux object.\n// Notes: (1) frame.id should be WEBP_CHUNK_ANMF\n//        (2) For setting a non-animated image, use WebPMuxSetImage() instead.\n//        (3) Type of frame being pushed must be same as the frames in mux.\n//        (4) As WebP only supports even offsets, any odd offset will be snapped\n//            to an even location using: offset &= ~1\n// Parameters:\n//   mux - (in/out) object to which the frame is to be added\n//   frame - (in) frame data.\n//   copy_data - (in) value 1 indicates given data WILL be copied to the mux\n//               object and value 0 indicates data will NOT be copied.\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL\n//                               or if content of 'frame' is invalid.\n//   WEBP_MUX_MEMORY_ERROR - on memory allocation error.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxPushFrame(\n    WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data);\n\n// Gets the nth frame from the mux object.\n// The content of 'frame->bitstream' is allocated using malloc(), and NOT\n// owned by the 'mux' object. It MUST be deallocated by the caller by calling\n// WebPDataClear().\n// nth=0 has a special meaning - last position.\n// Parameters:\n//   mux - (in) object from which the info is to be fetched\n//   nth - (in) index of the frame in the mux object\n//   frame - (out) data of the returned frame\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL.\n//   WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object.\n//   WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid.\n//   WEBP_MUX_MEMORY_ERROR - on memory allocation error.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxGetFrame(\n    const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame);\n\n// Deletes a frame from the mux object.\n// nth=0 has a special meaning - last position.\n// Parameters:\n//   mux - (in/out) object from which a frame is to be deleted\n//   nth - (in) The position from which the frame is to be deleted\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux is NULL.\n//   WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object\n//                        before deletion.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth);\n\n//------------------------------------------------------------------------------\n// Animation.\n\n// Animation parameters.\nstruct WebPMuxAnimParams {\n  uint32_t bgcolor;  // Background color of the canvas stored (in MSB order) as:\n                     // Bits 00 to 07: Alpha.\n                     // Bits 08 to 15: Red.\n                     // Bits 16 to 23: Green.\n                     // Bits 24 to 31: Blue.\n  int loop_count;    // Number of times to repeat the animation [0 = infinite].\n};\n\n// Sets the animation parameters in the mux object. Any existing ANIM chunks\n// will be removed.\n// Parameters:\n//   mux - (in/out) object in which ANIM chunk is to be set/added\n//   params - (in) animation parameters.\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL.\n//   WEBP_MUX_MEMORY_ERROR - on memory allocation error.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxSetAnimationParams(\n    WebPMux* mux, const WebPMuxAnimParams* params);\n\n// Gets the animation parameters from the mux object.\n// Parameters:\n//   mux - (in) object from which the animation parameters to be fetched\n//   params - (out) animation parameters extracted from the ANIM chunk\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL.\n//   WEBP_MUX_NOT_FOUND - if ANIM chunk is not present in mux object.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxGetAnimationParams(\n    const WebPMux* mux, WebPMuxAnimParams* params);\n\n//------------------------------------------------------------------------------\n// Misc Utilities.\n\n// Sets the canvas size for the mux object. The width and height can be\n// specified explicitly or left as zero (0, 0).\n// * When width and height are specified explicitly, then this frame bound is\n//   enforced during subsequent calls to WebPMuxAssemble() and an error is\n//   reported if any animated frame does not completely fit within the canvas.\n// * When unspecified (0, 0), the constructed canvas will get the frame bounds\n//   from the bounding-box over all frames after calling WebPMuxAssemble().\n// Parameters:\n//   mux - (in) object to which the canvas size is to be set\n//   width - (in) canvas width\n//   height - (in) canvas height\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux is NULL; or\n//                               width or height are invalid or out of bounds\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxSetCanvasSize(WebPMux* mux,\n                                               int width, int height);\n\n// Gets the canvas size from the mux object.\n// Note: This method assumes that the VP8X chunk, if present, is up-to-date.\n// That is, the mux object hasn't been modified since the last call to\n// WebPMuxAssemble() or WebPMuxCreate().\n// Parameters:\n//   mux - (in) object from which the canvas size is to be fetched\n//   width - (out) canvas width\n//   height - (out) canvas height\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux, width or height is NULL.\n//   WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxGetCanvasSize(const WebPMux* mux,\n                                               int* width, int* height);\n\n// Gets the feature flags from the mux object.\n// Note: This method assumes that the VP8X chunk, if present, is up-to-date.\n// That is, the mux object hasn't been modified since the last call to\n// WebPMuxAssemble() or WebPMuxCreate().\n// Parameters:\n//   mux - (in) object from which the features are to be fetched\n//   flags - (out) the flags specifying which features are present in the\n//           mux object. This will be an OR of various flag values.\n//           Enum 'WebPFeatureFlags' can be used to test individual flag values.\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL.\n//   WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxGetFeatures(const WebPMux* mux,\n                                             uint32_t* flags);\n\n// Gets number of chunks with the given 'id' in the mux object.\n// Parameters:\n//   mux - (in) object from which the info is to be fetched\n//   id - (in) chunk id specifying the type of chunk\n//   num_elements - (out) number of chunks with the given chunk id\n// Returns:\n//   WEBP_MUX_INVALID_ARGUMENT - if mux, or num_elements is NULL.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux,\n                                           WebPChunkId id, int* num_elements);\n\n// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'.\n// This function also validates the mux object.\n// Note: The content of 'assembled_data' will be ignored and overwritten.\n// Also, the content of 'assembled_data' is allocated using malloc(), and NOT\n// owned by the 'mux' object. It MUST be deallocated by the caller by calling\n// WebPDataClear(). It's always safe to call WebPDataClear() upon return,\n// even in case of error.\n// Parameters:\n//   mux - (in/out) object whose chunks are to be assembled\n//   assembled_data - (out) assembled WebP data\n// Returns:\n//   WEBP_MUX_BAD_DATA - if mux object is invalid.\n//   WEBP_MUX_INVALID_ARGUMENT - if mux or assembled_data is NULL.\n//   WEBP_MUX_MEMORY_ERROR - on memory allocation error.\n//   WEBP_MUX_OK - on success.\nWEBP_EXTERN(WebPMuxError) WebPMuxAssemble(WebPMux* mux,\n                                          WebPData* assembled_data);\n\n//------------------------------------------------------------------------------\n// WebPAnimEncoder API\n//\n// This API allows encoding (possibly) animated WebP images.\n//\n// Code Example:\n/*\n  WebPAnimEncoderOptions enc_options;\n  WebPAnimEncoderOptionsInit(&enc_options);\n  // Tune 'enc_options' as needed.\n  WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options);\n  while(<there are more frames>) {\n    WebPConfig config;\n    WebPConfigInit(&config);\n    // Tune 'config' as needed.\n    WebPAnimEncoderAdd(enc, frame, timestamp_ms, &config);\n  }\n  WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL);\n  WebPAnimEncoderAssemble(enc, webp_data);\n  WebPAnimEncoderDelete(enc);\n  // Write the 'webp_data' to a file, or re-mux it further.\n*/\n\ntypedef struct WebPAnimEncoder WebPAnimEncoder;  // Main opaque object.\n\n// Forward declarations. Defined in encode.h.\nstruct WebPPicture;\nstruct WebPConfig;\n\n// Global options.\nstruct WebPAnimEncoderOptions {\n  WebPMuxAnimParams anim_params;  // Animation parameters.\n  int minimize_size;    // If true, minimize the output size (slow). Implicitly\n                        // disables key-frame insertion.\n  int kmin;\n  int kmax;             // Minimum and maximum distance between consecutive key\n                        // frames in the output. The library may insert some key\n                        // frames as needed to satisfy this criteria.\n                        // Note that these conditions should hold: kmax > kmin\n                        // and kmin >= kmax / 2 + 1. Also, if kmax <= 0, then\n                        // key-frame insertion is disabled; and if kmax == 1,\n                        // then all frames will be key-frames (kmin value does\n                        // not matter for these special cases).\n  int allow_mixed;      // If true, use mixed compression mode; may choose\n                        // either lossy and lossless for each frame.\n  int verbose;          // If true, print info and warning messages to stderr.\n\n  uint32_t padding[4];  // Padding for later use.\n};\n\n// Internal, version-checked, entry point.\nWEBP_EXTERN(int) WebPAnimEncoderOptionsInitInternal(\n    WebPAnimEncoderOptions*, int);\n\n// Should always be called, to initialize a fresh WebPAnimEncoderOptions\n// structure before modification. Returns false in case of version mismatch.\n// WebPAnimEncoderOptionsInit() must have succeeded before using the\n// 'enc_options' object.\nstatic WEBP_INLINE int WebPAnimEncoderOptionsInit(\n    WebPAnimEncoderOptions* enc_options) {\n  return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION);\n}\n\n// Internal, version-checked, entry point.\nWEBP_EXTERN(WebPAnimEncoder*) WebPAnimEncoderNewInternal(\n    int, int, const WebPAnimEncoderOptions*, int);\n\n// Creates and initializes a WebPAnimEncoder object.\n// Parameters:\n//   width/height - (in) canvas width and height of the animation.\n//   enc_options - (in) encoding options; can be passed NULL to pick\n//                      reasonable defaults.\n// Returns:\n//   A pointer to the newly created WebPAnimEncoder object.\n//   Or NULL in case of memory error.\nstatic WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew(\n    int width, int height, const WebPAnimEncoderOptions* enc_options) {\n  return WebPAnimEncoderNewInternal(width, height, enc_options,\n                                    WEBP_MUX_ABI_VERSION);\n}\n\n// Optimize the given frame for WebP, encode it and add it to the\n// WebPAnimEncoder object.\n// The last call to 'WebPAnimEncoderAdd' should be with frame = NULL, which\n// indicates that no more frames are to be added. This call is also used to\n// determine the duration of the last frame.\n// Parameters:\n//   enc - (in/out) object to which the frame is to be added.\n//   frame - (in/out) frame data in ARGB or YUV(A) format. If it is in YUV(A)\n//           format, it will be converted to ARGB, which incurs a small loss.\n//   timestamp_ms - (in) timestamp of this frame in milliseconds.\n//                       Duration of a frame would be calculated as\n//                       \"timestamp of next frame - timestamp of this frame\".\n//                       Hence, timestamps should be in non-decreasing order.\n//   config - (in) encoding options; can be passed NULL to pick\n//            reasonable defaults.\n// Returns:\n//   On error, returns false and frame->error_code is set appropriately.\n//   Otherwise, returns true.\nWEBP_EXTERN(int) WebPAnimEncoderAdd(\n    WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms,\n    const struct WebPConfig* config);\n\n// Assemble all frames added so far into a WebP bitstream.\n// This call should be preceded by  a call to 'WebPAnimEncoderAdd' with\n// frame = NULL; if not, the duration of the last frame will be internally\n// estimated.\n// Parameters:\n//   enc - (in/out) object from which the frames are to be assembled.\n//   webp_data - (out) generated WebP bitstream.\n// Returns:\n//   True on success.\nWEBP_EXTERN(int) WebPAnimEncoderAssemble(WebPAnimEncoder* enc,\n                                         WebPData* webp_data);\n\n// Get error string corresponding to the most recent call using 'enc'. The\n// returned string is owned by 'enc' and is valid only until the next call to\n// WebPAnimEncoderAdd() or WebPAnimEncoderAssemble() or WebPAnimEncoderDelete().\n// Parameters:\n//   enc - (in/out) object from which the error string is to be fetched.\n// Returns:\n//   NULL if 'enc' is NULL. Otherwise, returns the error string if the last call\n//   to 'enc' had an error, or an empty string if the last call was a success.\nWEBP_EXTERN(const char*) WebPAnimEncoderGetError(WebPAnimEncoder* enc);\n\n// Deletes the WebPAnimEncoder object.\n// Parameters:\n//   enc - (in/out) object to be deleted\nWEBP_EXTERN(void) WebPAnimEncoderDelete(WebPAnimEncoder* enc);\n\n//------------------------------------------------------------------------------\n\n#ifdef __cplusplus\n}    // extern \"C\"\n#endif\n\n#endif  /* WEBP_WEBP_MUX_H_ */\n"
  },
  {
    "path": "WebP.framework/Headers/mux_types.h",
    "content": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Use of this source code is governed by a BSD-style license\n// that can be found in the COPYING file in the root of the source\n// tree. An additional intellectual property rights grant can be found\n// in the file PATENTS. All contributing project authors may\n// be found in the AUTHORS file in the root of the source tree.\n// -----------------------------------------------------------------------------\n//\n// Data-types common to the mux and demux libraries.\n//\n// Author: Urvang (urvang@google.com)\n\n#ifndef WEBP_WEBP_MUX_TYPES_H_\n#define WEBP_WEBP_MUX_TYPES_H_\n\n#include <stdlib.h>  // free()\n#include <string.h>  // memset()\n#include \"./types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// Note: forward declaring enumerations is not allowed in (strict) C and C++,\n// the types are left here for reference.\n// typedef enum WebPFeatureFlags WebPFeatureFlags;\n// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose;\n// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend;\ntypedef struct WebPData WebPData;\n\n// VP8X Feature Flags.\ntypedef enum WebPFeatureFlags {\n  ANIMATION_FLAG  = 0x00000002,\n  XMP_FLAG        = 0x00000004,\n  EXIF_FLAG       = 0x00000008,\n  ALPHA_FLAG      = 0x00000010,\n  ICCP_FLAG       = 0x00000020,\n\n  ALL_VALID_FLAGS = 0x0000003e\n} WebPFeatureFlags;\n\n// Dispose method (animation only). Indicates how the area used by the current\n// frame is to be treated before rendering the next frame on the canvas.\ntypedef enum WebPMuxAnimDispose {\n  WEBP_MUX_DISPOSE_NONE,       // Do not dispose.\n  WEBP_MUX_DISPOSE_BACKGROUND  // Dispose to background color.\n} WebPMuxAnimDispose;\n\n// Blend operation (animation only). Indicates how transparent pixels of the\n// current frame are blended with those of the previous canvas.\ntypedef enum WebPMuxAnimBlend {\n  WEBP_MUX_BLEND,              // Blend.\n  WEBP_MUX_NO_BLEND            // Do not blend.\n} WebPMuxAnimBlend;\n\n// Data type used to describe 'raw' data, e.g., chunk data\n// (ICC profile, metadata) and WebP compressed image data.\nstruct WebPData {\n  const uint8_t* bytes;\n  size_t size;\n};\n\n// Initializes the contents of the 'webp_data' object with default values.\nstatic WEBP_INLINE void WebPDataInit(WebPData* webp_data) {\n  if (webp_data != NULL) {\n    memset(webp_data, 0, sizeof(*webp_data));\n  }\n}\n\n// Clears the contents of the 'webp_data' object by calling free(). Does not\n// deallocate the object itself.\nstatic WEBP_INLINE void WebPDataClear(WebPData* webp_data) {\n  if (webp_data != NULL) {\n    free((void*)webp_data->bytes);\n    WebPDataInit(webp_data);\n  }\n}\n\n// Allocates necessary storage for 'dst' and copies the contents of 'src'.\n// Returns true on success.\nstatic WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {\n  if (src == NULL || dst == NULL) return 0;\n  WebPDataInit(dst);\n  if (src->bytes != NULL && src->size != 0) {\n    dst->bytes = (uint8_t*)malloc(src->size);\n    if (dst->bytes == NULL) return 0;\n    memcpy((void*)dst->bytes, src->bytes, src->size);\n    dst->size = src->size;\n  }\n  return 1;\n}\n\n#ifdef __cplusplus\n}    // extern \"C\"\n#endif\n\n#endif  /* WEBP_WEBP_MUX_TYPES_H_ */\n"
  },
  {
    "path": "WebP.framework/Headers/types.h",
    "content": "// Copyright 2010 Google Inc. All Rights Reserved.\n//\n// Use of this source code is governed by a BSD-style license\n// that can be found in the COPYING file in the root of the source\n// tree. An additional intellectual property rights grant can be found\n// in the file PATENTS. All contributing project authors may\n// be found in the AUTHORS file in the root of the source tree.\n// -----------------------------------------------------------------------------\n//\n//  Common types\n//\n// Author: Skal (pascal.massimino@gmail.com)\n\n#ifndef WEBP_WEBP_TYPES_H_\n#define WEBP_WEBP_TYPES_H_\n\n#include <stddef.h>  // for size_t\n\n#ifndef _MSC_VER\n#include <inttypes.h>\n#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \\\n    (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)\n#define WEBP_INLINE inline\n#else\n#define WEBP_INLINE\n#endif\n#else\ntypedef signed   char int8_t;\ntypedef unsigned char uint8_t;\ntypedef signed   short int16_t;\ntypedef unsigned short uint16_t;\ntypedef signed   int int32_t;\ntypedef unsigned int uint32_t;\ntypedef unsigned long long int uint64_t;\ntypedef long long int int64_t;\n#define WEBP_INLINE __forceinline\n#endif  /* _MSC_VER */\n\n#ifndef WEBP_EXTERN\n// This explicitly marks library functions and allows for changing the\n// signature for e.g., Windows DLL builds.\n# if defined(__GNUC__) && __GNUC__ >= 4\n#  define WEBP_EXTERN(type) extern __attribute__ ((visibility (\"default\"))) type\n# else\n#  define WEBP_EXTERN(type) extern type\n# endif  /* __GNUC__ >= 4 */\n#endif  /* WEBP_EXTERN */\n\n// Macro to check ABI compatibility (same major revision number)\n#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))\n\n#endif  /* WEBP_WEBP_TYPES_H_ */\n"
  },
  {
    "path": "WebSocket/AsyncSocket.h",
    "content": "//\n//  AsyncSocket.h\n//\n//  This class is in the public domain.\n//  Originally created by Dustin Voss on Wed Jan 29 2003.\n//  Updated and maintained by Deusty Designs and the Mac development community.\n//\n//  http://code.google.com/p/cocoaasyncsocket/\n//\n\n#import <Foundation/Foundation.h>\n\n@class AsyncSocket;\n@class AsyncReadPacket;\n@class AsyncWritePacket;\n\nextern NSString *const AsyncSocketException;\nextern NSString *const AsyncSocketErrorDomain;\n\nenum AsyncSocketError\n{\n\tAsyncSocketCFSocketError = kCFSocketError,\t// From CFSocketError enum.\n\tAsyncSocketNoError = 0,\t\t\t\t\t\t// Never used.\n\tAsyncSocketCanceledError,\t\t\t\t\t// onSocketWillConnect: returned NO.\n\tAsyncSocketConnectTimeoutError,\n\tAsyncSocketReadMaxedOutError,               // Reached set maxLength without completing\n\tAsyncSocketReadTimeoutError,\n\tAsyncSocketWriteTimeoutError\n};\ntypedef enum AsyncSocketError AsyncSocketError;\n\n@protocol AsyncSocketDelegate\n@optional\n\n/**\n * In the event of an error, the socket is closed.\n * You may call \"unreadData\" during this call-back to get the last bit of data off the socket.\n * When connecting, this delegate method may be called\n * before\"onSocket:didAcceptNewSocket:\" or \"onSocket:didConnectToHost:\".\n **/\n- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;\n\n/**\n * Called when a socket disconnects with or without error.  If you want to release a socket after it disconnects,\n * do so here. It is not safe to do that during \"onSocket:willDisconnectWithError:\".\n *\n * If you call the disconnect method, and the socket wasn't already disconnected,\n * this delegate method will be called before the disconnect method returns.\n **/\n- (void)onSocketDidDisconnect:(AsyncSocket *)sock;\n\n/**\n * Called when a socket accepts a connection.  Another socket is spawned to handle it. The new socket will have\n * the same delegate and will call \"onSocket:didConnectToHost:port:\".\n **/\n- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;\n\n/**\n * Called when a new socket is spawned to handle a connection.  This method should return the run-loop of the\n * thread on which the new socket and its delegate should operate. If omitted, [NSRunLoop currentRunLoop] is used.\n **/\n- (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket;\n\n/**\n * Called when a socket is about to connect. This method should return YES to continue, or NO to abort.\n * If aborted, will result in AsyncSocketCanceledError.\n *\n * If the connectToHost:onPort:error: method was called, the delegate will be able to access and configure the\n * CFReadStream and CFWriteStream as desired prior to connection.\n *\n * If the connectToAddress:error: method was called, the delegate will be able to access and configure the\n * CFSocket and CFSocketNativeHandle (BSD socket) as desired prior to connection. You will be able to access and\n * configure the CFReadStream and CFWriteStream in the onSocket:didConnectToHost:port: method.\n **/\n- (BOOL)onSocketWillConnect:(AsyncSocket *)sock;\n\n/**\n * Called when a socket connects and is ready for reading and writing.\n * The host parameter will be an IP address, not a DNS name.\n **/\n- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port;\n\n/**\n * Called when a socket has completed reading the requested data into memory.\n * Not called if there is an error.\n **/\n- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;\n\n/**\n * Called when a socket has read in data, but has not yet completed the read.\n * This would occur if using readToData: or readToLength: methods.\n * It may be used to for things such as updating progress bars.\n **/\n- (void)onSocket:(AsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;\n\n/**\n * Called when a socket has completed writing the requested data. Not called if there is an error.\n **/\n- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;\n\n/**\n * Called when a socket has written some data, but has not yet completed the entire write.\n * It may be used to for things such as updating progress bars.\n **/\n- (void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;\n\n/**\n * Called if a read operation has reached its timeout without completing.\n * This method allows you to optionally extend the timeout.\n * If you return a positive time interval (> 0) the read's timeout will be extended by the given amount.\n * If you don't implement this method, or return a non-positive time interval (<= 0) the read will timeout as usual.\n *\n * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method.\n * The length parameter is the number of bytes that have been read so far for the read operation.\n *\n * Note that this method may be called multiple times for a single read if you return positive numbers.\n **/\n- (NSTimeInterval)onSocket:(AsyncSocket *)sock\n  shouldTimeoutReadWithTag:(long)tag\n                   elapsed:(NSTimeInterval)elapsed\n                 bytesDone:(NSUInteger)length;\n\n/**\n * Called if a write operation has reached its timeout without completing.\n * This method allows you to optionally extend the timeout.\n * If you return a positive time interval (> 0) the write's timeout will be extended by the given amount.\n * If you don't implement this method, or return a non-positive time interval (<= 0) the write will timeout as usual.\n *\n * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method.\n * The length parameter is the number of bytes that have been written so far for the write operation.\n *\n * Note that this method may be called multiple times for a single write if you return positive numbers.\n **/\n- (NSTimeInterval)onSocket:(AsyncSocket *)sock\n shouldTimeoutWriteWithTag:(long)tag\n                   elapsed:(NSTimeInterval)elapsed\n                 bytesDone:(NSUInteger)length;\n\n/**\n * Called after the socket has successfully completed SSL/TLS negotiation.\n * This method is not called unless you use the provided startTLS method.\n *\n * If a SSL/TLS negotiation fails (invalid certificate, etc) then the socket will immediately close,\n * and the onSocket:willDisconnectWithError: delegate method will be called with the specific SSL error code.\n **/\n- (void)onSocketDidSecure:(AsyncSocket *)sock;\n\n@end\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark -\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n@interface AsyncSocket : NSObject\n{\n\tCFSocketNativeHandle theNativeSocket4;\n\tCFSocketNativeHandle theNativeSocket6;\n\t\n\tCFSocketRef theSocket4;            // IPv4 accept or connect socket\n\tCFSocketRef theSocket6;            // IPv6 accept or connect socket\n\t\n\tCFReadStreamRef theReadStream;\n\tCFWriteStreamRef theWriteStream;\n    \n\tCFRunLoopSourceRef theSource4;     // For theSocket4\n\tCFRunLoopSourceRef theSource6;     // For theSocket6\n\tCFRunLoopRef theRunLoop;\n\tCFSocketContext theContext;\n\tNSArray *theRunLoopModes;\n\t\n\tNSTimer *theConnectTimer;\n    \n\tNSMutableArray *theReadQueue;\n\tAsyncReadPacket *theCurrentRead;\n\tNSTimer *theReadTimer;\n\tNSMutableData *partialReadBuffer;\n\t\n\tNSMutableArray *theWriteQueue;\n\tAsyncWritePacket *theCurrentWrite;\n\tNSTimer *theWriteTimer;\n    \n\tid theDelegate;\n\tUInt16 theFlags;\n\t\n\tlong theUserData;\n}\n\n- (id)init;\n- (id)initWithDelegate:(id)delegate;\n- (id)initWithDelegate:(id)delegate userData:(long)userData;\n\n/* String representation is long but has no \"\\n\". */\n- (NSString *)description;\n\n/**\n * Use \"canSafelySetDelegate\" to see if there is any pending business (reads and writes) with the current delegate\n * before changing it.  It is, of course, safe to change the delegate before connecting or accepting connections.\n **/\n- (id)delegate;\n- (BOOL)canSafelySetDelegate;\n- (void)setDelegate:(id)delegate;\n\n/* User data can be a long, or an id or void * cast to a long. */\n- (long)userData;\n- (void)setUserData:(long)userData;\n\n/* Don't use these to read or write. And don't close them either! */\n- (CFSocketRef)getCFSocket;\n- (CFReadStreamRef)getCFReadStream;\n- (CFWriteStreamRef)getCFWriteStream;\n\n// Once one of the accept or connect methods are called, the AsyncSocket instance is locked in\n// and the other accept/connect methods can't be called without disconnecting the socket first.\n// If the attempt fails or times out, these methods either return NO or\n// call \"onSocket:willDisconnectWithError:\" and \"onSockedDidDisconnect:\".\n\n// When an incoming connection is accepted, AsyncSocket invokes several delegate methods.\n// These methods are (in chronological order):\n// 1. onSocket:didAcceptNewSocket:\n// 2. onSocket:wantsRunLoopForNewSocket:\n// 3. onSocketWillConnect:\n//\n// Your server code will need to retain the accepted socket (if you want to accept it).\n// The best place to do this is probably in the onSocket:didAcceptNewSocket: method.\n//\n// After the read and write streams have been setup for the newly accepted socket,\n// the onSocket:didConnectToHost:port: method will be called on the proper run loop.\n//\n// Multithreading Note: If you're going to be moving the newly accepted socket to another run\n// loop by implementing onSocket:wantsRunLoopForNewSocket:, then you should wait until the\n// onSocket:didConnectToHost:port: method before calling read, write, or startTLS methods.\n// Otherwise read/write events are scheduled on the incorrect runloop, and chaos may ensue.\n\n/**\n * Tells the socket to begin listening and accepting connections on the given port.\n * When a connection comes in, the AsyncSocket instance will call the various delegate methods (see above).\n * The socket will listen on all available interfaces (e.g. wifi, ethernet, etc)\n **/\n- (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr;\n\n/**\n * This method is the same as acceptOnPort:error: with the additional option\n * of specifying which interface to listen on. So, for example, if you were writing code for a server that\n * has multiple IP addresses, you could specify which address you wanted to listen on.  Or you could use it\n * to specify that the socket should only accept connections over ethernet, and not other interfaces such as wifi.\n * You may also use the special strings \"localhost\" or \"loopback\" to specify that\n * the socket only accept connections from the local machine.\n *\n * To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method.\n **/\n- (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr;\n\n/**\n * Connects to the given host and port.\n * The host may be a domain name (e.g. \"deusty.com\") or an IP address string (e.g. \"192.168.0.2\")\n **/\n- (BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr;\n\n/**\n * This method is the same as connectToHost:onPort:error: with an additional timeout option.\n * To not time out use a negative time interval, or simply use the connectToHost:onPort:error: method.\n **/\n- (BOOL)connectToHost:(NSString *)hostname\n\t\t\t   onPort:(UInt16)port\n\t\t  withTimeout:(NSTimeInterval)timeout\n\t\t\t\terror:(NSError **)errPtr;\n\n/**\n * Connects to the given address, specified as a sockaddr structure wrapped in a NSData object.\n * For example, a NSData object returned from NSNetService's addresses method.\n *\n * If you have an existing struct sockaddr you can convert it to a NSData object like so:\n * struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];\n * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];\n **/\n- (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr;\n\n/**\n * This method is the same as connectToAddress:error: with an additional timeout option.\n * To not time out use a negative time interval, or simply use the connectToAddress:error: method.\n **/\n- (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr;\n\n- (BOOL)connectToAddress:(NSData *)remoteAddr\n     viaInterfaceAddress:(NSData *)interfaceAddr\n             withTimeout:(NSTimeInterval)timeout\n                   error:(NSError **)errPtr;\n\n/**\n * Disconnects immediately. Any pending reads or writes are dropped.\n * If the socket is not already disconnected, the onSocketDidDisconnect delegate method\n * will be called immediately, before this method returns.\n *\n * Please note the recommended way of releasing an AsyncSocket instance (e.g. in a dealloc method)\n * [asyncSocket setDelegate:nil];\n * [asyncSocket disconnect];\n * [asyncSocket release];\n **/\n- (void)disconnect;\n\n/**\n * Disconnects after all pending reads have completed.\n * After calling this, the read and write methods will do nothing.\n * The socket will disconnect even if there are still pending writes.\n **/\n- (void)disconnectAfterReading;\n\n/**\n * Disconnects after all pending writes have completed.\n * After calling this, the read and write methods will do nothing.\n * The socket will disconnect even if there are still pending reads.\n **/\n- (void)disconnectAfterWriting;\n\n/**\n * Disconnects after all pending reads and writes have completed.\n * After calling this, the read and write methods will do nothing.\n **/\n- (void)disconnectAfterReadingAndWriting;\n\n/* Returns YES if the socket and streams are open, connected, and ready for reading and writing. */\n- (BOOL)isConnected;\n\n/**\n * Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected.\n * The host will be an IP address.\n **/\n- (NSString *)connectedHost;\n- (UInt16)connectedPort;\n\n- (NSString *)localHost;\n- (UInt16)localPort;\n\n/**\n * Returns the local or remote address to which this socket is connected,\n * specified as a sockaddr structure wrapped in a NSData object.\n *\n * See also the connectedHost, connectedPort, localHost and localPort methods.\n **/\n- (NSData *)connectedAddress;\n- (NSData *)localAddress;\n\n/**\n * Returns whether the socket is IPv4 or IPv6.\n * An accepting socket may be both.\n **/\n- (BOOL)isIPv4;\n- (BOOL)isIPv6;\n\n// The readData and writeData methods won't block (they are asynchronous).\n//\n// When a read is complete the onSocket:didReadData:withTag: delegate method is called.\n// When a write is complete the onSocket:didWriteDataWithTag: delegate method is called.\n//\n// You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.)\n// If a read/write opertion times out, the corresponding \"onSocket:shouldTimeout...\" delegate method\n// is called to optionally allow you to extend the timeout.\n// Upon a timeout, the \"onSocket:willDisconnectWithError:\" method is called, followed by \"onSocketDidDisconnect\".\n//\n// The tag is for your convenience.\n// You can use it as an array index, step number, state id, pointer, etc.\n\n/**\n * Reads the first available bytes that become available on the socket.\n *\n * If the timeout value is negative, the read operation will not use a timeout.\n **/\n- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag;\n\n/**\n * Reads the first available bytes that become available on the socket.\n * The bytes will be appended to the given byte buffer starting at the given offset.\n * The given buffer will automatically be increased in size if needed.\n *\n * If the timeout value is negative, the read operation will not use a timeout.\n * If the buffer if nil, the socket will create a buffer for you.\n *\n * If the bufferOffset is greater than the length of the given buffer,\n * the method will do nothing, and the delegate will not be called.\n *\n * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it.\n * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer.\n * That is, it will reference the bytes that were appended to the given buffer.\n **/\n- (void)readDataWithTimeout:(NSTimeInterval)timeout\n\t\t\t\t\t buffer:(NSMutableData *)buffer\n\t\t\t   bufferOffset:(NSUInteger)offset\n\t\t\t\t\t\ttag:(long)tag;\n\n/**\n * Reads the first available bytes that become available on the socket.\n * The bytes will be appended to the given byte buffer starting at the given offset.\n * The given buffer will automatically be increased in size if needed.\n * A maximum of length bytes will be read.\n *\n * If the timeout value is negative, the read operation will not use a timeout.\n * If the buffer if nil, a buffer will automatically be created for you.\n * If maxLength is zero, no length restriction is enforced.\n *\n * If the bufferOffset is greater than the length of the given buffer,\n * the method will do nothing, and the delegate will not be called.\n *\n * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it.\n * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer.\n * That is, it will reference the bytes that were appended to the given buffer.\n **/\n- (void)readDataWithTimeout:(NSTimeInterval)timeout\n                     buffer:(NSMutableData *)buffer\n               bufferOffset:(NSUInteger)offset\n                  maxLength:(NSUInteger)length\n                        tag:(long)tag;\n\n/**\n * Reads the given number of bytes.\n *\n * If the timeout value is negative, the read operation will not use a timeout.\n *\n * If the length is 0, this method does nothing and the delegate is not called.\n **/\n- (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;\n\n/**\n * Reads the given number of bytes.\n * The bytes will be appended to the given byte buffer starting at the given offset.\n * The given buffer will automatically be increased in size if needed.\n *\n * If the timeout value is negative, the read operation will not use a timeout.\n * If the buffer if nil, a buffer will automatically be created for you.\n *\n * If the length is 0, this method does nothing and the delegate is not called.\n * If the bufferOffset is greater than the length of the given buffer,\n * the method will do nothing, and the delegate will not be called.\n *\n * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it.\n * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer.\n * That is, it will reference the bytes that were appended to the given buffer.\n **/\n- (void)readDataToLength:(NSUInteger)length\n             withTimeout:(NSTimeInterval)timeout\n                  buffer:(NSMutableData *)buffer\n            bufferOffset:(NSUInteger)offset\n                     tag:(long)tag;\n\n/**\n * Reads bytes until (and including) the passed \"data\" parameter, which acts as a separator.\n *\n * If the timeout value is negative, the read operation will not use a timeout.\n *\n * If you pass nil or zero-length data as the \"data\" parameter,\n * the method will do nothing, and the delegate will not be called.\n *\n * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the \"data\" parameter.\n * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for\n * a character, the read will prematurely end.\n **/\n- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;\n\n/**\n * Reads bytes until (and including) the passed \"data\" parameter, which acts as a separator.\n * The bytes will be appended to the given byte buffer starting at the given offset.\n * The given buffer will automatically be increased in size if needed.\n *\n * If the timeout value is negative, the read operation will not use a timeout.\n * If the buffer if nil, a buffer will automatically be created for you.\n *\n * If the bufferOffset is greater than the length of the given buffer,\n * the method will do nothing, and the delegate will not be called.\n *\n * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it.\n * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer.\n * That is, it will reference the bytes that were appended to the given buffer.\n *\n * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the \"data\" parameter.\n * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for\n * a character, the read will prematurely end.\n **/\n- (void)readDataToData:(NSData *)data\n           withTimeout:(NSTimeInterval)timeout\n                buffer:(NSMutableData *)buffer\n          bufferOffset:(NSUInteger)offset\n                   tag:(long)tag;\n\n/**\n * Reads bytes until (and including) the passed \"data\" parameter, which acts as a separator.\n *\n * If the timeout value is negative, the read operation will not use a timeout.\n *\n * If maxLength is zero, no length restriction is enforced.\n * Otherwise if maxLength bytes are read without completing the read,\n * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError.\n * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end.\n *\n * If you pass nil or zero-length data as the \"data\" parameter,\n * the method will do nothing, and the delegate will not be called.\n * If you pass a maxLength parameter that is less than the length of the data parameter,\n * the method will do nothing, and the delegate will not be called.\n *\n * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the \"data\" parameter.\n * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for\n * a character, the read will prematurely end.\n **/\n- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag;\n\n/**\n * Reads bytes until (and including) the passed \"data\" parameter, which acts as a separator.\n * The bytes will be appended to the given byte buffer starting at the given offset.\n * The given buffer will automatically be increased in size if needed.\n * A maximum of length bytes will be read.\n *\n * If the timeout value is negative, the read operation will not use a timeout.\n * If the buffer if nil, a buffer will automatically be created for you.\n *\n * If maxLength is zero, no length restriction is enforced.\n * Otherwise if maxLength bytes are read without completing the read,\n * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError.\n * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end.\n *\n * If you pass a maxLength parameter that is less than the length of the data parameter,\n * the method will do nothing, and the delegate will not be called.\n * If the bufferOffset is greater than the length of the given buffer,\n * the method will do nothing, and the delegate will not be called.\n *\n * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it.\n * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer.\n * That is, it will reference the bytes that were appended to the given buffer.\n *\n * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the \"data\" parameter.\n * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for\n * a character, the read will prematurely end.\n **/\n- (void)readDataToData:(NSData *)data\n           withTimeout:(NSTimeInterval)timeout\n                buffer:(NSMutableData *)buffer\n          bufferOffset:(NSUInteger)offset\n             maxLength:(NSUInteger)length\n                   tag:(long)tag;\n\n/**\n * Writes data to the socket, and calls the delegate when finished.\n *\n * If you pass in nil or zero-length data, this method does nothing and the delegate will not be called.\n * If the timeout value is negative, the write operation will not use a timeout.\n **/\n- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;\n\n/**\n * Returns progress of current read or write, from 0.0 to 1.0, or NaN if no read/write (use isnan() to check).\n * \"tag\", \"done\" and \"total\" will be filled in if they aren't NULL.\n **/\n- (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;\n- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;\n\n/**\n * Secures the connection using SSL/TLS.\n *\n * This method may be called at any time, and the TLS handshake will occur after all pending reads and writes\n * are finished. This allows one the option of sending a protocol dependent StartTLS message, and queuing\n * the upgrade to TLS at the same time, without having to wait for the write to finish.\n * Any reads or writes scheduled after this method is called will occur over the secured connection.\n *\n * The possible keys and values for the TLS settings are well documented.\n * Some possible keys are:\n * - kCFStreamSSLLevel\n * - kCFStreamSSLAllowsExpiredCertificates\n * - kCFStreamSSLAllowsExpiredRoots\n * - kCFStreamSSLAllowsAnyRoot\n * - kCFStreamSSLValidatesCertificateChain\n * - kCFStreamSSLPeerName\n * - kCFStreamSSLCertificates\n * - kCFStreamSSLIsServer\n *\n * Please refer to Apple's documentation for associated values, as well as other possible keys.\n *\n * If you pass in nil or an empty dictionary, the default settings will be used.\n *\n * The default settings will check to make sure the remote party's certificate is signed by a\n * trusted 3rd party certificate agency (e.g. verisign) and that the certificate is not expired.\n * However it will not verify the name on the certificate unless you\n * give it a name to verify against via the kCFStreamSSLPeerName key.\n * The security implications of this are important to understand.\n * Imagine you are attempting to create a secure connection to MySecureServer.com,\n * but your socket gets directed to MaliciousServer.com because of a hacked DNS server.\n * If you simply use the default settings, and MaliciousServer.com has a valid certificate,\n * the default settings will not detect any problems since the certificate is valid.\n * To properly secure your connection in this particular scenario you\n * should set the kCFStreamSSLPeerName property to \"MySecureServer.com\".\n * If you do not know the peer name of the remote host in advance (for example, you're not sure\n * if it will be \"domain.com\" or \"www.domain.com\"), then you can use the default settings to validate the\n * certificate, and then use the X509Certificate class to verify the issuer after the socket has been secured.\n * The X509Certificate class is part of the CocoaAsyncSocket open source project.\n **/\n- (void)startTLS:(NSDictionary *)tlsSettings;\n\n/**\n * For handling readDataToData requests, data is necessarily read from the socket in small increments.\n * The performance can be much improved by allowing AsyncSocket to read larger chunks at a time and\n * store any overflow in a small internal buffer.\n * This is termed pre-buffering, as some data may be read for you before you ask for it.\n * If you use readDataToData a lot, enabling pre-buffering will result in better performance, especially on the iPhone.\n *\n * The default pre-buffering state is controlled by the DEFAULT_PREBUFFERING definition.\n * It is highly recommended one leave this set to YES.\n *\n * This method exists in case pre-buffering needs to be disabled by default for some unforeseen reason.\n * In that case, this method exists to allow one to easily enable pre-buffering when ready.\n **/\n- (void)enablePreBuffering;\n\n/**\n * When you create an AsyncSocket, it is added to the runloop of the current thread.\n * So for manually created sockets, it is easiest to simply create the socket on the thread you intend to use it.\n *\n * If a new socket is accepted, the delegate method onSocket:wantsRunLoopForNewSocket: is called to\n * allow you to place the socket on a separate thread. This works best in conjunction with a thread pool design.\n *\n * If, however, you need to move the socket to a separate thread at a later time, this\n * method may be used to accomplish the task.\n *\n * This method must be called from the thread/runloop the socket is currently running on.\n *\n * Note: After calling this method, all further method calls to this object should be done from the given runloop.\n * Also, all delegate calls will be sent on the given runloop.\n **/\n- (BOOL)moveToRunLoop:(NSRunLoop *)runLoop;\n\n/**\n * Allows you to configure which run loop modes the socket uses.\n * The default set of run loop modes is NSDefaultRunLoopMode.\n *\n * If you'd like your socket to continue operation during other modes, you may want to add modes such as\n * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes.\n *\n * Accepted sockets will automatically inherit the same run loop modes as the listening socket.\n *\n * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes.\n **/\n- (BOOL)setRunLoopModes:(NSArray *)runLoopModes;\n- (BOOL)addRunLoopMode:(NSString *)runLoopMode;\n- (BOOL)removeRunLoopMode:(NSString *)runLoopMode;\n\n/**\n * Returns the current run loop modes the AsyncSocket instance is operating in.\n * The default set of run loop modes is NSDefaultRunLoopMode.\n **/\n- (NSArray *)runLoopModes;\n\n/**\n * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read\n * any data that's left on the socket.\n **/\n- (NSData *)unreadData;\n\n/* A few common line separators, for use with the readDataToData:... methods. */\n+ (NSData *)CRLFData;   // 0x0D0A\n+ (NSData *)CRData;     // 0x0D\n+ (NSData *)LFData;     // 0x0A\n+ (NSData *)ZeroData;   // 0x00\n\n@end"
  },
  {
    "path": "WebSocket/AsyncSocket.m",
    "content": "//\n//  AsyncSocket.m\n//\n//  This class is in the public domain.\n//  Originally created by Dustin Voss on Wed Jan 29 2003.\n//  Updated and maintained by Deusty Designs and the Mac development community.\n//\n//  http://code.google.com/p/cocoaasyncsocket/\n//\n\n#if ! __has_feature(objc_arc)\n#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).\n#endif\n\n#import \"AsyncSocket.h\"\n#import <sys/socket.h>\n#import <netinet/in.h>\n#import <arpa/inet.h>\n#import <netdb.h>\n\n#if TARGET_OS_IPHONE\n// Note: You may need to add the CFNetwork Framework to your project\n#import <CFNetwork/CFNetwork.h>\n#endif\n\n#pragma mark Declarations\n\n#define DEFAULT_PREBUFFERING YES        // Whether pre-buffering is enabled by default\n\n#define READQUEUE_CAPACITY\t5           // Initial capacity\n#define WRITEQUEUE_CAPACITY 5           // Initial capacity\n#define READALL_CHUNKSIZE\t256         // Incremental increase in buffer size\n#define WRITE_CHUNKSIZE    (1024 * 4)   // Limit on size of each write pass\n\n// AsyncSocket is RunLoop based, and is thus not thread-safe.\n// You must always access your AsyncSocket instance from the thread/runloop in which the instance is running.\n// You can use methods such as performSelectorOnThread to accomplish this.\n// Failure to comply with these thread-safety rules may result in errors.\n// You can enable this option to help diagnose where you are incorrectly accessing your socket.\n#if DEBUG\n#define DEBUG_THREAD_SAFETY 1\n#else\n#define DEBUG_THREAD_SAFETY 0\n#endif\n//\n// If you constantly need to access your socket from multiple threads\n// then you may consider using GCDAsyncSocket instead, which is thread-safe.\n\nNSString *const AsyncSocketException = @\"AsyncSocketException\";\nNSString *const AsyncSocketErrorDomain = @\"AsyncSocketErrorDomain\";\n\n\nenum AsyncSocketFlags\n{\n\tkEnablePreBuffering      = 1 <<  0,  // If set, pre-buffering is enabled\n\tkDidStartDelegate        = 1 <<  1,  // If set, disconnection results in delegate call\n\tkDidCompleteOpenForRead  = 1 <<  2,  // If set, open callback has been called for read stream\n\tkDidCompleteOpenForWrite = 1 <<  3,  // If set, open callback has been called for write stream\n\tkStartingReadTLS         = 1 <<  4,  // If set, we're waiting for TLS negotiation to complete\n\tkStartingWriteTLS        = 1 <<  5,  // If set, we're waiting for TLS negotiation to complete\n\tkForbidReadsWrites       = 1 <<  6,  // If set, no new reads or writes are allowed\n\tkDisconnectAfterReads    = 1 <<  7,  // If set, disconnect after no more reads are queued\n\tkDisconnectAfterWrites   = 1 <<  8,  // If set, disconnect after no more writes are queued\n\tkClosingWithError        = 1 <<  9,  // If set, the socket is being closed due to an error\n\tkDequeueReadScheduled    = 1 << 10,  // If set, a maybeDequeueRead operation is already scheduled\n\tkDequeueWriteScheduled   = 1 << 11,  // If set, a maybeDequeueWrite operation is already scheduled\n\tkSocketCanAcceptBytes    = 1 << 12,  // If set, we know socket can accept bytes. If unset, it's unknown.\n\tkSocketHasBytesAvailable = 1 << 13,  // If set, we know socket has bytes available. If unset, it's unknown.\n};\n\n@interface AsyncSocket (Private)\n\n// Connecting\n- (void)startConnectTimeout:(NSTimeInterval)timeout;\n- (void)endConnectTimeout;\n- (void)doConnectTimeout:(NSTimer *)timer;\n\n// Socket Implementation\n- (CFSocketRef)newAcceptSocketForAddress:(NSData *)addr error:(NSError **)errPtr;\n- (BOOL)createSocketForAddress:(NSData *)remoteAddr error:(NSError **)errPtr;\n- (BOOL)bindSocketToAddress:(NSData *)interfaceAddr error:(NSError **)errPtr;\n- (BOOL)attachSocketsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr;\n- (BOOL)configureSocketAndReturnError:(NSError **)errPtr;\n- (BOOL)connectSocketToAddress:(NSData *)remoteAddr error:(NSError **)errPtr;\n- (void)doAcceptWithSocket:(CFSocketNativeHandle)newSocket;\n- (void)doSocketOpen:(CFSocketRef)sock withCFSocketError:(CFSocketError)err;\n\n// Stream Implementation\n- (BOOL)createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr;\n- (BOOL)createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr;\n- (BOOL)attachStreamsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr;\n- (BOOL)configureStreamsAndReturnError:(NSError **)errPtr;\n- (BOOL)openStreamsAndReturnError:(NSError **)errPtr;\n- (void)doStreamOpen;\n- (BOOL)setSocketFromStreamsAndReturnError:(NSError **)errPtr;\n\n// Disconnect Implementation\n- (void)closeWithError:(NSError *)err;\n- (void)recoverUnreadData;\n- (void)emptyQueues;\n- (void)close;\n\n// Errors\n- (NSError *)getErrnoError;\n- (NSError *)getAbortError;\n- (NSError *)getStreamError;\n- (NSError *)getSocketError;\n- (NSError *)getConnectTimeoutError;\n- (NSError *)getReadMaxedOutError;\n- (NSError *)getReadTimeoutError;\n- (NSError *)getWriteTimeoutError;\n- (NSError *)errorFromCFStreamError:(CFStreamError)err;\n\n// Diagnostics\n- (BOOL)isDisconnected;\n- (BOOL)areStreamsConnected;\n- (NSString *)connectedHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket;\n- (NSString *)connectedHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket;\n- (NSString *)connectedHostFromCFSocket4:(CFSocketRef)socket;\n- (NSString *)connectedHostFromCFSocket6:(CFSocketRef)socket;\n- (UInt16)connectedPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket;\n- (UInt16)connectedPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket;\n- (UInt16)connectedPortFromCFSocket4:(CFSocketRef)socket;\n- (UInt16)connectedPortFromCFSocket6:(CFSocketRef)socket;\n- (NSString *)localHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket;\n- (NSString *)localHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket;\n- (NSString *)localHostFromCFSocket4:(CFSocketRef)socket;\n- (NSString *)localHostFromCFSocket6:(CFSocketRef)socket;\n- (UInt16)localPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket;\n- (UInt16)localPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket;\n- (UInt16)localPortFromCFSocket4:(CFSocketRef)socket;\n- (UInt16)localPortFromCFSocket6:(CFSocketRef)socket;\n- (NSString *)hostFromAddress4:(struct sockaddr_in *)pSockaddr4;\n- (NSString *)hostFromAddress6:(struct sockaddr_in6 *)pSockaddr6;\n- (UInt16)portFromAddress4:(struct sockaddr_in *)pSockaddr4;\n- (UInt16)portFromAddress6:(struct sockaddr_in6 *)pSockaddr6;\n\n// Reading\n- (void)doBytesAvailable;\n- (void)completeCurrentRead;\n- (void)endCurrentRead;\n- (void)scheduleDequeueRead;\n- (void)maybeDequeueRead;\n- (void)doReadTimeout:(NSTimer *)timer;\n\n// Writing\n- (void)doSendBytes;\n- (void)completeCurrentWrite;\n- (void)endCurrentWrite;\n- (void)scheduleDequeueWrite;\n- (void)maybeDequeueWrite;\n- (void)maybeScheduleDisconnect;\n- (void)doWriteTimeout:(NSTimer *)timer;\n\n// Run Loop\n- (void)runLoopAddSource:(CFRunLoopSourceRef)source;\n- (void)runLoopRemoveSource:(CFRunLoopSourceRef)source;\n- (void)runLoopAddTimer:(NSTimer *)timer;\n- (void)runLoopRemoveTimer:(NSTimer *)timer;\n- (void)runLoopUnscheduleReadStream;\n- (void)runLoopUnscheduleWriteStream;\n\n// Security\n- (void)maybeStartTLS;\n- (void)onTLSHandshakeSuccessful;\n\n// Callbacks\n- (void)doCFCallback:(CFSocketCallBackType)type\n           forSocket:(CFSocketRef)sock withAddress:(NSData *)address withData:(const void *)pData;\n- (void)doCFReadStreamCallback:(CFStreamEventType)type forStream:(CFReadStreamRef)stream;\n- (void)doCFWriteStreamCallback:(CFStreamEventType)type forStream:(CFWriteStreamRef)stream;\n\n@end\n\nstatic void MyCFSocketCallback(CFSocketRef, CFSocketCallBackType, CFDataRef, const void *, void *);\nstatic void MyCFReadStreamCallback(CFReadStreamRef stream, CFStreamEventType type, void *pInfo);\nstatic void MyCFWriteStreamCallback(CFWriteStreamRef stream, CFStreamEventType type, void *pInfo);\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark -\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n/**\n * The AsyncReadPacket encompasses the instructions for any given read.\n * The content of a read packet allows the code to determine if we're:\n *  - reading to a certain length\n *  - reading to a certain separator\n *  - or simply reading the first chunk of available data\n **/\n@interface AsyncReadPacket : NSObject\n{\n@public\n\tNSMutableData *buffer;\n\tNSUInteger startOffset;\n\tNSUInteger bytesDone;\n\tNSUInteger maxLength;\n\tNSTimeInterval timeout;\n\tNSUInteger readLength;\n\tNSData *term;\n\tBOOL bufferOwner;\n\tNSUInteger originalBufferLength;\n\tlong tag;\n}\n- (id)initWithData:(NSMutableData *)d\n       startOffset:(NSUInteger)s\n         maxLength:(NSUInteger)m\n           timeout:(NSTimeInterval)t\n        readLength:(NSUInteger)l\n        terminator:(NSData *)e\n               tag:(long)i;\n\n- (NSUInteger)readLengthForNonTerm;\n- (NSUInteger)readLengthForTerm;\n- (NSUInteger)readLengthForTermWithPreBuffer:(NSData *)preBuffer found:(BOOL *)foundPtr;\n\n- (NSUInteger)prebufferReadLengthForTerm;\n- (NSInteger)searchForTermAfterPreBuffering:(NSUInteger)numBytes;\n@end\n\n@implementation AsyncReadPacket\n\n- (id)initWithData:(NSMutableData *)d\n       startOffset:(NSUInteger)s\n         maxLength:(NSUInteger)m\n           timeout:(NSTimeInterval)t\n        readLength:(NSUInteger)l\n        terminator:(NSData *)e\n               tag:(long)i\n{\n\tif((self = [super init]))\n\t{\n\t\tif (d)\n\t\t{\n\t\t\tbuffer = d;\n\t\t\tstartOffset = s;\n\t\t\tbufferOwner = NO;\n\t\t\toriginalBufferLength = [d length];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (readLength > 0)\n\t\t\t\tbuffer = [[NSMutableData alloc] initWithLength:readLength];\n\t\t\telse\n\t\t\t\tbuffer = [[NSMutableData alloc] initWithLength:0];\n\t\t\t\n\t\t\tstartOffset = 0;\n\t\t\tbufferOwner = YES;\n\t\t\toriginalBufferLength = 0;\n\t\t}\n\t\t\n\t\tbytesDone = 0;\n\t\tmaxLength = m;\n\t\ttimeout = t;\n\t\treadLength = l;\n\t\tterm = [e copy];\n\t\ttag = i;\n\t}\n\treturn self;\n}\n\n/**\n * For read packets without a set terminator, returns the safe length of data that can be read\n * without exceeding the maxLength, or forcing a resize of the buffer if at all possible.\n **/\n- (NSUInteger)readLengthForNonTerm\n{\n\tNSAssert(term == nil, @\"This method does not apply to term reads\");\n\t\n\tif (readLength > 0)\n\t{\n\t\t// Read a specific length of data\n\t\t\n\t\treturn readLength - bytesDone;\n\t\t\n\t\t// No need to avoid resizing the buffer.\n\t\t// It should be resized if the buffer space is less than the requested read length.\n\t}\n\telse\n\t{\n\t\t// Read all available data\n\t\t\n\t\tNSUInteger result = READALL_CHUNKSIZE;\n\t\t\n\t\tif (maxLength > 0)\n\t\t{\n\t\t\tresult = MIN(result, (maxLength - bytesDone));\n\t\t}\n\t\t\n\t\tif (!bufferOwner)\n\t\t{\n\t\t\t// We did NOT create the buffer.\n\t\t\t// It is owned by the caller.\n\t\t\t// Avoid resizing the buffer if at all possible.\n\t\t\t\n\t\t\tif ([buffer length] == originalBufferLength)\n\t\t\t{\n\t\t\t\tNSUInteger buffSize = [buffer length];\n\t\t\t\tNSUInteger buffSpace = buffSize - startOffset - bytesDone;\n\t\t\t\t\n\t\t\t\tif (buffSpace > 0)\n\t\t\t\t{\n\t\t\t\t\tresult = MIN(result, buffSpace);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn result;\n\t}\n}\n\n/**\n * For read packets with a set terminator, returns the safe length of data that can be read\n * without going over a terminator, or the maxLength, or forcing a resize of the buffer if at all possible.\n *\n * It is assumed the terminator has not already been read.\n **/\n- (NSUInteger)readLengthForTerm\n{\n\tNSAssert(term != nil, @\"This method does not apply to non-term reads\");\n\t\n\t// What we're going to do is look for a partial sequence of the terminator at the end of the buffer.\n\t// If a partial sequence occurs, then we must assume the next bytes to arrive will be the rest of the term,\n\t// and we can only read that amount.\n\t// Otherwise, we're safe to read the entire length of the term.\n\t\n\tNSUInteger termLength = [term length];\n\t\n\t// Shortcuts\n\tif (bytesDone == 0) return termLength;\n\tif (termLength == 1) return termLength;\n\t\n\t// i = index within buffer at which to check data\n\t// j = length of term to check against\n\t\n\tNSUInteger i, j;\n\tif (bytesDone >= termLength)\n\t{\n\t\ti = bytesDone - termLength + 1;\n\t\tj = termLength - 1;\n\t}\n\telse\n\t{\n\t\ti = 0;\n\t\tj = bytesDone;\n\t}\n\t\n\tNSUInteger result = termLength;\n\t\n\tvoid *buf = [buffer mutableBytes];\n\tconst void *termBuf = [term bytes];\n\t\n\twhile (i < bytesDone)\n\t{\n\t\tvoid *subbuf = buf + startOffset + i;\n\t\t\n\t\tif (memcmp(subbuf, termBuf, j) == 0)\n\t\t{\n\t\t\tresult = termLength - j;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\ti++;\n\t\tj--;\n\t}\n\t\n\tif (maxLength > 0)\n\t{\n\t\tresult = MIN(result, (maxLength - bytesDone));\n\t}\n\t\n\tif (!bufferOwner)\n\t{\n\t\t// We did NOT create the buffer.\n\t\t// It is owned by the caller.\n\t\t// Avoid resizing the buffer if at all possible.\n\t\t\n\t\tif ([buffer length] == originalBufferLength)\n\t\t{\n\t\t\tNSUInteger buffSize = [buffer length];\n\t\t\tNSUInteger buffSpace = buffSize - startOffset - bytesDone;\n\t\t\t\n\t\t\tif (buffSpace > 0)\n\t\t\t{\n\t\t\t\tresult = MIN(result, buffSpace);\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn result;\n}\n\n/**\n * For read packets with a set terminator,\n * returns the safe length of data that can be read from the given preBuffer,\n * without going over a terminator or the maxLength.\n *\n * It is assumed the terminator has not already been read.\n **/\n- (NSUInteger)readLengthForTermWithPreBuffer:(NSData *)preBuffer found:(BOOL *)foundPtr\n{\n\tNSAssert(term != nil, @\"This method does not apply to non-term reads\");\n\tNSAssert([preBuffer length] > 0, @\"Invoked with empty pre buffer!\");\n\t\n\t// We know that the terminator, as a whole, doesn't exist in our own buffer.\n\t// But it is possible that a portion of it exists in our buffer.\n\t// So we're going to look for the terminator starting with a portion of our own buffer.\n\t//\n\t// Example:\n\t//\n\t// term length      = 3 bytes\n\t// bytesDone        = 5 bytes\n\t// preBuffer length = 5 bytes\n\t//\n\t// If we append the preBuffer to our buffer,\n\t// it would look like this:\n\t//\n\t// ---------------------\n\t// |B|B|B|B|B|P|P|P|P|P|\n\t// ---------------------\n\t//\n\t// So we start our search here:\n\t//\n\t// ---------------------\n\t// |B|B|B|B|B|P|P|P|P|P|\n\t// -------^-^-^---------\n\t//\n\t// And move forwards...\n\t//\n\t// ---------------------\n\t// |B|B|B|B|B|P|P|P|P|P|\n\t// ---------^-^-^-------\n\t//\n\t// Until we find the terminator or reach the end.\n\t//\n\t// ---------------------\n\t// |B|B|B|B|B|P|P|P|P|P|\n\t// ---------------^-^-^-\n\t\n\tBOOL found = NO;\n\t\n\tNSUInteger termLength = [term length];\n\tNSUInteger preBufferLength = [preBuffer length];\n\t\n\tif ((bytesDone + preBufferLength) < termLength)\n\t{\n\t\t// Not enough data for a full term sequence yet\n\t\treturn preBufferLength;\n\t}\n\t\n\tNSUInteger maxPreBufferLength;\n\tif (maxLength > 0) {\n\t\tmaxPreBufferLength = MIN(preBufferLength, (maxLength - bytesDone));\n\t\t\n\t\t// Note: maxLength >= termLength\n\t}\n\telse {\n\t\tmaxPreBufferLength = preBufferLength;\n\t}\n\t\n\tByte seq[termLength];\n\tconst void *termBuf = [term bytes];\n\t\n\tNSUInteger bufLen = MIN(bytesDone, (termLength - 1));\n\tvoid *buf = [buffer mutableBytes] + startOffset + bytesDone - bufLen;\n\t\n\tNSUInteger preLen = termLength - bufLen;\n\tvoid *pre = (void *)[preBuffer bytes];\n\t\n\tNSUInteger loopCount = bufLen + maxPreBufferLength - termLength + 1; // Plus one. See example above.\n\t\n\tNSUInteger result = preBufferLength;\n\t\n\tNSUInteger i;\n\tfor (i = 0; i < loopCount; i++)\n\t{\n\t\tif (bufLen > 0)\n\t\t{\n\t\t\t// Combining bytes from buffer and preBuffer\n\t\t\t\n\t\t\tmemcpy(seq, buf, bufLen);\n\t\t\tmemcpy(seq + bufLen, pre, preLen);\n\t\t\t\n\t\t\tif (memcmp(seq, termBuf, termLength) == 0)\n\t\t\t{\n\t\t\t\tresult = preLen;\n\t\t\t\tfound = YES;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tbuf++;\n\t\t\tbufLen--;\n\t\t\tpreLen++;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Comparing directly from preBuffer\n\t\t\t\n\t\t\tif (memcmp(pre, termBuf, termLength) == 0)\n\t\t\t{\n\t\t\t\tNSUInteger preOffset = pre - [preBuffer bytes]; // pointer arithmetic\n\t\t\t\t\n\t\t\t\tresult = preOffset + termLength;\n\t\t\t\tfound = YES;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tpre++;\n\t\t}\n\t}\n\t\n\t// There is no need to avoid resizing the buffer in this particular situation.\n\t\n\tif (foundPtr) *foundPtr = found;\n\treturn result;\n}\n\n/**\n * Assuming pre-buffering is enabled, returns the amount of data that can be read\n * without going over the maxLength.\n **/\n- (NSUInteger)prebufferReadLengthForTerm\n{\n\tNSAssert(term != nil, @\"This method does not apply to non-term reads\");\n\t\n\tNSUInteger result = READALL_CHUNKSIZE;\n\t\n\tif (maxLength > 0)\n\t{\n\t\tresult = MIN(result, (maxLength - bytesDone));\n\t}\n\t\n\tif (!bufferOwner)\n\t{\n\t\t// We did NOT create the buffer.\n\t\t// It is owned by the caller.\n\t\t// Avoid resizing the buffer if at all possible.\n\t\t\n\t\tif ([buffer length] == originalBufferLength)\n\t\t{\n\t\t\tNSUInteger buffSize = [buffer length];\n\t\t\tNSUInteger buffSpace = buffSize - startOffset - bytesDone;\n\t\t\t\n\t\t\tif (buffSpace > 0)\n\t\t\t{\n\t\t\t\tresult = MIN(result, buffSpace);\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn result;\n}\n\n/**\n * For read packets with a set terminator, scans the packet buffer for the term.\n * It is assumed the terminator had not been fully read prior to the new bytes.\n *\n * If the term is found, the number of excess bytes after the term are returned.\n * If the term is not found, this method will return -1.\n *\n * Note: A return value of zero means the term was found at the very end.\n **/\n- (NSInteger)searchForTermAfterPreBuffering:(NSUInteger)numBytes\n{\n\tNSAssert(term != nil, @\"This method does not apply to non-term reads\");\n\tNSAssert(bytesDone >= numBytes, @\"Invoked with invalid numBytes!\");\n\t\n\t// We try to start the search such that the first new byte read matches up with the last byte of the term.\n\t// We continue searching forward after this until the term no longer fits into the buffer.\n\t\n\tNSUInteger termLength = [term length];\n\tconst void *termBuffer = [term bytes];\n\t\n\t// Remember: This method is called after the bytesDone variable has been updated.\n\t\n\tNSUInteger prevBytesDone = bytesDone - numBytes;\n\t\n\tNSUInteger i;\n\tif (prevBytesDone >= termLength)\n\t\ti = prevBytesDone - termLength + 1;\n\telse\n\t\ti = 0;\n\t\n\twhile ((i + termLength) <= bytesDone)\n\t{\n\t\tvoid *subBuffer = [buffer mutableBytes] + startOffset + i;\n\t\t\n\t\tif(memcmp(subBuffer, termBuffer, termLength) == 0)\n\t\t{\n\t\t\treturn bytesDone - (i + termLength);\n\t\t}\n\t\t\n\t\ti++;\n\t}\n\t\n\treturn -1;\n}\n\n\n@end\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark -\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n/**\n * The AsyncWritePacket encompasses the instructions for any given write.\n **/\n@interface AsyncWritePacket : NSObject\n{\n@public\n\tNSData *buffer;\n\tNSUInteger bytesDone;\n\tlong tag;\n\tNSTimeInterval timeout;\n}\n- (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i;\n@end\n\n@implementation AsyncWritePacket\n\n- (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i\n{\n\tif((self = [super init]))\n\t{\n\t\tbuffer = d;\n\t\ttimeout = t;\n\t\ttag = i;\n\t\tbytesDone = 0;\n\t}\n\treturn self;\n}\n\n\n@end\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark -\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n/**\n * The AsyncSpecialPacket encompasses special instructions for interruptions in the read/write queues.\n * This class my be altered to support more than just TLS in the future.\n **/\n@interface AsyncSpecialPacket : NSObject\n{\n@public\n\tNSDictionary *tlsSettings;\n}\n- (id)initWithTLSSettings:(NSDictionary *)settings;\n@end\n\n@implementation AsyncSpecialPacket\n\n- (id)initWithTLSSettings:(NSDictionary *)settings\n{\n\tif((self = [super init]))\n\t{\n\t\ttlsSettings = [settings copy];\n\t}\n\treturn self;\n}\n\n\n@end\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark -\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n@implementation AsyncSocket\n\n- (id)init\n{\n\treturn [self initWithDelegate:nil userData:0];\n}\n\n- (id)initWithDelegate:(id)delegate\n{\n\treturn [self initWithDelegate:delegate userData:0];\n}\n\n// Designated initializer.\n- (id)initWithDelegate:(id)delegate userData:(long)userData\n{\n\tif((self = [super init]))\n\t{\n\t\ttheFlags = DEFAULT_PREBUFFERING ? kEnablePreBuffering : 0;\n\t\ttheDelegate = delegate;\n\t\ttheUserData = userData;\n\t\t\n\t\ttheNativeSocket4 = 0;\n\t\ttheNativeSocket6 = 0;\n\t\t\n\t\ttheSocket4 = NULL;\n\t\ttheSource4 = NULL;\n\t\t\n\t\ttheSocket6 = NULL;\n\t\ttheSource6 = NULL;\n\t\t\n\t\ttheRunLoop = NULL;\n\t\ttheReadStream = NULL;\n\t\ttheWriteStream = NULL;\n\t\t\n\t\ttheConnectTimer = nil;\n\t\t\n\t\ttheReadQueue = [[NSMutableArray alloc] initWithCapacity:READQUEUE_CAPACITY];\n\t\ttheCurrentRead = nil;\n\t\ttheReadTimer = nil;\n\t\t\n\t\tpartialReadBuffer = [[NSMutableData alloc] initWithCapacity:READALL_CHUNKSIZE];\n\t\t\n\t\ttheWriteQueue = [[NSMutableArray alloc] initWithCapacity:WRITEQUEUE_CAPACITY];\n\t\ttheCurrentWrite = nil;\n\t\ttheWriteTimer = nil;\n\t\t\n\t\t// Socket context\n\t\tNSAssert(sizeof(CFSocketContext) == sizeof(CFStreamClientContext), @\"CFSocketContext != CFStreamClientContext\");\n\t\ttheContext.version = 0;\n\t\ttheContext.info = (__bridge void *)(self);\n\t\ttheContext.retain = nil;\n\t\ttheContext.release = nil;\n\t\ttheContext.copyDescription = nil;\n\t\t\n\t\t// Default run loop modes\n\t\ttheRunLoopModes = [NSArray arrayWithObject:NSDefaultRunLoopMode];\n\t}\n\treturn self;\n}\n\n// The socket may been initialized in a connected state and auto-released, so this should close it down cleanly.\n- (void)dealloc\n{\n\t[self close];\n\t[NSObject cancelPreviousPerformRequestsWithTarget:self];\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Thread-Safety\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (void)checkForThreadSafety\n{\n\tif (theRunLoop && (theRunLoop != CFRunLoopGetCurrent()))\n\t{\n\t\t// AsyncSocket is RunLoop based.\n\t\t// It is designed to be run and accessed from a particular thread/runloop.\n\t\t// As such, it is faster as it does not have the overhead of locks/synchronization.\n\t\t//\n\t\t// However, this places a minimal requirement on the developer to maintain thread-safety.\n\t\t// If you are seeing errors or crashes in AsyncSocket,\n\t\t// it is very likely that thread-safety has been broken.\n\t\t// This method may be enabled via the DEBUG_THREAD_SAFETY macro,\n\t\t// and will allow you to discover the place in your code where thread-safety is being broken.\n\t\t//\n\t\t// Note:\n\t\t//\n\t\t// If you find you constantly need to access your socket from various threads,\n\t\t// you may prefer to use GCDAsyncSocket which is thread-safe.\n\t\t\n\t\t[NSException raise:AsyncSocketException\n\t\t            format:@\"Attempting to access AsyncSocket instance from incorrect thread.\"];\n\t}\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Accessors\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (long)userData\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\treturn theUserData;\n}\n\n- (void)setUserData:(long)userData\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\ttheUserData = userData;\n}\n\n- (id)delegate\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\treturn theDelegate;\n}\n\n- (void)setDelegate:(id)delegate\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\ttheDelegate = delegate;\n}\n\n- (BOOL)canSafelySetDelegate\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\treturn ([theReadQueue count] == 0 && [theWriteQueue count] == 0 && theCurrentRead == nil && theCurrentWrite == nil);\n}\n\n- (CFSocketRef)getCFSocket\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif(theSocket4)\n\t\treturn theSocket4;\n\telse\n\t\treturn theSocket6;\n}\n\n- (CFReadStreamRef)getCFReadStream\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\treturn theReadStream;\n}\n\n- (CFWriteStreamRef)getCFWriteStream\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\treturn theWriteStream;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Progress\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\t// Check to make sure we're actually reading something right now,\n\t// and that the read packet isn't an AsyncSpecialPacket (upgrade to TLS).\n\tif (!theCurrentRead || ![theCurrentRead isKindOfClass:[AsyncReadPacket class]])\n\t{\n\t\tif (tag != NULL)   *tag = 0;\n\t\tif (done != NULL)  *done = 0;\n\t\tif (total != NULL) *total = 0;\n\t\t\n\t\treturn NAN;\n\t}\n\t\n\t// It's only possible to know the progress of our read if we're reading to a certain length.\n\t// If we're reading to data, we of course have no idea when the data will arrive.\n\t// If we're reading to timeout, then we have no idea when the next chunk of data will arrive.\n\t\n\tNSUInteger d = theCurrentRead->bytesDone;\n\tNSUInteger t = theCurrentRead->readLength;\n\t\n\tif (tag != NULL)   *tag = theCurrentRead->tag;\n\tif (done != NULL)  *done = d;\n\tif (total != NULL) *total = t;\n\t\n\tif (t > 0.0)\n\t\treturn (float)d / (float)t;\n\telse\n\t\treturn 1.0F;\n}\n\n- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\t// Check to make sure we're actually writing something right now,\n\t// and that the write packet isn't an AsyncSpecialPacket (upgrade to TLS).\n\tif (!theCurrentWrite || ![theCurrentWrite isKindOfClass:[AsyncWritePacket class]])\n\t{\n\t\tif (tag != NULL)   *tag = 0;\n\t\tif (done != NULL)  *done = 0;\n\t\tif (total != NULL) *total = 0;\n\t\t\n\t\treturn NAN;\n\t}\n\t\n\tNSUInteger d = theCurrentWrite->bytesDone;\n\tNSUInteger t = [theCurrentWrite->buffer length];\n\t\n\tif (tag != NULL)   *tag = theCurrentWrite->tag;\n\tif (done != NULL)  *done = d;\n\tif (total != NULL) *total = t;\n\t\n\treturn (float)d / (float)t;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Run Loop\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (void)runLoopAddSource:(CFRunLoopSourceRef)source\n{\n\tfor (NSString *runLoopMode in theRunLoopModes)\n\t{\n\t\tCFRunLoopAddSource(theRunLoop, source, (__bridge CFStringRef)runLoopMode);\n\t}\n}\n\n- (void)runLoopRemoveSource:(CFRunLoopSourceRef)source\n{\n\tfor (NSString *runLoopMode in theRunLoopModes)\n\t{\n\t\tCFRunLoopRemoveSource(theRunLoop, source, (__bridge CFStringRef)runLoopMode);\n\t}\n}\n\n- (void)runLoopAddSource:(CFRunLoopSourceRef)source mode:(NSString *)runLoopMode\n{\n\tCFRunLoopAddSource(theRunLoop, source, (__bridge CFStringRef)runLoopMode);\n}\n\n- (void)runLoopRemoveSource:(CFRunLoopSourceRef)source mode:(NSString *)runLoopMode\n{\n\tCFRunLoopRemoveSource(theRunLoop, source, (__bridge CFStringRef)runLoopMode);\n}\n\n- (void)runLoopAddTimer:(NSTimer *)timer\n{\n\tfor (NSString *runLoopMode in theRunLoopModes)\n\t{\n\t\tCFRunLoopAddTimer(theRunLoop, (__bridge CFRunLoopTimerRef)timer, (__bridge CFStringRef)runLoopMode);\n\t}\n}\n\n- (void)runLoopRemoveTimer:(NSTimer *)timer\n{\n\tfor (NSString *runLoopMode in theRunLoopModes)\n\t{\n\t\tCFRunLoopRemoveTimer(theRunLoop, (__bridge CFRunLoopTimerRef)timer, (__bridge CFStringRef)runLoopMode);\n\t}\n}\n\n- (void)runLoopAddTimer:(NSTimer *)timer mode:(NSString *)runLoopMode\n{\n\tCFRunLoopAddTimer(theRunLoop, (__bridge CFRunLoopTimerRef)timer, (__bridge CFStringRef)runLoopMode);\n}\n\n- (void)runLoopRemoveTimer:(NSTimer *)timer mode:(NSString *)runLoopMode\n{\n\tCFRunLoopRemoveTimer(theRunLoop, (__bridge CFRunLoopTimerRef)timer, (__bridge CFStringRef)runLoopMode);\n}\n\n- (void)runLoopUnscheduleReadStream\n{\n\tfor (NSString *runLoopMode in theRunLoopModes)\n\t{\n\t\tCFReadStreamUnscheduleFromRunLoop(theReadStream, theRunLoop, (__bridge CFStringRef)runLoopMode);\n\t}\n\tCFReadStreamSetClient(theReadStream, kCFStreamEventNone, NULL, NULL);\n}\n\n- (void)runLoopUnscheduleWriteStream\n{\n\tfor (NSString *runLoopMode in theRunLoopModes)\n\t{\n\t\tCFWriteStreamUnscheduleFromRunLoop(theWriteStream, theRunLoop, (__bridge CFStringRef)runLoopMode);\n\t}\n\tCFWriteStreamSetClient(theWriteStream, kCFStreamEventNone, NULL, NULL);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Configuration\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n/**\n * See the header file for a full explanation of pre-buffering.\n **/\n- (void)enablePreBuffering\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\ttheFlags |= kEnablePreBuffering;\n}\n\n/**\n * See the header file for a full explanation of this method.\n **/\n- (BOOL)moveToRunLoop:(NSRunLoop *)runLoop\n{\n\tNSAssert((theRunLoop == NULL) || (theRunLoop == CFRunLoopGetCurrent()),\n\t\t\t @\"moveToRunLoop must be called from within the current RunLoop!\");\n\t\n\tif(runLoop == nil)\n\t{\n\t\treturn NO;\n\t}\n\tif(theRunLoop == [runLoop getCFRunLoop])\n\t{\n\t\treturn YES;\n\t}\n\t\n\t[NSObject cancelPreviousPerformRequestsWithTarget:self];\n\ttheFlags &= ~kDequeueReadScheduled;\n\ttheFlags &= ~kDequeueWriteScheduled;\n\t\n\tif(theReadStream && theWriteStream)\n    {\n        [self runLoopUnscheduleReadStream];\n        [self runLoopUnscheduleWriteStream];\n    }\n    \n\tif(theSource4) [self runLoopRemoveSource:theSource4];\n\tif(theSource6) [self runLoopRemoveSource:theSource6];\n\t\n\tif(theReadTimer) [self runLoopRemoveTimer:theReadTimer];\n\tif(theWriteTimer) [self runLoopRemoveTimer:theWriteTimer];\n\t\n\ttheRunLoop = [runLoop getCFRunLoop];\n\t\n\tif(theReadTimer) [self runLoopAddTimer:theReadTimer];\n\tif(theWriteTimer) [self runLoopAddTimer:theWriteTimer];\n\t\n\tif(theSource4) [self runLoopAddSource:theSource4];\n\tif(theSource6) [self runLoopAddSource:theSource6];\n    \n    if(theReadStream && theWriteStream)\n\t{\n\t\tif(![self attachStreamsToRunLoop:runLoop error:nil])\n\t\t{\n\t\t\treturn NO;\n\t\t}\n\t}\n\t\n\t[runLoop performSelector:@selector(maybeDequeueRead) target:self argument:nil order:0 modes:theRunLoopModes];\n\t[runLoop performSelector:@selector(maybeDequeueWrite) target:self argument:nil order:0 modes:theRunLoopModes];\n\t[runLoop performSelector:@selector(maybeScheduleDisconnect) target:self argument:nil order:0 modes:theRunLoopModes];\n\t\n\treturn YES;\n}\n\n/**\n * See the header file for a full explanation of this method.\n **/\n- (BOOL)setRunLoopModes:(NSArray *)runLoopModes\n{\n\tNSAssert((theRunLoop == NULL) || (theRunLoop == CFRunLoopGetCurrent()),\n\t\t\t @\"setRunLoopModes must be called from within the current RunLoop!\");\n\t\n\tif([runLoopModes count] == 0)\n\t{\n\t\treturn NO;\n\t}\n\tif([theRunLoopModes isEqualToArray:runLoopModes])\n\t{\n\t\treturn YES;\n\t}\n\t\n\t[NSObject cancelPreviousPerformRequestsWithTarget:self];\n\ttheFlags &= ~kDequeueReadScheduled;\n\ttheFlags &= ~kDequeueWriteScheduled;\n\t\n\tif(theReadStream && theWriteStream)\n    {\n        [self runLoopUnscheduleReadStream];\n        [self runLoopUnscheduleWriteStream];\n    }\n    \n\tif(theSource4) [self runLoopRemoveSource:theSource4];\n\tif(theSource6) [self runLoopRemoveSource:theSource6];\n\t\n\tif(theReadTimer) [self runLoopRemoveTimer:theReadTimer];\n\tif(theWriteTimer) [self runLoopRemoveTimer:theWriteTimer];\n\t\n\ttheRunLoopModes = [runLoopModes copy];\n\t\n\tif(theReadTimer) [self runLoopAddTimer:theReadTimer];\n\tif(theWriteTimer) [self runLoopAddTimer:theWriteTimer];\n\t\n\tif(theSource4) [self runLoopAddSource:theSource4];\n\tif(theSource6) [self runLoopAddSource:theSource6];\n    \n\tif(theReadStream && theWriteStream)\n\t{\n\t\t// Note: theRunLoop variable is a CFRunLoop, and NSRunLoop is NOT toll-free bridged with CFRunLoop.\n\t\t// So we cannot pass theRunLoop to the method below, which is expecting a NSRunLoop parameter.\n\t\t// Instead we pass nil, which will result in the method properly using the current run loop.\n\t\t\n\t\tif(![self attachStreamsToRunLoop:nil error:nil])\n\t\t{\n\t\t\treturn NO;\n\t\t}\n\t}\n\t\n\t[self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t[self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t[self performSelector:@selector(maybeScheduleDisconnect) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t\n\treturn YES;\n}\n\n- (BOOL)addRunLoopMode:(NSString *)runLoopMode\n{\n\tNSAssert((theRunLoop == NULL) || (theRunLoop == CFRunLoopGetCurrent()),\n\t\t\t @\"addRunLoopMode must be called from within the current RunLoop!\");\n\t\n\tif(runLoopMode == nil)\n\t{\n\t\treturn NO;\n\t}\n\tif([theRunLoopModes containsObject:runLoopMode])\n\t{\n\t\treturn YES;\n\t}\n\t\n\t[NSObject cancelPreviousPerformRequestsWithTarget:self];\n\ttheFlags &= ~kDequeueReadScheduled;\n\ttheFlags &= ~kDequeueWriteScheduled;\n    \n\tNSArray *newRunLoopModes = [theRunLoopModes arrayByAddingObject:runLoopMode];\n\ttheRunLoopModes = newRunLoopModes;\n\t\n\tif(theReadTimer)  [self runLoopAddTimer:theReadTimer  mode:runLoopMode];\n\tif(theWriteTimer) [self runLoopAddTimer:theWriteTimer mode:runLoopMode];\n\t\n\tif(theSource4) [self runLoopAddSource:theSource4 mode:runLoopMode];\n\tif(theSource6) [self runLoopAddSource:theSource6 mode:runLoopMode];\n    \n\tif(theReadStream && theWriteStream)\n\t{\n\t\tCFReadStreamScheduleWithRunLoop(theReadStream, CFRunLoopGetCurrent(), (__bridge CFStringRef)runLoopMode);\n\t\tCFWriteStreamScheduleWithRunLoop(theWriteStream, CFRunLoopGetCurrent(), (__bridge CFStringRef)runLoopMode);\n\t}\n\t\n\t[self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t[self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t[self performSelector:@selector(maybeScheduleDisconnect) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t\n\treturn YES;\n}\n\n- (BOOL)removeRunLoopMode:(NSString *)runLoopMode\n{\n\tNSAssert((theRunLoop == NULL) || (theRunLoop == CFRunLoopGetCurrent()),\n\t\t\t @\"addRunLoopMode must be called from within the current RunLoop!\");\n\t\n\tif(runLoopMode == nil)\n\t{\n\t\treturn NO;\n\t}\n\tif(![theRunLoopModes containsObject:runLoopMode])\n\t{\n\t\treturn YES;\n\t}\n\t\n\tNSMutableArray *newRunLoopModes = [theRunLoopModes mutableCopy];\n\t[newRunLoopModes removeObject:runLoopMode];\n\t\n\tif([newRunLoopModes count] == 0)\n\t{\n\t\treturn NO;\n\t}\n\t\n\t[NSObject cancelPreviousPerformRequestsWithTarget:self];\n\ttheFlags &= ~kDequeueReadScheduled;\n\ttheFlags &= ~kDequeueWriteScheduled;\n\t\n\ttheRunLoopModes = [newRunLoopModes copy];\n\t\n\tif(theReadTimer)  [self runLoopRemoveTimer:theReadTimer  mode:runLoopMode];\n\tif(theWriteTimer) [self runLoopRemoveTimer:theWriteTimer mode:runLoopMode];\n\t\n\tif(theSource4) [self runLoopRemoveSource:theSource4 mode:runLoopMode];\n\tif(theSource6) [self runLoopRemoveSource:theSource6 mode:runLoopMode];\n    \n\tif(theReadStream && theWriteStream)\n\t{\n\t\tCFReadStreamScheduleWithRunLoop(theReadStream, CFRunLoopGetCurrent(), (__bridge CFStringRef)runLoopMode);\n\t\tCFWriteStreamScheduleWithRunLoop(theWriteStream, CFRunLoopGetCurrent(), (__bridge CFStringRef)runLoopMode);\n\t}\n\t\n\t[self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t[self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t[self performSelector:@selector(maybeScheduleDisconnect) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t\n\treturn YES;\n}\n\n- (NSArray *)runLoopModes\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\treturn theRunLoopModes;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Accepting\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr\n{\n\treturn [self acceptOnInterface:nil port:port error:errPtr];\n}\n\n/**\n * To accept on a certain interface, pass the address to accept on.\n * To accept on any interface, pass nil or an empty string.\n * To accept only connections from localhost pass \"localhost\" or \"loopback\".\n **/\n- (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr\n{\n\tif (theDelegate == NULL)\n    {\n\t\t[NSException raise:AsyncSocketException\n\t\t            format:@\"Attempting to accept without a delegate. Set a delegate first.\"];\n    }\n\t\n\tif (![self isDisconnected])\n    {\n\t\t[NSException raise:AsyncSocketException\n\t\t            format:@\"Attempting to accept while connected or accepting connections. Disconnect first.\"];\n    }\n\t\n\t// Clear queues (spurious read/write requests post disconnect)\n\t[self emptyQueues];\n    \n\t// Set up the listen sockaddr structs if needed.\n\t\n\tNSData *address4 = nil, *address6 = nil;\n\tif(interface == nil || ([interface length] == 0))\n\t{\n\t\t// Accept on ANY address\n\t\tstruct sockaddr_in nativeAddr4;\n\t\tnativeAddr4.sin_len         = sizeof(struct sockaddr_in);\n\t\tnativeAddr4.sin_family      = AF_INET;\n\t\tnativeAddr4.sin_port        = htons(port);\n\t\tnativeAddr4.sin_addr.s_addr = htonl(INADDR_ANY);\n\t\tmemset(&(nativeAddr4.sin_zero), 0, sizeof(nativeAddr4.sin_zero));\n\t\t\n\t\tstruct sockaddr_in6 nativeAddr6;\n\t\tnativeAddr6.sin6_len       = sizeof(struct sockaddr_in6);\n\t\tnativeAddr6.sin6_family    = AF_INET6;\n\t\tnativeAddr6.sin6_port      = htons(port);\n\t\tnativeAddr6.sin6_flowinfo  = 0;\n\t\tnativeAddr6.sin6_addr      = in6addr_any;\n\t\tnativeAddr6.sin6_scope_id  = 0;\n\t\t\n\t\t// Wrap the native address structures for CFSocketSetAddress.\n\t\taddress4 = [NSData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)];\n\t\taddress6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];\n\t}\n\telse if([interface isEqualToString:@\"localhost\"] || [interface isEqualToString:@\"loopback\"])\n\t{\n\t\t// Accept only on LOOPBACK address\n\t\tstruct sockaddr_in nativeAddr4;\n\t\tnativeAddr4.sin_len         = sizeof(struct sockaddr_in);\n\t\tnativeAddr4.sin_family      = AF_INET;\n\t\tnativeAddr4.sin_port        = htons(port);\n\t\tnativeAddr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);\n\t\tmemset(&(nativeAddr4.sin_zero), 0, sizeof(nativeAddr4.sin_zero));\n        \n\t\tstruct sockaddr_in6 nativeAddr6;\n\t\tnativeAddr6.sin6_len       = sizeof(struct sockaddr_in6);\n\t\tnativeAddr6.sin6_family    = AF_INET6;\n\t\tnativeAddr6.sin6_port      = htons(port);\n\t\tnativeAddr6.sin6_flowinfo  = 0;\n\t\tnativeAddr6.sin6_addr      = in6addr_loopback;\n\t\tnativeAddr6.sin6_scope_id  = 0;\n\t\t\n\t\t// Wrap the native address structures for CFSocketSetAddress.\n\t\taddress4 = [NSData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)];\n\t\taddress6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];\n\t}\n\telse\n\t{\n\t\tNSString *portStr = [NSString stringWithFormat:@\"%hu\", port];\n        \n\t\tstruct addrinfo hints, *res, *res0;\n\t\t\n\t\tmemset(&hints, 0, sizeof(hints));\n\t\thints.ai_family   = PF_UNSPEC;\n\t\thints.ai_socktype = SOCK_STREAM;\n\t\thints.ai_protocol = IPPROTO_TCP;\n\t\thints.ai_flags    = AI_PASSIVE;\n\t\t\n\t\tint error = getaddrinfo([interface UTF8String], [portStr UTF8String], &hints, &res0);\n\t\t\n\t\tif (error)\n\t\t{\n\t\t\tif (errPtr)\n\t\t\t{\n\t\t\t\tNSString *errMsg = [NSString stringWithCString:gai_strerror(error) encoding:NSASCIIStringEncoding];\n\t\t\t\tNSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];\n\t\t\t\t\n\t\t\t\t*errPtr = [NSError errorWithDomain:@\"kCFStreamErrorDomainNetDB\" code:error userInfo:info];\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (res = res0; res; res = res->ai_next)\n\t\t\t{\n\t\t\t\tif (!address4 && (res->ai_family == AF_INET))\n\t\t\t\t{\n\t\t\t\t\t// Found IPv4 address\n\t\t\t\t\t// Wrap the native address structures for CFSocketSetAddress.\n\t\t\t\t\taddress4 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];\n\t\t\t\t}\n\t\t\t\telse if (!address6 && (res->ai_family == AF_INET6))\n\t\t\t\t{\n\t\t\t\t\t// Found IPv6 address\n\t\t\t\t\t// Wrap the native address structures for CFSocketSetAddress.\n\t\t\t\t\taddress6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];\n\t\t\t\t}\n\t\t\t}\n\t\t\tfreeaddrinfo(res0);\n\t\t}\n\t\t\n\t\tif(!address4 && !address6) return NO;\n\t}\n    \n\t// Create the sockets.\n    \n\tif (address4)\n\t{\n\t\ttheSocket4 = [self newAcceptSocketForAddress:address4 error:errPtr];\n\t\tif (theSocket4 == NULL) goto Failed;\n\t}\n\t\n\tif (address6)\n\t{\n\t\ttheSocket6 = [self newAcceptSocketForAddress:address6 error:errPtr];\n\t\t\n\t\t// Note: The iPhone doesn't currently support IPv6\n\t\t\n#if !TARGET_OS_IPHONE\n\t\tif (theSocket6 == NULL) goto Failed;\n#endif\n\t}\n\t\n\t// Attach the sockets to the run loop so that callback methods work\n\t\n\t[self attachSocketsToRunLoop:nil error:nil];\n\t\n\t// Set the SO_REUSEADDR flags.\n    \n\tint reuseOn = 1;\n\tif (theSocket4)\tsetsockopt(CFSocketGetNative(theSocket4), SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));\n\tif (theSocket6)\tsetsockopt(CFSocketGetNative(theSocket6), SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));\n    \n\t// Set the local bindings which causes the sockets to start listening.\n    \n\tCFSocketError err;\n\tif (theSocket4)\n\t{\n\t\terr = CFSocketSetAddress(theSocket4, (__bridge CFDataRef)address4);\n\t\tif (err != kCFSocketSuccess) goto Failed;\n\t\t\n\t\t//NSLog(@\"theSocket4: %hu\", [self localPortFromCFSocket4:theSocket4]);\n\t}\n\t\n\tif(port == 0 && theSocket4 && theSocket6)\n\t{\n\t\t// The user has passed in port 0, which means he wants to allow the kernel to choose the port for them\n\t\t// However, the kernel will choose a different port for both theSocket4 and theSocket6\n\t\t// So we grab the port the kernel choose for theSocket4, and set it as the port for theSocket6\n\t\tUInt16 chosenPort = [self localPortFromCFSocket4:theSocket4];\n\t\t\n\t\tstruct sockaddr_in6 *pSockAddr6 = (struct sockaddr_in6 *)[address6 bytes];\n\t\tif (pSockAddr6) // If statement to quiet the static analyzer\n\t\t{\n\t\t\tpSockAddr6->sin6_port = htons(chosenPort);\n\t\t}\n    }\n\t\n\tif (theSocket6)\n\t{\n\t\terr = CFSocketSetAddress(theSocket6, (__bridge CFDataRef)address6);\n\t\tif (err != kCFSocketSuccess) goto Failed;\n\t\t\n\t\t//NSLog(@\"theSocket6: %hu\", [self localPortFromCFSocket6:theSocket6]);\n\t}\n    \n\ttheFlags |= kDidStartDelegate;\n\treturn YES;\n\t\nFailed:\n\tif(errPtr) *errPtr = [self getSocketError];\n\tif(theSocket4 != NULL)\n\t{\n\t\tCFSocketInvalidate(theSocket4);\n\t\tCFRelease(theSocket4);\n\t\ttheSocket4 = NULL;\n\t}\n\tif(theSocket6 != NULL)\n\t{\n\t\tCFSocketInvalidate(theSocket6);\n\t\tCFRelease(theSocket6);\n\t\ttheSocket6 = NULL;\n\t}\n\treturn NO;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Connecting\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (BOOL)connectToHost:(NSString*)hostname onPort:(UInt16)port error:(NSError **)errPtr\n{\n\treturn [self connectToHost:hostname onPort:port withTimeout:-1 error:errPtr];\n}\n\n/**\n * This method creates an initial CFReadStream and CFWriteStream to the given host on the given port.\n * The connection is then opened, and the corresponding CFSocket will be extracted after the connection succeeds.\n *\n * Thus the delegate will have access to the CFReadStream and CFWriteStream prior to connection,\n * specifically in the onSocketWillConnect: method.\n **/\n- (BOOL)connectToHost:(NSString *)hostname\n\t\t\t   onPort:(UInt16)port\n\t\t  withTimeout:(NSTimeInterval)timeout\n\t\t\t\terror:(NSError **)errPtr\n{\n\tif (theDelegate == NULL)\n\t{\n\t\t[NSException raise:AsyncSocketException\n\t\t            format:@\"Attempting to connect without a delegate. Set a delegate first.\"];\n\t}\n    \n\tif (![self isDisconnected])\n\t{\n\t\t[NSException raise:AsyncSocketException\n\t\t            format:@\"Attempting to connect while connected or accepting connections. Disconnect first.\"];\n\t}\n\t\n\t// Clear queues (spurious read/write requests post disconnect)\n\t[self emptyQueues];\n\t\n\tif(![self createStreamsToHost:hostname onPort:port error:errPtr]) goto Failed;\n\tif(![self attachStreamsToRunLoop:nil error:errPtr])               goto Failed;\n\tif(![self configureStreamsAndReturnError:errPtr])                 goto Failed;\n\tif(![self openStreamsAndReturnError:errPtr])                      goto Failed;\n\t\n\t[self startConnectTimeout:timeout];\n\ttheFlags |= kDidStartDelegate;\n\t\n\treturn YES;\n\t\nFailed:\n\t[self close];\n\treturn NO;\n}\n\n- (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr\n{\n\treturn [self connectToAddress:remoteAddr viaInterfaceAddress:nil withTimeout:-1 error:errPtr];\n}\n\n/**\n * This method creates an initial CFSocket to the given address.\n * The connection is then opened, and the corresponding CFReadStream and CFWriteStream will be\n * created from the low-level sockets after the connection succeeds.\n *\n * Thus the delegate will have access to the CFSocket and CFSocketNativeHandle (BSD socket) prior to connection,\n * specifically in the onSocketWillConnect: method.\n *\n * Note: The NSData parameter is expected to be a sockaddr structure. For example, an NSData object returned from\n * NSNetService addresses method.\n * If you have an existing struct sockaddr you can convert it to an NSData object like so:\n * struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];\n * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];\n **/\n- (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr\n{\n\treturn [self connectToAddress:remoteAddr viaInterfaceAddress:nil withTimeout:timeout error:errPtr];\n}\n\n/**\n * This method is similar to the one above, but allows you to specify which socket interface\n * the connection should run over. E.g. ethernet, wifi, bluetooth, etc.\n **/\n- (BOOL)connectToAddress:(NSData *)remoteAddr\n     viaInterfaceAddress:(NSData *)interfaceAddr\n             withTimeout:(NSTimeInterval)timeout\n                   error:(NSError **)errPtr\n{\n\tif (theDelegate == NULL)\n\t{\n\t\t[NSException raise:AsyncSocketException\n\t\t            format:@\"Attempting to connect without a delegate. Set a delegate first.\"];\n\t}\n\t\n\tif (![self isDisconnected])\n\t{\n\t\t[NSException raise:AsyncSocketException\n\t\t            format:@\"Attempting to connect while connected or accepting connections. Disconnect first.\"];\n\t}\n\t\n\t// Clear queues (spurious read/write requests post disconnect)\n\t[self emptyQueues];\n\t\n\tif(![self createSocketForAddress:remoteAddr error:errPtr])   goto Failed;\n\tif(![self bindSocketToAddress:interfaceAddr error:errPtr])   goto Failed;\n\tif(![self attachSocketsToRunLoop:nil error:errPtr])          goto Failed;\n\tif(![self configureSocketAndReturnError:errPtr])             goto Failed;\n\tif(![self connectSocketToAddress:remoteAddr error:errPtr])   goto Failed;\n\t\n\t[self startConnectTimeout:timeout];\n\ttheFlags |= kDidStartDelegate;\n\t\n\treturn YES;\n\t\nFailed:\n\t[self close];\n\treturn NO;\n}\n\n- (void)startConnectTimeout:(NSTimeInterval)timeout\n{\n\tif(timeout >= 0.0)\n\t{\n\t\ttheConnectTimer = [NSTimer timerWithTimeInterval:timeout\n\t\t\t\t\t\t\t\t\t\t\t      target:self\n\t\t\t\t\t\t\t\t\t\t\t    selector:@selector(doConnectTimeout:)\n\t\t\t\t\t\t\t\t\t\t\t    userInfo:nil\n\t\t\t\t\t\t\t\t\t\t\t     repeats:NO];\n\t\t[self runLoopAddTimer:theConnectTimer];\n\t}\n}\n\n- (void)endConnectTimeout\n{\n\t[theConnectTimer invalidate];\n\ttheConnectTimer = nil;\n}\n\n- (void)doConnectTimeout:(NSTimer *)timer\n{\n#pragma unused(timer)\n\t\n\t[self endConnectTimeout];\n\t[self closeWithError:[self getConnectTimeoutError]];\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Socket Implementation\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Creates the accept sockets.\n * Returns true if either IPv4 or IPv6 is created.\n * If either is missing, an error is returned (even though the method may return true).\n **/\n- (CFSocketRef)newAcceptSocketForAddress:(NSData *)addr error:(NSError **)errPtr\n{\n\tstruct sockaddr *pSockAddr = (struct sockaddr *)[addr bytes];\n\tint addressFamily = pSockAddr->sa_family;\n\t\n\tCFSocketRef theSocket = CFSocketCreate(kCFAllocatorDefault,\n\t                                       addressFamily,\n\t                                       SOCK_STREAM,\n\t                                       0,\n\t                                       kCFSocketAcceptCallBack,                // Callback flags\n\t                                       (CFSocketCallBack)&MyCFSocketCallback,  // Callback method\n\t                                       &theContext);\n    \n\tif(theSocket == NULL)\n\t{\n\t\tif(errPtr) *errPtr = [self getSocketError];\n\t}\n\t\n\treturn theSocket;\n}\n\n- (BOOL)createSocketForAddress:(NSData *)remoteAddr error:(NSError **)errPtr\n{\n\tstruct sockaddr *pSockAddr = (struct sockaddr *)[remoteAddr bytes];\n\t\n\tif(pSockAddr->sa_family == AF_INET)\n\t{\n\t\ttheSocket4 = CFSocketCreate(NULL,                                   // Default allocator\n\t\t                            PF_INET,                                // Protocol Family\n\t\t                            SOCK_STREAM,                            // Socket Type\n\t\t                            IPPROTO_TCP,                            // Protocol\n\t\t                            kCFSocketConnectCallBack,               // Callback flags\n\t\t                            (CFSocketCallBack)&MyCFSocketCallback,  // Callback method\n\t\t                            &theContext);                           // Socket Context\n\t\t\n\t\tif(theSocket4 == NULL)\n\t\t{\n\t\t\tif (errPtr) *errPtr = [self getSocketError];\n\t\t\treturn NO;\n\t\t}\n\t}\n\telse if(pSockAddr->sa_family == AF_INET6)\n\t{\n\t\ttheSocket6 = CFSocketCreate(NULL,                                   // Default allocator\n\t\t\t\t\t\t\t\t    PF_INET6,                               // Protocol Family\n\t\t\t\t\t\t\t\t    SOCK_STREAM,                            // Socket Type\n\t\t\t\t\t\t\t\t    IPPROTO_TCP,                            // Protocol\n\t\t\t\t\t\t\t\t    kCFSocketConnectCallBack,               // Callback flags\n\t\t\t\t\t\t\t\t    (CFSocketCallBack)&MyCFSocketCallback,  // Callback method\n\t\t\t\t\t\t\t\t    &theContext);                           // Socket Context\n\t\t\n\t\tif(theSocket6 == NULL)\n\t\t{\n\t\t\tif (errPtr) *errPtr = [self getSocketError];\n\t\t\treturn NO;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (errPtr)\n\t\t{\n\t\t\tNSString *errMsg = @\"Remote address is not IPv4 or IPv6\";\n\t\t\tNSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];\n\t\t\t\n\t\t\t*errPtr = [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCFSocketError userInfo:info];\n\t\t}\n\t\treturn NO;\n\t}\n\t\n\treturn YES;\n}\n\n- (BOOL)bindSocketToAddress:(NSData *)interfaceAddr error:(NSError **)errPtr\n{\n\tif (interfaceAddr == nil) return YES;\n\t\n\tstruct sockaddr *pSockAddr = (struct sockaddr *)[interfaceAddr bytes];\n\t\n\tCFSocketRef theSocket = (theSocket4 != NULL) ? theSocket4 : theSocket6;\n\tNSAssert((theSocket != NULL), @\"bindSocketToAddress called without valid socket\");\n\t\n\tCFSocketNativeHandle nativeSocket = CFSocketGetNative(theSocket);\n\t\n\tif (pSockAddr->sa_family == AF_INET || pSockAddr->sa_family == AF_INET6)\n\t{\n\t\tint result = bind(nativeSocket, pSockAddr, (socklen_t)[interfaceAddr length]);\n\t\tif (result != 0)\n\t\t{\n\t\t\tif (errPtr) *errPtr = [self getErrnoError];\n\t\t\treturn NO;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (errPtr)\n\t\t{\n\t\t\tNSString *errMsg = @\"Interface address is not IPv4 or IPv6\";\n\t\t\tNSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];\n\t\t\t\n\t\t\t*errPtr = [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCFSocketError userInfo:info];\n\t\t}\n\t\treturn NO;\n\t}\n\t\n\treturn YES;\n}\n\n/**\n * Adds the CFSocket's to the run-loop so that callbacks will work properly.\n **/\n- (BOOL)attachSocketsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr\n{\n#pragma unused(errPtr)\n\t\n\t// Get the CFRunLoop to which the socket should be attached.\n\ttheRunLoop = (runLoop == nil) ? CFRunLoopGetCurrent() : [runLoop getCFRunLoop];\n\t\n\tif(theSocket4)\n\t{\n\t\ttheSource4 = CFSocketCreateRunLoopSource (kCFAllocatorDefault, theSocket4, 0);\n        [self runLoopAddSource:theSource4];\n\t}\n\t\n\tif(theSocket6)\n\t{\n\t\ttheSource6 = CFSocketCreateRunLoopSource (kCFAllocatorDefault, theSocket6, 0);\n        [self runLoopAddSource:theSource6];\n\t}\n\t\n\treturn YES;\n}\n\n/**\n * Allows the delegate method to configure the CFSocket or CFNativeSocket as desired before we connect.\n * Note that the CFReadStream and CFWriteStream will not be available until after the connection is opened.\n **/\n- (BOOL)configureSocketAndReturnError:(NSError **)errPtr\n{\n\t// Call the delegate method for further configuration.\n\tif([theDelegate respondsToSelector:@selector(onSocketWillConnect:)])\n\t{\n\t\tif([theDelegate onSocketWillConnect:self] == NO)\n\t\t{\n\t\t\tif (errPtr) *errPtr = [self getAbortError];\n\t\t\treturn NO;\n\t\t}\n\t}\n\treturn YES;\n}\n\n- (BOOL)connectSocketToAddress:(NSData *)remoteAddr error:(NSError **)errPtr\n{\n\t// Start connecting to the given address in the background\n\t// The MyCFSocketCallback method will be called when the connection succeeds or fails\n\tif(theSocket4)\n\t{\n\t\tCFSocketError err = CFSocketConnectToAddress(theSocket4, (__bridge CFDataRef)remoteAddr, -1);\n\t\tif(err != kCFSocketSuccess)\n\t\t{\n\t\t\tif (errPtr) *errPtr = [self getSocketError];\n\t\t\treturn NO;\n\t\t}\n\t}\n\telse if(theSocket6)\n\t{\n\t\tCFSocketError err = CFSocketConnectToAddress(theSocket6, (__bridge CFDataRef)remoteAddr, -1);\n\t\tif(err != kCFSocketSuccess)\n\t\t{\n\t\t\tif (errPtr) *errPtr = [self getSocketError];\n\t\t\treturn NO;\n\t\t}\n\t}\n\t\n\treturn YES;\n}\n\n/**\n * Attempt to make the new socket.\n * If an error occurs, ignore this event.\n **/\n- (void)doAcceptFromSocket:(CFSocketRef)parentSocket withNewNativeSocket:(CFSocketNativeHandle)newNativeSocket\n{\n\tif(newNativeSocket)\n\t{\n\t\t// New socket inherits same delegate and run loop modes.\n\t\t// Note: We use [self class] to support subclassing AsyncSocket.\n\t\tAsyncSocket *newSocket = [[[self class] alloc] initWithDelegate:theDelegate];\n\t\t[newSocket setRunLoopModes:theRunLoopModes];\n\t\t\n\t\tif (![newSocket createStreamsFromNative:newNativeSocket error:nil])\n\t\t{\n\t\t\t[newSocket close];\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tif (parentSocket == theSocket4)\n\t\t\tnewSocket->theNativeSocket4 = newNativeSocket;\n\t\telse\n\t\t\tnewSocket->theNativeSocket6 = newNativeSocket;\n\t\t\n\t\tif ([theDelegate respondsToSelector:@selector(onSocket:didAcceptNewSocket:)])\n\t\t\t[theDelegate onSocket:self didAcceptNewSocket:newSocket];\n\t\t\n\t\tnewSocket->theFlags |= kDidStartDelegate;\n\t\t\n\t\tNSRunLoop *runLoop = nil;\n\t\tif ([theDelegate respondsToSelector:@selector(onSocket:wantsRunLoopForNewSocket:)])\n\t\t{\n\t\t\trunLoop = [theDelegate onSocket:self wantsRunLoopForNewSocket:newSocket];\n\t\t}\n\t\t\n\t\tif(![newSocket attachStreamsToRunLoop:runLoop error:nil]) goto Failed;\n\t\tif(![newSocket configureStreamsAndReturnError:nil])       goto Failed;\n\t\tif(![newSocket openStreamsAndReturnError:nil])            goto Failed;\n\t\t\n\t\treturn;\n\t\t\n\tFailed:\n\t\t[newSocket close];\n\t}\n}\n\n/**\n * This method is called as a result of connectToAddress:withTimeout:error:.\n * At this point we have an open CFSocket from which we need to create our read and write stream.\n **/\n- (void)doSocketOpen:(CFSocketRef)sock withCFSocketError:(CFSocketError)socketError\n{\n\tNSParameterAssert ((sock == theSocket4) || (sock == theSocket6));\n\t\n\tif(socketError == kCFSocketTimeout || socketError == kCFSocketError)\n\t{\n\t\t[self closeWithError:[self getSocketError]];\n\t\treturn;\n\t}\n\t\n\t// Get the underlying native (BSD) socket\n\tCFSocketNativeHandle nativeSocket = CFSocketGetNative(sock);\n\t\n\t// Store a reference to it\n\tif (sock == theSocket4)\n\t\ttheNativeSocket4 = nativeSocket;\n\telse\n\t\ttheNativeSocket6 = nativeSocket;\n\t\n\t// Setup the CFSocket so that invalidating it will not close the underlying native socket\n\tCFSocketSetSocketFlags(sock, 0);\n\t\n\t// Invalidate and release the CFSocket - All we need from here on out is the nativeSocket.\n\t// Note: If we don't invalidate the CFSocket (leaving the native socket open)\n\t// then theReadStream and theWriteStream won't function properly.\n\t// Specifically, their callbacks won't work, with the exception of kCFStreamEventOpenCompleted.\n\t//\n\t// This is likely due to the mixture of the CFSocketCreateWithNative method,\n\t// along with the CFStreamCreatePairWithSocket method.\n\t// The documentation for CFSocketCreateWithNative states:\n\t//\n\t//   If a CFSocket object already exists for sock,\n\t//   the function returns the pre-existing object instead of creating a new object;\n\t//   the context, callout, and callBackTypes parameters are ignored in this case.\n\t//\n\t// So the CFStreamCreateWithNative method invokes the CFSocketCreateWithNative method,\n\t// thinking that is creating a new underlying CFSocket for it's own purposes.\n\t// When it does this, it uses the context/callout/callbackTypes parameters to setup everything appropriately.\n\t// However, if a CFSocket already exists for the native socket,\n\t// then it is returned (as per the documentation), which in turn screws up the CFStreams.\n\t\n\tCFSocketInvalidate(sock);\n\tCFRelease(sock);\n\ttheSocket4 = NULL;\n\ttheSocket6 = NULL;\n\t\n\tNSError *err;\n\tBOOL pass = YES;\n\t\n\tif(pass && ![self createStreamsFromNative:nativeSocket error:&err]) pass = NO;\n\tif(pass && ![self attachStreamsToRunLoop:nil error:&err])           pass = NO;\n\tif(pass && ![self openStreamsAndReturnError:&err])                  pass = NO;\n\t\n\tif(!pass)\n\t{\n\t\t[self closeWithError:err];\n\t}\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Stream Implementation\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Creates the CFReadStream and CFWriteStream from the given native socket.\n * The CFSocket may be extracted from either stream after the streams have been opened.\n *\n * Note: The given native socket must already be connected!\n **/\n- (BOOL)createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr\n{\n\t// Create the socket & streams.\n\tCFStreamCreatePairWithSocket(kCFAllocatorDefault, native, &theReadStream, &theWriteStream);\n\tif (theReadStream == NULL || theWriteStream == NULL)\n\t{\n\t\tNSError *err = [self getStreamError];\n\t\t\n\t\tNSLog(@\"AsyncSocket %p couldn't create streams from accepted socket: %@\", self, err);\n\t\t\n\t\tif (errPtr) *errPtr = err;\n\t\treturn NO;\n\t}\n\t\n\t// Ensure the CF & BSD socket is closed when the streams are closed.\n\tCFReadStreamSetProperty(theReadStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);\n\tCFWriteStreamSetProperty(theWriteStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);\n\t\n\treturn YES;\n}\n\n/**\n * Creates the CFReadStream and CFWriteStream from the given hostname and port number.\n * The CFSocket may be extracted from either stream after the streams have been opened.\n **/\n- (BOOL)createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr\n{\n\t// Create the socket & streams.\n\tCFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)hostname, port, &theReadStream, &theWriteStream);\n\tif (theReadStream == NULL || theWriteStream == NULL)\n\t{\n\t\tif (errPtr) *errPtr = [self getStreamError];\n\t\treturn NO;\n\t}\n\t\n\t// Ensure the CF & BSD socket is closed when the streams are closed.\n\tCFReadStreamSetProperty(theReadStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);\n\tCFWriteStreamSetProperty(theWriteStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);\n\t\n\treturn YES;\n}\n\n- (BOOL)attachStreamsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr\n{\n\t// Get the CFRunLoop to which the socket should be attached.\n\ttheRunLoop = (runLoop == nil) ? CFRunLoopGetCurrent() : [runLoop getCFRunLoop];\n    \n\t// Setup read stream callbacks\n\t\n\tCFOptionFlags readStreamEvents = kCFStreamEventHasBytesAvailable |\n    kCFStreamEventErrorOccurred     |\n    kCFStreamEventEndEncountered    |\n    kCFStreamEventOpenCompleted;\n\t\n\tif (!CFReadStreamSetClient(theReadStream,\n\t\t\t\t\t\t\t   readStreamEvents,\n\t\t\t\t\t\t\t   (CFReadStreamClientCallBack)&MyCFReadStreamCallback,\n\t\t\t\t\t\t\t   (CFStreamClientContext *)(&theContext)))\n\t{\n\t\tNSError *err = [self getStreamError];\n\t\t\n\t\tNSLog (@\"AsyncSocket %p couldn't attach read stream to run-loop,\", self);\n\t\tNSLog (@\"Error: %@\", err);\n\t\t\n\t\tif (errPtr) *errPtr = err;\n\t\treturn NO;\n\t}\n    \n\t// Setup write stream callbacks\n\t\n\tCFOptionFlags writeStreamEvents = kCFStreamEventCanAcceptBytes |\n    kCFStreamEventErrorOccurred  |\n    kCFStreamEventEndEncountered |\n    kCFStreamEventOpenCompleted;\n\t\n\tif (!CFWriteStreamSetClient (theWriteStream,\n\t\t\t\t\t\t\t\t writeStreamEvents,\n\t\t\t\t\t\t\t\t (CFWriteStreamClientCallBack)&MyCFWriteStreamCallback,\n\t\t\t\t\t\t\t\t (CFStreamClientContext *)(&theContext)))\n\t{\n\t\tNSError *err = [self getStreamError];\n\t\t\n\t\tNSLog (@\"AsyncSocket %p couldn't attach write stream to run-loop,\", self);\n\t\tNSLog (@\"Error: %@\", err);\n\t\t\n\t\tif (errPtr) *errPtr = err;\n\t\treturn NO;\n\t}\n\t\n\t// Add read and write streams to run loop\n\t\n\tfor (NSString *runLoopMode in theRunLoopModes)\n\t{\n\t\tCFReadStreamScheduleWithRunLoop(theReadStream, theRunLoop, (__bridge CFStringRef)runLoopMode);\n\t\tCFWriteStreamScheduleWithRunLoop(theWriteStream, theRunLoop, (__bridge CFStringRef)runLoopMode);\n\t}\n\t\n\treturn YES;\n}\n\n/**\n * Allows the delegate method to configure the CFReadStream and/or CFWriteStream as desired before we connect.\n *\n * If being called from a connect method,\n * the CFSocket and CFNativeSocket will not be available until after the connection is opened.\n **/\n- (BOOL)configureStreamsAndReturnError:(NSError **)errPtr\n{\n\t// Call the delegate method for further configuration.\n\tif([theDelegate respondsToSelector:@selector(onSocketWillConnect:)])\n\t{\n\t\tif([theDelegate onSocketWillConnect:self] == NO)\n\t\t{\n\t\t\tif (errPtr) *errPtr = [self getAbortError];\n\t\t\treturn NO;\n\t\t}\n\t}\n\treturn YES;\n}\n\n- (BOOL)openStreamsAndReturnError:(NSError **)errPtr\n{\n\tBOOL pass = YES;\n\t\n\tif(pass && !CFReadStreamOpen(theReadStream))\n\t{\n\t\tNSLog (@\"AsyncSocket %p couldn't open read stream,\", self);\n\t\tpass = NO;\n\t}\n\t\n\tif(pass && !CFWriteStreamOpen(theWriteStream))\n\t{\n\t\tNSLog (@\"AsyncSocket %p couldn't open write stream,\", self);\n\t\tpass = NO;\n\t}\n\t\n\tif(!pass)\n\t{\n\t\tif (errPtr) *errPtr = [self getStreamError];\n\t}\n\t\n\treturn pass;\n}\n\n/**\n * Called when read or write streams open.\n * When the socket is connected and both streams are open, consider the AsyncSocket instance to be ready.\n **/\n- (void)doStreamOpen\n{\n\tif ((theFlags & kDidCompleteOpenForRead) && (theFlags & kDidCompleteOpenForWrite))\n\t{\n\t\tNSError *err = nil;\n\t\t\n\t\t// Get the socket\n\t\tif (![self setSocketFromStreamsAndReturnError: &err])\n\t\t{\n\t\t\tNSLog (@\"AsyncSocket %p couldn't get socket from streams, %@. Disconnecting.\", self, err);\n\t\t\t[self closeWithError:err];\n\t\t\treturn;\n\t\t}\n\t\t\n        // Stop the connection attempt timeout timer\n\t\t[self endConnectTimeout];\n        \n\t\tif ([theDelegate respondsToSelector:@selector(onSocket:didConnectToHost:port:)])\n\t\t{\n\t\t\t[theDelegate onSocket:self didConnectToHost:[self connectedHost] port:[self connectedPort]];\n\t\t}\n\t\t\n\t\t// Immediately deal with any already-queued requests.\n\t\t[self maybeDequeueRead];\n\t\t[self maybeDequeueWrite];\n\t}\n}\n\n- (BOOL)setSocketFromStreamsAndReturnError:(NSError **)errPtr\n{\n\t// Get the CFSocketNativeHandle from theReadStream\n\tCFSocketNativeHandle native;\n\tCFDataRef nativeProp = CFReadStreamCopyProperty(theReadStream, kCFStreamPropertySocketNativeHandle);\n\tif(nativeProp == NULL)\n\t{\n\t\tif (errPtr) *errPtr = [self getStreamError];\n\t\treturn NO;\n\t}\n\t\n\tCFIndex nativePropLen = CFDataGetLength(nativeProp);\n\tCFIndex nativeLen = (CFIndex)sizeof(native);\n\t\n\tCFIndex len = MIN(nativePropLen, nativeLen);\n\t\n\tCFDataGetBytes(nativeProp, CFRangeMake(0, len), (UInt8 *)&native);\n\tCFRelease(nativeProp);\n\t\n\tCFSocketRef theSocket = CFSocketCreateWithNative(kCFAllocatorDefault, native, 0, NULL, NULL);\n\tif(theSocket == NULL)\n\t{\n\t\tif (errPtr) *errPtr = [self getSocketError];\n\t\treturn NO;\n\t}\n\t\n\t// Determine whether the connection was IPv4 or IPv6.\n\t// We may already know if this was an accepted socket,\n\t// or if the connectToAddress method was used.\n\t// In either of the above two cases, the native socket variable would already be set.\n\t\n\tif (theNativeSocket4 > 0)\n\t{\n\t\ttheSocket4 = theSocket;\n\t\treturn YES;\n\t}\n\tif (theNativeSocket6 > 0)\n\t{\n\t\ttheSocket6 = theSocket;\n\t\treturn YES;\n\t}\n\t\n\tCFDataRef peeraddr = CFSocketCopyPeerAddress(theSocket);\n\tif(peeraddr == NULL)\n\t{\n\t\tNSLog(@\"AsyncSocket couldn't determine IP version of socket\");\n\t\t\n\t\tCFRelease(theSocket);\n\t\t\n\t\tif (errPtr) *errPtr = [self getSocketError];\n\t\treturn NO;\n\t}\n\tstruct sockaddr *sa = (struct sockaddr *)CFDataGetBytePtr(peeraddr);\n\t\n\tif(sa->sa_family == AF_INET)\n\t{\n\t\ttheSocket4 = theSocket;\n\t\ttheNativeSocket4 = native;\n\t}\n\telse\n\t{\n\t\ttheSocket6 = theSocket;\n\t\ttheNativeSocket6 = native;\n\t}\n\t\n\tCFRelease(peeraddr);\n    \n\treturn YES;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Disconnect Implementation\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n// Sends error message and disconnects\n- (void)closeWithError:(NSError *)err\n{\n\ttheFlags |= kClosingWithError;\n\t\n\tif (theFlags & kDidStartDelegate)\n\t{\n\t\t// Try to salvage what data we can.\n\t\t[self recoverUnreadData];\n\t\t\n\t\t// Let the delegate know, so it can try to recover if it likes.\n\t\tif ([theDelegate respondsToSelector:@selector(onSocket:willDisconnectWithError:)])\n\t\t{\n\t\t\t[theDelegate onSocket:self willDisconnectWithError:err];\n\t\t}\n\t}\n\t[self close];\n}\n\n// Prepare partially read data for recovery.\n- (void)recoverUnreadData\n{\n\tif(theCurrentRead != nil)\n\t{\n\t\t// We never finished the current read.\n\t\t// Check to see if it's a normal read packet (not AsyncSpecialPacket) and if it had read anything yet.\n\t\t\n\t\tif(([theCurrentRead isKindOfClass:[AsyncReadPacket class]]) && (theCurrentRead->bytesDone > 0))\n\t\t{\n\t\t\t// We need to move its data into the front of the partial read buffer.\n\t\t\t\n\t\t\tvoid *buffer = [theCurrentRead->buffer mutableBytes] + theCurrentRead->startOffset;\n\t\t\t\n\t\t\t[partialReadBuffer replaceBytesInRange:NSMakeRange(0, 0)\n\t\t\t\t\t\t\t\t\t\t withBytes:buffer\n\t\t\t\t\t\t\t\t\t\t\tlength:theCurrentRead->bytesDone];\n\t\t}\n\t}\n\t\n\t[self emptyQueues];\n}\n\n- (void)emptyQueues\n{\n\tif (theCurrentRead != nil)\t[self endCurrentRead];\n\tif (theCurrentWrite != nil)\t[self endCurrentWrite];\n\t\n\t[theReadQueue removeAllObjects];\n\t[theWriteQueue removeAllObjects];\n\t\n\t[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(maybeDequeueRead) object:nil];\n\t[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(maybeDequeueWrite) object:nil];\n\t\n\ttheFlags &= ~kDequeueReadScheduled;\n\ttheFlags &= ~kDequeueWriteScheduled;\n}\n\n/**\n * Disconnects. This is called for both error and clean disconnections.\n **/\n- (void)close\n{\n\t// Empty queues\n\t[self emptyQueues];\n\t\n\t// Clear partialReadBuffer (pre-buffer and also unreadData buffer in case of error)\n\t[partialReadBuffer replaceBytesInRange:NSMakeRange(0, [partialReadBuffer length]) withBytes:NULL length:0];\n\t\n\t[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(disconnect) object:nil];\n\t\n\t// Stop the connection attempt timeout timer\n\tif (theConnectTimer != nil)\n\t{\n\t\t[self endConnectTimeout];\n\t}\n\t\n\t// Close streams.\n\tif (theReadStream != NULL)\n\t{\n        [self runLoopUnscheduleReadStream];\n\t\tCFReadStreamClose(theReadStream);\n\t\tCFRelease(theReadStream);\n\t\ttheReadStream = NULL;\n\t}\n\tif (theWriteStream != NULL)\n\t{\n        [self runLoopUnscheduleWriteStream];\n\t\tCFWriteStreamClose(theWriteStream);\n\t\tCFRelease(theWriteStream);\n\t\ttheWriteStream = NULL;\n\t}\n\t\n\t// Close sockets.\n\tif (theSocket4 != NULL)\n\t{\n\t\tCFSocketInvalidate (theSocket4);\n\t\tCFRelease (theSocket4);\n\t\ttheSocket4 = NULL;\n\t}\n\tif (theSocket6 != NULL)\n\t{\n\t\tCFSocketInvalidate (theSocket6);\n\t\tCFRelease (theSocket6);\n\t\ttheSocket6 = NULL;\n\t}\n\t\n\t// Closing the streams or sockets resulted in closing the underlying native socket\n\ttheNativeSocket4 = 0;\n\ttheNativeSocket6 = 0;\n\t\n\t// Remove run loop sources\n    if (theSource4 != NULL)\n    {\n        [self runLoopRemoveSource:theSource4];\n\t\tCFRelease (theSource4);\n\t\ttheSource4 = NULL;\n\t}\n\tif (theSource6 != NULL)\n\t{\n        [self runLoopRemoveSource:theSource6];\n\t\tCFRelease (theSource6);\n\t\ttheSource6 = NULL;\n\t}\n\ttheRunLoop = NULL;\n\t\n\t// If the client has passed the connect/accept method, then the connection has at least begun.\n\t// Notify delegate that it is now ending.\n\tBOOL shouldCallDelegate = (theFlags & kDidStartDelegate);\n\t\n\t// Clear all flags (except the pre-buffering flag, which should remain as is)\n\ttheFlags &= kEnablePreBuffering;\n\t\n\tif (shouldCallDelegate)\n\t{\n\t\tif ([theDelegate respondsToSelector: @selector(onSocketDidDisconnect:)])\n\t\t{\n\t\t\t[theDelegate onSocketDidDisconnect:self];\n\t\t}\n\t}\n\t\n\t// Do not access any instance variables after calling onSocketDidDisconnect.\n\t// This gives the delegate freedom to release us without returning here and crashing.\n}\n\n/**\n * Disconnects immediately. Any pending reads or writes are dropped.\n **/\n- (void)disconnect\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\t[self close];\n}\n\n/**\n * Diconnects after all pending reads have completed.\n **/\n- (void)disconnectAfterReading\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\ttheFlags |= (kForbidReadsWrites | kDisconnectAfterReads);\n\t\n\t[self maybeScheduleDisconnect];\n}\n\n/**\n * Disconnects after all pending writes have completed.\n **/\n- (void)disconnectAfterWriting\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\ttheFlags |= (kForbidReadsWrites | kDisconnectAfterWrites);\n\t\n\t[self maybeScheduleDisconnect];\n}\n\n/**\n * Disconnects after all pending reads and writes have completed.\n **/\n- (void)disconnectAfterReadingAndWriting\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\ttheFlags |= (kForbidReadsWrites | kDisconnectAfterReads | kDisconnectAfterWrites);\n\t\n\t[self maybeScheduleDisconnect];\n}\n\n/**\n * Schedules a call to disconnect if possible.\n * That is, if all writes have completed, and we're set to disconnect after writing,\n * or if all reads have completed, and we're set to disconnect after reading.\n **/\n- (void)maybeScheduleDisconnect\n{\n\tBOOL shouldDisconnect = NO;\n\t\n\tif(theFlags & kDisconnectAfterReads)\n\t{\n\t\tif(([theReadQueue count] == 0) && (theCurrentRead == nil))\n\t\t{\n\t\t\tif(theFlags & kDisconnectAfterWrites)\n\t\t\t{\n\t\t\t\tif(([theWriteQueue count] == 0) && (theCurrentWrite == nil))\n\t\t\t\t{\n\t\t\t\t\tshouldDisconnect = YES;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tshouldDisconnect = YES;\n\t\t\t}\n\t\t}\n\t}\n\telse if(theFlags & kDisconnectAfterWrites)\n\t{\n\t\tif(([theWriteQueue count] == 0) && (theCurrentWrite == nil))\n\t\t{\n\t\t\tshouldDisconnect = YES;\n\t\t}\n\t}\n\t\n\tif(shouldDisconnect)\n\t{\n\t\t[self performSelector:@selector(disconnect) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t}\n}\n\n/**\n * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read\n * any data that's left on the socket.\n **/\n- (NSData *)unreadData\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\t// Ensure this method will only return data in the event of an error\n\tif (!(theFlags & kClosingWithError)) return nil;\n\t\n\tif (theReadStream == NULL) return nil;\n\t\n\tNSUInteger totalBytesRead = [partialReadBuffer length];\n\t\n\tBOOL error = NO;\n\twhile (!error && CFReadStreamHasBytesAvailable(theReadStream))\n\t{\n\t\tif (totalBytesRead == [partialReadBuffer length])\n\t\t{\n\t\t\t[partialReadBuffer increaseLengthBy:READALL_CHUNKSIZE];\n\t\t}\n\t\t\n\t\t// Number of bytes to read is space left in packet buffer.\n\t\tNSUInteger bytesToRead = [partialReadBuffer length] - totalBytesRead;\n\t\t\n\t\t// Read data into packet buffer\n\t\tUInt8 *packetbuf = (UInt8 *)( [partialReadBuffer mutableBytes] + totalBytesRead );\n\t\t\n\t\tCFIndex result = CFReadStreamRead(theReadStream, packetbuf, bytesToRead);\n\t\t\n\t\t// Check results\n\t\tif (result < 0)\n\t\t{\n\t\t\terror = YES;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tCFIndex bytesRead = result;\n\t\t\t\n\t\t\ttotalBytesRead += bytesRead;\n\t\t}\n\t}\n\t\n\t[partialReadBuffer setLength:totalBytesRead];\n\t\n\treturn partialReadBuffer;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Errors\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Returns a standard error object for the current errno value.\n * Errno is used for low-level BSD socket errors.\n **/\n- (NSError *)getErrnoError\n{\n\tNSString *errorMsg = [NSString stringWithUTF8String:strerror(errno)];\n\tNSDictionary *userInfo = [NSDictionary dictionaryWithObject:errorMsg forKey:NSLocalizedDescriptionKey];\n\t\n\treturn [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:userInfo];\n}\n\n/**\n * Returns a standard error message for a CFSocket error.\n * Unfortunately, CFSocket offers no feedback on its errors.\n **/\n- (NSError *)getSocketError\n{\n\tNSString *errMsg = NSLocalizedStringWithDefaultValue(@\"AsyncSocketCFSocketError\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"AsyncSocket\", [NSBundle mainBundle],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"General CFSocket error\", nil);\n\t\n\tNSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];\n\t\n\treturn [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCFSocketError userInfo:info];\n}\n\n- (NSError *)getStreamError\n{\n\tCFStreamError err;\n\tif (theReadStream != NULL)\n\t{\n\t\terr = CFReadStreamGetError (theReadStream);\n\t\tif (err.error != 0) return [self errorFromCFStreamError: err];\n\t}\n\t\n\tif (theWriteStream != NULL)\n\t{\n\t\terr = CFWriteStreamGetError (theWriteStream);\n\t\tif (err.error != 0) return [self errorFromCFStreamError: err];\n\t}\n\t\n\treturn nil;\n}\n\n/**\n * Returns a standard AsyncSocket abort error.\n **/\n- (NSError *)getAbortError\n{\n\tNSString *errMsg = NSLocalizedStringWithDefaultValue(@\"AsyncSocketCanceledError\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"AsyncSocket\", [NSBundle mainBundle],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"Connection canceled\", nil);\n\t\n\tNSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];\n\t\n\treturn [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCanceledError userInfo:info];\n}\n\n/**\n * Returns a standard AsyncSocket connect timeout error.\n **/\n- (NSError *)getConnectTimeoutError\n{\n\tNSString *errMsg = NSLocalizedStringWithDefaultValue(@\"AsyncSocketConnectTimeoutError\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"AsyncSocket\", [NSBundle mainBundle],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"Attempt to connect to host timed out\", nil);\n\t\n\tNSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];\n\t\n\treturn [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketConnectTimeoutError userInfo:info];\n}\n\n/**\n * Returns a standard AsyncSocket maxed out error.\n **/\n- (NSError *)getReadMaxedOutError\n{\n\tNSString *errMsg = NSLocalizedStringWithDefaultValue(@\"AsyncSocketReadMaxedOutError\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"AsyncSocket\", [NSBundle mainBundle],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"Read operation reached set maximum length\", nil);\n\t\n\tNSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];\n\t\n\treturn [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketReadMaxedOutError userInfo:info];\n}\n\n/**\n * Returns a standard AsyncSocket read timeout error.\n **/\n- (NSError *)getReadTimeoutError\n{\n\tNSString *errMsg = NSLocalizedStringWithDefaultValue(@\"AsyncSocketReadTimeoutError\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"AsyncSocket\", [NSBundle mainBundle],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"Read operation timed out\", nil);\n\t\n\tNSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];\n\t\n\treturn [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketReadTimeoutError userInfo:info];\n}\n\n/**\n * Returns a standard AsyncSocket write timeout error.\n **/\n- (NSError *)getWriteTimeoutError\n{\n\tNSString *errMsg = NSLocalizedStringWithDefaultValue(@\"AsyncSocketWriteTimeoutError\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"AsyncSocket\", [NSBundle mainBundle],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t @\"Write operation timed out\", nil);\n\t\n\tNSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];\n\t\n\treturn [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketWriteTimeoutError userInfo:info];\n}\n\n- (NSError *)errorFromCFStreamError:(CFStreamError)err\n{\n\tif (err.domain == 0 && err.error == 0) return nil;\n\t\n\t// Can't use switch; these constants aren't int literals.\n\tNSString *domain = @\"CFStreamError (unlisted domain)\";\n\tNSString *message = nil;\n\t\n\tif(err.domain == kCFStreamErrorDomainPOSIX) {\n\t\tdomain = NSPOSIXErrorDomain;\n\t}\n\telse if(err.domain == kCFStreamErrorDomainMacOSStatus) {\n\t\tdomain = NSOSStatusErrorDomain;\n\t}\n\telse if(err.domain == kCFStreamErrorDomainMach) {\n\t\tdomain = NSMachErrorDomain;\n\t}\n\telse if(err.domain == kCFStreamErrorDomainNetDB)\n\t{\n\t\tdomain = @\"kCFStreamErrorDomainNetDB\";\n\t\tmessage = [NSString stringWithCString:gai_strerror(err.error) encoding:NSASCIIStringEncoding];\n\t}\n\telse if(err.domain == kCFStreamErrorDomainNetServices) {\n\t\tdomain = @\"kCFStreamErrorDomainNetServices\";\n\t}\n\telse if(err.domain == kCFStreamErrorDomainSOCKS) {\n\t\tdomain = @\"kCFStreamErrorDomainSOCKS\";\n\t}\n\telse if(err.domain == kCFStreamErrorDomainSystemConfiguration) {\n\t\tdomain = @\"kCFStreamErrorDomainSystemConfiguration\";\n\t}\n\telse if(err.domain == kCFStreamErrorDomainSSL) {\n\t\tdomain = @\"kCFStreamErrorDomainSSL\";\n\t}\n\t\n\tNSDictionary *info = nil;\n\tif(message != nil)\n\t{\n\t\tinfo = [NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey];\n\t}\n\treturn [NSError errorWithDomain:domain code:err.error userInfo:info];\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Diagnostics\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (BOOL)isDisconnected\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif (theNativeSocket4 > 0) return NO;\n\tif (theNativeSocket6 > 0) return NO;\n\t\n\tif (theSocket4) return NO;\n\tif (theSocket6) return NO;\n\t\n\tif (theReadStream)  return NO;\n\tif (theWriteStream) return NO;\n\t\n\treturn YES;\n}\n\n- (BOOL)isConnected\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\treturn [self areStreamsConnected];\n}\n\n- (NSString *)connectedHost\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif(theSocket4)\n\t\treturn [self connectedHostFromCFSocket4:theSocket4];\n\tif(theSocket6)\n\t\treturn [self connectedHostFromCFSocket6:theSocket6];\n\t\n\tif(theNativeSocket4 > 0)\n\t\treturn [self connectedHostFromNativeSocket4:theNativeSocket4];\n\tif(theNativeSocket6 > 0)\n\t\treturn [self connectedHostFromNativeSocket6:theNativeSocket6];\n\t\n\treturn nil;\n}\n\n- (UInt16)connectedPort\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif(theSocket4)\n\t\treturn [self connectedPortFromCFSocket4:theSocket4];\n\tif(theSocket6)\n\t\treturn [self connectedPortFromCFSocket6:theSocket6];\n\t\n\tif(theNativeSocket4 > 0)\n\t\treturn [self connectedPortFromNativeSocket4:theNativeSocket4];\n\tif(theNativeSocket6 > 0)\n\t\treturn [self connectedPortFromNativeSocket6:theNativeSocket6];\n\t\n\treturn 0;\n}\n\n- (NSString *)localHost\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif(theSocket4)\n\t\treturn [self localHostFromCFSocket4:theSocket4];\n\tif(theSocket6)\n\t\treturn [self localHostFromCFSocket6:theSocket6];\n\t\n\tif(theNativeSocket4 > 0)\n\t\treturn [self localHostFromNativeSocket4:theNativeSocket4];\n\tif(theNativeSocket6 > 0)\n\t\treturn [self localHostFromNativeSocket6:theNativeSocket6];\n\t\n\treturn nil;\n}\n\n- (UInt16)localPort\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif(theSocket4)\n\t\treturn [self localPortFromCFSocket4:theSocket4];\n\tif(theSocket6)\n\t\treturn [self localPortFromCFSocket6:theSocket6];\n\t\n\tif(theNativeSocket4 > 0)\n\t\treturn [self localPortFromNativeSocket4:theNativeSocket4];\n\tif(theNativeSocket6 > 0)\n\t\treturn [self localPortFromNativeSocket6:theNativeSocket6];\n\t\n\treturn 0;\n}\n\n- (NSString *)connectedHost4\n{\n\tif(theSocket4)\n\t\treturn [self connectedHostFromCFSocket4:theSocket4];\n\tif(theNativeSocket4 > 0)\n\t\treturn [self connectedHostFromNativeSocket4:theNativeSocket4];\n\t\n\treturn nil;\n}\n\n- (NSString *)connectedHost6\n{\n\tif(theSocket6)\n\t\treturn [self connectedHostFromCFSocket6:theSocket6];\n\tif(theNativeSocket6 > 0)\n\t\treturn [self connectedHostFromNativeSocket6:theNativeSocket6];\n\t\n\treturn nil;\n}\n\n- (UInt16)connectedPort4\n{\n\tif(theSocket4)\n\t\treturn [self connectedPortFromCFSocket4:theSocket4];\n\tif(theNativeSocket4 > 0)\n\t\treturn [self connectedPortFromNativeSocket4:theNativeSocket4];\n\t\n\treturn 0;\n}\n\n- (UInt16)connectedPort6\n{\n\tif(theSocket6)\n\t\treturn [self connectedPortFromCFSocket6:theSocket6];\n\tif(theNativeSocket6 > 0)\n\t\treturn [self connectedPortFromNativeSocket6:theNativeSocket6];\n\t\n\treturn 0;\n}\n\n- (NSString *)localHost4\n{\n\tif(theSocket4)\n\t\treturn [self localHostFromCFSocket4:theSocket4];\n\tif(theNativeSocket4 > 0)\n\t\treturn [self localHostFromNativeSocket4:theNativeSocket4];\n\t\n\treturn nil;\n}\n\n- (NSString *)localHost6\n{\n\tif(theSocket6)\n\t\treturn [self localHostFromCFSocket6:theSocket6];\n\tif(theNativeSocket6 > 0)\n\t\treturn [self localHostFromNativeSocket6:theNativeSocket6];\n\t\n\treturn nil;\n}\n\n- (UInt16)localPort4\n{\n\tif(theSocket4)\n\t\treturn [self localPortFromCFSocket4:theSocket4];\n\tif(theNativeSocket4 > 0)\n\t\treturn [self localPortFromNativeSocket4:theNativeSocket4];\n\t\n\treturn 0;\n}\n\n- (UInt16)localPort6\n{\n\tif(theSocket6)\n\t\treturn [self localPortFromCFSocket6:theSocket6];\n\tif(theNativeSocket6 > 0)\n\t\treturn [self localPortFromNativeSocket6:theNativeSocket6];\n\t\n\treturn 0;\n}\n\n- (NSString *)connectedHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket\n{\n\tstruct sockaddr_in sockaddr4;\n\tsocklen_t sockaddr4len = sizeof(sockaddr4);\n\t\n\tif(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)\n\t{\n\t\treturn nil;\n\t}\n\treturn [self hostFromAddress4:&sockaddr4];\n}\n\n- (NSString *)connectedHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket\n{\n\tstruct sockaddr_in6 sockaddr6;\n\tsocklen_t sockaddr6len = sizeof(sockaddr6);\n\t\n\tif(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)\n\t{\n\t\treturn nil;\n\t}\n\treturn [self hostFromAddress6:&sockaddr6];\n}\n\n- (NSString *)connectedHostFromCFSocket4:(CFSocketRef)theSocket\n{\n\tCFDataRef peeraddr;\n\tNSString *peerstr = nil;\n    \n\tif((peeraddr = CFSocketCopyPeerAddress(theSocket)))\n\t{\n\t\tstruct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(peeraddr);\n        \n\t\tpeerstr = [self hostFromAddress4:pSockAddr];\n\t\tCFRelease (peeraddr);\n\t}\n    \n\treturn peerstr;\n}\n\n- (NSString *)connectedHostFromCFSocket6:(CFSocketRef)theSocket\n{\n\tCFDataRef peeraddr;\n\tNSString *peerstr = nil;\n    \n\tif((peeraddr = CFSocketCopyPeerAddress(theSocket)))\n\t{\n\t\tstruct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(peeraddr);\n\t\t\n\t\tpeerstr = [self hostFromAddress6:pSockAddr];\n\t\tCFRelease (peeraddr);\n\t}\n    \n\treturn peerstr;\n}\n\n- (UInt16)connectedPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket\n{\n\tstruct sockaddr_in sockaddr4;\n\tsocklen_t sockaddr4len = sizeof(sockaddr4);\n\t\n\tif(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)\n\t{\n\t\treturn 0;\n\t}\n\treturn [self portFromAddress4:&sockaddr4];\n}\n\n- (UInt16)connectedPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket\n{\n\tstruct sockaddr_in6 sockaddr6;\n\tsocklen_t sockaddr6len = sizeof(sockaddr6);\n\t\n\tif(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)\n\t{\n\t\treturn 0;\n\t}\n\treturn [self portFromAddress6:&sockaddr6];\n}\n\n- (UInt16)connectedPortFromCFSocket4:(CFSocketRef)theSocket\n{\n\tCFDataRef peeraddr;\n\tUInt16 peerport = 0;\n    \n\tif((peeraddr = CFSocketCopyPeerAddress(theSocket)))\n\t{\n\t\tstruct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(peeraddr);\n\t\t\n\t\tpeerport = [self portFromAddress4:pSockAddr];\n\t\tCFRelease (peeraddr);\n\t}\n    \n\treturn peerport;\n}\n\n- (UInt16)connectedPortFromCFSocket6:(CFSocketRef)theSocket\n{\n\tCFDataRef peeraddr;\n\tUInt16 peerport = 0;\n    \n\tif((peeraddr = CFSocketCopyPeerAddress(theSocket)))\n\t{\n\t\tstruct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(peeraddr);\n\t\t\n\t\tpeerport = [self portFromAddress6:pSockAddr];\n\t\tCFRelease (peeraddr);\n\t}\n    \n\treturn peerport;\n}\n\n- (NSString *)localHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket\n{\n\tstruct sockaddr_in sockaddr4;\n\tsocklen_t sockaddr4len = sizeof(sockaddr4);\n\t\n\tif(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)\n\t{\n\t\treturn nil;\n\t}\n\treturn [self hostFromAddress4:&sockaddr4];\n}\n\n- (NSString *)localHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket\n{\n\tstruct sockaddr_in6 sockaddr6;\n\tsocklen_t sockaddr6len = sizeof(sockaddr6);\n\t\n\tif(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)\n\t{\n\t\treturn nil;\n\t}\n\treturn [self hostFromAddress6:&sockaddr6];\n}\n\n- (NSString *)localHostFromCFSocket4:(CFSocketRef)theSocket\n{\n\tCFDataRef selfaddr;\n\tNSString *selfstr = nil;\n    \n\tif((selfaddr = CFSocketCopyAddress(theSocket)))\n\t{\n\t\tstruct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(selfaddr);\n\t\t\n\t\tselfstr = [self hostFromAddress4:pSockAddr];\n\t\tCFRelease (selfaddr);\n\t}\n    \n\treturn selfstr;\n}\n\n- (NSString *)localHostFromCFSocket6:(CFSocketRef)theSocket\n{\n\tCFDataRef selfaddr;\n\tNSString *selfstr = nil;\n    \n\tif((selfaddr = CFSocketCopyAddress(theSocket)))\n\t{\n\t\tstruct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(selfaddr);\n\t\t\n\t\tselfstr = [self hostFromAddress6:pSockAddr];\n\t\tCFRelease (selfaddr);\n\t}\n    \n\treturn selfstr;\n}\n\n- (UInt16)localPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket\n{\n\tstruct sockaddr_in sockaddr4;\n\tsocklen_t sockaddr4len = sizeof(sockaddr4);\n\t\n\tif(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)\n\t{\n\t\treturn 0;\n\t}\n\treturn [self portFromAddress4:&sockaddr4];\n}\n\n- (UInt16)localPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket\n{\n\tstruct sockaddr_in6 sockaddr6;\n\tsocklen_t sockaddr6len = sizeof(sockaddr6);\n\t\n\tif(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)\n\t{\n\t\treturn 0;\n\t}\n\treturn [self portFromAddress6:&sockaddr6];\n}\n\n- (UInt16)localPortFromCFSocket4:(CFSocketRef)theSocket\n{\n\tCFDataRef selfaddr;\n\tUInt16 selfport = 0;\n    \n\tif ((selfaddr = CFSocketCopyAddress(theSocket)))\n\t{\n\t\tstruct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(selfaddr);\n\t\t\n\t\tselfport = [self portFromAddress4:pSockAddr];\n\t\tCFRelease (selfaddr);\n\t}\n    \n\treturn selfport;\n}\n\n- (UInt16)localPortFromCFSocket6:(CFSocketRef)theSocket\n{\n\tCFDataRef selfaddr;\n\tUInt16 selfport = 0;\n    \n\tif ((selfaddr = CFSocketCopyAddress(theSocket)))\n\t{\n\t\tstruct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(selfaddr);\n\t\t\n\t\tselfport = [self portFromAddress6:pSockAddr];\n\t\tCFRelease (selfaddr);\n\t}\n    \n\treturn selfport;\n}\n\n- (NSString *)hostFromAddress4:(struct sockaddr_in *)pSockaddr4\n{\n\tchar addrBuf[INET_ADDRSTRLEN];\n\t\n\tif(inet_ntop(AF_INET, &pSockaddr4->sin_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL)\n\t{\n\t\t[NSException raise:NSInternalInconsistencyException format:@\"Cannot convert IPv4 address to string.\"];\n\t}\n\t\n\treturn [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding];\n}\n\n- (NSString *)hostFromAddress6:(struct sockaddr_in6 *)pSockaddr6\n{\n\tchar addrBuf[INET6_ADDRSTRLEN];\n\t\n\tif(inet_ntop(AF_INET6, &pSockaddr6->sin6_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL)\n\t{\n\t\t[NSException raise:NSInternalInconsistencyException format:@\"Cannot convert IPv6 address to string.\"];\n\t}\n\t\n\treturn [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding];\n}\n\n- (UInt16)portFromAddress4:(struct sockaddr_in *)pSockaddr4\n{\n\treturn ntohs(pSockaddr4->sin_port);\n}\n\n- (UInt16)portFromAddress6:(struct sockaddr_in6 *)pSockaddr6\n{\n\treturn ntohs(pSockaddr6->sin6_port);\n}\n\n- (NSData *)connectedAddress\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\t// Extract address from CFSocket\n\t\n    CFSocketRef theSocket;\n    \n    if (theSocket4)\n        theSocket = theSocket4;\n    else\n        theSocket = theSocket6;\n    \n    if (theSocket)\n    {\n\t\tCFDataRef peeraddr = CFSocketCopyPeerAddress(theSocket);\n\t\t\n\t\tif (peeraddr == NULL) return nil;\n\t\t\n\t\tNSData *result = (__bridge_transfer NSData *)peeraddr;\n\t\treturn result;\n\t}\n\t\n\t// Extract address from CFSocketNativeHandle\n\t\n\tsocklen_t sockaddrlen;\n\tCFSocketNativeHandle theNativeSocket = 0;\n\t\n\tif (theNativeSocket4 > 0)\n\t{\n\t\ttheNativeSocket = theNativeSocket4;\n\t\tsockaddrlen = sizeof(struct sockaddr_in);\n\t}\n\telse\n\t{\n\t\ttheNativeSocket = theNativeSocket6;\n\t\tsockaddrlen = sizeof(struct sockaddr_in6);\n\t}\n\t\n\tNSData *result = nil;\n\tvoid *sockaddr = malloc(sockaddrlen);\n\t\n\tif(getpeername(theNativeSocket, (struct sockaddr *)sockaddr, &sockaddrlen) >= 0)\n\t{\n\t\tresult = [NSData dataWithBytesNoCopy:sockaddr length:sockaddrlen freeWhenDone:YES];\n\t}\n\telse\n\t{\n\t\tfree(sockaddr);\n\t}\n\t\n\treturn result;\n}\n\n- (NSData *)localAddress\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\t// Extract address from CFSocket\n\t\n    CFSocketRef theSocket;\n    \n    if (theSocket4)\n        theSocket = theSocket4;\n    else\n        theSocket = theSocket6;\n    \n    if (theSocket)\n    {\n\t\tCFDataRef selfaddr = CFSocketCopyAddress(theSocket);\n\t\t\n\t\tif (selfaddr == NULL) return nil;\n\t\t\n\t\tNSData *result = (__bridge_transfer NSData *)selfaddr;\n\t\treturn result;\n\t}\n\t\n\t// Extract address from CFSocketNativeHandle\n\t\n\tsocklen_t sockaddrlen;\n\tCFSocketNativeHandle theNativeSocket = 0;\n\t\n\tif (theNativeSocket4 > 0)\n\t{\n\t\ttheNativeSocket = theNativeSocket4;\n\t\tsockaddrlen = sizeof(struct sockaddr_in);\n\t}\n\telse\n\t{\n\t\ttheNativeSocket = theNativeSocket6;\n\t\tsockaddrlen = sizeof(struct sockaddr_in6);\n\t}\n\t\n\tNSData *result = nil;\n\tvoid *sockaddr = malloc(sockaddrlen);\n\t\n\tif(getsockname(theNativeSocket, (struct sockaddr *)sockaddr, &sockaddrlen) >= 0)\n\t{\n\t\tresult = [NSData dataWithBytesNoCopy:sockaddr length:sockaddrlen freeWhenDone:YES];\n\t}\n\telse\n\t{\n\t\tfree(sockaddr);\n\t}\n\t\n\treturn result;\n}\n\n- (BOOL)isIPv4\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\treturn (theNativeSocket4 > 0 || theSocket4 != NULL);\n}\n\n- (BOOL)isIPv6\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\treturn (theNativeSocket6 > 0 || theSocket6 != NULL);\n}\n\n- (BOOL)areStreamsConnected\n{\n\tCFStreamStatus s;\n    \n\tif (theReadStream != NULL)\n\t{\n\t\ts = CFReadStreamGetStatus(theReadStream);\n\t\tif ( !(s == kCFStreamStatusOpen || s == kCFStreamStatusReading || s == kCFStreamStatusError) )\n\t\t\treturn NO;\n\t}\n\telse return NO;\n    \n\tif (theWriteStream != NULL)\n\t{\n\t\ts = CFWriteStreamGetStatus(theWriteStream);\n\t\tif ( !(s == kCFStreamStatusOpen || s == kCFStreamStatusWriting || s == kCFStreamStatusError) )\n\t\t\treturn NO;\n\t}\n\telse return NO;\n    \n\treturn YES;\n}\n\n- (NSString *)description\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tstatic const char *statstr[] = {\"not open\",\"opening\",\"open\",\"reading\",\"writing\",\"at end\",\"closed\",\"has error\"};\n\tCFStreamStatus rs = (theReadStream != NULL) ? CFReadStreamGetStatus(theReadStream) : 0;\n\tCFStreamStatus ws = (theWriteStream != NULL) ? CFWriteStreamGetStatus(theWriteStream) : 0;\n\t\n\tNSString *peerstr, *selfstr;\n    \n\tBOOL is4 = [self isIPv4];\n\tBOOL is6 = [self isIPv6];\n\t\n\tif (is4 || is6)\n\t{\n\t\tif (is4 && is6)\n\t\t{\n\t\t\tpeerstr = [NSString stringWithFormat: @\"%@/%@ %u\",\n\t\t\t\t\t   [self connectedHost4],\n\t\t\t\t\t   [self connectedHost6],\n\t\t\t\t\t   [self connectedPort]];\n\t\t}\n\t\telse if (is4)\n\t\t{\n\t\t\tpeerstr = [NSString stringWithFormat: @\"%@ %u\",\n\t\t\t\t\t   [self connectedHost4],\n\t\t\t\t\t   [self connectedPort4]];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpeerstr = [NSString stringWithFormat: @\"%@ %u\",\n\t\t\t\t\t   [self connectedHost6],\n\t\t\t\t\t   [self connectedPort6]];\n\t\t}\n\t}\n\telse peerstr = @\"nowhere\";\n    \n\tif (is4 || is6)\n\t{\n\t\tif (is4 && is6)\n\t\t{\n\t\t\tselfstr = [NSString stringWithFormat: @\"%@/%@ %u\",\n\t\t\t\t\t   [self localHost4],\n\t\t\t\t\t   [self localHost6],\n\t\t\t\t\t   [self localPort]];\n\t\t}\n\t\telse if (is4)\n\t\t{\n\t\t\tselfstr = [NSString stringWithFormat: @\"%@ %u\",\n\t\t\t\t\t   [self localHost4],\n\t\t\t\t\t   [self localPort4]];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tselfstr = [NSString stringWithFormat: @\"%@ %u\",\n\t\t\t\t\t   [self localHost6],\n\t\t\t\t\t   [self localPort6]];\n\t\t}\n\t}\n\telse selfstr = @\"nowhere\";\n\t\n\tNSMutableString *ms = [[NSMutableString alloc] initWithCapacity:150];\n\t\n\t[ms appendString:[NSString stringWithFormat:@\"<AsyncSocket %p\", self]];\n\t[ms appendString:[NSString stringWithFormat:@\" local %@ remote %@ \", selfstr, peerstr]];\n\t\n\tunsigned readQueueCount  = (unsigned)[theReadQueue count];\n\tunsigned writeQueueCount = (unsigned)[theWriteQueue count];\n\t\n\t[ms appendString:[NSString stringWithFormat:@\"has queued %u reads %u writes, \", readQueueCount, writeQueueCount]];\n    \n\tif (theCurrentRead == nil || [theCurrentRead isKindOfClass:[AsyncSpecialPacket class]])\n\t\t[ms appendString: @\"no current read, \"];\n\telse\n\t{\n\t\tint percentDone;\n\t\tif (theCurrentRead->readLength > 0)\n\t\t\tpercentDone = (float)theCurrentRead->bytesDone / (float)theCurrentRead->readLength * 100.0F;\n\t\telse\n\t\t\tpercentDone = 100.0F;\n        \n\t\t[ms appendString: [NSString stringWithFormat:@\"currently read %u bytes (%d%% done), \",\n                           (unsigned int)[theCurrentRead->buffer length],\n                           theCurrentRead->bytesDone ? percentDone : 0]];\n\t}\n    \n\tif (theCurrentWrite == nil || [theCurrentWrite isKindOfClass:[AsyncSpecialPacket class]])\n\t\t[ms appendString: @\"no current write, \"];\n\telse\n\t{\n\t\tint percentDone = (float)theCurrentWrite->bytesDone / (float)[theCurrentWrite->buffer length] * 100.0F;\n        \n\t\t[ms appendString: [NSString stringWithFormat:@\"currently written %u (%d%%), \",\n                           (unsigned int)[theCurrentWrite->buffer length],\n                           theCurrentWrite->bytesDone ? percentDone : 0]];\n\t}\n\t\n\t[ms appendString:[NSString stringWithFormat:@\"read stream %p %s, \", theReadStream, statstr[rs]]];\n\t[ms appendString:[NSString stringWithFormat:@\"write stream %p %s\", theWriteStream, statstr[ws]]];\n\t\n\tif(theFlags & kDisconnectAfterReads)\n\t{\n\t\tif(theFlags & kDisconnectAfterWrites)\n\t\t\t[ms appendString: @\", will disconnect after reads & writes\"];\n\t\telse\n\t\t\t[ms appendString: @\", will disconnect after reads\"];\n\t}\n\telse if(theFlags & kDisconnectAfterWrites)\n\t{\n\t\t[ms appendString: @\", will disconnect after writes\"];\n\t}\n\t\n\tif (![self isConnected]) [ms appendString: @\", not connected\"];\n    \n\t[ms appendString:@\">\"];\n    \n\treturn ms;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Reading\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag\n{\n\t[self readDataWithTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag];\n}\n\n- (void)readDataWithTimeout:(NSTimeInterval)timeout\n                     buffer:(NSMutableData *)buffer\n               bufferOffset:(NSUInteger)offset\n                        tag:(long)tag\n{\n\t[self readDataWithTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag];\n}\n\n- (void)readDataWithTimeout:(NSTimeInterval)timeout\n                     buffer:(NSMutableData *)buffer\n               bufferOffset:(NSUInteger)offset\n                  maxLength:(NSUInteger)length\n                        tag:(long)tag\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif (offset > [buffer length]) return;\n\tif (theFlags & kForbidReadsWrites) return;\n\t\n\tAsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer\n\t                                                    startOffset:offset\n\t                                                      maxLength:length\n\t                                                        timeout:timeout\n\t                                                     readLength:0\n\t                                                     terminator:nil\n\t                                                            tag:tag];\n\t[theReadQueue addObject:packet];\n\t[self scheduleDequeueRead];\n\t\n}\n\n- (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag\n{\n\t[self readDataToLength:length withTimeout:timeout buffer:nil bufferOffset:0 tag:tag];\n}\n\n- (void)readDataToLength:(NSUInteger)length\n             withTimeout:(NSTimeInterval)timeout\n                  buffer:(NSMutableData *)buffer\n            bufferOffset:(NSUInteger)offset\n                     tag:(long)tag\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif (length == 0) return;\n\tif (offset > [buffer length]) return;\n\tif (theFlags & kForbidReadsWrites) return;\n\t\n\tAsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer\n\t                                                    startOffset:offset\n\t                                                      maxLength:0\n\t                                                        timeout:timeout\n\t                                                     readLength:length\n\t                                                     terminator:nil\n\t                                                            tag:tag];\n\t[theReadQueue addObject:packet];\n\t[self scheduleDequeueRead];\n\t\n}\n\n- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag\n{\n\t[self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag];\n}\n\n- (void)readDataToData:(NSData *)data\n           withTimeout:(NSTimeInterval)timeout\n                buffer:(NSMutableData *)buffer\n          bufferOffset:(NSUInteger)offset\n                   tag:(long)tag\n{\n\t[self readDataToData:data withTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag];\n}\n\n- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag\n{\n\t[self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:length tag:tag];\n}\n\n- (void)readDataToData:(NSData *)data\n           withTimeout:(NSTimeInterval)timeout\n                buffer:(NSMutableData *)buffer\n          bufferOffset:(NSUInteger)offset\n             maxLength:(NSUInteger)length\n                   tag:(long)tag\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif (data == nil || [data length] == 0) return;\n\tif (offset > [buffer length]) return;\n\tif (length > 0 && length < [data length]) return;\n\tif (theFlags & kForbidReadsWrites) return;\n\t\n\tAsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer\n\t                                                    startOffset:offset\n\t                                                      maxLength:length\n\t                                                        timeout:timeout\n\t                                                     readLength:0\n\t                                                     terminator:data\n\t                                                            tag:tag];\n\t[theReadQueue addObject:packet];\n\t[self scheduleDequeueRead];\n\t\n}\n\n/**\n * Puts a maybeDequeueRead on the run loop.\n * An assumption here is that selectors will be performed consecutively within their priority.\n **/\n- (void)scheduleDequeueRead\n{\n\tif((theFlags & kDequeueReadScheduled) == 0)\n\t{\n\t\ttheFlags |= kDequeueReadScheduled;\n\t\t[self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t}\n}\n\n/**\n * This method starts a new read, if needed.\n * It is called when a user requests a read,\n * or when a stream opens that may have requested reads sitting in the queue, etc.\n **/\n- (void)maybeDequeueRead\n{\n\t// Unset the flag indicating a call to this method is scheduled\n\ttheFlags &= ~kDequeueReadScheduled;\n\t\n\t// If we're not currently processing a read AND we have an available read stream\n\tif((theCurrentRead == nil) && (theReadStream != NULL))\n\t{\n\t\tif([theReadQueue count] > 0)\n\t\t{\n\t\t\t// Dequeue the next object in the write queue\n\t\t\ttheCurrentRead = [theReadQueue objectAtIndex:0];\n\t\t\t[theReadQueue removeObjectAtIndex:0];\n\t\t\t\n\t\t\tif([theCurrentRead isKindOfClass:[AsyncSpecialPacket class]])\n\t\t\t{\n\t\t\t\t// Attempt to start TLS\n\t\t\t\ttheFlags |= kStartingReadTLS;\n\t\t\t\t\n\t\t\t\t// This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set\n\t\t\t\t[self maybeStartTLS];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Start time-out timer\n\t\t\t\tif(theCurrentRead->timeout >= 0.0)\n\t\t\t\t{\n\t\t\t\t\ttheReadTimer = [NSTimer timerWithTimeInterval:theCurrentRead->timeout\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   target:self\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t selector:@selector(doReadTimeout:)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t userInfo:nil\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  repeats:NO];\n\t\t\t\t\t[self runLoopAddTimer:theReadTimer];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Immediately read, if possible\n\t\t\t\t[self doBytesAvailable];\n\t\t\t}\n\t\t}\n\t\telse if(theFlags & kDisconnectAfterReads)\n\t\t{\n\t\t\tif(theFlags & kDisconnectAfterWrites)\n\t\t\t{\n\t\t\t\tif(([theWriteQueue count] == 0) && (theCurrentWrite == nil))\n\t\t\t\t{\n\t\t\t\t\t[self disconnect];\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t[self disconnect];\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Call this method in doBytesAvailable instead of CFReadStreamHasBytesAvailable().\n * This method supports pre-buffering properly as well as the kSocketHasBytesAvailable flag.\n **/\n- (BOOL)hasBytesAvailable\n{\n\tif ((theFlags & kSocketHasBytesAvailable) || ([partialReadBuffer length] > 0))\n\t{\n\t\treturn YES;\n\t}\n\telse\n\t{\n\t\treturn CFReadStreamHasBytesAvailable(theReadStream);\n\t}\n}\n\n/**\n * Call this method in doBytesAvailable instead of CFReadStreamRead().\n * This method support pre-buffering properly.\n **/\n- (CFIndex)readIntoBuffer:(void *)buffer maxLength:(NSUInteger)length\n{\n\tif([partialReadBuffer length] > 0)\n\t{\n\t\t// Determine the maximum amount of data to read\n\t\tNSUInteger bytesToRead = MIN(length, [partialReadBuffer length]);\n\t\t\n\t\t// Copy the bytes from the partial read buffer\n\t\tmemcpy(buffer, [partialReadBuffer bytes], (size_t)bytesToRead);\n\t\t\n\t\t// Remove the copied bytes from the partial read buffer\n\t\t[partialReadBuffer replaceBytesInRange:NSMakeRange(0, bytesToRead) withBytes:NULL length:0];\n\t\t\n\t\treturn (CFIndex)bytesToRead;\n\t}\n\telse\n\t{\n\t\t// Unset the \"has-bytes-available\" flag\n\t\ttheFlags &= ~kSocketHasBytesAvailable;\n\t\t\n\t\treturn CFReadStreamRead(theReadStream, (UInt8 *)buffer, length);\n\t}\n}\n\n/**\n * This method is called when a new read is taken from the read queue or when new data becomes available on the stream.\n **/\n- (void)doBytesAvailable\n{\n\t// If data is available on the stream, but there is no read request, then we don't need to process the data yet.\n\t// Also, if there is a read request but no read stream setup, we can't process any data yet.\n\tif((theCurrentRead == nil) || (theReadStream == NULL))\n\t{\n\t\treturn;\n\t}\n\t\n\t// Note: This method is not called if theCurrentRead is an AsyncSpecialPacket (startTLS packet)\n\t\n\tNSUInteger totalBytesRead = 0;\n\t\n\tBOOL done = NO;\n\tBOOL socketError = NO;\n\tBOOL maxoutError = NO;\n\t\n\twhile(!done && !socketError && !maxoutError && [self hasBytesAvailable])\n\t{\n\t\tBOOL didPreBuffer = NO;\n\t\tBOOL didReadFromPreBuffer = NO;\n\t\t\n\t\t// There are 3 types of read packets:\n\t\t//\n\t\t// 1) Read all available data.\n\t\t// 2) Read a specific length of data.\n\t\t// 3) Read up to a particular terminator.\n\t\t\n\t\tNSUInteger bytesToRead;\n\t\t\n\t\tif (theCurrentRead->term != nil)\n\t\t{\n\t\t\t// Read type #3 - read up to a terminator\n\t\t\t//\n\t\t\t// If pre-buffering is enabled we'll read a chunk and search for the terminator.\n\t\t\t// If the terminator is found, overflow data will be placed in the partialReadBuffer for the next read.\n\t\t\t//\n\t\t\t// If pre-buffering is disabled we'll be forced to read only a few bytes.\n\t\t\t// Just enough to ensure we don't go past our term or over our max limit.\n\t\t\t//\n\t\t\t// If we already have data pre-buffered, we can read directly from it.\n\t\t\t\n\t\t\tif ([partialReadBuffer length] > 0)\n\t\t\t{\n\t\t\t\tdidReadFromPreBuffer = YES;\n\t\t\t\tbytesToRead = [theCurrentRead readLengthForTermWithPreBuffer:partialReadBuffer found:&done];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (theFlags & kEnablePreBuffering)\n\t\t\t\t{\n\t\t\t\t\tdidPreBuffer = YES;\n\t\t\t\t\tbytesToRead = [theCurrentRead prebufferReadLengthForTerm];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbytesToRead = [theCurrentRead readLengthForTerm];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Read type #1 or #2\n\t\t\t\n\t\t\tbytesToRead = [theCurrentRead readLengthForNonTerm];\n\t\t}\n\t\t\n\t\t// Make sure we have enough room in the buffer for our read\n\t\t\n\t\tNSUInteger buffSize = [theCurrentRead->buffer length];\n\t\tNSUInteger buffSpace = buffSize - theCurrentRead->startOffset - theCurrentRead->bytesDone;\n\t\t\n\t\tif (bytesToRead > buffSpace)\n\t\t{\n\t\t\tNSUInteger buffInc = bytesToRead - buffSpace;\n\t\t\t\n\t\t\t[theCurrentRead->buffer increaseLengthBy:buffInc];\n\t\t}\n\t\t\n\t\t// Read data into packet buffer\n\t\t\n\t\tvoid *buffer = [theCurrentRead->buffer mutableBytes] + theCurrentRead->startOffset;\n\t\tvoid *subBuffer = buffer + theCurrentRead->bytesDone;\n\t\t\n\t\tCFIndex result = [self readIntoBuffer:subBuffer maxLength:bytesToRead];\n\t\t\n\t\t// Check results\n\t\tif (result < 0)\n\t\t{\n\t\t\tsocketError = YES;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tCFIndex bytesRead = result;\n\t\t\t\n\t\t\t// Update total amount read for the current read\n\t\t\ttheCurrentRead->bytesDone += bytesRead;\n\t\t\t\n\t\t\t// Update total amount read in this method invocation\n\t\t\ttotalBytesRead += bytesRead;\n            \n            \n\t\t\t// Is packet done?\n\t\t\tif (theCurrentRead->readLength > 0)\n\t\t\t{\n\t\t\t\t// Read type #2 - read a specific length of data\n\t\t\t\t\n\t\t\t\tdone = (theCurrentRead->bytesDone == theCurrentRead->readLength);\n\t\t\t}\n\t\t\telse if (theCurrentRead->term != nil)\n\t\t\t{\n\t\t\t\t// Read type #3 - read up to a terminator\n\t\t\t\t\n\t\t\t\tif (didPreBuffer)\n\t\t\t\t{\n\t\t\t\t\t// Search for the terminating sequence within the big chunk we just read.\n\t\t\t\t\t\n\t\t\t\t\tNSInteger overflow = [theCurrentRead searchForTermAfterPreBuffering:result];\n\t\t\t\t\t\n\t\t\t\t\tif (overflow > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Copy excess data into partialReadBuffer\n\t\t\t\t\t\tvoid *overflowBuffer = buffer + theCurrentRead->bytesDone - overflow;\n\t\t\t\t\t\t\n\t\t\t\t\t\t[partialReadBuffer appendBytes:overflowBuffer length:overflow];\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Update the bytesDone variable.\n\t\t\t\t\t\ttheCurrentRead->bytesDone -= overflow;\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Note: The completeCurrentRead method will trim the buffer for us.\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tdone = (overflow >= 0);\n\t\t\t\t}\n\t\t\t\telse if (didReadFromPreBuffer)\n\t\t\t\t{\n\t\t\t\t\t// Our 'done' variable was updated via the readLengthForTermWithPreBuffer:found: method\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Search for the terminating sequence at the end of the buffer\n\t\t\t\t\t\n\t\t\t\t\tNSUInteger termlen = [theCurrentRead->term length];\n\t\t\t\t\t\n\t\t\t\t\tif(theCurrentRead->bytesDone >= termlen)\n\t\t\t\t\t{\n\t\t\t\t\t\tvoid *bufferEnd = buffer + (theCurrentRead->bytesDone - termlen);\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst void *seq = [theCurrentRead->term bytes];\n\t\t\t\t\t\t\n\t\t\t\t\t\tdone = (memcmp (bufferEnd, seq, termlen) == 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(!done && theCurrentRead->maxLength > 0)\n\t\t\t\t{\n\t\t\t\t\t// We're not done and there's a set maxLength.\n\t\t\t\t\t// Have we reached that maxLength yet?\n\t\t\t\t\t\n\t\t\t\t\tif(theCurrentRead->bytesDone >= theCurrentRead->maxLength)\n\t\t\t\t\t{\n\t\t\t\t\t\tmaxoutError = YES;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Read type #1 - read all available data\n\t\t\t\t//\n\t\t\t\t// We're done when:\n\t\t\t\t// - we reach maxLength (if there is a max)\n\t\t\t\t// - all readable is read (see below)\n\t\t\t\t\n\t\t\t\tif (theCurrentRead->maxLength > 0)\n\t\t\t\t{\n\t\t\t\t\tdone = (theCurrentRead->bytesDone >= theCurrentRead->maxLength);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif (theCurrentRead->readLength <= 0 && theCurrentRead->term == nil)\n\t{\n\t\t// Read type #1 - read all available data\n\t\t\n\t\tif (theCurrentRead->bytesDone > 0)\n\t\t{\n\t\t\t// Ran out of bytes, so the \"read-all-available-data\" type packet is done\n\t\t\tdone = YES;\n\t\t}\n\t}\n\t\n\tif (done)\n\t{\n\t\t[self completeCurrentRead];\n\t\tif (!socketError) [self scheduleDequeueRead];\n\t}\n\telse if (totalBytesRead > 0)\n\t{\n\t\t// We're not done with the readToLength or readToData yet, but we have read in some bytes\n\t\tif ([theDelegate respondsToSelector:@selector(onSocket:didReadPartialDataOfLength:tag:)])\n\t\t{\n\t\t\t[theDelegate onSocket:self didReadPartialDataOfLength:totalBytesRead tag:theCurrentRead->tag];\n\t\t}\n\t}\n\t\n\tif(socketError)\n\t{\n\t\tCFStreamError err = CFReadStreamGetError(theReadStream);\n\t\t[self closeWithError:[self errorFromCFStreamError:err]];\n\t\treturn;\n\t}\n\t\n\tif(maxoutError)\n\t{\n\t\t[self closeWithError:[self getReadMaxedOutError]];\n\t\treturn;\n\t}\n}\n\n// Ends current read and calls delegate.\n- (void)completeCurrentRead\n{\n\tNSAssert(theCurrentRead, @\"Trying to complete current read when there is no current read.\");\n\t\n\tNSData *result;\n\t\n\tif (theCurrentRead->bufferOwner)\n\t{\n\t\t// We created the buffer on behalf of the user.\n\t\t// Trim our buffer to be the proper size.\n\t\t[theCurrentRead->buffer setLength:theCurrentRead->bytesDone];\n\t\t\n\t\tresult = theCurrentRead->buffer;\n\t}\n\telse\n\t{\n\t\t// We did NOT create the buffer.\n\t\t// The buffer is owned by the caller.\n\t\t// Only trim the buffer if we had to increase its size.\n\t\t\n\t\tif ([theCurrentRead->buffer length] > theCurrentRead->originalBufferLength)\n\t\t{\n\t\t\tNSUInteger readSize = theCurrentRead->startOffset + theCurrentRead->bytesDone;\n\t\t\tNSUInteger origSize = theCurrentRead->originalBufferLength;\n\t\t\t\n\t\t\tNSUInteger buffSize = MAX(readSize, origSize);\n\t\t\t\n\t\t\t[theCurrentRead->buffer setLength:buffSize];\n\t\t}\n\t\t\n\t\tvoid *buffer = [theCurrentRead->buffer mutableBytes] + theCurrentRead->startOffset;\n\t\t\n\t\tresult = [NSData dataWithBytesNoCopy:buffer length:theCurrentRead->bytesDone freeWhenDone:NO];\n\t}\n\t\n\tif([theDelegate respondsToSelector:@selector(onSocket:didReadData:withTag:)])\n\t{\n\t\t[theDelegate onSocket:self didReadData:result withTag:theCurrentRead->tag];\n\t}\n\t\n\t// Caller may have disconnected in the above delegate method\n\tif (theCurrentRead != nil)\n\t{\n\t\t[self endCurrentRead];\n\t}\n}\n\n// Ends current read.\n- (void)endCurrentRead\n{\n\tNSAssert(theCurrentRead, @\"Trying to end current read when there is no current read.\");\n\t\n\t[theReadTimer invalidate];\n\ttheReadTimer = nil;\n\t\n\ttheCurrentRead = nil;\n}\n\n- (void)doReadTimeout:(NSTimer *)timer\n{\n#pragma unused(timer)\n\t\n\tNSTimeInterval timeoutExtension = 0.0;\n\t\n\tif([theDelegate respondsToSelector:@selector(onSocket:shouldTimeoutReadWithTag:elapsed:bytesDone:)])\n\t{\n\t\ttimeoutExtension = [theDelegate onSocket:self shouldTimeoutReadWithTag:theCurrentRead->tag\n                                         elapsed:theCurrentRead->timeout\n                                       bytesDone:theCurrentRead->bytesDone];\n\t}\n\t\n\tif(timeoutExtension > 0.0)\n\t{\n\t\ttheCurrentRead->timeout += timeoutExtension;\n\t\t\n\t\ttheReadTimer = [NSTimer timerWithTimeInterval:timeoutExtension\n\t\t\t\t\t\t\t\t\t\t\t   target:self\n\t\t\t\t\t\t\t\t\t\t\t selector:@selector(doReadTimeout:)\n\t\t\t\t\t\t\t\t\t\t\t userInfo:nil\n\t\t\t\t\t\t\t\t\t\t\t  repeats:NO];\n\t\t[self runLoopAddTimer:theReadTimer];\n\t}\n\telse\n\t{\n\t\t// Do not call endCurrentRead here.\n\t\t// We must allow the delegate access to any partial read in the unreadData method.\n\t\t\n\t\t[self closeWithError:[self getReadTimeoutError]];\n\t}\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Writing\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif (data == nil || [data length] == 0) return;\n\tif (theFlags & kForbidReadsWrites) return;\n\t\n\tAsyncWritePacket *packet = [[AsyncWritePacket alloc] initWithData:data timeout:timeout tag:tag];\n\t\n\t[theWriteQueue addObject:packet];\n\t[self scheduleDequeueWrite];\n\t\n}\n\n- (void)scheduleDequeueWrite\n{\n\tif((theFlags & kDequeueWriteScheduled) == 0)\n\t{\n\t\ttheFlags |= kDequeueWriteScheduled;\n\t\t[self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0 inModes:theRunLoopModes];\n\t}\n}\n\n/**\n * Conditionally starts a new write.\n *\n * IF there is not another write in process\n * AND there is a write queued\n * AND we have a write stream available\n *\n * This method also handles auto-disconnect post read/write completion.\n **/\n- (void)maybeDequeueWrite\n{\n\t// Unset the flag indicating a call to this method is scheduled\n\ttheFlags &= ~kDequeueWriteScheduled;\n\t\n\t// If we're not currently processing a write AND we have an available write stream\n\tif((theCurrentWrite == nil) && (theWriteStream != NULL))\n\t{\n\t\tif([theWriteQueue count] > 0)\n\t\t{\n\t\t\t// Dequeue the next object in the write queue\n\t\t\ttheCurrentWrite = [theWriteQueue objectAtIndex:0];\n\t\t\t[theWriteQueue removeObjectAtIndex:0];\n\t\t\t\n\t\t\tif([theCurrentWrite isKindOfClass:[AsyncSpecialPacket class]])\n\t\t\t{\n\t\t\t\t// Attempt to start TLS\n\t\t\t\ttheFlags |= kStartingWriteTLS;\n\t\t\t\t\n\t\t\t\t// This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set\n\t\t\t\t[self maybeStartTLS];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Start time-out timer\n\t\t\t\tif(theCurrentWrite->timeout >= 0.0)\n\t\t\t\t{\n\t\t\t\t\ttheWriteTimer = [NSTimer timerWithTimeInterval:theCurrentWrite->timeout\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttarget:self\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  selector:@selector(doWriteTimeout:)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  userInfo:nil\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   repeats:NO];\n\t\t\t\t\t[self runLoopAddTimer:theWriteTimer];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Immediately write, if possible\n\t\t\t\t[self doSendBytes];\n\t\t\t}\n\t\t}\n\t\telse if(theFlags & kDisconnectAfterWrites)\n\t\t{\n\t\t\tif(theFlags & kDisconnectAfterReads)\n\t\t\t{\n\t\t\t\tif(([theReadQueue count] == 0) && (theCurrentRead == nil))\n\t\t\t\t{\n\t\t\t\t\t[self disconnect];\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t[self disconnect];\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Call this method in doSendBytes instead of CFWriteStreamCanAcceptBytes().\n * This method supports the kSocketCanAcceptBytes flag.\n **/\n- (BOOL)canAcceptBytes\n{\n\tif (theFlags & kSocketCanAcceptBytes)\n\t{\n\t\treturn YES;\n\t}\n\telse\n\t{\n\t\treturn CFWriteStreamCanAcceptBytes(theWriteStream);\n\t}\n}\n\n- (void)doSendBytes\n{\n\tif ((theCurrentWrite == nil) || (theWriteStream == NULL))\n\t{\n\t\treturn;\n\t}\n\t\n\t// Note: This method is not called if theCurrentWrite is an AsyncSpecialPacket (startTLS packet)\n\t\n\tNSUInteger totalBytesWritten = 0;\n\t\n\tBOOL done = NO;\n\tBOOL error = NO;\n\t\n\twhile (!done && !error && [self canAcceptBytes])\n\t{\n\t\t// Figure out what to write\n\t\tNSUInteger bytesRemaining = [theCurrentWrite->buffer length] - theCurrentWrite->bytesDone;\n\t\tNSUInteger bytesToWrite = (bytesRemaining < WRITE_CHUNKSIZE) ? bytesRemaining : WRITE_CHUNKSIZE;\n\t\t\n\t\tUInt8 *writestart = (UInt8 *)([theCurrentWrite->buffer bytes] + theCurrentWrite->bytesDone);\n\t\t\n\t\t// Write\n\t\tCFIndex result = CFWriteStreamWrite(theWriteStream, writestart, bytesToWrite);\n\t\t\n\t\t// Unset the \"can accept bytes\" flag\n\t\ttheFlags &= ~kSocketCanAcceptBytes;\n\t\t\n\t\t// Check results\n\t\tif (result < 0)\n\t\t{\n\t\t\terror = YES;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tCFIndex bytesWritten = result;\n\t\t\t\n\t\t\t// Update total amount read for the current write\n\t\t\ttheCurrentWrite->bytesDone += bytesWritten;\n\t\t\t\n\t\t\t// Update total amount written in this method invocation\n\t\t\ttotalBytesWritten += bytesWritten;\n\t\t\t\n\t\t\t// Is packet done?\n\t\t\tdone = ([theCurrentWrite->buffer length] == theCurrentWrite->bytesDone);\n\t\t}\n\t}\n\t\n\tif(done)\n\t{\n\t\t[self completeCurrentWrite];\n\t\t[self scheduleDequeueWrite];\n\t}\n\telse if(error)\n\t{\n\t\tCFStreamError err = CFWriteStreamGetError(theWriteStream);\n\t\t[self closeWithError:[self errorFromCFStreamError:err]];\n\t\treturn;\n\t}\n\telse if (totalBytesWritten > 0)\n\t{\n\t\t// We're not done with the entire write, but we have written some bytes\n\t\tif ([theDelegate respondsToSelector:@selector(onSocket:didWritePartialDataOfLength:tag:)])\n\t\t{\n\t\t\t[theDelegate onSocket:self didWritePartialDataOfLength:totalBytesWritten tag:theCurrentWrite->tag];\n\t\t}\n\t}\n}\n\n// Ends current write and calls delegate.\n- (void)completeCurrentWrite\n{\n\tNSAssert(theCurrentWrite, @\"Trying to complete current write when there is no current write.\");\n\t\n\tif ([theDelegate respondsToSelector:@selector(onSocket:didWriteDataWithTag:)])\n\t{\n\t\t[theDelegate onSocket:self didWriteDataWithTag:theCurrentWrite->tag];\n\t}\n\t\n\tif (theCurrentWrite != nil) [self endCurrentWrite]; // Caller may have disconnected.\n}\n\n// Ends current write.\n- (void)endCurrentWrite\n{\n\tNSAssert(theCurrentWrite, @\"Trying to complete current write when there is no current write.\");\n\t\n\t[theWriteTimer invalidate];\n\ttheWriteTimer = nil;\n\t\n\ttheCurrentWrite = nil;\n}\n\n- (void)doWriteTimeout:(NSTimer *)timer\n{\n#pragma unused(timer)\n\t\n\tNSTimeInterval timeoutExtension = 0.0;\n\t\n\tif([theDelegate respondsToSelector:@selector(onSocket:shouldTimeoutWriteWithTag:elapsed:bytesDone:)])\n\t{\n\t\ttimeoutExtension = [theDelegate onSocket:self shouldTimeoutWriteWithTag:theCurrentWrite->tag\n                                         elapsed:theCurrentWrite->timeout\n                                       bytesDone:theCurrentWrite->bytesDone];\n\t}\n\t\n\tif(timeoutExtension > 0.0)\n\t{\n\t\ttheCurrentWrite->timeout += timeoutExtension;\n\t\t\n\t\ttheWriteTimer = [NSTimer timerWithTimeInterval:timeoutExtension\n\t\t                                        target:self\n\t\t                                      selector:@selector(doWriteTimeout:)\n\t\t                                      userInfo:nil\n\t\t                                       repeats:NO];\n\t\t[self runLoopAddTimer:theWriteTimer];\n\t}\n\telse\n\t{\n\t\t[self closeWithError:[self getWriteTimeoutError]];\n\t}\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Security\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (void)startTLS:(NSDictionary *)tlsSettings\n{\n#if DEBUG_THREAD_SAFETY\n\t[self checkForThreadSafety];\n#endif\n\t\n\tif(tlsSettings == nil)\n    {\n        // Passing nil/NULL to CFReadStreamSetProperty will appear to work the same as passing an empty dictionary,\n        // but causes problems if we later try to fetch the remote host's certificate.\n        //\n        // To be exact, it causes the following to return NULL instead of the normal result:\n        // CFReadStreamCopyProperty(readStream, kCFStreamPropertySSLPeerCertificates)\n        //\n        // So we use an empty dictionary instead, which works perfectly.\n        \n        tlsSettings = [NSDictionary dictionary];\n    }\n\t\n\tAsyncSpecialPacket *packet = [[AsyncSpecialPacket alloc] initWithTLSSettings:tlsSettings];\n\t\n\t[theReadQueue addObject:packet];\n\t[self scheduleDequeueRead];\n\t\n\t[theWriteQueue addObject:packet];\n\t[self scheduleDequeueWrite];\n\t\n}\n\n- (void)maybeStartTLS\n{\n\t// We can't start TLS until:\n\t// - All queued reads prior to the user calling StartTLS are complete\n\t// - All queued writes prior to the user calling StartTLS are complete\n\t//\n\t// We'll know these conditions are met when both kStartingReadTLS and kStartingWriteTLS are set\n\t\n\tif((theFlags & kStartingReadTLS) && (theFlags & kStartingWriteTLS))\n\t{\n\t\tAsyncSpecialPacket *tlsPacket = (AsyncSpecialPacket *)theCurrentRead;\n\t\t\n\t\tBOOL didStartOnReadStream = CFReadStreamSetProperty(theReadStream, kCFStreamPropertySSLSettings,\n                                                            (__bridge CFDictionaryRef)tlsPacket->tlsSettings);\n\t\tBOOL didStartOnWriteStream = CFWriteStreamSetProperty(theWriteStream, kCFStreamPropertySSLSettings,\n                                                              (__bridge CFDictionaryRef)tlsPacket->tlsSettings);\n\t\t\n\t\tif(!didStartOnReadStream || !didStartOnWriteStream)\n\t\t{\n            [self closeWithError:[self getSocketError]];\n\t\t}\n\t}\n}\n\n- (void)onTLSHandshakeSuccessful\n{\n\tif((theFlags & kStartingReadTLS) && (theFlags & kStartingWriteTLS))\n\t{\n\t\ttheFlags &= ~kStartingReadTLS;\n\t\ttheFlags &= ~kStartingWriteTLS;\n\t\t\n\t\tif([theDelegate respondsToSelector:@selector(onSocketDidSecure:)])\n\t\t{\n\t\t\t[theDelegate onSocketDidSecure:self];\n\t\t}\n\t\t\n\t\t[self endCurrentRead];\n\t\t[self endCurrentWrite];\n\t\t\n\t\t[self scheduleDequeueRead];\n\t\t[self scheduleDequeueWrite];\n\t}\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark CF Callbacks\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n- (void)doCFSocketCallback:(CFSocketCallBackType)type\n\t\t\t\t forSocket:(CFSocketRef)sock\n\t\t\t   withAddress:(NSData *)address\n\t\t\t\t  withData:(const void *)pData\n{\n#pragma unused(address)\n\t\n\tNSParameterAssert ((sock == theSocket4) || (sock == theSocket6));\n\t\n\tswitch (type)\n\t{\n\t\tcase kCFSocketConnectCallBack:\n\t\t\t// The data argument is either NULL or a pointer to an SInt32 error code, if the connect failed.\n\t\t\tif(pData)\n\t\t\t\t[self doSocketOpen:sock withCFSocketError:kCFSocketError];\n\t\t\telse\n\t\t\t\t[self doSocketOpen:sock withCFSocketError:kCFSocketSuccess];\n\t\t\tbreak;\n\t\tcase kCFSocketAcceptCallBack:\n\t\t\t[self doAcceptFromSocket:sock withNewNativeSocket:*((CFSocketNativeHandle *)pData)];\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tNSLog(@\"AsyncSocket %p received unexpected CFSocketCallBackType %i\", self, (int)type);\n\t\t\tbreak;\n\t}\n}\n\n- (void)doCFReadStreamCallback:(CFStreamEventType)type forStream:(CFReadStreamRef)stream\n{\n#pragma unused(stream)\n\t\n\tNSParameterAssert(theReadStream != NULL);\n\t\n\tCFStreamError err;\n\tswitch (type)\n\t{\n\t\tcase kCFStreamEventOpenCompleted:\n\t\t\ttheFlags |= kDidCompleteOpenForRead;\n\t\t\t[self doStreamOpen];\n\t\t\tbreak;\n\t\tcase kCFStreamEventHasBytesAvailable:\n\t\t\tif(theFlags & kStartingReadTLS) {\n\t\t\t\t[self onTLSHandshakeSuccessful];\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttheFlags |= kSocketHasBytesAvailable;\n\t\t\t\t[self doBytesAvailable];\n\t\t\t}\n\t\t\tbreak;\n\t\tcase kCFStreamEventErrorOccurred:\n\t\tcase kCFStreamEventEndEncountered:\n\t\t\terr = CFReadStreamGetError (theReadStream);\n\t\t\t[self closeWithError: [self errorFromCFStreamError:err]];\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tNSLog(@\"AsyncSocket %p received unexpected CFReadStream callback, CFStreamEventType %i\", self, (int)type);\n\t}\n}\n\n- (void)doCFWriteStreamCallback:(CFStreamEventType)type forStream:(CFWriteStreamRef)stream\n{\n#pragma unused(stream)\n\t\n\tNSParameterAssert(theWriteStream != NULL);\n\t\n\tCFStreamError err;\n\tswitch (type)\n\t{\n\t\tcase kCFStreamEventOpenCompleted:\n\t\t\ttheFlags |= kDidCompleteOpenForWrite;\n\t\t\t[self doStreamOpen];\n\t\t\tbreak;\n\t\tcase kCFStreamEventCanAcceptBytes:\n\t\t\tif(theFlags & kStartingWriteTLS) {\n\t\t\t\t[self onTLSHandshakeSuccessful];\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttheFlags |= kSocketCanAcceptBytes;\n\t\t\t\t[self doSendBytes];\n\t\t\t}\n\t\t\tbreak;\n\t\tcase kCFStreamEventErrorOccurred:\n\t\tcase kCFStreamEventEndEncountered:\n\t\t\terr = CFWriteStreamGetError (theWriteStream);\n\t\t\t[self closeWithError: [self errorFromCFStreamError:err]];\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tNSLog(@\"AsyncSocket %p received unexpected CFWriteStream callback, CFStreamEventType %i\", self, (int)type);\n\t}\n}\n\n/**\n * This is the callback we setup for CFSocket.\n * This method does nothing but forward the call to it's Objective-C counterpart\n **/\nstatic void MyCFSocketCallback (CFSocketRef sref, CFSocketCallBackType type, CFDataRef inAddress, const void *pData, void *pInfo)\n{\n\t@autoreleasepool {\n        \n\t\tAsyncSocket *theSocket = (__bridge AsyncSocket *)pInfo;\n\t\tNSData *address = [(__bridge NSData *)inAddress copy];\n\t\t\n\t\t[theSocket doCFSocketCallback:type forSocket:sref withAddress:address withData:pData];\n        \n\t}\n}\n\n/**\n * This is the callback we setup for CFReadStream.\n * This method does nothing but forward the call to it's Objective-C counterpart\n **/\nstatic void MyCFReadStreamCallback (CFReadStreamRef stream, CFStreamEventType type, void *pInfo)\n{\n\t@autoreleasepool {\n        \n\t\tAsyncSocket *theSocket = (__bridge AsyncSocket *)pInfo;\n\t\t[theSocket doCFReadStreamCallback:type forStream:stream];\n        \n\t}\n}\n\n/**\n * This is the callback we setup for CFWriteStream.\n * This method does nothing but forward the call to it's Objective-C counterpart\n **/\nstatic void MyCFWriteStreamCallback (CFWriteStreamRef stream, CFStreamEventType type, void *pInfo)\n{\n\t@autoreleasepool {\n        \n\t\tAsyncSocket *theSocket = (__bridge AsyncSocket *)pInfo;\n\t\t[theSocket doCFWriteStreamCallback:type forStream:stream];\n        \n\t}\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark Class Methods\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n// Return line separators.\n+ (NSData *)CRLFData\n{\n\treturn [NSData dataWithBytes:\"\\x0D\\x0A\" length:2];\n}\n\n+ (NSData *)CRData\n{\n\treturn [NSData dataWithBytes:\"\\x0D\" length:1];\n}\n\n+ (NSData *)LFData\n{\n\treturn [NSData dataWithBytes:\"\\x0A\" length:1];\n}\n\n+ (NSData *)ZeroData\n{\n\treturn [NSData dataWithBytes:\"\" length:1];\n}\n\n@end"
  },
  {
    "path": "WebSocket/HandshakeHeader.h",
    "content": "//\n//  HandshakeHeader.h\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 10/2/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface HandshakeHeader : NSObject\n{\n    NSString* key;\n    NSString* value;\n}\n\n@property (copy) NSString* key;\n@property (copy) NSString* value;\n\n+ (id) header;\n+ (id) headerWithValue:(NSString*) aValue forKey:(NSString*) aKey;\n- (id) initWithValue:(NSString*) aValue forKey:(NSString*) aKey;\n\n- (BOOL) keyMatchesCaseInsensitiveString:(NSString*) aStringToCompare;\n\n@end\n"
  },
  {
    "path": "WebSocket/HandshakeHeader.m",
    "content": "//\n//  HandshakeHeader.m\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 10/2/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import \"HandshakeHeader.h\"\n\n@implementation HandshakeHeader\n\n@synthesize key;\n@synthesize value;\n\n\n#pragma mark - Header\n- (BOOL) keyMatchesCaseInsensitiveString:(NSString*) aStringToCompare\n{\n    if (aStringToCompare && self.key)\n    {\n        return [self.key caseInsensitiveCompare:aStringToCompare] == NSOrderedSame;\n    }\n    \n    return NO;\n}\n\n\n#pragma mark - Lifecycle\n+ (id) header\n{\n    return [[[self class] alloc] init] ;\n}\n\n+ (id) headerWithValue:(NSString*) aValue forKey:(NSString*) aKey\n{\n    return [[[self class] alloc] initWithValue:aValue forKey:aKey];\n}\n\n- (id) initWithValue:(NSString*) aValue forKey:(NSString*) aKey\n{\n    self = [super init];\n    if (self) \n    {\n        self.key = aKey;\n        self.value = aValue;\n    }\n    \n    return self;    \n}\n\n- (id) init\n{\n    self = [super init];\n    if (self) \n    {\n    }\n    \n    return self;\n}\n\n- (void) dealloc \n{\n    self.key = nil;\n    self.value = nil;\n}\n\n@end\n"
  },
  {
    "path": "WebSocket/MutableQueue.h",
    "content": "//\n//  NSMutableArray+QueueAddition.h\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 6/16/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import <Foundation/Foundation.h>\n\n\n@interface MutableQueue : NSObject\n{\n    NSMutableArray* items;\n}\n\n- (NSUInteger) count;\n- (id) dequeue;\n- (void) enqueue:(id) aObject;\n- (id) lastObject;\n- (void) removeLastObject;\n\n@end\n"
  },
  {
    "path": "WebSocket/MutableQueue.m",
    "content": "//\n//  NSMutableArray+QueueAddition.m\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 6/16/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import \"MutableQueue.h\"\n\n\n@implementation MutableQueue\n\n#pragma mark Queue\n- (NSUInteger)count {\n    return items.count;\n}\n\n- (id) dequeue\n{\n    if ([items count] == 0) \n    {\n        return nil;\n    }\n    id headObject = [items objectAtIndex:0];\n    if (headObject != nil)\n    {\n        [items removeObjectAtIndex:0];\n    }\n    return headObject;\n}\n\n- (void) enqueue:(id) aObject \n{\n    [items addObject:aObject];\n}\n\n- (id) lastObject\n{\n    return [items lastObject];\n}\n\n- (void) removeLastObject {\n    [items removeLastObject];\n}\n\n\n#pragma mark Lifecycle\n- (id) init \n{\n    self = [super init];\n    if (self) \n    {\n        items = [[NSMutableArray alloc] init];\n    }\n    return self;\n}\n\n@end\n"
  },
  {
    "path": "WebSocket/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": "WebSocket/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 =\n\t\t[[NSString alloc]\n\t\t\tinitWithBytes:outputBuffer\n\t\t\tlength:outputLength\n\t\t\tencoding:NSASCIIStringEncoding];\n\tfree(outputBuffer);\n\treturn result;\n}\n\n@end\n"
  },
  {
    "path": "WebSocket/UnittWebSocketClient-Prefix.pch",
    "content": "//\n// Prefix header for all source files of the 'UnittWebSocketClient' target in the 'UnittWebSocketClient' project\n//\n\n#ifdef __OBJC__\n    #import <Foundation/Foundation.h>\n#endif\n"
  },
  {
    "path": "WebSocket/WebSocket.h",
    "content": "//\n//  WebSocket.h\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 9/26/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n\n#import <Foundation/Foundation.h>\n#include <Network/Network.h>\n#import <Security/Security.h>\n#import <CommonCrypto/CommonDigest.h>\n#import <CommonCrypto/CommonCryptor.h>\n#import \"NSData+Base64.h\"\n#import \"MutableQueue.h\"\n#import \"WebSocketConnectConfig.h\"\n#include \"zlib.h\"\n\nenum \n{\n    WebSocketCloseStatusNormal = 1000, //indicates a normal closure, meaning whatever purpose the \n                                       //connection was established for has been fulfilled\n    WebSocketCloseStatusEndpointGone = 1001, //indicates that an endpoint is \"going away\", such as a \n                                             //server going down, or a browser having navigated away from \n                                             //a page\n    WebSocketCloseStatusProtocolError = 1002, //indicates that an endpoint is terminating the connection \n                                              //due to a protocol error\n    WebSocketCloseStatusInvalidDataType = 1003, //indicates that an endpoint is terminating the connection\n                                                //because it has received a type of data it cannot accept \n                                                //(e.g. an endpoint that understands only text data MAY \n                                                //send this if it receives a binary message)\n    WebSocketCloseStatusLegacyMessageTooLarge = 1004, //indicates that an endpoint is terminating the connection\n                                                //because it has received a message that is too large (prior to rfc6455)\n    WebSocketCloseStatusNormalButMissingStatus = 1005, //designated for use in applications expecting a status code \n                                                       //to indicate that no status code was actually present\n    WebSocketCloseStatusAbnormalButMissingStatus = 1006, //designated for use in applications expecting a status code\n                                                         //to indicate that the connection was closed abnormally, e.g.\n                                                         //without sending or receiving a Close control frame.\n    WebSocketCloseStatusInvalidData = 1007, //indicates that an endpoint is terminating the connection because it has\n                                           //received data that is invalid, ex: supposed be UTF-8 (such as in a text frame)\n                                           // that was in fact not valid UTF-8\n    WebSocketCloseStatusViolatesPolicy = 1008, //indicates that an endpoint is terminating the connection because it has\n                                         // received a message that violates its policy.  This is a generic status code\n                                         // that can be returned when there is no other more suitable status code\n                                         // or if there is a need to hide specific details about the policy.\n    WebSocketCloseStatusMessageTooLarge = 1009, //indicates that an endpoint is terminating the connection\n                                                //because it has received a message that is too large\n    WebSocketCloseStatusMissingExtensions = 1010, //indicates that an endpoint (client) is terminating the connection because\n                                                // it has expected the server to negotiate one or more extension, but the\n                                                // server didn't return them in the response message of the WebSocket handshake\n    WebSocketCloseStatusServerError = 1011, //indicates that a server is terminating the connection because it encountered an\n                                            // unexpected condition that prevented it from fulfilling the request\n    WebSocketCloseStatusTlsHandshakeError = 1015 //indicate that the connection was closed due to a failure to perform a TLS handshake\n};\ntypedef NSUInteger WebSocketCloseStatus;\n\nenum \n{\n    WebSocketReadyStateConnecting = 0, //The connection has not yet been established.\n    WebSocketReadyStateOpen = 1, //The WebSocket connection is established and communication is possible.\n    WebSocketReadyStateClosing = 2, //The connection is going through the closing handshake.\n    WebSocketReadyStateClosed = 3 //The connection has been closed or could not be opened\n};\ntypedef NSUInteger WebSocketReadyState;\n\n@class WebSocket;\n\n@protocol WebSocketDelegate <NSObject>\n\n/**\n * Called when the web socket connects and is ready for reading and writing.\n **/\n- (void) webSocketDidOpen:(WebSocket *)socket;\n\n/**\n * Called when the web socket closes. aError will be nil if it closes cleanly.\n **/\n- (void) webSocket:(WebSocket *)socket didClose:(NSUInteger) aStatusCode message:(NSString*) aMessage error:(NSError*) aError;\n\n/**\n * Called when the web socket receives an error. Such an error can result in the\n socket being closed.\n **/\n- (void) webSocket:(WebSocket *)socket didReceiveError:(NSError*) aError;\n\n/**\n * Called when the web socket receives a message.\n **/\n- (void) webSocket:(WebSocket *)socket didReceiveTextMessage:(NSString*) aMessage;\n\n/**\n * Called when the web socket receives a message.\n **/\n- (void) webSocket:(WebSocket *)socket didReceiveBinaryMessage:(NSData*) aMessage;\n\n@optional\n/**\n * Called when pong is sent... For keep-alive optimization.\n **/\n- (void) didSendPong:(NSData*) aMessage;\n\n@end\n\n\n@interface WebSocket : NSObject\n{\n@protected\n    nw_connection_t connection;\n    NSError* closingError;\n    NSString* wsSecKey;\n    NSString* wsSecKeyHandshake;\n    MutableQueue* pendingFragments;\n    BOOL isClosing;\n    NSUInteger closeStatusCode;\n    NSString* closeMessage;\n    BOOL sendCloseInfoToListener;\n    NSMutableData* fragmentBuffer;\n@private\n    id<WebSocketDelegate> delegate;\n    WebSocketReadyState readystate;\n    WebSocketConnectConfig* config;\n    dispatch_queue_t delegateQueue;\n    dispatch_queue_t networkQueue;\n    NSTimer* pingTimer;\n    BOOL _deflate;\n    z_stream zstrm_in;\n    z_stream zstrm_out;\n    NSObject *zlibLock;\n    NSMutableData *handshakeBuffer;\n}\n\n\n/**\n * Callback delegate for websocket events.\n **/\n@property(nonatomic,retain) id<WebSocketDelegate> delegate;\n\n/**\n * Config info for the websocket connection.\n **/\n@property(nonatomic,retain) WebSocketConnectConfig* config;\n\n/**\n * Represents the state of the connection. It can have the following values:\n * - WebSocketReadyStateConnecting: The connection has not yet been established.\n * - WebSocketReadyStateOpen: The WebSocket connection is established and communication is possible.\n * - WebSocketReadyStateClosing: The connection is going through the closing handshake.\n * - WebSocketReadyStateClosed: The connection has been closed or could not be opened.\n **/\n@property(nonatomic,readonly) WebSocketReadyState readystate;\n\n\n+ (id) webSocketWithConfig:(WebSocketConnectConfig*) aConfig delegate:(id<WebSocketDelegate>) aDelegate;\n- (id) initWithConfig:(WebSocketConnectConfig*) aConfig delegate:(id<WebSocketDelegate>) aDelegate;\n+ (id) webSocketWithConfig:(WebSocketConnectConfig*) aConfig queue:(dispatch_queue_t) aDispatchQueue delegate:(id<WebSocketDelegate>) aDelegate;\n- (id) initWithConfig:(WebSocketConnectConfig*) aConfig queue:(dispatch_queue_t) aDispatchQueue delegate:(id<WebSocketDelegate>) aDelegate;\n\n\n/**\n * Connect the websocket and prepare it for reading and writing.\n **/\n- (void) open;\n\n/**\n * Finish all reads/writes and close the websocket. Sends a status of WebSocketCloseStatusNormal and no message.\n **/\n- (void) close;\n\n/**\n * Finish all reads/writes and close the websocket. Sends the specified status and message.\n **/\n- (void) close:(NSUInteger) aStatusCode message:(NSString*) aMessage;\n\n/**\n * Write a UTF-8 encoded NSString message to the websocket.\n **/\n- (void) sendText:(NSString*)message;\n\n/**\n * Write a binary message to the websocket.\n **/\n- (void) sendBinary:(NSData*)message;\n\n/**\n * Send ping message to the websocket\n */\n- (void) sendPing:(NSData*)message;\n\n\nextern NSString *const WebSocketException;\nextern NSString *const WebSocketErrorDomain;\n\n@end\n"
  },
  {
    "path": "WebSocket/WebSocket.m",
    "content": "//\n//  WebSocket.m\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 9/26/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import <Security/Security.h>\n#import \"WebSocket.h\"\n#import \"WebSocketFragment.h\"\n#import \"HandshakeHeader.h\"\n#import \"TrustKit+Private.h\"\n#include <zlib.h>\n\nenum {\n    WebSocketWaitingStateMessage = 0, //Starting on waiting for a new message\n    WebSocketWaitingStateHeader = 1, //Waiting for the remaining header bytes\n    WebSocketWaitingStatePayload = 2, //Waiting for the remaining payload bytes\n    WebSocketWaitingStateFragment = 3 //Waiting for the next fragment\n};\ntypedef NSUInteger WebSocketWaitingState;\n\n\n@interface WebSocket (Private)\n- (void)repeatPing;\n\n- (void)dispatchFailure:(NSError *)aError;\n\n- (void)dispatchClosed:(NSUInteger)aStatusCode message:(NSString *)aMessage error:(NSError *)aError;\n\n- (void)dispatchOpened;\n\n- (void)dispatchTextMessageReceived:(NSString *)aMessage;\n\n- (void)dispatchBinaryMessageReceived:(NSData *)aMessage;\n\n- (void)continueReadingMessageStream;\n\n- (NSString *)getRequest:(NSString *)aRequestPath;\n\n- (NSData *)getSHA1:(NSData *)aPlainText;\n\n- (void)generateSecKeys;\n\n- (NSString *)getExtensionsAsString:(NSArray *)aExtensions;\n\n- (BOOL)supportsAnotherSupportedVersion:(NSString *)aResponse;\n\n- (BOOL)isUpgradeResponse:(NSString *)aResponse;\n\n- (NSMutableArray *)getServerExtensions:(NSMutableArray *)aServerHeaders;\n\n- (BOOL)isValidServerExtension:(NSArray *)aServerExtensions;\n\n- (void)sendClose:(NSUInteger)aStatusCode message:(NSString *)aMessage;\n\n- (void)sendMessage:(NSData *)aMessage messageWithOpCode:(MessageOpCode)aOpCode;\n\n- (void)sendMessage:(WebSocketFragment *)aFragment;\n\n- (NSInteger)handleMessageData:(NSData *)aData offset:(NSUInteger)aOffset;\n\n- (void)handleCompleteFragment:(WebSocketFragment *)aFragment;\n\n- (void)handleCompleteFragments;\n\n- (void)handleClose:(WebSocketFragment *)aFragment;\n\n- (void)handlePing:(NSData *)aMessage;\n\n- (void)closeSocket;\n\n- (void)checkClose:(NSTimer *)aTimer;\n\n- (NSString *)buildStringFromHeaders:(NSMutableArray *)aHeaders resource:(NSString *)aResource;\n\n- (NSMutableArray *)buildHeadersFromString:(NSString *)aHeaders;\n\n- (HandshakeHeader *)headerForKey:(NSString *)aKey inHeaders:(NSMutableArray *)aHeaders;\n\n- (NSArray *)headersForKey:(NSString *)aKey inHeaders:(NSMutableArray *)aHeaders;\n@end\n\n\n@implementation WebSocket {\n    BOOL isInContinuation;\n}\n\nNSString *const WebSocketException = @\"WebSocketException\";\nNSString *const WebSocketErrorDomain = @\"WebSocketErrorDomain\";\n\nenum {\n    TagHandshake = 0,\n    TagMessage = 1\n};\n\nWebSocketWaitingState waitingState;\n\n@synthesize config;\n@synthesize delegate;\n@synthesize readystate;\n\n\n#pragma mark Public Interface\n- (void)open {\n    UInt16 port = self.config.isSecure ? 443 : 80;\n    if (self.config.url.port) {\n        port = [self.config.url.port intValue];\n    }\n    NSError *error = nil;\n    BOOL successful = false;\n    @try {\n        nw_endpoint_t endpoint = nw_endpoint_create_host(self.config.url.host.UTF8String, [NSNumber numberWithInt:port].stringValue.UTF8String);\n        nw_parameters_configure_protocol_block_t configure_tls = NW_PARAMETERS_DISABLE_PROTOCOL;\n        if (self.config.isSecure) {\n            configure_tls = ^(nw_protocol_options_t tls_options) {\n                sec_protocol_options_t options = nw_tls_copy_sec_protocol_options(tls_options);\n                sec_protocol_options_set_tls_server_name(options, self.config.host.UTF8String);                \n                sec_protocol_options_set_verify_block(options, ^(sec_protocol_metadata_t metadata, sec_trust_t trust_ref, sec_protocol_verify_complete_t complete) {\n                    SecTrustRef trust = sec_trust_copy_ref(trust_ref);\n                    TSKTrustDecision trustDecision = [TSKPinningValidator evaluateTrust:trust forHostname:self.config.host];\n                    complete(trustDecision != TSKTrustDecisionShouldBlockConnection);\n                }, dispatch_get_main_queue());\n            };\n        }\n        nw_parameters_t parameters = nw_parameters_create_secure_tcp(configure_tls, ^(nw_protocol_options_t tcp_options) {\n            nw_tcp_options_set_connection_timeout(tcp_options, self.config.timeout);\n        });\n        connection = nw_connection_create(endpoint, parameters);\n        if (connection != NULL) {\n            nw_connection_set_queue(connection, networkQueue);\n            \n            nw_connection_set_state_changed_handler(connection, ^(nw_connection_state_t state, nw_error_t error) {\n                if (state == nw_connection_state_waiting || state == nw_connection_state_failed) {\n                    [self socketDidDisconnectWithError:(__bridge NSError *)nw_error_copy_cf_error(error)];\n                } else if (state == nw_connection_state_ready) {\n                    [self socketDidConnectToHost:self.config.url.host port:port];\n                } else if (state == nw_connection_state_cancelled) {\n                    [self socketDidDisconnectWithError:NULL];\n                }\n            });\n            \n            nw_connection_start(connection);\n            successful = YES;\n        }\n        if (self.config.version == WebSocketVersion07) {\n            closeStatusCode = WebSocketCloseStatusNormal;\n        }\n        else {\n            closeStatusCode = 0;\n        }\n        closeMessage = nil;\n    }\n    @catch (NSException *exception) {\n        error = [NSError errorWithDomain:WebSocketErrorDomain code:0 userInfo:exception.userInfo];\n    }\n    @finally {\n        if (!successful) {\n            [self dispatchClosed:WebSocketCloseStatusProtocolError message:nil error:error];\n        }\n    }\n}\n\n- (void)close {\n    [self close:WebSocketCloseStatusNormal message:nil];\n}\n\n- (void)close:(NSUInteger)aStatusCode message:(NSString *)aMessage {\n    readystate = WebSocketReadyStateClosing;\n    //any rev before 10 does not perform a UTF8 check\n    if (self.config.version < WebSocketVersion10) {\n        [self sendClose:aStatusCode message:aMessage];\n    }\n    else {\n        if (aMessage && [aMessage canBeConvertedToEncoding:NSUTF8StringEncoding]) {\n            [self sendClose:aStatusCode message:aMessage];\n        }\n        else {\n            [self sendClose:aStatusCode message:nil];\n        }\n    }\n    isClosing = YES;\n}\n\n- (void)scheduleForceCloseCheck {\n    [NSTimer scheduledTimerWithTimeInterval:self.config.closeTimeout\n                                     target:self\n                                   selector:@selector(checkClose:)\n                                   userInfo:nil repeats:NO];\n}\n\n- (void)checkClose:(NSTimer *)aTimer {\n    if (self.readystate == WebSocketReadyStateClosing) {\n        [self closeSocket];\n    }\n}\n\n- (void)sendClose:(NSUInteger)aStatusCode message:(NSString *)aMessage {\n    //create payload\n    NSMutableData *payload = nil;\n    if (aStatusCode > 0) {\n        closeStatusCode = aStatusCode;\n        payload = [NSMutableData data];\n        unsigned char current = (unsigned char) (aStatusCode / 0x100);\n        [payload appendBytes:&current length:1];\n        current = (unsigned char) (aStatusCode % 0x100);\n        [payload appendBytes:&current length:1];\n        if (aMessage) {\n            closeMessage = [aMessage copy];\n            [payload appendData:[aMessage dataUsingEncoding:NSUTF8StringEncoding]];\n        }\n    }\n\n    //send close message\n    [self sendMessage:[WebSocketFragment fragmentWithOpCode:MessageOpCodeClose isFinal:YES payload:payload]];\n\n    //schedule the force close\n    if (self.config.closeTimeout >= 0) {\n        [self scheduleForceCloseCheck];\n    }\n}\n\n- (void)sendText:(NSString *)aMessage {\n    //no reason to grab data if we won't send it anyways\n    if (!isClosing) {\n        //only send non-nil data\n        if (aMessage) {\n            if ([aMessage canBeConvertedToEncoding:NSUTF8StringEncoding]) {\n                [self sendMessage:[aMessage dataUsingEncoding:NSUTF8StringEncoding] messageWithOpCode:MessageOpCodeText];\n            }\n            else if (self.config.version >= WebSocketVersion10) {\n                [self close:WebSocketCloseStatusInvalidData message:nil];\n            }\n        }\n    }\n}\n\n- (void)sendBinary:(NSData *)aMessage {\n    [self sendMessage:aMessage messageWithOpCode:MessageOpCodeBinary];\n}\n\n- (void)sendPing:(NSData *)aMessage {\n    [self sendMessage:aMessage messageWithOpCode:MessageOpCodePing];\n}\n\n- (void)sendMessage:(NSData *)aMessage messageWithOpCode:(MessageOpCode)aOpCode {\n    if (!isClosing) {\n        BOOL isRSV1 = _deflate;\n        if(_deflate) {\n            NSData *deflated = [self deflate:aMessage];\n            if(deflated) {\n                aMessage = deflated;\n            } else {\n                isRSV1 = NO;\n                NSLog(@\"An error occured while compressing fragment, sending uncompressed\");\n            }\n        }\n        NSUInteger messageLength = [aMessage length];\n        if (messageLength <= self.config.maxPayloadSize) {\n            //create and send fragment\n            WebSocketFragment *fragment = [WebSocketFragment fragmentWithOpCode:aOpCode isFinal:YES payload:aMessage];\n            if(_deflate)\n                fragment.isRSV1 = isRSV1;\n            [fragment buildFragment];\n            [self sendMessage:fragment];\n        }\n        else {\n            NSMutableArray *fragments = [NSMutableArray array];\n            NSUInteger fragmentCount = messageLength / self.config.maxPayloadSize;\n            if (messageLength % self.config.maxPayloadSize) {\n                fragmentCount++;\n            }\n\n            //build fragments\n            for (int i = 0; i < fragmentCount; i++) {\n                WebSocketFragment *fragment;\n                NSUInteger fragmentLength = self.config.maxPayloadSize;\n                if (i == 0) {\n                    fragment = [WebSocketFragment fragmentWithOpCode:aOpCode isFinal:NO payload:[aMessage subdataWithRange:NSMakeRange(i * self.config.maxPayloadSize, fragmentLength)]];\n                }\n                else if (i == fragmentCount - 1) {\n                    fragmentLength = messageLength % self.config.maxPayloadSize;\n                    if (fragmentLength == 0) {\n                        fragmentLength = self.config.maxPayloadSize;\n                    }\n                    fragment = [WebSocketFragment fragmentWithOpCode:MessageOpCodeContinuation isFinal:YES payload:[aMessage subdataWithRange:NSMakeRange(i * self.config.maxPayloadSize, fragmentLength)]];\n                }\n                else {\n                    fragment = [WebSocketFragment fragmentWithOpCode:MessageOpCodeContinuation isFinal:NO payload:[aMessage subdataWithRange:NSMakeRange(i * self.config.maxPayloadSize, fragmentLength)]];\n                }\n                if(_deflate)\n                    fragment.isRSV1 = YES;\n                [fragments addObject:fragment];\n            }\n\n            //send fragments\n            for (WebSocketFragment *fragment in fragments) {\n                [self sendMessage:fragment];\n            }\n        }\n    }\n}\n\n- (void)sendMessage:(WebSocketFragment *)aFragment {\n    if (!isClosing || aFragment.opCode == MessageOpCodeClose) {\n        [self writeData:aFragment.fragment withTag:TagMessage];\n    }\n}\n\n\n#pragma mark Internal Web Socket Logic\n- (void)continueReadingMessageStream {\n    dispatch_block_t schedule_next_receive = ^{\n        [self readDataWithTag:TagMessage];\n    };\n    schedule_next_receive();\n}\n\n- (void)repeatPing {\n    if (readystate == WebSocketReadyStateOpen) {\n        [self sendPing:nil];\n    }\n}\n\n- (void)startPingTimer {\n    if (self.config.keepAlive) {\n        pingTimer = [NSTimer scheduledTimerWithTimeInterval:self.config.keepAlive target:self selector:@selector(repeatPing) userInfo:nil repeats:YES];\n    }\n}\n\n- (void)stopPingTimer {\n    if (pingTimer) {\n        [pingTimer invalidate];\n    }\n}\n\n- (void)closeSocket {\n    readystate = WebSocketReadyStateClosing;\n    nw_connection_send(connection, NULL, NW_CONNECTION_FINAL_MESSAGE_CONTEXT, true, ^(nw_error_t  _Nullable error) {\n        if (error != NULL) {\n            [self socketDidDisconnectWithError:(__bridge NSError *)nw_error_copy_cf_error(error)];\n        }\n    });\n}\n\n- (void)handleCompleteFragment:(WebSocketFragment *)aFragment {\n    //if we are not in continuation and its final, dequeue\n    if (aFragment.isFinal && aFragment.opCode != MessageOpCodeContinuation) {\n        [pendingFragments removeLastObject];\n    }\n\n    //continue to process\n    switch (aFragment.opCode) {\n        case MessageOpCodeContinuation:\n            if (aFragment.isFinal) {\n                [self handleCompleteFragments];\n            }\n            break;\n        case MessageOpCodeText:\n            /*if (aFragment.isFinal) {\n                if (aFragment.payloadData.length) {\n                    NSString *textMsg = [[NSString alloc] initWithData:aFragment.payloadData encoding:NSUTF8StringEncoding];\n                    if (textMsg) {\n                        [self dispatchTextMessageReceived:textMsg];\n                    }\n                    else if (self.config.version >= WebSocketVersion10) {\n                        [self close:WebSocketCloseStatusInvalidData message:nil];\n                    }\n                }\n                else {\n                    [self dispatchTextMessageReceived:@\"\"];\n                }\n            }\n            break;*/\n        case MessageOpCodeBinary:\n            if (aFragment.isFinal) {\n                if(&deflate && aFragment.isRSV1)\n                    [self dispatchBinaryMessageReceived:[self inflate:aFragment.payloadData]];\n                else\n                    [self dispatchBinaryMessageReceived:aFragment.payloadData];\n            }\n            break;\n        case MessageOpCodeClose:\n            [self handleClose:aFragment];\n            break;\n        case MessageOpCodePing:\n            if (aFragment.payloadLength > 125) {\n                [self close:WebSocketCloseStatusProtocolError message:@\"Pings cannot have payloads longer than 125 octets.\"];\n            } else {\n                [self handlePing:aFragment.payloadData];\n            }\n            break;\n    }\n}\n\n//Based on http://stackoverflow.com/a/11389847\n- (NSData *)inflate:(NSData*)d\n{\n    @synchronized(zlibLock) {\n        if([d length] == 0)\n            return d;\n\n        //Append 0x00 0x00 0xFF 0xFF\n        unsigned char tail[4] = {0,0,255,255};\n        NSMutableData *data = [d mutableCopy];\n        [data appendBytes:tail length:4];\n        \n        NSUInteger full_length = [data length];\n        NSUInteger half_length = [data length] / 2;\n        \n        NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];\n        BOOL done = NO;\n        int status;\n        \n        zstrm_in.next_in = (Bytef *)[data bytes];\n        zstrm_in.avail_in = (unsigned int)[data length];\n        zstrm_in.total_out = 0;\n        \n        while (!done) {\n            // Make sure we have enough room and reset the lengths.\n            if (zstrm_in.total_out >= [decompressed length])\n                [decompressed increaseLengthBy: half_length];\n            zstrm_in.next_out = [decompressed mutableBytes] + zstrm_in.total_out;\n            zstrm_in.avail_out = (unsigned int)([decompressed length] - zstrm_in.total_out);\n            \n            // Inflate another chunk.\n            status = inflate(&zstrm_in, Z_FULL_FLUSH);\n            if(zstrm_in.avail_in == 0)\n                done = YES;\n            else if (status != Z_OK && status != Z_BUF_ERROR)\n                break;\n        }\n        \n        // Set real length.\n        if (done) {\n            [decompressed setLength: zstrm_in.total_out];\n            return [NSData dataWithData: decompressed];\n        } else\n            return nil;\n    }\n}\n\n- (NSData *)deflate:(NSData*)data\n{\n    @synchronized(zlibLock) {\n        if ([data length] == 0)\n            return nil;\n        \n        zstrm_out.next_in=(Bytef *)[data bytes];\n        zstrm_out.avail_in = (unsigned int)[data length];\n        zstrm_out.total_out = 0;\n        \n        NSMutableData *compressed = [NSMutableData dataWithLength:16384];  // 16K chunks for expansion\n        \n        do {\n            if (zstrm_out.total_out >= [compressed length])\n                [compressed increaseLengthBy: 16384];\n            \n            zstrm_out.next_out = [compressed mutableBytes] + zstrm_out.total_out;\n            zstrm_out.avail_out = (unsigned int)([compressed length] - zstrm_out.total_out);\n            \n            deflate(&zstrm_out, Z_FULL_FLUSH);\n            \n        } while (zstrm_out.avail_out == 0);\n        \n        //Chop off the 0x00 0x00 0xFF 0xFF from the tail\n        if(zstrm_out.total_out)\n            [compressed setLength: zstrm_out.total_out - 4];\n        else\n            return nil;\n        return [NSData dataWithData:compressed];\n    }\n}\n\n- (void)handleCompleteFragments {\n    WebSocketFragment *fragment = [pendingFragments dequeue];\n    if (fragment != nil) {\n        //init\n        NSMutableData *messageData = [NSMutableData data];\n        MessageOpCode messageOpCode = fragment.opCode;\n\n        //loop through, constructing single message\n        while (fragment != nil) {\n            if (fragment.payloadLength > 0) {\n                if(&deflate && fragment.isRSV1)\n                    [messageData appendData:[self inflate:fragment.payloadData]];\n                else\n                    [messageData appendData:fragment.payloadData];\n            }\n            fragment = [pendingFragments dequeue];\n        }\n\n        //handle final message contents        \n        switch (messageOpCode) {\n            case MessageOpCodeText: {\n                if (messageData.length) {\n                    NSString *textMsg = [[NSString alloc] initWithData:messageData encoding:NSUTF8StringEncoding];\n                    if (textMsg) {\n                        [self dispatchTextMessageReceived:textMsg];\n                    }\n                    else if (self.config.version >= WebSocketVersion10) {\n                        [self close:WebSocketCloseStatusInvalidData message:nil];\n                    }\n                } else {\n                    [self dispatchTextMessageReceived:@\"\"];\n                }\n                break;\n            }\n            case MessageOpCodeBinary:\n                [self dispatchBinaryMessageReceived:messageData];\n                break;\n        }\n    }\n}\n\n- (void)handleClose:(WebSocketFragment *)aFragment {\n    NSData *payloadData = aFragment.payloadData;\n    if(&deflate && aFragment.isRSV1)\n        payloadData = [self inflate:aFragment.payloadData];\n    \n    //close status & message\n    BOOL invalidUTF8 = NO;\n    if (payloadData) {\n        NSUInteger length = payloadData.length;\n        if (length >= 2) {\n            //get status code\n            unsigned char buffer[2];\n            [payloadData getBytes:&buffer length:2];\n            closeStatusCode = buffer[0] << 8 | buffer[1];\n\n            //get message\n            if (length > 2) {\n                closeMessage = [[NSString alloc] initWithData:[payloadData subdataWithRange:NSMakeRange(2, length - 2)] encoding:NSUTF8StringEncoding];\n                if (!closeMessage) {\n                    invalidUTF8 = YES;\n                }\n            }\n        }\n    }\n\n    //handle close\n    if (isClosing) {\n        [self closeSocket];\n    }\n    else {\n        isClosing = YES;\n        if (!invalidUTF8 || self.config.version < WebSocketVersion10) {\n            [self close:0 message:nil];\n        }\n        else {\n            [self close:WebSocketCloseStatusInvalidData message:nil];\n        }\n    }\n}\n\n- (void)handlePing:(NSData *)aMessage {\n    [self sendMessage:aMessage messageWithOpCode:MessageOpCodePong];\n    if ([delegate respondsToSelector:@selector(didSendPong:)]) {\n        [delegate didSendPong:aMessage];\n    }\n}\n\n// TODO: use a temporary buffer for the fragment payload instead of a queue of fragments\n- (NSInteger)handleMessageData:(NSData *)aData offset:(NSUInteger)aOffset {\n    //init\n    NSUInteger lengthOfRemainder = 0;\n    NSUInteger existingLength = 0;\n    NSInteger offset = -1;\n\n    //grab last fragment, use if not complete\n    WebSocketFragment *fragment = [pendingFragments lastObject];\n    if (!fragment || fragment.isValid) {\n        //assign web socket fragment since the last one was complete\n        fragment = [[WebSocketFragment alloc] init];\n        [pendingFragments enqueue:fragment];\n    }\n    else {\n        //grab existing length\n        existingLength = fragment.fragment.length;\n    }\n    NSAssert(fragment != nil, @\"Websocket fragment should never be nil\");\n\n    //if we dont know the length - try to figure it out\n    if (!fragment.isHeaderValid) {\n        [fragment parseHeader];\n\n        //if we still don't have a length, see if we have enough\n        if (!fragment.isHeaderValid) {\n            if (![fragment parseHeader:aData from:aOffset]) {\n                //if we still don't have a valid length, append all data and return\n                if (fragment.fragment) {\n                    [fragment.fragment appendData:[aData subdataWithRange:NSMakeRange(aOffset, aData.length - aOffset)]];\n                } else {\n                    fragment.fragment = [NSMutableData dataWithData:[aData subdataWithRange:NSMakeRange(aOffset, aData.length - aOffset)]];\n                }\n                return offset;\n            }\n        }\n    }\n\n    //validate reserved bits\n    if (!self.config.activeExtensionModifiesReservedBits) {\n        if (!&deflate || fragment.isRSV2 || fragment.isRSV3) {\n            [self close:WebSocketCloseStatusProtocolError message:[NSString stringWithFormat:@\"No extension is defined that modifies reserved bits: RSV1=%@, RSV2=%@, RSV3=%@\", fragment.isRSV1 ? @\"YES\" : @\"NO\", fragment.isRSV2 ? @\"YES\" : @\"NO\", fragment.isRSV3 ? @\"YES\" : @\"NO\"]];\n        }\n    }\n\n    //make sure we have a valid op code\n    if (fragment.opCode != MessageOpCodeContinuation && fragment.opCode != MessageOpCodeText && fragment.opCode != MessageOpCodeBinary && fragment.opCode != MessageOpCodeClose && fragment.opCode != MessageOpCodePing && fragment.opCode != MessageOpCodePong) {\n        [self close:WebSocketCloseStatusProtocolError message:@\"Illegal Opcode\"];\n    }\n\n    //disallow fragmented control op codes\n    if (fragment.opCode == MessageOpCodePing || fragment.opCode == MessageOpCodePong) {\n        if (!fragment.isFinal) {\n            [self close:WebSocketCloseStatusProtocolError message:@\"Control frames cannot be fragmented\"];\n        }\n    }\n\n    //validate continuation state\n    if (fragment.isFinal) {\n        if (fragment.opCode == MessageOpCodeContinuation && !isInContinuation) {\n            [self close:WebSocketCloseStatusProtocolError message:[NSString stringWithFormat:@\"Cannot send the final fragment without a fragmented stream: isFinal=%@, opCode=%li\", fragment.isFinal ? @\"YES\" : @\"NO\", (long)fragment.opCode]];\n        } else if (isInContinuation && !fragment.isControlFrame && fragment.opCode != MessageOpCodeContinuation) {\n            [self close:WebSocketCloseStatusProtocolError message:[NSString stringWithFormat:@\"Cannot embed complete messages in a fragmented stream: isFinal=%@, opCode=%li\", fragment.isFinal ? @\"YES\" : @\"NO\", (long)fragment.opCode]];\n        }\n    } else if (isInContinuation && fragment.opCode != MessageOpCodeContinuation) {\n        [self close:WebSocketCloseStatusProtocolError message:[NSString stringWithFormat:@\"Cannot embed non-control, non-continuation frames in a fragmented stream: isFinal=%@, opCode=%li\", fragment.isFinal ? @\"YES\" : @\"NO\", (long)fragment.opCode]];\n    } else if (!isInContinuation && fragment.opCode != MessageOpCodeText && fragment.opCode != MessageOpCodeBinary) {\n        [self close:WebSocketCloseStatusProtocolError message:@\"Illegal continuation start frame\"];\n    }\n\n    //determine data length\n    NSUInteger possibleDataLength = aData.length - aOffset;\n    NSUInteger actualDataLength = possibleDataLength;\n    if ((possibleDataLength + existingLength > fragment.messageLength)) {\n        lengthOfRemainder = possibleDataLength - (fragment.messageLength - existingLength);\n        actualDataLength = possibleDataLength - lengthOfRemainder;\n    }\n\n    unsigned char *actualData = malloc(actualDataLength);\n    [aData getBytes:actualData range:NSMakeRange(aOffset, actualDataLength)];\n    \n    if (fragment.fragment) {\n        [fragment.fragment appendBytes:actualData length:actualDataLength];\n    } else {\n        fragment.fragment = [NSMutableData dataWithBytes:actualData length:actualDataLength];\n    }\n    free(actualData);\n\n    //parse the data, if possible\n    if (fragment.canBeParsed) {\n        if (fragment.hasMask) {\n            //client is not allowed to receive data that is masked and must fail the connection\n            [self close:WebSocketCloseStatusProtocolError message:@\"Server cannot mask data.\"];\n            return offset;\n        }\n        [fragment parseContent];\n\n        //if we have a complete fragment, handle it\n        if (fragment.isValid && fragment.isFinal) {\n            [self handleCompleteFragment:fragment];\n        }\n    }\n\n    //if we have extra data, handle it\n    if (fragment.messageLength > 0) {\n        //if we have an offset, trim the data and call back into\n        if (lengthOfRemainder > 0) {\n            offset = actualDataLength + aOffset;\n        }\n    }\n\n    //set continuation state, if we have a valid fragment\n    if (fragment.isValid) {\n        if (fragment.isFinal && fragment.opCode == MessageOpCodeContinuation && isInContinuation) {\n            isInContinuation = NO;\n        } else if (!fragment.isFinal && (fragment.opCode == MessageOpCodeText || fragment.opCode == MessageOpCodeBinary)) {\n            isInContinuation = YES;\n        }\n    }\n\n    return offset;\n}\n\n- (NSData *)getSHA1:(NSData *)aPlainText {\n    CC_SHA1_CTX ctx;\n    uint8_t *hashBytes;\n    NSData *hash;\n\n    // Malloc a buffer to hold hash.\n    hashBytes = malloc(CC_SHA1_DIGEST_LENGTH * sizeof(uint8_t));\n    memset((void *) hashBytes, 0x0, CC_SHA1_DIGEST_LENGTH);\n\n    // Initialize the context.\n    CC_SHA1_Init(&ctx);\n    // Perform the hash.\n    CC_SHA1_Update(&ctx, (void *) [aPlainText bytes], (CC_LONG)[aPlainText length]);\n    // Finalize the output.\n    CC_SHA1_Final(hashBytes, &ctx);\n\n    // Build up the SHA1 blob.\n    hash = [NSData dataWithBytes:(const void *) hashBytes length:(NSUInteger) CC_SHA1_DIGEST_LENGTH];\n\n    if (hashBytes) free(hashBytes);\n\n    return hash;\n}\n\n- (NSString *)getRequest:(NSString *)aRequestPath {\n    //create headers if they are missing\n    NSMutableArray *headers = self.config.headers;\n    if (headers == nil) {\n        headers = [NSMutableArray array];\n        self.config.headers = headers;\n    }\n\n    //handle security keys\n    [self generateSecKeys];\n    [headers addObject:[HandshakeHeader headerWithValue:wsSecKey forKey:@\"Sec-WebSocket-Key\"]];\n\n    //handle host\n    [headers addObject:[HandshakeHeader headerWithValue:self.config.host forKey:@\"Host\"]];\n\n    //handle origin\n    if (self.config.useOrigin) {\n        if (self.config.version < WebSocketVersionRFC6455) {\n            [headers addObject:[HandshakeHeader headerWithValue:self.config.origin forKey:@\"Sec-WebSocket-Origin\"]];\n        } else {\n            [headers addObject:[HandshakeHeader headerWithValue:self.config.origin forKey:@\"Origin\"]];\n        }\n    }\n\n    //handle version\n    if (self.config.version == WebSocketVersion10) {\n        [headers addObject:[HandshakeHeader headerWithValue:[NSString stringWithFormat:@\"%i\", 8] forKey:@\"Sec-WebSocket-Version\"]];\n    } else if (self.config.version == WebSocketVersionRFC6455) {\n        [headers addObject:[HandshakeHeader headerWithValue:[NSString stringWithFormat:@\"%i\", 13] forKey:@\"Sec-WebSocket-Version\"]];\n    } else {\n        [headers addObject:[HandshakeHeader headerWithValue:[NSString stringWithFormat:@\"%lu\", (unsigned long)self.config.version] forKey:@\"Sec-WebSocket-Version\"]];\n    }\n\n    //handle protocol\n    if (self.config.protocols && self.config.protocols.count > 0) {\n        //build protocol fragment\n        NSMutableString *protocolFragment = [NSMutableString string];\n        for (NSString *item in self.config.protocols) {\n            if ([protocolFragment length] > 0) {\n                [protocolFragment appendString:@\", \"];\n            }\n            [protocolFragment appendString:item];\n        }\n\n        //include protocols, if any\n        if ([protocolFragment length] > 0) {\n            [headers addObject:[HandshakeHeader headerWithValue:protocolFragment forKey:@\"Sec-WebSocket-Protocol\"]];\n        }\n    }\n\n    //handle extensions\n    if (self.config.extensions && self.config.extensions.count > 0) {\n        //build extensions fragment\n        NSString *extensionFragment = [self getExtensionsAsString:self.config.extensions];\n\n        //return request with extensions\n        if ([extensionFragment length] > 0) {\n            [headers addObject:[HandshakeHeader headerWithValue:extensionFragment forKey:@\"Sec-WebSocket-Extensions\"]];\n        }\n    }\n\n    return [self buildStringFromHeaders:headers resource:aRequestPath];\n}\n\n- (NSString *)getExtensionsAsString:(NSArray *)aExtensions {\n    NSMutableString *extensionFragment = [NSMutableString string];\n    for (id item in aExtensions) {\n        if ([item isKindOfClass:[NSString class]]) {\n            if ([extensionFragment length] > 0) {\n                [extensionFragment appendString:@\"; \"];\n            }\n            [extensionFragment appendString:(NSString *) item];\n        }\n        else if ([item isKindOfClass:[NSArray class]]) {\n            //build ordered list of extensions\n            NSArray *items = (NSArray *) item;\n            NSMutableString *itemFragment = [NSMutableString string];\n            for (NSString *childItem in items) {\n                if ([itemFragment length] > 0) {\n                    [itemFragment appendString:@\", \"];\n                }\n                [itemFragment appendString:childItem];\n            }\n\n            //add to list of extensions\n            if ([extensionFragment length] > 0) {\n                [extensionFragment appendString:@\"; \"];\n            }\n            [extensionFragment appendString:itemFragment];\n        }\n    }\n    return extensionFragment;\n}\n\n- (NSString *)buildStringFromHeaders:(NSMutableArray *)aHeaders resource:(NSString *)aResource {\n    //init\n    NSMutableString *result = [NSMutableString stringWithFormat:@\"GET %@ HTTP/1.1\\r\\nUpgrade: websocket\\r\\nConnection: Upgrade\\r\\n\", aResource];\n\n    //add headers\n    if (aHeaders) {\n        for (HandshakeHeader *header in aHeaders) {\n            if (header) {\n                [result appendFormat:@\"%@: %@\\r\\n\", header.key, header.value];\n            }\n        }\n    }\n\n    //add terminator\n    [result appendFormat:@\"\\r\\n\"];\n\n    return result;\n}\n\n- (NSMutableArray *)buildHeadersFromString:(NSString *)aHeaders {\n    NSMutableArray *results = [NSMutableArray array];\n    NSArray *listItems = [aHeaders componentsSeparatedByString:@\"\\r\\n\"];\n    for (NSString *item in listItems) {\n        NSRange range = [item rangeOfString:@\":\" options:NSLiteralSearch];\n        if (range.location != NSNotFound) {\n            NSString *key = [item substringWithRange:NSMakeRange(0, range.location)];\n            key = [key stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];\n            NSString *value = [item substringFromIndex:range.length + range.location];\n            value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];\n            [results addObject:[HandshakeHeader headerWithValue:value forKey:key]];\n        }\n    }\n    return results;\n}\n\n- (void)generateSecKeys {\n    NSString *initialString = [NSString stringWithFormat:@\"%f\", [NSDate timeIntervalSinceReferenceDate]];\n    NSData *data = [initialString dataUsingEncoding:NSUTF8StringEncoding];\n    NSString *key = [data base64EncodedString];\n    wsSecKey = [key copy];\n    key = [NSString stringWithFormat:@\"%@%@\", wsSecKey, @\"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\"];\n    data = [self getSHA1:[key dataUsingEncoding:NSUTF8StringEncoding]];\n    key = [data base64EncodedString];\n    wsSecKeyHandshake = [key copy];\n}\n\n- (HandshakeHeader *)headerForKey:(NSString *)aKey inHeaders:(NSMutableArray *)aHeaders {\n    for (HandshakeHeader *header in aHeaders) {\n        if (header) {\n            if ([header keyMatchesCaseInsensitiveString:aKey]) {\n                return header;\n            }\n        }\n    }\n\n    return nil;\n}\n\n- (NSArray *)headersForKey:(NSString *)aKey inHeaders:(NSMutableArray *)aHeaders {\n    NSMutableArray *results = [NSMutableArray array];\n\n    for (HandshakeHeader *header in aHeaders) {\n        if (header) {\n            if ([header keyMatchesCaseInsensitiveString:aKey]) {\n                [results addObject:header];\n            }\n        }\n    }\n\n    return results;\n}\n\n- (BOOL)supportsAnotherSupportedVersion:(NSString *)aResponse {\n    //a HTTP 400 response is the only valid one\n    if ([aResponse hasPrefix:@\"HTTP/1.1 400\"]) {\n        return [aResponse rangeOfString:@\"Sec-WebSocket-Version\"].location != NSNotFound;\n    }\n\n    return false;\n}\n\n- (BOOL)isUpgradeResponse:(NSString *)aResponse {\n    //a HTTP 101 response is the only valid one\n    if ([aResponse hasPrefix:@\"HTTP/1.1 101\"]) {\n        //build headers\n        self.config.serverHeaders = [self buildHeadersFromString:aResponse];\n\n        //check security key, if requested\n        if (self.config.verifySecurityKey) {\n            HandshakeHeader *header = [self headerForKey:@\"Sec-WebSocket-Accept\" inHeaders:self.config.serverHeaders];\n            if (![wsSecKeyHandshake isEqualToString:header.value]) {\n                return false;\n            }\n        }\n\n        //verify we have a \"Upgrade: websocket\" header\n        HandshakeHeader *header = [self headerForKey:@\"Upgrade\" inHeaders:self.config.serverHeaders];\n        if (header.value && [@\"websocket\" caseInsensitiveCompare:header.value] != NSOrderedSame) {\n            return false;\n        }\n\n        //verify we have a \"Connection: Upgrade\" header\n        header = [self headerForKey:@\"Connection\" inHeaders:self.config.serverHeaders];\n        if (header.value && [@\"Upgrade\" caseInsensitiveCompare:header.value] != NSOrderedSame) {\n            return false;\n        }\n\n        //verify that version specified matches the version we requested\n\n\n        return true;\n    }\n\n    return false;\n}\n\n- (void)sendHandshake {\n    //continue with handshake\n    NSString *requestPath = self.config.url.path;\n    if (requestPath == nil || requestPath.length == 0) {\n        requestPath = @\"/\";\n    }\n    if (self.config.url.query) {\n        requestPath = [requestPath stringByAppendingFormat:@\"?%@\", self.config.url.query];\n    }\n    NSString *getRequest = [self getRequest:requestPath];\n    [self writeData:[getRequest dataUsingEncoding:NSASCIIStringEncoding] withTag:TagHandshake];\n}\n\n- (NSMutableArray *)getServerVersions:(NSMutableArray *)aServerHeaders {\n    NSMutableArray *results = [NSMutableArray array];\n    NSMutableArray *tempResults = [NSMutableArray array];\n\n    //find all entries keyed by Sec-WebSocket-Version or Sec-WebSocket-Version-Server\n//    [tempResults addObjectsFromArray:[self headersForKey:@\"Sec-WebSocket-Version\" inHeaders:self.config.serverHeaders]];\n//    [tempResults addObjectsFromArray:[self headersForKey:@\"Sec-WebSocket-Version-Server\" inHeaders:self.config.serverHeaders]];\n    [tempResults addObjectsFromArray:[self headersForKey:@\"Sec-WebSocket-Version\" inHeaders:aServerHeaders]];\n    [tempResults addObjectsFromArray:[self headersForKey:@\"Sec-WebSocket-Version-Server\" inHeaders:aServerHeaders]];\n\n    //loop through values trimming and adding to versions\n    for (HandshakeHeader *header in tempResults) {\n        NSString *extensionValues = header.value;\n        NSArray *listItems = [extensionValues componentsSeparatedByString:@\",\"];\n        for (NSString *item in listItems) {\n            if (item) {\n                NSString *value = [item stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];\n                if (value && value.length) {\n                    [results addObject:value];\n                }\n            }\n        }\n    }\n\n    return results;\n}\n\n- (NSMutableArray *)getServerExtensions:(NSMutableArray *)aServerHeaders {\n    NSMutableArray *results = [NSMutableArray array];\n\n    //loop through values trimming and adding to extensions \n//    HandshakeHeader *header = [self headerForKey:@\"Sec-WebSocket-Extensions\" inHeaders:self.config.serverHeaders];\n    HandshakeHeader *header = [self headerForKey:@\"Sec-WebSocket-Extensions\" inHeaders:aServerHeaders];\n    if (header) {\n        NSString *extensionValues = header.value;\n        NSArray *listItems = [extensionValues componentsSeparatedByString:@\",\"];\n        for (NSString *item in listItems) {\n            if (item) {\n                NSString *value = [item stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];\n                if (value && value.length) {\n                    [results addObject:value];\n                }\n            }\n        }\n    }\n\n    return results;\n}\n\n- (BOOL)isValidServerExtension:(NSArray *)aServerExtensions {\n    if (self.config.extensions && self.config.extensions.count > 0) {\n        //if we only have one extension, see if its in our list of accepted extensions\n        if (aServerExtensions.count == 1) {\n            NSString *serverExtension = [aServerExtensions objectAtIndex:0];\n            for (id item in self.config.extensions) {\n                if ([item isKindOfClass:[NSString class]]) {\n                    if ([serverExtension isEqualToString:(NSString *) item]) {\n                        return YES;\n                    }\n                }\n            }\n        }\n\n        //if we have a list of extensions, see if this exact ordered list exists in our list of accepted extensions\n        for (id item in self.config.extensions) {\n            if ([item isKindOfClass:[NSArray class]]) {\n                if ([aServerExtensions isEqualToArray:(NSArray *) item]) {\n                    return YES;\n                }\n            }\n        }\n\n        return NO;\n    }\n\n    return (aServerExtensions == nil || aServerExtensions.count == 0);\n}\n\n\n#pragma mark Web Socket Delegate\n- (void)dispatchFailure:(NSError *)aError {\n    if (delegate) {\n        if (delegateQueue) {\n            dispatch_async(delegateQueue, ^{\n                [self->delegate webSocket:self didReceiveError:aError];\n            });\n\n        } else {\n            [delegate webSocket:self didReceiveError:aError];\n        }\n    }\n}\n\n- (void)dispatchClosed:(NSUInteger)aStatusCode message:(NSString *)aMessage error:(NSError *)aError {\n    [self stopPingTimer];\n    if (delegate) {\n        if (delegateQueue) {\n            dispatch_async(delegateQueue, ^{\n                [self->delegate webSocket:self didClose:aStatusCode message:aMessage error:aError];\n            });\n\n        } else {\n            [delegate webSocket:self didClose:aStatusCode message:aMessage error:aError];\n        }\n    }\n}\n\n- (void)dispatchOpened {\n    if (delegate) {\n        if (delegateQueue) {\n            dispatch_async(delegateQueue, ^{\n                [self->delegate webSocketDidOpen:self];\n            });\n        } else {\n            [delegate webSocketDidOpen:self];\n        }\n    }\n    [self startPingTimer];\n}\n\n- (void)dispatchTextMessageReceived:(NSString *)aMessage {\n    if (delegate) {\n        if (delegateQueue) {\n            dispatch_async(delegateQueue, ^{\n                [self->delegate webSocket:self didReceiveTextMessage:aMessage];\n            });\n        } else {\n            [self->delegate webSocket:self didReceiveTextMessage:aMessage];\n        }\n    }\n}\n\n- (void)dispatchBinaryMessageReceived:(NSData *)aMessage {\n    if (delegate) {\n        if (delegateQueue) {\n            dispatch_async(delegateQueue, ^{\n                [self->delegate webSocket:self didReceiveBinaryMessage:aMessage];\n            });\n        } else {\n            [self->delegate webSocket:self didReceiveBinaryMessage:aMessage];\n        }\n    }\n}\n\n\n#pragma mark Network callbacks\n- (void)readDataWithTag:(long)tag {\n    nw_connection_receive(self->connection, 0, 8192, ^(dispatch_data_t content, nw_content_context_t context, bool is_complete, nw_error_t receive_error) {\n        if(content != NULL) {\n            [self socketDidReadData:(NSData *)content withTag:tag];\n        }\n        if (is_complete && (context == NULL || nw_content_context_get_is_final(context))) {\n            [self socketDidDisconnectWithError:NULL];\n        }\n    });\n}\n\n- (void)writeData:(NSData *)data withTag:(long)tag {\n    dispatch_data_t d = dispatch_data_create(data.bytes, data.length, delegateQueue, DISPATCH_DATA_DESTRUCTOR_DEFAULT);\n    nw_connection_send(self->connection, d, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, ^(nw_error_t  _Nullable error) {\n        if(error != NULL) {\n            [self socketDidDisconnectWithError:(__bridge NSError *)nw_error_copy_cf_error(error)];\n        } else {\n            [self socketDidWriteDataWithTag:tag];\n        }\n    });\n}\n\n- (void)readNextHandshakeByte {\n    nw_connection_receive(self->connection, 0, 8192, ^(dispatch_data_t content, nw_content_context_t context, bool is_complete, nw_error_t receive_error) {\n        if(content != NULL) {\n            [self->handshakeBuffer appendData:(NSData *)content];\n            if(self->handshakeBuffer.length > 4) {\n                char b[4];\n                [self->handshakeBuffer getBytes:b range:NSMakeRange(self->handshakeBuffer.length - 4, 4)];\n                if(b[0] == '\\r' && b[1] == '\\n' && b[2] == '\\r' && b[3] == '\\n') {\n                    [self socketDidReadData:self->handshakeBuffer withTag:TagHandshake];\n                    return;\n                }\n            }\n            [self readNextHandshakeByte];\n        }\n        if (is_complete && (context == NULL || nw_content_context_get_is_final(context))) {\n            [self socketDidDisconnectWithError:NULL];\n        }\n    });\n}\n\n- (void)socketDidDisconnectWithError:(NSError*)aError {\n    if (readystate != WebSocketReadyStateClosing && readystate != WebSocketReadyStateClosed) {\n        closingError = aError;\n    } else {\n        closingError = nil;\n    }\n    readystate = WebSocketReadyStateClosed;\n    if (self.config.version > WebSocketVersion07) {\n        if (closeStatusCode == 0) {\n            if (closingError != nil) {\n                closeStatusCode = WebSocketCloseStatusAbnormalButMissingStatus;\n            }\n            else {\n                closeStatusCode = WebSocketCloseStatusNormalButMissingStatus;\n            }\n        }\n    }\n    //End the zlib session\n    inflateEnd(&zstrm_in);\n    deflateEnd(&zstrm_out);\n    zstrm_in.total_out = 0;\n    zstrm_out.total_out = 0;\n    \n    [self dispatchClosed:closeStatusCode message:closeMessage error:closingError];\n}\n\n- (void)socketDidConnectToHost:(NSString *)aHost port:(UInt16)aPort {\n    [self sendHandshake];\n}\n\n- (void)socketDidWriteDataWithTag:(long)aTag {\n    if (aTag == TagHandshake) {\n        self->handshakeBuffer = [[NSMutableData alloc] initWithCapacity:8192];\n        [self readNextHandshakeByte];\n    }\n}\n\n- (void)socketDidReadData:(NSData *)aData withTag:(long)aTag {\n    if (aTag == TagHandshake) {\n        NSString *response = [[NSString alloc] initWithData:aData encoding:NSASCIIStringEncoding];\n        if ([self isUpgradeResponse:response]) {\n            //grab protocol from server\n            HandshakeHeader *header = [self headerForKey:@\"Sec-WebSocket-Protocol\" inHeaders:self.config.serverHeaders];\n            if (!header) {\n                header = [self headerForKey:@\"Sec-WebSocket-Protocol-Server\" inHeaders:self.config.serverHeaders];\n            }\n            if (header) {\n                //if version is rfc6455 or later, null out value if it was not a requested protocol\n                if (self.config.version < WebSocketVersionRFC6455 || [self.config.protocols containsObject:header]) {\n                    self.config.serverProtocol = header.value;\n                }\n            }\n\n            //grab extensions from the server\n            _deflate = NO;\n            NSMutableArray *extensions = [self getServerExtensions:self.config.serverHeaders];\n            if (extensions) {\n                self.config.serverExtensions = extensions;\n                for(NSString *extension in extensions) {\n                    if([extension hasPrefix:@\"x-webkit-deflate-frame\"]) {\n                        if(zstrm_in.total_out > 0)\n                            inflateEnd(&zstrm_in);\n                        memset(&zstrm_in, 0, sizeof(zstrm_in));\n                        zstrm_in.zalloc = Z_NULL;\n                        zstrm_in.zfree = Z_NULL;\n                        inflateInit2(&zstrm_in,-15);\n                        if(zstrm_out.total_out > 0)\n                            deflateEnd(&zstrm_out);\n                        memset(&zstrm_out, 0, sizeof(zstrm_out));\n                        zstrm_out.zalloc = Z_NULL;\n                        zstrm_out.zfree = Z_NULL;\n                        deflateInit2(&zstrm_out, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);\n                        _deflate = YES;\n                    }\n                }\n            }\n\n            //handle state & delegates\n            readystate = WebSocketReadyStateOpen;\n            [self dispatchOpened];\n            [self continueReadingMessageStream];\n        }\n        else if ([self supportsAnotherSupportedVersion:response]) {\n            //use property to determine if we try a different version\n            BOOL retry = NO;\n            NSArray *versions = [self getServerVersions:self.config.serverHeaders];\n            if (self.config.retryOtherVersion) {\n                for (NSString *version in versions) {\n                    if (version && version.length) {\n                        switch ([version intValue]) {\n                            case WebSocketVersion07:\n                                self.config.version = WebSocketVersion07;\n                                retry = YES;\n                                break;\n                            case WebSocketVersion10:\n                                self.config.version = WebSocketVersion10;\n                                retry = YES;\n                                break;\n                        }\n                    }\n                }\n            }\n\n            //retry if able\n            if (retry) {\n                [self open];\n            }\n            else {\n                //send failure since we can't retry a supported version\n                [self dispatchFailure:[NSError errorWithDomain:WebSocketErrorDomain code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Unsupported Version\", NSLocalizedDescriptionKey, response, NSLocalizedFailureReasonErrorKey, nil]]];\n            }\n        }\n        else {\n            [self dispatchFailure:[NSError errorWithDomain:WebSocketErrorDomain code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Bad handshake\", NSLocalizedDescriptionKey, response, NSLocalizedFailureReasonErrorKey, nil]]];\n        }\n    }\n    else if (aTag == TagMessage) {\n        //handle data\n        NSInteger offset = 0;\n        do {\n            offset = [self handleMessageData:aData offset:offset];\n        } while (offset >= 0);\n\n        //keep reading\n        [self continueReadingMessageStream];\n    }\n}\n\n\n#pragma mark Lifecycle\n+ (id)webSocketWithConfig:(WebSocketConnectConfig *)aConfig delegate:(id <WebSocketDelegate>)aDelegate {\n    return [[[self class] alloc] initWithConfig:aConfig delegate:aDelegate];\n}\n\n+ (id)webSocketWithConfig:(WebSocketConnectConfig *)aConfig queue:(dispatch_queue_t)aDispatchQueue delegate:(id <WebSocketDelegate>)aDelegate {\n    return [[[self class] alloc] initWithConfig:aConfig queue:aDispatchQueue delegate:aDelegate];\n}\n\n- (id)initWithConfig:(WebSocketConnectConfig *)aConfig delegate:(id <WebSocketDelegate>)aDelegate {\n    CFUUIDRef uuidObj = CFUUIDCreate(nil);\n    NSString *uuidString = (NSString *) CFBridgingRelease(CFUUIDCreateString(nil, uuidObj));\n    CFRelease(uuidObj);\n    NSString *gcdDelegateQueueName = [NSString stringWithFormat:@\"com.unitt.ws.delegate:%@\", uuidString];\n    dispatch_queue_t gcdDelegateQueue = dispatch_queue_create([gcdDelegateQueueName cStringUsingEncoding:NSASCIIStringEncoding], 0);\n    id result = [self initWithConfig:aConfig queue:gcdDelegateQueue delegate:aDelegate];\n    return result;\n}\n\n- (id)initWithConfig:(WebSocketConnectConfig *)aConfig queue:(dispatch_queue_t)aDispatchQueue delegate:(id <WebSocketDelegate>)aDelegate {\n    self = [super init];\n    if (self) {\n        //apply properties\n        self.delegate = aDelegate;\n        self.config = aConfig;\n        delegateQueue = aDispatchQueue;\n        pendingFragments = [[MutableQueue alloc] init];\n        isClosing = NO;\n        isInContinuation = NO;\n        zlibLock = [[NSObject alloc] init];\n        networkQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);\n    }\n    return self;\n}\n\n@end\n"
  },
  {
    "path": "WebSocket/WebSocketConnectConfig.h",
    "content": "//\n//  WebSocketConnectConfig.h\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 9/26/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import <Foundation/Foundation.h>\n\n\nenum \n{\n    WebSocketVersion07 = 7,\n    WebSocketVersion08 = 8,\n    WebSocketVersion10 = 10,\n    WebSocketVersionRFC6455 = 6455\n};\ntypedef NSUInteger WebSocketVersion;\n\n\n@interface WebSocketConnectConfig : NSObject\n{\n@private\n    NSTimeInterval keepAlive;\n    NSURL* url;\n    NSString* origin;\n    NSString* host;\n    NSTimeInterval timeout;\n    NSMutableArray* protocols;\n    NSString* serverProtocol;\n    BOOL verifySecurityKey;\n    NSUInteger maxPayloadSize;\n    NSTimeInterval closeTimeout;\n    WebSocketVersion version;\n    BOOL isSecure;\n    NSMutableArray* headers;\n    NSMutableArray* serverHeaders;\n    NSMutableArray* extensions;\n    NSMutableArray* serverExtensions;\n    BOOL activeExtensionModifiesReservedBits;\n}\n\n/**\n * String name/value pairs to be provided in the websocket handshake as \n * http headers.\n **/\n@property(nonatomic,retain) NSMutableArray* headers;\n\n/**\n * String name/value pairs provided by the server in the websocket handshake \n * as http headers.\n **/\n@property(nonatomic,retain) NSMutableArray* serverHeaders;\n\n/**\n * Version of the websocket specification.\n **/\n@property(nonatomic,assign) WebSocketVersion version;\n\n/**\n * Max size of the payload. Any messages larger will be sent as fragments.\n **/\n@property(nonatomic,assign) NSUInteger maxPayloadSize;\n\n/**\n * Timeout used for sending messages, not establishing the socket connection. A\n * value of -1 will result in no timeouts being applied.\n **/\n@property(nonatomic,assign) NSTimeInterval timeout;\n\n/**\n * Timeout used for the closing handshake. If this timeout is exceeded, the socket\n * will be forced closed. A value of -1 will result in no timeouts being applied.\n **/\n@property(nonatomic,assign) NSTimeInterval closeTimeout;\n\n/**\n * URL of the websocket\n **/\n@property(nonatomic,retain) NSURL* url;\n\n/**\n * Indicates whether the websocket will be opened over a secure connection\n **/\n@property(nonatomic,assign) BOOL isSecure;\n\n/**\n * Indicates whether the websocket will try to reconnect using a different version if the specified\n * one is not supported.\n **/\n@property(nonatomic,assign) BOOL retryOtherVersion;\n\n/**\n * Origin is used more in a browser setting, but it is intended to prevent cross-site scripting. If\n * nil, the client will fill this in using the url provided by the websocket.\n **/\n@property(nonatomic,copy) NSString* origin;\n\n/**\n* Specifies whether to include the origin in the handshake request. Defaults to YES.\n*/\n@property(nonatomic,assign) BOOL useOrigin;\n\n/**\n * The host string is created from the url.\n **/\n@property(nonatomic,copy) NSString* host;\n\n/**\n * The list of extensions accepted by the host.\n **/\n@property(nonatomic,retain) NSMutableArray* serverExtensions;\n\n/**\n * The list of extensions supported by the client. An item can contain an ordered list of extensions as\n * an array of extensions. To add an ordered list of extensions, add an the array or call the addExtensions:\n * operation (unavailable in versions prior to the standard).\n **/\n@property(nonatomic,retain) NSMutableArray* extensions;\n\n/**\n * The subprotocols supported by the client. Each subprotocol is represented by an NSString.\n **/\n@property(nonatomic,retain) NSMutableArray* protocols;\n\n/**\n * True if the client should verify the handshake security key sent by the server. Since many of\n * the web socket servers may not have been updated to support this, set to false to ignore\n * and simply accept the connection to the server.\n **/\n@property(nonatomic,assign) BOOL verifySecurityKey; \n\n/**\n * The subprotocol selected by the server, nil if none was selected\n **/\n@property(nonatomic,copy) NSString* serverProtocol;\n\n/**\n* The time interval to send pings on. If zero, no automated pings will be sent. Default is zero.\n**/\n@property(nonatomic, assign) NSTimeInterval keepAlive;\n\n/**\n* Indicates whether an active extension should be allowed to modify the reserved bits. Default is false;\n*/\n@property(nonatomic, assign) BOOL activeExtensionModifiesReservedBits;\n\n\n+ (id) config;\n+ (id) configWithURLString:(NSString*) aUrlString origin:(NSString*) aOrigin protocols:(NSArray*) aProtocols headers:(NSArray*) aHeaders verifySecurityKey:(BOOL) aVerifySecurityKey extensions:(NSArray*) aExtensions;\n- (id) initWithURLString:(NSString *) aUrlString origin:(NSString*) aOrigin protocols:(NSArray*) aProtocols headers:(NSArray*) aHeaders verifySecurityKey:(BOOL) aVerifySecurityKey extensions:(NSArray*) aExtensions;\n\n/**\n* Add a supported extension.\n*/\n- (void) addExtension:(NSString*) aExtension;\n\n/**\n* Add an ordered set of supported extensions.\n*/\n- (void) addExtensions:(NSArray*) aExtensions;\n\n\n@end\n\nextern NSString *const WebSocketConnectConfigException;\nextern NSString *const WebSocketConnectConfigErrorDomain;\n\n"
  },
  {
    "path": "WebSocket/WebSocketConnectConfig.m",
    "content": "//\n//  WebSocketConnectConfig.m\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 9/26/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import \"WebSocketConnectConfig.h\"\n\n\n@interface WebSocketConnectConfig()\n\n- (NSString*) buildOrigin;\n- (NSString*) buildHost;\n\n@end\n\n\n@implementation WebSocketConnectConfig\n\n\n@synthesize version;\n@synthesize maxPayloadSize;\n@synthesize url;\n@synthesize origin;\n@synthesize useOrigin;\n@synthesize host;\n@synthesize timeout;\n@synthesize closeTimeout;\n@synthesize retryOtherVersion;\n@synthesize protocols;\n@synthesize verifySecurityKey;\n@synthesize serverProtocol;\n@synthesize isSecure;\n@synthesize serverHeaders;\n@synthesize headers;\n@synthesize extensions;\n@synthesize serverExtensions;\n@synthesize keepAlive;\n@synthesize activeExtensionModifiesReservedBits;\n\n\nNSString* const WebSocketConnectConfigException = @\"WebSocketConnectConfigException\";\nNSString* const WebSocketConnectConfigErrorDomain = @\"WebSocketConnectConfigErrorDomain\";\n\n#pragma mark Config Logic\n- (void) addExtension:(NSString *) aExtension\n{\n    [self.extensions addObject:aExtension];\n}\n\n- (void) addExtensions:(NSArray *)aExtensions\n{\n    [self.extensions addObject:aExtensions];\n}\n\n\n#pragma mark Lifecycle\n+ (id) config\n{\n    return [[[self class] alloc] init];\n}\n\n+ (id) configWithURLString:(NSString*) aUrlString origin:(NSString*) aOrigin protocols:(NSArray*) aProtocols headers:(NSArray*) aHeaders verifySecurityKey:(BOOL) aVerifySecurityKey extensions:(NSArray*) aExtensions\n{\n    return [[[self class] alloc] initWithURLString:aUrlString origin:aOrigin protocols:aProtocols headers:aHeaders verifySecurityKey:aVerifySecurityKey extensions:aExtensions];\n}\n\n- (id) initWithURLString:(NSString *) aUrlString origin:(NSString*) aOrigin protocols:(NSArray*) aProtocols headers:(NSArray*) aHeaders verifySecurityKey:(BOOL) aVerifySecurityKey extensions:(NSArray*) aExtensions\n{\n    self = [super init];\n    if (self) \n    {\n        //validate\n        NSURL* tempUrl = [NSURL URLWithString:aUrlString];\n        if (![tempUrl.scheme isEqualToString:@\"ws\"] && ![tempUrl.scheme isEqualToString:@\"wss\"]) \n        {\n            [NSException raise:WebSocketConnectConfigException format:@\"Unsupported protocol %@\",tempUrl.scheme];\n        }\n        \n        //apply properties\n        self.url = tempUrl;\n        self.isSecure = [self.url.scheme isEqualToString:@\"wss\"];\n        if (aOrigin)\n        {\n            self.origin = aOrigin;\n        }\n        else\n        {\n            self.origin = [self buildOrigin];\n        }\n        self.useOrigin = YES;\n        self.retryOtherVersion = YES;\n        self.host = [self buildHost];\n        if (aProtocols)\n        {\n            self.protocols = [NSMutableArray arrayWithArray:aProtocols];\n        }\n        if (aHeaders)\n        {\n            self.headers = [NSMutableArray arrayWithArray:aHeaders];\n        }\n        if (aExtensions)\n        {\n            self.extensions = [NSMutableArray arrayWithArray:aExtensions];\n        }\n        self.verifySecurityKey = aVerifySecurityKey;\n        self.timeout = 30.0;\n        self.closeTimeout = 30.0;\n        self.maxPayloadSize = 32*1024;\n        self.version = WebSocketVersionRFC6455;\n    }\n    return self;\n}\n\n- (NSString*) buildOrigin\n{\n    return [NSString stringWithFormat:@\"%@://%@%@\", isSecure ? @\"https\" : @\"http\", [self buildHost], (self.url.path && ![self.url.path isEqualToString:@\"/\"]) ? self.url.path : @\"\"];\n}\n\n- (NSString*) buildHost\n{\n    if (self.url.port)\n    {\n        if ([self.url.port intValue] == 80 || [self.url.port intValue] == 443)\n        {\n            return self.url.host;\n        }\n        \n        return [NSString stringWithFormat:@\"%@:%i\", self.url.host, [self.url.port intValue]];\n    }\n    \n    return self.url.host;\n}\n\n@end\n"
  },
  {
    "path": "WebSocket/WebSocketFragment.h",
    "content": "//\n//  WebSocketFragment.h\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 6/12/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import <Foundation/Foundation.h>\n\n\nenum \n{\n    MessageOpCodeIllegal = -1,\n    MessageOpCodeContinuation = 0x0,\n    MessageOpCodeText = 0x1,\n    MessageOpCodeBinary = 0x2,\n    MessageOpCodeClose = 0x8,\n    MessageOpCodePing = 0x9,\n    MessageOpCodePong = 0xA\n};\ntypedef NSInteger MessageOpCode;\n\nenum \n{\n    PayloadTypeUnknown = 0,\n    PayloadTypeText = 1,\n    PayloadTypeBinary = 2\n};\ntypedef NSInteger PayloadType;\n\nenum \n{\n    PayloadLengthIllegal = -1,\n    PayloadLengthMinimum = 0,\n    PayloadLengthShort = 1,\n    PayloadLengthLong = 2\n};\ntypedef NSInteger PayloadLength;\n\n\n@interface WebSocketFragment : NSObject \n{\n    BOOL isFinal;\n    int mask;\n    NSUInteger payloadStart;\n    NSUInteger payloadLength;\n    BOOL isRSV1;\n    BOOL isRSV2;\n    BOOL isRSV3;\n    PayloadType payloadType;\n    NSData* payloadData;\n    MessageOpCode opCode;\n    NSMutableData* fragment;\n}\n\n@property (nonatomic,assign) BOOL isFinal;\n@property (nonatomic,readonly) BOOL hasMask;\n@property (nonatomic,readonly) BOOL isControlFrame;\n@property (nonatomic,readonly) BOOL isDataFrame;\n@property (nonatomic,readonly) BOOL isValid;\n@property (nonatomic,readonly) BOOL canBeParsed;\n@property (nonatomic,readonly) BOOL isHeaderValid;\n@property (nonatomic,assign) BOOL isRSV1;\n@property (nonatomic,assign) BOOL isRSV2;\n@property (nonatomic,assign) BOOL isRSV3;\n@property (nonatomic,assign) int mask;\n@property (nonatomic,assign) MessageOpCode opCode;\n@property (nonatomic,retain) NSData* payloadData;\n@property (nonatomic,assign) PayloadType payloadType;\n@property (nonatomic,retain) NSMutableData* fragment;\n@property (nonatomic,readonly) NSUInteger messageLength;\n@property (nonatomic,readonly) NSUInteger payloadLength;\n@property (nonatomic,readonly) NSUInteger payloadStart;\n\n@property (nonatomic,readonly) BOOL isDataValid;\n\n- (int) generateMask;\n- (NSData*) mask:(int) aMask data:(NSData*) aData;\n- (NSData*) mask:(int) aMask data:(NSData*) aData range:(NSRange) aRange;\n- (void) maskInPlace:(int) aMask data:(NSMutableData*) aData range:(NSRange) aRange;\n- (NSData*) unmask:(int) aMask data:(NSData*) aData;\n- (NSData*) unmask:(int) aMask data:(NSData*) aData range:(NSRange) aRange;\n- (void) unmaskInPlace:(int) aMask data:(NSMutableData*) aData range:(NSRange) aRange;\n\n- (void) parseHeader;\n- (BOOL) parseHeader:(NSData*) aData from:(NSUInteger) aOffset;\n- (void) parseContent;\n\n- (BOOL) parseContent:(NSData*) aData;\n\n- (void) buildFragment;\n\n+ (id) fragmentWithOpCode:(MessageOpCode) aOpCode isFinal:(BOOL) aIsFinal payload:(NSData*) aPayload;\n+ (id) fragmentWithData:(NSData*) aData;\n- (id) initWithOpCode:(MessageOpCode) aOpCode isFinal:(BOOL) aIsFinal payload:(NSData*) aPayload;\n- (id) initWithData:(NSData*) aData;\n\n@end\n"
  },
  {
    "path": "WebSocket/WebSocketFragment.m",
    "content": "//\n//  WebSocketFragment.m\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 6/12/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import \"WebSocketFragment.h\"\n\n@implementation WebSocketFragment {\n}\n\n\n@synthesize isFinal;\n@synthesize mask;\n@synthesize opCode;\n@synthesize payloadData;\n@synthesize payloadType;\n@synthesize fragment;\n@synthesize payloadLength;\n@synthesize payloadStart;\n@synthesize isRSV1;\n@synthesize isRSV2;\n@synthesize isRSV3;\n\n\n\n\n\n#pragma mark Properties\n- (BOOL) hasMask\n{\n    return self.mask != 0;\n}\n\n- (int) generateMask\n{\n    return arc4random();\n}\n\n- (BOOL) isControlFrame\n{\n    return self.opCode == MessageOpCodeClose || self.opCode == MessageOpCodePing || self.opCode == MessageOpCodePong;\n}\n\n- (BOOL) isDataFrame\n{\n    return self.opCode == MessageOpCodeContinuation || self.opCode == MessageOpCodeText || self.opCode == MessageOpCodeBinary;\n}\n\n- (BOOL) isValid\n{\n    if (self.messageLength > 0)\n    {\n        if (payloadData) {\n            return payloadData.length == payloadLength;\n        }\n        return payloadStart + payloadLength == [fragment length];\n    }\n    \n    return NO;\n}\n\n- (BOOL) canBeParsed\n{\n    if (self.messageLength > 0 && self.isHeaderValid)\n    {\n        return [fragment length] >= (payloadStart + payloadLength);\n    }\n\n    return NO;\n}\n\n- (BOOL) isHeaderValid\n{\n    return payloadStart > 0;\n}\n\n- (BOOL) isDataValid\n{\n    return self.payloadData && [self.payloadData length];\n}\n\n- (NSUInteger) messageLength\n{\n    if (payloadStart > 0)\n    {\n        return (NSUInteger) payloadStart + payloadLength;\n    }\n\n    return 0;\n}\n\n\n#pragma mark Parsing\n- (BOOL) parseContent:(NSData *) aData {\n    if ([aData length] >= payloadStart + payloadLength)\n    {\n        //set payload\n        if (self.hasMask)\n        {\n            self.payloadData = [self unmask:self.mask data:aData range:NSMakeRange(payloadStart, payloadLength)];\n        }\n        else\n        {\n            self.payloadData = [aData subdataWithRange:NSMakeRange(payloadStart, payloadLength)];\n        }\n\n        self.fragment = nil;\n        return YES;\n    }\n\n    return NO;\n}\n\n- (void) parseContent\n{\n    if (self.fragment) {\n        [self parseContent:self.fragment];\n    }\n}\n\n\n- (BOOL) parseHeader:(NSData *) aData from:(NSUInteger) aOffset {\n    //get header data bits\n    NSUInteger bufferLength = 14;\n\n    NSData* data = aData;\n\n    //do we have an existing fragment to work with\n    if (self.fragment) {\n        if (self.fragment.length >= bufferLength) {\n            data = self.fragment;\n        } else if (aData) {\n            NSMutableData* both = [NSMutableData dataWithData:self.fragment];\n            //@todo: handle when data is 16 bytes - i.e. longer than buffer length\n            if (aData.length - aOffset >= bufferLength - both.length) {\n                [both appendData:[aData subdataWithRange:NSMakeRange(aOffset, bufferLength - both.length)]];\n            } else {\n                [both appendData:aData];\n            }\n            data = both;\n        }\n    }\n\n    if (data.length - aOffset < bufferLength)\n    {\n        bufferLength = data.length - aOffset;\n    }\n    if (!data || bufferLength <= 0) {\n        return NO;\n    }\n    unsigned char buffer[bufferLength];\n    [data getBytes:&buffer range:NSMakeRange(aOffset, bufferLength)];\n    \n    //determine opcode\n    if (bufferLength > 0) \n    {\n        int index = 0;\n        self.isFinal = buffer[index] & 0x80;\n        self.isRSV1 = buffer[index] & 0x40;\n        self.isRSV2 = buffer[index] & 0x20;\n        self.isRSV3 = buffer[index] & 0x10;\n        self.opCode = buffer[index++] & 0x0F;\n\n        //handle data depending on opcode\n        switch (self.opCode) \n        {\n            case MessageOpCodeText:\n                self.payloadType = PayloadTypeText;\n                break;\n            case MessageOpCodeBinary:\n                self.payloadType = PayloadTypeBinary;\n                break;\n        }\n        \n        //handle content, if any     \n        if (bufferLength > 1)\n        {\n            //do we have a mask\n            BOOL hasMask = buffer[index] & 0x80;\n            \n            //get payload length\n            NSUInteger dataLength = buffer[index++] & 0x7F;\n            if (dataLength == 126)\n            {\n                //exit if we are missing bytes\n                if (bufferLength < 4)\n                {\n                    return NO;\n                }\n                \n                uint16_t len;\n                memcpy(&len, &buffer[index], sizeof(len));\n                index += sizeof(len);\n                dataLength = CFSwapInt16(len);\n            }\n            else if (dataLength == 127)\n            {\n                //exit if we are missing bytes\n                if (bufferLength < 10)\n                {\n                    return NO;\n                }\n                \n                uint64_t len;\n                memcpy(&len, &buffer[index], sizeof(len));\n                index += sizeof(len);\n                dataLength = (NSUInteger)CFSwapInt64(len);\n            }\n            \n            //if applicable, set mask value\n            if (hasMask)\n            {              \n                //exit if we are missing bytes\n                if (bufferLength < index + 4)\n                {\n                    return NO;\n                }\n                \n                //grab mask\n                self.mask = buffer[index] << 24 | buffer[index+1] << 16 | buffer[index+2] << 8 | buffer[index+3];\n                index += 4;\n            }\n            \n            payloadStart = index;\n            payloadLength = dataLength;\n\n            return YES;\n        }\n    }\n\n    return NO;\n}\n\n- (void) parseHeader\n{\n    if (self.fragment) {\n        [self parseHeader:nil from:0];\n    }\n}\n\n- (void) buildFragment\n{\n    NSMutableData* temp = [NSMutableData data];\n    \n    //build fin & reserved\n    unsigned char byte = 0x0;\n    if (self.isFinal)\n    {\n        byte = 0x80;\n    }\n    \n    if(self.isRSV1)\n        byte = byte | 0x40;\n    \n    if(self.isRSV2)\n        byte = byte | 0x20;\n    \n    if(self.isRSV3)\n        byte = byte | 0x10;\n    \n    //build opmask\n    byte = byte | (self.opCode & 0xF);\n    \n    //push first byte\n    [temp appendBytes:&byte length:1];\n    \n    //use mask\n    byte = 0x80;\n    \n    //payload length\n    unsigned long long fullPayloadLength = self.payloadData.length;\n    if (fullPayloadLength <= 125)\n    {\n        byte |= (fullPayloadLength & 0xFF);\n        [temp appendBytes:&byte length:1];\n    }\n    else if (fullPayloadLength <= UINT16_MAX)\n    {\n        byte |= (126 & 0xFF);\n        [temp appendBytes:&byte length:1];\n        short shortLength = CFSwapInt16(fullPayloadLength & 0xFFFF);\n        [temp appendBytes:&shortLength length:2];\n    }\n    else if (fullPayloadLength <= UINT64_MAX)\n    {\n        byte |= (127 & 0xFF);\n        [temp appendBytes:&byte length:1];\n        unsigned long long longLength = CFSwapInt64(fullPayloadLength);\n        [temp appendBytes:&longLength length:8];\n    }\n    \n    //mask\n    unsigned char maskBytes[4];\n    maskBytes[0] = (int)((self.mask >> 24) & 0xFF) ;\n    maskBytes[1] = (int)((self.mask >> 16) & 0xFF) ;\n    maskBytes[2] = (int)((self.mask >> 8) & 0XFF);\n    maskBytes[3] = (int)((self.mask & 0XFF));\n    [temp appendBytes:maskBytes length:4];\n    \n    //payload data\n    payloadStart = [temp length];\n    payloadLength = (NSUInteger)fullPayloadLength;\n    [temp appendData:[self mask:self.mask data:self.payloadData]];\n    self.fragment = temp;\n}\n\n- (NSData*) mask:(int) aMask data:(NSData*) aData\n{\n    return [self mask:aMask data:aData range:NSMakeRange(0, [aData length])];\n}\n\n- (NSData*) mask:(int) aMask data:(NSData*) aData range:(NSRange) aRange\n{\n    NSMutableData* result = [NSMutableData data];\n    unsigned char maskBytes[4];\n    maskBytes[0] = (int)((aMask >> 24) & 0xFF) ;\n    maskBytes[1] = (int)((aMask >> 16) & 0xFF) ;\n    maskBytes[2] = (int)((aMask >> 8) & 0XFF);\n    maskBytes[3] = (int)((aMask & 0XFF));\n    unsigned char current;\n    NSUInteger index = aRange.location;\n    NSUInteger end = aRange.location + aRange.length;\n    if (end > [aData length])\n    {\n        end = [aData length];\n    }\n    int m = 0;\n    NSRange range = NSMakeRange(index, 1);\n    while (index < end)\n    {\n        //set current byte\n        range.location = index;\n        [aData getBytes:&current range:range];\n\n        //mask\n        current ^= maskBytes[m++ % 4];\n\n        //append result & continue\n        [result appendBytes:&current length:1];\n        index++;\n    }\n    return result;\n}\n\n- (void) unmaskInPlace:(int) aMask data:(NSMutableData*) aData range:(NSRange) aRange {\n    [self maskInPlace:aMask data:aData range:aRange];\n}\n\n- (void) maskInPlace:(int) aMask data:(NSMutableData*) aData range:(NSRange) aRange\n{\n    unsigned char maskBytes[4];\n    maskBytes[0] = (int)((aMask >> 24) & 0xFF) ;\n    maskBytes[1] = (int)((aMask >> 16) & 0xFF) ;\n    maskBytes[2] = (int)((aMask >> 8) & 0XFF);\n    maskBytes[3] = (int)((aMask & 0XFF));\n    unsigned char current;\n    NSUInteger index = aRange.location;\n    NSUInteger end = aRange.location + aRange.length;\n    if (end > [aData length])\n    {\n        end = [aData length];\n    }\n    int m = 0;\n    NSRange range = NSMakeRange(index, 1);\n    while (index < end) \n    {\n        //set current byte\n        range.location = index;\n        [aData getBytes:&current range:range];\n        \n        //mask\n        current ^= maskBytes[m++ % 4];\n        \n        //append result & continue\n        [aData replaceBytesInRange:range withBytes:&current];\n        index++;\n    }\n}\n\n- (NSData*) unmask:(int) aMask data:(NSData*) aData\n{\n    return [self unmask:aMask data:aData range:NSMakeRange(0, [aData length])];\n}\n\n- (NSData*) unmask:(int) aMask data:(NSData*) aData range:(NSRange) aRange\n{\n    return [self mask:aMask data:aData range:aRange];\n}\n\n\n#pragma mark Lifecycle\n+ (id) fragmentWithOpCode:(MessageOpCode) aOpCode isFinal:(BOOL) aIsFinal payload:(NSData*) aPayload \n{\n    return [[[self class] alloc] initWithOpCode:aOpCode isFinal:aIsFinal payload:aPayload];\n}\n\n+ (id) fragmentWithData:(NSData*) aData\n{\n    return [[[self class] alloc] initWithData:aData];\n}\n\n- (id) initWithOpCode:(MessageOpCode) aOpCode isFinal:(BOOL) aIsFinal payload:(NSData*) aPayload\n{\n    self = [super init];\n    if (self)\n    {\n        self.mask = [self generateMask];\n        self.opCode = aOpCode;\n        self.isFinal = aIsFinal;\n        self.payloadData = aPayload;\n        [self buildFragment];\n    }\n    return self;\n}\n\n- (id) initWithData:(NSData*) aData\n{\n    self = [super init];\n    if (self)\n    {\n        self.opCode = MessageOpCodeIllegal;\n        self.fragment = [NSMutableData dataWithData:aData];\n        if(aData)\n            [self parseHeader];\n        if (self.messageLength <= [aData length])\n        {\n            [self parseContent];\n        }\n    }\n    return self;\n}\n\n- (id) init\n{\n    self = [super init];\n    if (self)\n    {\n        self.opCode = MessageOpCodeIllegal;\n    }\n    return self;\n}\n\n@end\n"
  },
  {
    "path": "WebSocket/WebSocketMessage.h",
    "content": "//\n//  WebSocketMessage.h\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 6/12/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import <Foundation/Foundation.h>\n#import \"WebSocketFragment.h\"\n\n\n@interface WebSocketMessage : NSObject \n{\n@private\n    NSMutableArray* fragments;\n}\n\n- (void) pushFragment:(WebSocketFragment*) aFragment;\n- (NSData*) parse;\n- (void) clear;\n\n+ (id) messageWithFragment:(WebSocketFragment*) aFragment;\n- (id) initWithFragment:(WebSocketFragment*) aFragment;\n- (id) init;\n\n@end\n"
  },
  {
    "path": "WebSocket/WebSocketMessage.m",
    "content": "//\n//  WebSocketMessage.m\n//  UnittWebSocketClient\n//\n//  Created by Josh Morris on 6/12/11.\n//  Copyright 2011 UnitT Software. All rights reserved.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n//  use this file except in compliance with the License. You may obtain a copy of\n//  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, WITHOUT\n//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n//  License for the specific language governing permissions and limitations under\n//  the License.\n//\n\n#import \"WebSocketMessage.h\"\n\n\n@implementation WebSocketMessage\n\n- (void) pushFragment:(WebSocketFragment*) aFragment\n{\n    [fragments addObject:aFragment];\n}\n\n- (NSData*) parse\n{\n    //parse fragments\n    NSMutableData* data = [NSMutableData data];\n    for (WebSocketFragment* fragment in fragments) \n    {\n        [data appendData:fragment.payloadData];\n    }\n    return data;\n}\n\n- (void) clear\n{\n    [fragments removeAllObjects];\n}\n\n\n#pragma mark Lifecycle\n+ (id) messageWithFragment:(WebSocketFragment*) aFragment\n{\n    return [[[self class] alloc] initWithFragment:aFragment];\n}\n\n- (id) initWithFragment:(WebSocketFragment*) aFragment\n{\n    self = [super init];\n    if (self)\n    {\n        fragments = [[NSMutableArray alloc] init];\n        [self pushFragment:aFragment];\n    }\n    return self;\n}\n\n- (id) init\n{\n    self = [super init];\n    if (self)\n    {\n        fragments = [[NSMutableArray alloc] init];\n    }\n    return self;\n}\n\n@end\n"
  },
  {
    "path": "YYImage/YYAnimatedImageView.h",
    "content": "//\n//  YYAnimatedImageView.h\n//  YYImage <https://github.com/ibireme/YYImage>\n//\n//  Created by ibireme on 14/10/19.\n//  Copyright (c) 2015 ibireme.\n//\n//  This source code is licensed under the MIT-style license found in the\n//  LICENSE file in the root directory of this source tree.\n//\n\n#import <UIKit/UIKit.h>\n\nNS_ASSUME_NONNULL_BEGIN\n\n/**\n An image view for displaying animated image.\n \n @discussion It is a fully compatible `UIImageView` subclass.\n If the `image` or `highlightedImage` property adopt to the `YYAnimatedImage` protocol,\n then it can be used to play the multi-frame animation. The animation can also be \n controlled with the UIImageView methods `-startAnimating`, `-stopAnimating` and `-isAnimating`.\n \n This view request the frame data just in time. When the device has enough free memory, \n this view may cache some or all future frames in an inner buffer for lower CPU cost.\n Buffer size is dynamically adjusted based on the current state of the device memory.\n \n Sample Code:\n \n     // ani@3x.gif\n     YYImage *image = [YYImage imageNamed:@\"ani\"];\n     YYAnimatedImageView *imageView = [YYAnimatedImageView alloc] initWithImage:image];\n     [view addSubView:imageView];\n */\n@interface YYAnimatedImageView : UIImageView\n\n/**\n If the image has more than one frame, set this value to `YES` will automatically \n play/stop the animation when the view become visible/invisible.\n \n The default value is `YES`.\n */\n@property (nonatomic) BOOL autoPlayAnimatedImage;\n\n/**\n Index of the currently displayed frame (index from 0).\n \n Set a new value to this property will cause to display the new frame immediately.\n If the new value is invalid, this method has no effect.\n \n You can add an observer to this property to observe the playing status.\n */\n@property (nonatomic) NSUInteger currentAnimatedImageIndex;\n\n/**\n Whether the image view is playing animation currently.\n \n You can add an observer to this property to observe the playing status.\n */\n@property (nonatomic, readonly) BOOL currentIsPlayingAnimation;\n\n/**\n The animation timer's runloop mode, default is `NSRunLoopCommonModes`.\n \n Set this property to `NSDefaultRunLoopMode` will make the animation pause during\n UIScrollView scrolling.\n */\n@property (nonatomic, copy) NSString *runloopMode;\n\n/**\n The max size (in bytes) for inner frame buffer size, default is 0 (dynamically).\n \n When the device has enough free memory, this view will request and decode some or \n all future frame image into an inner buffer. If this property's value is 0, then \n the max buffer size will be dynamically adjusted based on the current state of \n the device free memory. Otherwise, the buffer size will be limited by this value.\n \n When receive memory warning or app enter background, the buffer will be released \n immediately, and may grow back at the right time.\n */\n@property (nonatomic) NSUInteger maxBufferSize;\n\n/**\n Adds a callback at the end of a loop\n */\n@property (nonatomic, copy) void(^loopCompletionBlock)(NSUInteger loopCountRemaining);\n\n@end\n\n\n\n/**\n The YYAnimatedImage protocol declares the required methods for animated image\n display with YYAnimatedImageView.\n \n Subclass a UIImage and implement this protocol, so that instances of that class \n can be set to YYAnimatedImageView.image or YYAnimatedImageView.highlightedImage\n to display animation.\n \n See `YYImage` and `YYFrameImage` for example.\n */\n@protocol YYAnimatedImage <NSObject>\n@required\n/// Total animated frame count.\n/// It the frame count is less than 1, then the methods below will be ignored.\n- (NSUInteger)animatedImageFrameCount;\n\n/// Animation loop count, 0 means infinite looping.\n- (NSUInteger)animatedImageLoopCount;\n\n/// Bytes per frame (in memory). It may used to optimize memory buffer size.\n- (NSUInteger)animatedImageBytesPerFrame;\n\n/// Returns the frame image from a specified index.\n/// This method may be called on background thread.\n/// @param index  Frame index (zero based).\n- (nullable UIImage *)animatedImageFrameAtIndex:(NSUInteger)index;\n\n/// Returns the frames's duration from a specified index.\n/// @param index  Frame index (zero based).\n- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index;\n\n@optional\n/// A rectangle in image coordinates defining the subrectangle of the image that\n/// will be displayed. The rectangle should not outside the image's bounds.\n/// It may used to display sprite animation with a single image (sprite sheet).\n- (CGRect)animatedImageContentsRectAtIndex:(NSUInteger)index;\n@end\n\nNS_ASSUME_NONNULL_END\n"
  },
  {
    "path": "YYImage/YYAnimatedImageView.m",
    "content": "//\n//  YYAnimatedImageView.m\n//  YYImage <https://github.com/ibireme/YYImage>\n//\n//  Created by ibireme on 14/10/19.\n//  Copyright (c) 2015 ibireme.\n//\n//  This source code is licensed under the MIT-style license found in the\n//  LICENSE file in the root directory of this source tree.\n//\n\n#import \"YYAnimatedImageView.h\"\n#import \"YYImageCoder.h\"\n#import <pthread.h>\n#import <mach/mach.h>\n\n\n#define BUFFER_SIZE (10 * 1024 * 1024) // 10MB (minimum memory buffer size)\n\n#define LOCK(...) dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER); \\\n__VA_ARGS__; \\\ndispatch_semaphore_signal(self->_lock);\n\n#define LOCK_VIEW(...) dispatch_semaphore_wait(view->_lock, DISPATCH_TIME_FOREVER); \\\n__VA_ARGS__; \\\ndispatch_semaphore_signal(view->_lock);\n\n\nstatic int64_t _YYDeviceMemoryTotal() {\n    int64_t mem = [[NSProcessInfo processInfo] physicalMemory];\n    if (mem < -1) mem = -1;\n        return mem;\n}\n\nstatic int64_t _YYDeviceMemoryFree() {\n    mach_port_t host_port = mach_host_self();\n    mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);\n    vm_size_t page_size;\n    vm_statistics_data_t vm_stat;\n    kern_return_t kern;\n    \n    kern = host_page_size(host_port, &page_size);\n    if (kern != KERN_SUCCESS) return -1;\n    kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);\n    if (kern != KERN_SUCCESS) return -1;\n    return vm_stat.free_count * page_size;\n}\n\n/**\n A proxy used to hold a weak object.\n It can be used to avoid retain cycles, such as the target in NSTimer or CADisplayLink.\n */\n@interface _YYImageWeakProxy : NSProxy\n@property (nonatomic, weak, readonly) id target;\n- (instancetype)initWithTarget:(id)target;\n+ (instancetype)proxyWithTarget:(id)target;\n@end\n\n@implementation _YYImageWeakProxy\n- (instancetype)initWithTarget:(id)target {\n    _target = target;\n    return self;\n}\n+ (instancetype)proxyWithTarget:(id)target {\n    return [[_YYImageWeakProxy alloc] initWithTarget:target];\n}\n- (id)forwardingTargetForSelector:(SEL)selector {\n    return _target;\n}\n- (void)forwardInvocation:(NSInvocation *)invocation {\n    void *null = NULL;\n    [invocation setReturnValue:&null];\n}\n- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {\n    return [NSObject instanceMethodSignatureForSelector:@selector(init)];\n}\n- (BOOL)respondsToSelector:(SEL)aSelector {\n    return [_target respondsToSelector:aSelector];\n}\n- (BOOL)isEqual:(id)object {\n    return [_target isEqual:object];\n}\n- (NSUInteger)hash {\n    return [_target hash];\n}\n- (Class)superclass {\n    return [_target superclass];\n}\n- (Class)class {\n    return [_target class];\n}\n- (BOOL)isKindOfClass:(Class)aClass {\n    return [_target isKindOfClass:aClass];\n}\n- (BOOL)isMemberOfClass:(Class)aClass {\n    return [_target isMemberOfClass:aClass];\n}\n- (BOOL)conformsToProtocol:(Protocol *)aProtocol {\n    return [_target conformsToProtocol:aProtocol];\n}\n- (BOOL)isProxy {\n    return YES;\n}\n- (NSString *)description {\n    return [_target description];\n}\n- (NSString *)debugDescription {\n    return [_target debugDescription];\n}\n@end\n\n\n\n\ntypedef NS_ENUM(NSUInteger, YYAnimatedImageType) {\n    YYAnimatedImageTypeNone = 0,\n    YYAnimatedImageTypeImage,\n    YYAnimatedImageTypeHighlightedImage,\n    YYAnimatedImageTypeImages,\n    YYAnimatedImageTypeHighlightedImages,\n};\n\n@interface YYAnimatedImageView() {\n    @package\n    UIImage <YYAnimatedImage> *_curAnimatedImage;\n    \n    dispatch_semaphore_t _lock; ///< lock for _buffer\n    NSOperationQueue *_requestQueue; ///< image request queue, serial\n    \n    CADisplayLink *_link; ///< ticker for change frame\n    NSTimeInterval _time; ///< time after last frame\n    \n    UIImage *_curFrame; ///< current frame to display\n    NSUInteger _curIndex; ///< current frame index (from 0)\n    NSUInteger _totalFrameCount; ///< total frame count\n    \n    BOOL _loopEnd; ///< whether the loop is end.\n    NSUInteger _curLoop; ///< current loop count (from 0)\n    NSUInteger _totalLoop; ///< total loop count, 0 means infinity\n    \n    NSMutableDictionary *_buffer; ///< frame buffer\n    BOOL _bufferMiss; ///< whether miss frame on last opportunity\n    NSUInteger _maxBufferCount; ///< maximum buffer count\n    NSInteger _incrBufferCount; ///< current allowed buffer count (will increase by step)\n    \n    CGRect _curContentsRect;\n    BOOL _curImageHasContentsRect; ///< image has implementated \"animatedImageContentsRectAtIndex:\"\n}\n@property (nonatomic, readwrite) BOOL currentIsPlayingAnimation;\n- (void)calcMaxBufferCount;\n@end\n\n/// An operation for image fetch\n@interface _YYAnimatedImageViewFetchOperation : NSOperation\n@property (nonatomic, weak) YYAnimatedImageView *view;\n@property (nonatomic, assign) NSUInteger nextIndex;\n@property (nonatomic, strong) UIImage <YYAnimatedImage> *curImage;\n@end\n\n@implementation _YYAnimatedImageViewFetchOperation\n- (void)main {\n    __strong YYAnimatedImageView *view = _view;\n    if (!view) return;\n    if ([self isCancelled]) return;\n    view->_incrBufferCount++;\n    if (view->_incrBufferCount == 0) [view calcMaxBufferCount];\n    if (view->_incrBufferCount > (NSInteger)view->_maxBufferCount) {\n        view->_incrBufferCount = view->_maxBufferCount;\n    }\n    NSUInteger idx = _nextIndex;\n    NSUInteger max = view->_incrBufferCount < 1 ? 1 : view->_incrBufferCount;\n    NSUInteger total = view->_totalFrameCount;\n    view = nil;\n    \n    for (int i = 0; i < max; i++, idx++) {\n        @autoreleasepool {\n            if (idx >= total) idx = 0;\n            if ([self isCancelled]) break;\n            __strong YYAnimatedImageView *view = _view;\n            if (!view) break;\n            LOCK_VIEW(BOOL miss = (view->_buffer[@(idx)] == nil));\n            \n            if (miss) {\n                UIImage *img = [_curImage animatedImageFrameAtIndex:idx];\n                img = img.yy_imageByDecoded;\n                if ([self isCancelled]) break;\n                LOCK_VIEW(view->_buffer[@(idx)] = img ? img : [NSNull null]);\n                view = nil;\n            }\n        }\n    }\n}\n@end\n\n@implementation YYAnimatedImageView\n\n- (instancetype)init {\n    self = [super init];\n    _runloopMode = NSRunLoopCommonModes;\n    _autoPlayAnimatedImage = YES;\n    return self;\n}\n\n- (instancetype)initWithFrame:(CGRect)frame {\n    self = [super initWithFrame:frame];\n    _runloopMode = NSRunLoopCommonModes;\n    _autoPlayAnimatedImage = YES;\n    return self;\n}\n\n- (instancetype)initWithImage:(UIImage *)image {\n    self = [super init];\n    _runloopMode = NSRunLoopCommonModes;\n    _autoPlayAnimatedImage = YES;\n    self.frame = (CGRect) {CGPointZero, image.size };\n    self.image = image;\n    return self;\n}\n\n- (instancetype)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage {\n    self = [super init];\n    _runloopMode = NSRunLoopCommonModes;\n    _autoPlayAnimatedImage = YES;\n    CGSize size = image ? image.size : highlightedImage.size;\n    self.frame = (CGRect) {CGPointZero, size };\n    self.image = image;\n    self.highlightedImage = highlightedImage;\n    return self;\n}\n\n// init the animated params.\n- (void)resetAnimated {\n    if (!_link) {\n        _lock = dispatch_semaphore_create(1);\n        _buffer = [NSMutableDictionary new];\n        _requestQueue = [[NSOperationQueue alloc] init];\n        _requestQueue.maxConcurrentOperationCount = 1;\n        _link = [CADisplayLink displayLinkWithTarget:[_YYImageWeakProxy proxyWithTarget:self] selector:@selector(step:)];\n        if (_runloopMode) {\n            [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:_runloopMode];\n        }\n        _link.paused = YES;\n        \n        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];\n        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];\n    }\n    \n    [_requestQueue cancelAllOperations];\n    LOCK(\n         if (_buffer.count) {\n             NSMutableDictionary *holder = _buffer;\n             _buffer = [NSMutableDictionary new];\n             dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{\n                 // Capture the dictionary to global queue,\n                 // release these images in background to avoid blocking UI thread.\n                 [holder class];\n             });\n         }\n    );\n    _link.paused = YES;\n    _time = 0;\n    if (_curIndex != 0) {\n        [self willChangeValueForKey:@\"currentAnimatedImageIndex\"];\n        _curIndex = 0;\n        [self didChangeValueForKey:@\"currentAnimatedImageIndex\"];\n    }\n    _curAnimatedImage = nil;\n    _curFrame = nil;\n    _curLoop = 0;\n    _totalLoop = 0;\n    _totalFrameCount = 1;\n    _loopEnd = NO;\n    _bufferMiss = NO;\n    _incrBufferCount = 0;\n}\n\n- (void)setImage:(UIImage *)image {\n    if (self.image == image) return;\n    [self setImage:image withType:YYAnimatedImageTypeImage];\n}\n\n- (void)setHighlightedImage:(UIImage *)highlightedImage {\n    if (self.highlightedImage == highlightedImage) return;\n    [self setImage:highlightedImage withType:YYAnimatedImageTypeHighlightedImage];\n}\n\n- (void)setAnimationImages:(NSArray *)animationImages {\n    if (self.animationImages == animationImages) return;\n    [self setImage:animationImages withType:YYAnimatedImageTypeImages];\n}\n\n- (void)setHighlightedAnimationImages:(NSArray *)highlightedAnimationImages {\n    if (self.highlightedAnimationImages == highlightedAnimationImages) return;\n    [self setImage:highlightedAnimationImages withType:YYAnimatedImageTypeHighlightedImages];\n}\n\n- (void)setHighlighted:(BOOL)highlighted {\n    [super setHighlighted:highlighted];\n    if (_link) [self resetAnimated];\n    [self imageChanged];\n}\n\n- (id)imageForType:(YYAnimatedImageType)type {\n    switch (type) {\n        case YYAnimatedImageTypeNone: return nil;\n        case YYAnimatedImageTypeImage: return self.image;\n        case YYAnimatedImageTypeHighlightedImage: return self.highlightedImage;\n        case YYAnimatedImageTypeImages: return self.animationImages;\n        case YYAnimatedImageTypeHighlightedImages: return self.highlightedAnimationImages;\n    }\n    return nil;\n}\n\n- (YYAnimatedImageType)currentImageType {\n    YYAnimatedImageType curType = YYAnimatedImageTypeNone;\n    if (self.highlighted) {\n        if (self.highlightedAnimationImages.count) curType = YYAnimatedImageTypeHighlightedImages;\n        else if (self.highlightedImage) curType = YYAnimatedImageTypeHighlightedImage;\n    }\n    if (curType == YYAnimatedImageTypeNone) {\n        if (self.animationImages.count) curType = YYAnimatedImageTypeImages;\n        else if (self.image) curType = YYAnimatedImageTypeImage;\n    }\n    return curType;\n}\n\n- (void)setImage:(id)image withType:(YYAnimatedImageType)type {\n    [self stopAnimating];\n    if (_link) [self resetAnimated];\n    _curFrame = nil;\n    switch (type) {\n        case YYAnimatedImageTypeNone: break;\n        case YYAnimatedImageTypeImage: super.image = image; break;\n        case YYAnimatedImageTypeHighlightedImage: super.highlightedImage = image; break;\n        case YYAnimatedImageTypeImages: super.animationImages = image; break;\n        case YYAnimatedImageTypeHighlightedImages: super.highlightedAnimationImages = image; break;\n    }\n    [self imageChanged];\n}\n\n- (void)imageChanged {\n    YYAnimatedImageType newType = [self currentImageType];\n    id newVisibleImage = [self imageForType:newType];\n    NSUInteger newImageFrameCount = 0;\n    BOOL hasContentsRect = NO;\n    if ([newVisibleImage isKindOfClass:[UIImage class]] &&\n        [newVisibleImage conformsToProtocol:@protocol(YYAnimatedImage)]) {\n        newImageFrameCount = ((UIImage<YYAnimatedImage> *) newVisibleImage).animatedImageFrameCount;\n        if (newImageFrameCount > 1) {\n            hasContentsRect = [((UIImage<YYAnimatedImage> *) newVisibleImage) respondsToSelector:@selector(animatedImageContentsRectAtIndex:)];\n        }\n    }\n    if (!hasContentsRect && _curImageHasContentsRect) {\n        if (!CGRectEqualToRect(self.layer.contentsRect, CGRectMake(0, 0, 1, 1)) ) {\n            [CATransaction begin];\n            [CATransaction setDisableActions:YES];\n            self.layer.contentsRect = CGRectMake(0, 0, 1, 1);\n            [CATransaction commit];\n        }\n    }\n    _curImageHasContentsRect = hasContentsRect;\n    if (hasContentsRect) {\n        CGRect rect = [((UIImage<YYAnimatedImage> *) newVisibleImage) animatedImageContentsRectAtIndex:0];\n        [self setContentsRect:rect forImage:newVisibleImage];\n    }\n    \n    if (newImageFrameCount > 1) {\n        [self resetAnimated];\n        _curAnimatedImage = newVisibleImage;\n        _curFrame = newVisibleImage;\n        _totalLoop = _curAnimatedImage.animatedImageLoopCount;\n        _totalFrameCount = _curAnimatedImage.animatedImageFrameCount;\n        [self calcMaxBufferCount];\n    }\n    [self setNeedsDisplay];\n    [self didMoved];\n}\n\n// dynamically adjust buffer size for current memory.\n- (void)calcMaxBufferCount {\n    int64_t bytes = (int64_t)_curAnimatedImage.animatedImageBytesPerFrame;\n    if (bytes == 0) bytes = 1024;\n    \n    int64_t total = _YYDeviceMemoryTotal();\n    int64_t free = _YYDeviceMemoryFree();\n    int64_t max = MIN(total * 0.2, free * 0.6);\n    max = MAX(max, BUFFER_SIZE);\n    if (_maxBufferSize) max = max > _maxBufferSize ? _maxBufferSize : max;\n    double maxBufferCount = (double)max / (double)bytes;\n    if (maxBufferCount < 1) maxBufferCount = 1;\n    else if (maxBufferCount > 512) maxBufferCount = 512;\n    _maxBufferCount = maxBufferCount;\n}\n\n- (void)dealloc {\n    [_requestQueue cancelAllOperations];\n    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];\n    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];\n    [_link invalidate];\n}\n\n- (BOOL)isAnimating {\n    return self.currentIsPlayingAnimation;\n}\n\n- (void)stopAnimating {\n    [super stopAnimating];\n    [_requestQueue cancelAllOperations];\n    _link.paused = YES;\n    self.currentIsPlayingAnimation = NO;\n}\n\n- (void)startAnimating {\n    YYAnimatedImageType type = [self currentImageType];\n    if (type == YYAnimatedImageTypeImages || type == YYAnimatedImageTypeHighlightedImages) {\n        NSArray *images = [self imageForType:type];\n        if (images.count > 0) {\n            [super startAnimating];\n            self.currentIsPlayingAnimation = YES;\n        }\n    } else {\n        if (_curAnimatedImage && _link.paused) {\n            _curLoop = 0;\n            _loopEnd = NO;\n            _link.paused = NO;\n            self.currentIsPlayingAnimation = YES;\n        }\n    }\n}\n\n- (void)didReceiveMemoryWarning:(NSNotification *)notification {\n    [_requestQueue cancelAllOperations];\n    [_requestQueue addOperationWithBlock: ^{\n        self->_incrBufferCount = -60 - (int)(arc4random() % 120); // about 1~3 seconds to grow back..\n        NSNumber *next = @((self->_curIndex + 1) % self->_totalFrameCount);\n        LOCK(\n             NSArray * keys = self->_buffer.allKeys;\n             for (NSNumber * key in keys) {\n                 if (![key isEqualToNumber:next]) { // keep the next frame for smoothly animation\n                     [self->_buffer removeObjectForKey:key];\n                 }\n             }\n        )//LOCK\n    }];\n}\n\n- (void)didEnterBackground:(NSNotification *)notification {\n    [_requestQueue cancelAllOperations];\n    NSNumber *next = @((_curIndex + 1) % _totalFrameCount);\n    LOCK(\n         NSArray * keys = _buffer.allKeys;\n         for (NSNumber * key in keys) {\n             if (![key isEqualToNumber:next]) { // keep the next frame for smoothly animation\n                 [_buffer removeObjectForKey:key];\n             }\n         }\n     )//LOCK\n}\n\n- (void)step:(CADisplayLink *)link {\n    UIImage <YYAnimatedImage> *image = _curAnimatedImage;\n    NSMutableDictionary *buffer = _buffer;\n    UIImage *bufferedImage = nil;\n    NSUInteger nextIndex = (_curIndex + 1) % _totalFrameCount;\n    BOOL bufferIsFull = NO;\n    \n    if (!image) return;\n    if (_loopEnd) { // view will keep in last frame\n        [self stopAnimating];\n        return;\n    }\n    \n    NSTimeInterval delay = 0;\n    if (!_bufferMiss) {\n        _time += link.duration;\n        delay = [image animatedImageDurationAtIndex:_curIndex];\n        if (_time < delay) return;\n        _time -= delay;\n        if (nextIndex == 0) {\n            _curLoop++;\n            if (_curLoop >= _totalLoop && _totalLoop != 0) {\n                _loopEnd = YES;\n                [self stopAnimating];\n                [self.layer setNeedsDisplay]; // let system call `displayLayer:` before runloop sleep\n                return; // stop at last frame\n            }\n        }\n        delay = [image animatedImageDurationAtIndex:nextIndex];\n        if (_time > delay) _time = delay; // do not jump over frame\n    }\n    LOCK(\n         bufferedImage = buffer[@(nextIndex)];\n         if (bufferedImage) {\n             if ((int)_incrBufferCount < (int)_totalFrameCount) {\n                 [buffer removeObjectForKey:@(nextIndex)];\n             }\n             [self willChangeValueForKey:@\"currentAnimatedImageIndex\"];\n             _curIndex = nextIndex;\n             [self didChangeValueForKey:@\"currentAnimatedImageIndex\"];\n             if (_curIndex + 1 == _totalFrameCount && self.loopCompletionBlock) {\n                 self.loopCompletionBlock(_totalLoop - _curLoop);\n             }\n             _curFrame = bufferedImage == (id)[NSNull null] ? nil : bufferedImage;\n             if (_curImageHasContentsRect) {\n                 _curContentsRect = [image animatedImageContentsRectAtIndex:_curIndex];\n                 [self setContentsRect:_curContentsRect forImage:_curFrame];\n             }\n             nextIndex = (_curIndex + 1) % _totalFrameCount;\n             _bufferMiss = NO;\n             if (buffer.count == _totalFrameCount) {\n                 bufferIsFull = YES;\n             }\n         } else {\n             _bufferMiss = YES;\n         }\n    )//LOCK\n    \n    if (!_bufferMiss) {\n        [self.layer setNeedsDisplay]; // let system call `displayLayer:` before runloop sleep\n    }\n    \n    if (!bufferIsFull && _requestQueue.operationCount == 0) { // if some work not finished, wait for next opportunity\n        _YYAnimatedImageViewFetchOperation *operation = [_YYAnimatedImageViewFetchOperation new];\n        operation.view = self;\n        operation.nextIndex = nextIndex;\n        operation.curImage = image;\n        [_requestQueue addOperation:operation];\n    }\n}\n\n- (void)displayLayer:(CALayer *)layer {\n    UIImage *frame = _curFrame;\n    if(!frame)\n        frame = self.image;\n\n    layer.contents = (__bridge id)frame.CGImage;\n    layer.contentsScale = frame.scale;\n}\n\n- (void)setContentsRect:(CGRect)rect forImage:(UIImage *)image{\n    CGRect layerRect = CGRectMake(0, 0, 1, 1);\n    if (image) {\n        CGSize imageSize = image.size;\n        if (imageSize.width > 0.01 && imageSize.height > 0.01) {\n            layerRect.origin.x = rect.origin.x / imageSize.width;\n            layerRect.origin.y = rect.origin.y / imageSize.height;\n            layerRect.size.width = rect.size.width / imageSize.width;\n            layerRect.size.height = rect.size.height / imageSize.height;\n            layerRect = CGRectIntersection(layerRect, CGRectMake(0, 0, 1, 1));\n            if (CGRectIsNull(layerRect) || CGRectIsEmpty(layerRect)) {\n                layerRect = CGRectMake(0, 0, 1, 1);\n            }\n        }\n    }\n    [CATransaction begin];\n    [CATransaction setDisableActions:YES];\n    self.layer.contentsRect = layerRect;\n    [CATransaction commit];\n}\n\n- (void)didMoved {\n    if (self.autoPlayAnimatedImage) {\n        if(self.superview && self.window) {\n            [self startAnimating];\n        } else {\n            [self stopAnimating];\n        }\n    }\n}\n\n- (void)didMoveToWindow {\n    [super didMoveToWindow];\n    [self didMoved];\n}\n\n- (void)didMoveToSuperview {\n    [super didMoveToSuperview];\n    [self didMoved];\n}\n\n- (void)setCurrentAnimatedImageIndex:(NSUInteger)currentAnimatedImageIndex {\n    if (!_curAnimatedImage) return;\n    if (currentAnimatedImageIndex >= _curAnimatedImage.animatedImageFrameCount) return;\n    if (_curIndex == currentAnimatedImageIndex) return;\n    \n    void (^block)(void) = ^{\n        LOCK(\n             [self->_requestQueue cancelAllOperations];\n             [self->_buffer removeAllObjects];\n             [self willChangeValueForKey:@\"currentAnimatedImageIndex\"];\n             self->_curIndex = currentAnimatedImageIndex;\n             [self didChangeValueForKey:@\"currentAnimatedImageIndex\"];\n             self->_curFrame = [self->_curAnimatedImage animatedImageFrameAtIndex:self->_curIndex];\n             if (self->_curImageHasContentsRect) {\n            self->_curContentsRect = [self->_curAnimatedImage animatedImageContentsRectAtIndex:self->_curIndex];\n             }\n             self->_time = 0;\n             self->_loopEnd = NO;\n             self->_bufferMiss = NO;\n             [self.layer setNeedsDisplay];\n        )//LOCK\n    };\n    \n    if (pthread_main_np()) {\n        block();\n    } else {\n        dispatch_async(dispatch_get_main_queue(), block);\n    }\n}\n\n- (NSUInteger)currentAnimatedImageIndex {\n    return _curIndex;\n}\n\n- (void)setRunloopMode:(NSString *)runloopMode {\n    if ([_runloopMode isEqual:runloopMode]) return;\n    if (_link) {\n        if (_runloopMode) {\n            [_link removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:_runloopMode];\n        }\n        if (runloopMode.length) {\n            [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:runloopMode];\n        }\n    }\n    _runloopMode = runloopMode.copy;\n}\n\n#pragma mark - Override NSObject(NSKeyValueObservingCustomization)\n\n+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {\n    if ([key isEqualToString:@\"currentAnimatedImageIndex\"]) {\n        return NO;\n    }\n    return [super automaticallyNotifiesObserversForKey:key];\n}\n\n#pragma mark - NSCoding\n\n- (instancetype)initWithCoder:(NSCoder *)aDecoder {\n    self = [super initWithCoder:aDecoder];\n    _runloopMode = [aDecoder decodeObjectForKey:@\"runloopMode\"];\n    if (_runloopMode.length == 0) _runloopMode = NSRunLoopCommonModes;\n    if ([aDecoder containsValueForKey:@\"autoPlayAnimatedImage\"]) {\n        _autoPlayAnimatedImage = [aDecoder decodeBoolForKey:@\"autoPlayAnimatedImage\"];\n    } else {\n        _autoPlayAnimatedImage = YES;\n    }\n    \n    UIImage *image = [aDecoder decodeObjectForKey:@\"YYAnimatedImage\"];\n    UIImage *highlightedImage = [aDecoder decodeObjectForKey:@\"YYHighlightedAnimatedImage\"];\n    if (image) {\n        self.image = image;\n        [self setImage:image withType:YYAnimatedImageTypeImage];\n    }\n    if (highlightedImage) {\n        self.highlightedImage = highlightedImage;\n        [self setImage:highlightedImage withType:YYAnimatedImageTypeHighlightedImage];\n    }\n    return self;\n}\n\n- (void)encodeWithCoder:(NSCoder *)aCoder {\n    [super encodeWithCoder:aCoder];\n    [aCoder encodeObject:_runloopMode forKey:@\"runloopMode\"];\n    [aCoder encodeBool:_autoPlayAnimatedImage forKey:@\"autoPlayAnimatedImage\"];\n    \n    BOOL ani, multi;\n    ani = [self.image conformsToProtocol:@protocol(YYAnimatedImage)];\n    multi = (ani && ((UIImage <YYAnimatedImage> *)self.image).animatedImageFrameCount > 1);\n    if (multi) [aCoder encodeObject:self.image forKey:@\"YYAnimatedImage\"];\n    \n    ani = [self.highlightedImage conformsToProtocol:@protocol(YYAnimatedImage)];\n    multi = (ani && ((UIImage <YYAnimatedImage> *)self.highlightedImage).animatedImageFrameCount > 1);\n    if (multi) [aCoder encodeObject:self.highlightedImage forKey:@\"YYHighlightedAnimatedImage\"];\n}\n\n@end\n"
  },
  {
    "path": "YYImage/YYFrameImage.h",
    "content": "//\n//  YYFrameImage.h\n//  YYImage <https://github.com/ibireme/YYImage>\n//\n//  Created by ibireme on 14/12/9.\n//  Copyright (c) 2015 ibireme.\n//\n//  This source code is licensed under the MIT-style license found in the\n//  LICENSE file in the root directory of this source tree.\n//\n\n#import <UIKit/UIKit.h>\n\n#if __has_include(<YYImage/YYImage.h>)\n#import <YYImage/YYAnimatedImageView.h>\n#elif __has_include(<YYWebImage/YYImage.h>)\n#import <YYWebImage/YYAnimatedImageView.h>\n#else\n#import \"YYAnimatedImageView.h\"\n#endif\n\nNS_ASSUME_NONNULL_BEGIN\n\n/**\n An image to display frame-based animation.\n \n @discussion It is a fully compatible `UIImage` subclass.\n It only support system image format such as png and jpeg.\n The animation can be played by YYAnimatedImageView.\n \n Sample Code:\n     \n     NSArray *paths = @[@\"/ani/frame1.png\", @\"/ani/frame2.png\", @\"/ani/frame3.png\"];\n     NSArray *times = @[@0.1, @0.2, @0.1];\n     YYFrameImage *image = [YYFrameImage alloc] initWithImagePaths:paths frameDurations:times repeats:YES];\n     YYAnimatedImageView *imageView = [YYAnimatedImageView alloc] initWithImage:image];\n     [view addSubView:imageView];\n */\n@interface YYFrameImage : UIImage <YYAnimatedImage>\n\n/**\n Create a frame animated image from files.\n \n @param paths            An array of NSString objects, contains the full or \n                         partial path to each image file.\n                         e.g. @[@\"/ani/1.png\",@\"/ani/2.png\",@\"/ani/3.png\"]\n \n @param oneFrameDuration The duration (in seconds) per frame.\n \n @param loopCount        The animation loop count, 0 means infinite.\n \n @return An initialized YYFrameImage object, or nil when an error occurs.\n */\n- (nullable instancetype)initWithImagePaths:(NSArray<NSString *> *)paths\n                           oneFrameDuration:(NSTimeInterval)oneFrameDuration\n                                  loopCount:(NSUInteger)loopCount;\n\n/**\n Create a frame animated image from files.\n \n @param paths          An array of NSString objects, contains the full or\n                       partial path to each image file.\n                       e.g. @[@\"/ani/frame1.png\",@\"/ani/frame2.png\",@\"/ani/frame3.png\"]\n \n @param frameDurations An array of NSNumber objects, contains the duration (in seconds) per frame.\n                       e.g. @[@0.1, @0.2, @0.3];\n \n @param loopCount      The animation loop count, 0 means infinite.\n \n @return An initialized YYFrameImage object, or nil when an error occurs.\n */\n- (nullable instancetype)initWithImagePaths:(NSArray<NSString *> *)paths\n                             frameDurations:(NSArray<NSNumber *> *)frameDurations\n                                  loopCount:(NSUInteger)loopCount;\n\n/**\n Create a frame animated image from an array of data.\n \n @param dataArray        An array of NSData objects.\n \n @param oneFrameDuration The duration (in seconds) per frame.\n \n @param loopCount        The animation loop count, 0 means infinite.\n \n @return An initialized YYFrameImage object, or nil when an error occurs.\n */\n- (nullable instancetype)initWithImageDataArray:(NSArray<NSData *> *)dataArray\n                               oneFrameDuration:(NSTimeInterval)oneFrameDuration\n                                      loopCount:(NSUInteger)loopCount;\n\n/**\n Create a frame animated image from an array of data.\n \n @param dataArray      An array of NSData objects.\n \n @param frameDurations An array of NSNumber objects, contains the duration (in seconds) per frame.\n                       e.g. @[@0.1, @0.2, @0.3];\n \n @param loopCount      The animation loop count, 0 means infinite.\n \n @return An initialized YYFrameImage object, or nil when an error occurs.\n */\n- (nullable instancetype)initWithImageDataArray:(NSArray<NSData *> *)dataArray\n                                 frameDurations:(NSArray *)frameDurations\n                                      loopCount:(NSUInteger)loopCount;\n\n@end\n\nNS_ASSUME_NONNULL_END\n"
  },
  {
    "path": "YYImage/YYFrameImage.m",
    "content": "//\n//  YYFrameImage.m\n//  YYImage <https://github.com/ibireme/YYImage>\n//\n//  Created by ibireme on 14/12/9.\n//  Copyright (c) 2015 ibireme.\n//\n//  This source code is licensed under the MIT-style license found in the\n//  LICENSE file in the root directory of this source tree.\n//\n\n#import \"YYFrameImage.h\"\n#import \"YYImageCoder.h\"\n\n\n/**\n Return the path scale.\n \n e.g.\n <table>\n <tr><th>Path            </th><th>Scale </th></tr>\n <tr><td>\"icon.png\"      </td><td>1     </td></tr>\n <tr><td>\"icon@2x.png\"   </td><td>2     </td></tr>\n <tr><td>\"icon@2.5x.png\" </td><td>2.5   </td></tr>\n <tr><td>\"icon@2x\"       </td><td>1     </td></tr>\n <tr><td>\"icon@2x..png\"  </td><td>1     </td></tr>\n <tr><td>\"icon@2x.png/\"  </td><td>1     </td></tr>\n </table>\n */\nstatic CGFloat _NSStringPathScale(NSString *string) {\n    if (string.length == 0 || [string hasSuffix:@\"/\"]) return 1;\n    NSString *name = string.stringByDeletingPathExtension;\n    __block CGFloat scale = 1;\n    \n    NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:@\"@[0-9]+\\\\.?[0-9]*x$\" options:NSRegularExpressionAnchorsMatchLines error:nil];\n    [pattern enumerateMatchesInString:name options:kNilOptions range:NSMakeRange(0, name.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {\n        if (result.range.location >= 3) {\n            scale = [string substringWithRange:NSMakeRange(result.range.location + 1, result.range.length - 2)].doubleValue;\n        }\n    }];\n    \n    return scale;\n}\n\n\n\n@implementation YYFrameImage {\n    NSUInteger _loopCount;\n    NSUInteger _oneFrameBytes;\n    NSArray *_imagePaths;\n    NSArray *_imageDatas;\n    NSArray *_frameDurations;\n}\n\n- (instancetype)initWithImagePaths:(NSArray *)paths oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount {\n    NSMutableArray *durations = [NSMutableArray new];\n    for (int i = 0, max = (int)paths.count; i < max; i++) {\n        [durations addObject:@(oneFrameDuration)];\n    }\n    return [self initWithImagePaths:paths frameDurations:durations loopCount:loopCount];\n}\n\n- (instancetype)initWithImagePaths:(NSArray *)paths frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount {\n    if (paths.count == 0) return nil;\n    if (paths.count != frameDurations.count) return nil;\n    \n    NSString *firstPath = paths[0];\n    NSData *firstData = [NSData dataWithContentsOfFile:firstPath];\n    CGFloat scale = _NSStringPathScale(firstPath);\n    UIImage *firstCG = [[[UIImage alloc] initWithData:firstData] yy_imageByDecoded];\n    self = [self initWithCGImage:firstCG.CGImage scale:scale orientation:firstCG.imageOrientation];\n    if (!self) return nil;\n    long frameByte = CGImageGetBytesPerRow(firstCG.CGImage) * CGImageGetHeight(firstCG.CGImage);\n    _oneFrameBytes = (NSUInteger)frameByte;\n    _imagePaths = paths.copy;\n    _frameDurations = frameDurations.copy;\n    _loopCount = loopCount;\n    \n    return self;\n}\n\n- (instancetype)initWithImageDataArray:(NSArray *)dataArray oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount {\n    NSMutableArray *durations = [NSMutableArray new];\n    for (int i = 0, max = (int)dataArray.count; i < max; i++) {\n        [durations addObject:@(oneFrameDuration)];\n    }\n    return [self initWithImageDataArray:dataArray frameDurations:durations loopCount:loopCount];\n}\n\n- (instancetype)initWithImageDataArray:(NSArray *)dataArray frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount {\n    if (dataArray.count == 0) return nil;\n    if (dataArray.count != frameDurations.count) return nil;\n    \n    NSData *firstData = dataArray[0];\n    CGFloat scale = [UIScreen mainScreen].scale;\n    UIImage *firstCG = [[[UIImage alloc] initWithData:firstData] yy_imageByDecoded];\n    self = [self initWithCGImage:firstCG.CGImage scale:scale orientation:firstCG.imageOrientation];\n    if (!self) return nil;\n    long frameByte = CGImageGetBytesPerRow(firstCG.CGImage) * CGImageGetHeight(firstCG.CGImage);\n    _oneFrameBytes = (NSUInteger)frameByte;\n    _imageDatas = dataArray.copy;\n    _frameDurations = frameDurations.copy;\n    _loopCount = loopCount;\n    \n    return self;\n}\n\n#pragma mark - YYAnimtedImage\n\n- (NSUInteger)animatedImageFrameCount {\n    if (_imagePaths) {\n        return _imagePaths.count;\n    } else if (_imageDatas) {\n        return _imageDatas.count;\n    } else {\n        return 1;\n    }\n}\n\n- (NSUInteger)animatedImageLoopCount {\n    return _loopCount;\n}\n\n- (NSUInteger)animatedImageBytesPerFrame {\n    return _oneFrameBytes;\n}\n\n- (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index {\n    if (_imagePaths) {\n        if (index >= _imagePaths.count) return nil;\n        NSString *path = _imagePaths[index];\n        CGFloat scale = _NSStringPathScale(path);\n        NSData *data = [NSData dataWithContentsOfFile:path];\n        return [[UIImage imageWithData:data scale:scale] yy_imageByDecoded];\n    } else if (_imageDatas) {\n        if (index >= _imageDatas.count) return nil;\n        NSData *data = _imageDatas[index];\n        return [[UIImage imageWithData:data scale:[UIScreen mainScreen].scale] yy_imageByDecoded];\n    } else {\n        return index == 0 ? self : nil;\n    }\n}\n\n- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index {\n    if (index >= _frameDurations.count) return 0;\n    NSNumber *num = _frameDurations[index];\n    return [num doubleValue];\n}\n\n@end\n"
  },
  {
    "path": "YYImage/YYImage.h",
    "content": "//\n//  YYImage.h\n//  YYImage <https://github.com/ibireme/YYImage>\n//\n//  Created by ibireme on 14/10/20.\n//  Copyright (c) 2015 ibireme.\n//\n//  This source code is licensed under the MIT-style license found in the\n//  LICENSE file in the root directory of this source tree.\n//\n\n#import <UIKit/UIKit.h>\n\n#if __has_include(<YYImage/YYImage.h>)\nFOUNDATION_EXPORT double YYImageVersionNumber;\nFOUNDATION_EXPORT const unsigned char YYImageVersionString[];\n#import <YYImage/YYFrameImage.h>\n#import <YYImage/YYSpriteSheetImage.h>\n#import <YYImage/YYImageCoder.h>\n#import <YYImage/YYAnimatedImageView.h>\n#elif __has_include(<YYWebImage/YYImage.h>)\n#import <YYWebImage/YYFrameImage.h>\n#import <YYWebImage/YYSpriteSheetImage.h>\n#import <YYWebImage/YYImageCoder.h>\n#import <YYWebImage/YYAnimatedImageView.h>\n#else\n#import \"YYFrameImage.h\"\n#import \"YYSpriteSheetImage.h\"\n#import \"YYImageCoder.h\"\n#import \"YYAnimatedImageView.h\"\n#endif\n\nNS_ASSUME_NONNULL_BEGIN\n\n\n/**\n A YYImage object is a high-level way to display animated image data.\n \n @discussion It is a fully compatible `UIImage` subclass. It extends the UIImage\n to support animated WebP, APNG and GIF format image data decoding. It also \n support NSCoding protocol to archive and unarchive multi-frame image data.\n \n If the image is created from multi-frame image data, and you want to play the \n animation, try replace UIImageView with `YYAnimatedImageView`.\n \n Sample Code:\n \n     // animation@3x.webp\n     YYImage *image = [YYImage imageNamed:@\"animation.webp\"];\n     YYAnimatedImageView *imageView = [YYAnimatedImageView alloc] initWithImage:image];\n     [view addSubView:imageView];\n    \n */\n@interface YYImage : UIImage <YYAnimatedImage>\n\n+ (nullable YYImage *)imageNamed:(NSString *)name; // no cache!\n+ (nullable YYImage *)imageNamed:(NSString *)name inBundle:(NSBundle *)bundle;\n+ (nullable YYImage *)imageWithContentsOfFile:(NSString *)path;\n+ (nullable YYImage *)imageWithData:(NSData *)data;\n+ (nullable YYImage *)imageWithData:(NSData *)data scale:(CGFloat)scale;\n\n/**\n If the image is created from data or file, then the value indicates the data type.\n */\n@property (nonatomic, readonly) YYImageType animatedImageType;\n\n/**\n If the image is created from animated image data (multi-frame GIF/APNG/WebP),\n this property stores the original image data.\n */\n@property (nullable, nonatomic, readonly) NSData *animatedImageData;\n\n/**\n The total memory usage (in bytes) if all frame images was loaded into memory.\n The value is 0 if the image is not created from a multi-frame image data.\n */\n@property (nonatomic, readonly) NSUInteger animatedImageMemorySize;\n\n/**\n Preload all frame image to memory.\n \n @discussion Set this property to `YES` will block the calling thread to decode \n all animation frame image to memory, set to `NO` will release the preloaded frames.\n If the image is shared by lots of image views (such as emoticon), preload all\n frames will reduce the CPU cost.\n \n See `animatedImageMemorySize` for memory cost.\n */\n@property (nonatomic) BOOL preloadAllAnimatedImageFrames;\n\n@end\n\nNS_ASSUME_NONNULL_END\n"
  },
  {
    "path": "YYImage/YYImage.m",
    "content": "//\n//  YYImage.m\n//  YYImage <https://github.com/ibireme/YYImage>\n//\n//  Created by ibireme on 14/10/20.\n//  Copyright (c) 2015 ibireme.\n//\n//  This source code is licensed under the MIT-style license found in the\n//  LICENSE file in the root directory of this source tree.\n//\n\n#import \"YYImage.h\"\n\n/**\n An array of NSNumber objects, shows the best order for path scale search.\n e.g. iPhone3GS:@[@1,@2,@3] iPhone5:@[@2,@3,@1]  iPhone6 Plus:@[@3,@2,@1]\n */\nstatic NSArray *_NSBundlePreferredScales() {\n    static NSArray *scales;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        CGFloat screenScale = [UIScreen mainScreen].scale;\n        if (screenScale <= 1) {\n            scales = @[@1,@2,@3];\n        } else if (screenScale <= 2) {\n            scales = @[@2,@3,@1];\n        } else {\n            scales = @[@3,@2,@1];\n        }\n    });\n    return scales;\n}\n\n/**\n Add scale modifier to the file name (without path extension),\n From @\"name\" to @\"name@2x\".\n \n e.g.\n <table>\n <tr><th>Before     </th><th>After(scale:2)</th></tr>\n <tr><td>\"icon\"     </td><td>\"icon@2x\"     </td></tr>\n <tr><td>\"icon \"    </td><td>\"icon @2x\"    </td></tr>\n <tr><td>\"icon.top\" </td><td>\"icon.top@2x\" </td></tr>\n <tr><td>\"/p/name\"  </td><td>\"/p/name@2x\"  </td></tr>\n <tr><td>\"/path/\"   </td><td>\"/path/\"      </td></tr>\n </table>\n \n @param scale Resource scale.\n @return String by add scale modifier, or just return if it's not end with file name.\n */\nstatic NSString *_NSStringByAppendingNameScale(NSString *string, CGFloat scale) {\n    if (!string) return nil;\n    if (fabs(scale - 1) <= __FLT_EPSILON__ || string.length == 0 || [string hasSuffix:@\"/\"]) return string.copy;\n    return [string stringByAppendingFormat:@\"@%@x\", @(scale)];\n}\n\n/**\n Return the path scale.\n \n e.g.\n <table>\n <tr><th>Path            </th><th>Scale </th></tr>\n <tr><td>\"icon.png\"      </td><td>1     </td></tr>\n <tr><td>\"icon@2x.png\"   </td><td>2     </td></tr>\n <tr><td>\"icon@2.5x.png\" </td><td>2.5   </td></tr>\n <tr><td>\"icon@2x\"       </td><td>1     </td></tr>\n <tr><td>\"icon@2x..png\"  </td><td>1     </td></tr>\n <tr><td>\"icon@2x.png/\"  </td><td>1     </td></tr>\n </table>\n */\nstatic CGFloat _NSStringPathScale(NSString *string) {\n    if (string.length == 0 || [string hasSuffix:@\"/\"]) return 1;\n    NSString *name = string.stringByDeletingPathExtension;\n    __block CGFloat scale = 1;\n    \n    NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:@\"@[0-9]+\\\\.?[0-9]*x$\" options:NSRegularExpressionAnchorsMatchLines error:nil];\n    [pattern enumerateMatchesInString:name options:kNilOptions range:NSMakeRange(0, name.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {\n        if (result.range.location >= 3) {\n            scale = [string substringWithRange:NSMakeRange(result.range.location + 1, result.range.length - 2)].doubleValue;\n        }\n    }];\n    \n    return scale;\n}\n\n\n@implementation YYImage {\n    YYImageDecoder *_decoder;\n    NSArray *_preloadedFrames;\n    dispatch_semaphore_t _preloadedLock;\n    NSUInteger _bytesPerFrame;\n}\n\n+ (YYImage *)imageNamed:(NSString *)name {\n    return [self imageNamed:name inBundle:[NSBundle mainBundle]];\n}\n\n+ (YYImage *)imageNamed:(NSString *)name inBundle:(NSBundle *)bundle {\n    if (name.length == 0) return nil;\n    if ([name hasSuffix:@\"/\"]) return nil;\n    \n    NSString *res = name.stringByDeletingPathExtension;\n    NSString *ext = name.pathExtension;\n    NSString *path = nil;\n    CGFloat scale = 1;\n    \n    // If no extension, guess by system supported (same as UIImage).\n    NSArray *exts = ext.length > 0 ? @[ext] : @[@\"\", @\"png\", @\"jpeg\", @\"jpg\", @\"gif\", @\"webp\", @\"apng\"];\n    NSArray *scales = _NSBundlePreferredScales();\n    for (int s = 0; s < scales.count; s++) {\n        scale = ((NSNumber *)scales[s]).floatValue;\n        NSString *scaledName = _NSStringByAppendingNameScale(res, scale);\n        for (NSString *e in exts) {\n            path = [bundle pathForResource:scaledName ofType:e];\n            if (path) break;\n        }\n        if (path) break;\n    }\n    if (path.length == 0) return nil;\n    \n    NSData *data = [NSData dataWithContentsOfFile:path];\n    if (data.length == 0) return nil;\n    \n    return [[self alloc] initWithData:data scale:scale];\n}\n\n+ (YYImage *)imageWithContentsOfFile:(NSString *)path {\n    return [[self alloc] initWithContentsOfFile:path];\n}\n\n+ (YYImage *)imageWithData:(NSData *)data {\n    return [[self alloc] initWithData:data];\n}\n\n+ (YYImage *)imageWithData:(NSData *)data scale:(CGFloat)scale {\n    return [[self alloc] initWithData:data scale:scale];\n}\n\n- (instancetype)initWithContentsOfFile:(NSString *)path {\n    NSData *data = [NSData dataWithContentsOfFile:path];\n    return [self initWithData:data scale:_NSStringPathScale(path)];\n}\n\n- (instancetype)initWithData:(NSData *)data {\n    return [self initWithData:data scale:1];\n}\n\n- (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale {\n    if (data.length == 0) return nil;\n    if (scale <= 0) scale = [UIScreen mainScreen].scale;\n    _preloadedLock = dispatch_semaphore_create(1);\n    @autoreleasepool {\n        YYImageDecoder *decoder = [YYImageDecoder decoderWithData:data scale:scale];\n        YYImageFrame *frame = [decoder frameAtIndex:0 decodeForDisplay:YES];\n        UIImage *image = frame.image;\n        if (!image) return nil;\n        self = [self initWithCGImage:image.CGImage scale:decoder.scale orientation:image.imageOrientation];\n        if (!self) return nil;\n        _animatedImageType = decoder.type;\n        if (decoder.frameCount > 1) {\n            _decoder = decoder;\n            _bytesPerFrame = CGImageGetBytesPerRow(image.CGImage) * CGImageGetHeight(image.CGImage);\n            _animatedImageMemorySize = _bytesPerFrame * decoder.frameCount;\n        }\n        self.yy_isDecodedForDisplay = YES;\n    }\n    return self;\n}\n\n- (NSData *)animatedImageData {\n    return _decoder.data;\n}\n\n- (void)setPreloadAllAnimatedImageFrames:(BOOL)preloadAllAnimatedImageFrames {\n    if (_preloadAllAnimatedImageFrames != preloadAllAnimatedImageFrames) {\n        if (preloadAllAnimatedImageFrames && _decoder.frameCount > 0) {\n            NSMutableArray *frames = [NSMutableArray new];\n            for (NSUInteger i = 0, max = _decoder.frameCount; i < max; i++) {\n                UIImage *img = [self animatedImageFrameAtIndex:i];\n                if (img) {\n                    [frames addObject:img];\n                } else {\n                    [frames addObject:[NSNull null]];\n                }\n            }\n            dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER);\n            _preloadedFrames = frames;\n            dispatch_semaphore_signal(_preloadedLock);\n        } else {\n            dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER);\n            _preloadedFrames = nil;\n            dispatch_semaphore_signal(_preloadedLock);\n        }\n    }\n}\n\n#pragma mark - protocol NSCoding\n\n- (instancetype)initWithCoder:(NSCoder *)aDecoder {\n    NSNumber *scale = [aDecoder decodeObjectForKey:@\"YYImageScale\"];\n    NSData *data = [aDecoder decodeObjectForKey:@\"YYImageData\"];\n    if (data.length) {\n        self = [self initWithData:data scale:scale.doubleValue];\n    } else {\n        self = [super initWithCoder:aDecoder];\n    }\n    return self;\n}\n\n- (void)encodeWithCoder:(NSCoder *)aCoder {\n    if (_decoder.data.length) {\n        [aCoder encodeObject:@(self.scale) forKey:@\"YYImageScale\"];\n        [aCoder encodeObject:_decoder.data forKey:@\"YYImageData\"];\n    } else {\n        [super encodeWithCoder:aCoder]; // Apple use UIImagePNGRepresentation() to encode UIImage.\n    }\n}\n\n+ (BOOL)supportsSecureCoding {\n    return  YES;\n}\n\n#pragma mark - protocol YYAnimatedImage\n\n- (NSUInteger)animatedImageFrameCount {\n    return _decoder.frameCount;\n}\n\n- (NSUInteger)animatedImageLoopCount {\n    return _decoder.loopCount;\n}\n\n- (NSUInteger)animatedImageBytesPerFrame {\n    return _bytesPerFrame;\n}\n\n- (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index {\n    if (index >= _decoder.frameCount) return nil;\n    dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER);\n    UIImage *image = _preloadedFrames[index];\n    dispatch_semaphore_signal(_preloadedLock);\n    if (image) return image == (id)[NSNull null] ? nil : image;\n    return [_decoder frameAtIndex:index decodeForDisplay:YES].image;\n}\n\n- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index {\n    NSTimeInterval duration = [_decoder frameDurationAtIndex:index];\n    \n    /*\n     http://opensource.apple.com/source/WebCore/WebCore-7600.1.25/platform/graphics/cg/ImageSourceCG.cpp\n     Many annoying ads specify a 0 duration to make an image flash as quickly as \n     possible. We follow Safari and Firefox's behavior and use a duration of 100 ms \n     for any frames that specify a duration of <= 10 ms.\n     See <rdar://problem/7689300> and <http://webkit.org/b/36082> for more information.\n     \n     See also: http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser.\n     */\n    if (duration < 0.011f) return 0.100f;\n    return duration;\n}\n\n@end\n"
  },
  {
    "path": "YYImage/YYImageCoder.h",
    "content": "//\n//  YYImageCoder.h\n//  YYImage <https://github.com/ibireme/YYImage>\n//\n//  Created by ibireme on 15/5/13.\n//  Copyright (c) 2015 ibireme.\n//\n//  This source code is licensed under the MIT-style license found in the\n//  LICENSE file in the root directory of this source tree.\n//\n\n#import <UIKit/UIKit.h>\n\nNS_ASSUME_NONNULL_BEGIN\n\n/**\n Image file type.\n */\ntypedef NS_ENUM(NSUInteger, YYImageType) {\n    YYImageTypeUnknown = 0, ///< unknown\n    YYImageTypeJPEG,        ///< jpeg, jpg\n    YYImageTypeJPEG2000,    ///< jp2\n    YYImageTypeTIFF,        ///< tiff, tif\n    YYImageTypeBMP,         ///< bmp\n    YYImageTypeICO,         ///< ico\n    YYImageTypeICNS,        ///< icns\n    YYImageTypeGIF,         ///< gif\n    YYImageTypePNG,         ///< png\n    YYImageTypeWebP,        ///< webp\n    YYImageTypeOther,       ///< other image format\n};\n\n\n/**\n Dispose method specifies how the area used by the current frame is to be treated\n before rendering the next frame on the canvas.\n */\ntypedef NS_ENUM(NSUInteger, YYImageDisposeMethod) {\n    \n    /**\n     No disposal is done on this frame before rendering the next; the contents\n     of the canvas are left as is.\n     */\n    YYImageDisposeNone = 0,\n    \n    /**\n     The frame's region of the canvas is to be cleared to fully transparent black\n     before rendering the next frame.\n     */\n    YYImageDisposeBackground,\n    \n    /**\n     The frame's region of the canvas is to be reverted to the previous contents\n     before rendering the next frame.\n     */\n    YYImageDisposePrevious,\n};\n\n/**\n Blend operation specifies how transparent pixels of the current frame are\n blended with those of the previous canvas.\n */\ntypedef NS_ENUM(NSUInteger, YYImageBlendOperation) {\n    \n    /**\n     All color components of the frame, including alpha, overwrite the current\n     contents of the frame's canvas region.\n     */\n    YYImageBlendNone = 0,\n    \n    /**\n     The frame should be composited onto the output buffer based on its alpha.\n     */\n    YYImageBlendOver,\n};\n\n/**\n An image frame object.\n */\n@interface YYImageFrame : NSObject <NSCopying>\n@property (nonatomic) NSUInteger index;    ///< Frame index (zero based)\n@property (nonatomic) NSUInteger width;    ///< Frame width\n@property (nonatomic) NSUInteger height;   ///< Frame height\n@property (nonatomic) NSUInteger offsetX;  ///< Frame origin.x in canvas (left-bottom based)\n@property (nonatomic) NSUInteger offsetY;  ///< Frame origin.y in canvas (left-bottom based)\n@property (nonatomic) NSTimeInterval duration;          ///< Frame duration in seconds\n@property (nonatomic) YYImageDisposeMethod dispose;     ///< Frame dispose method.\n@property (nonatomic) YYImageBlendOperation blend;      ///< Frame blend operation.\n@property (nullable, nonatomic, strong) UIImage *image; ///< The image.\n+ (instancetype)frameWithImage:(UIImage *)image;\n@end\n\n\n#pragma mark - Decoder\n\n/**\n An image decoder to decode image data.\n \n @discussion This class supports decoding animated WebP, APNG, GIF and system\n image format such as PNG, JPG, JP2, BMP, TIFF, PIC, ICNS and ICO. It can be used \n to decode complete image data, or to decode incremental image data during image \n download. This class is thread-safe.\n \n Example:\n \n    // Decode single image:\n    NSData *data = [NSData dataWithContentOfFile:@\"/tmp/image.webp\"];\n    YYImageDecoder *decoder = [YYImageDecoder decoderWithData:data scale:2.0];\n    UIImage image = [decoder frameAtIndex:0 decodeForDisplay:YES].image;\n \n    // Decode image during download:\n    NSMutableData *data = [NSMutableData new];\n    YYImageDecoder *decoder = [[YYImageDecoder alloc] initWithScale:2.0];\n    while(newDataArrived) {\n        [data appendData:newData];\n        [decoder updateData:data final:NO];\n        if (decoder.frameCount > 0) {\n            UIImage image = [decoder frameAtIndex:0 decodeForDisplay:YES].image;\n            // progressive display...\n        }\n    }\n    [decoder updateData:data final:YES];\n    UIImage image = [decoder frameAtIndex:0 decodeForDisplay:YES].image;\n    // final display...\n \n */\n@interface YYImageDecoder : NSObject\n\n@property (nullable, nonatomic, readonly) NSData *data;    ///< Image data.\n@property (nonatomic, readonly) YYImageType type;          ///< Image data type.\n@property (nonatomic, readonly) CGFloat scale;             ///< Image scale.\n@property (nonatomic, readonly) NSUInteger frameCount;     ///< Image frame count.\n@property (nonatomic, readonly) NSUInteger loopCount;      ///< Image loop count, 0 means infinite.\n@property (nonatomic, readonly) NSUInteger width;          ///< Image canvas width.\n@property (nonatomic, readonly) NSUInteger height;         ///< Image canvas height.\n@property (nonatomic, readonly, getter=isFinalized) BOOL finalized;\n\n/**\n Creates an image decoder.\n \n @param scale  Image's scale.\n @return An image decoder.\n */\n- (instancetype)initWithScale:(CGFloat)scale NS_DESIGNATED_INITIALIZER;\n\n/**\n Updates the incremental image with new data.\n \n @discussion You can use this method to decode progressive/interlaced/baseline\n image when you do not have the complete image data. The `data` was retained by\n decoder, you should not modify the data in other thread during decoding.\n \n @param data  The data to add to the image decoder. Each time you call this \n function, the 'data' parameter must contain all of the image file data \n accumulated so far.\n \n @param final  A value that specifies whether the data is the final set. \n Pass YES if it is, NO otherwise. When the data is already finalized, you can\n not update the data anymore.\n \n @return Whether succeed.\n */\n- (BOOL)updateData:(nullable NSData *)data final:(BOOL)final;\n\n/**\n Convenience method to create a decoder with specified data.\n @param data  Image data.\n @param scale Image's scale.\n @return A new decoder, or nil if an error occurs.\n */\n+ (nullable instancetype)decoderWithData:(NSData *)data scale:(CGFloat)scale;\n\n/**\n Decodes and returns a frame from a specified index.\n @param index  Frame image index (zero-based).\n @param decodeForDisplay Whether decode the image to memory bitmap for display.\n    If NO, it will try to returns the original frame data without blend.\n @return A new frame with image, or nil if an error occurs.\n */\n- (nullable YYImageFrame *)frameAtIndex:(NSUInteger)index decodeForDisplay:(BOOL)decodeForDisplay;\n\n/**\n Returns the frame duration from a specified index.\n @param index  Frame image (zero-based).\n @return Duration in seconds.\n */\n- (NSTimeInterval)frameDurationAtIndex:(NSUInteger)index;\n\n/**\n Returns the frame's properties. See \"CGImageProperties.h\" in ImageIO.framework\n for more information.\n \n @param index  Frame image index (zero-based).\n @return The ImageIO frame property.\n */\n- (nullable NSDictionary *)framePropertiesAtIndex:(NSUInteger)index;\n\n/**\n Returns the image's properties. See \"CGImageProperties.h\" in ImageIO.framework\n for more information.\n */\n- (nullable NSDictionary *)imageProperties;\n\n@end\n\n\n\n#pragma mark - Encoder\n\n/**\n An image encoder to encode image to data.\n \n @discussion It supports encoding single frame image with the type defined in YYImageType.\n It also supports encoding multi-frame image with GIF, APNG and WebP.\n \n Example:\n    \n    YYImageEncoder *jpegEncoder = [[YYImageEncoder alloc] initWithType:YYImageTypeJPEG];\n    jpegEncoder.quality = 0.9;\n    [jpegEncoder addImage:image duration:0];\n    NSData jpegData = [jpegEncoder encode];\n \n    YYImageEncoder *gifEncoder = [[YYImageEncoder alloc] initWithType:YYImageTypeGIF];\n    gifEncoder.loopCount = 5;\n    [gifEncoder addImage:image0 duration:0.1];\n    [gifEncoder addImage:image1 duration:0.15];\n    [gifEncoder addImage:image2 duration:0.2];\n    NSData gifData = [gifEncoder encode];\n \n @warning It just pack the images together when encoding multi-frame image. If you\n want to reduce the image file size, try imagemagick/ffmpeg for GIF and WebP,\n and apngasm for APNG.\n */\n@interface YYImageEncoder : NSObject\n\n@property (nonatomic, readonly) YYImageType type; ///< Image type.\n@property (nonatomic) NSUInteger loopCount;       ///< Loop count, 0 means infinit, only available for GIF/APNG/WebP.\n@property (nonatomic) BOOL lossless;              ///< Lossless, only available for WebP.\n@property (nonatomic) CGFloat quality;            ///< Compress quality, 0.0~1.0, only available for JPG/JP2/WebP.\n\n- (instancetype)init UNAVAILABLE_ATTRIBUTE;\n+ (instancetype)new UNAVAILABLE_ATTRIBUTE;\n\n/**\n Create an image encoder with a specified type.\n @param type Image type.\n @return A new encoder, or nil if an error occurs.\n */\n- (nullable instancetype)initWithType:(YYImageType)type NS_DESIGNATED_INITIALIZER;\n\n/**\n Add an image to encoder.\n @param image    Image.\n @param duration Image duration for animation. Pass 0 to ignore this parameter.\n */\n- (void)addImage:(UIImage *)image duration:(NSTimeInterval)duration;\n\n/**\n Add an image with image data to encoder.\n @param data    Image data.\n @param duration Image duration for animation. Pass 0 to ignore this parameter.\n */\n- (void)addImageWithData:(NSData *)data duration:(NSTimeInterval)duration;\n\n/**\n Add an image from a file path to encoder.\n @param path    Image file path.\n @param duration Image duration for animation. Pass 0 to ignore this parameter.\n */\n- (void)addImageWithFile:(NSString *)path duration:(NSTimeInterval)duration;\n\n/**\n Encodes the image and returns the image data.\n @return The image data, or nil if an error occurs.\n */\n- (nullable NSData *)encode;\n\n/**\n Encodes the image to a file.\n @param path The file path (overwrite if exist).\n @return Whether succeed.\n */\n- (BOOL)encodeToFile:(NSString *)path;\n\n/**\n Convenience method to encode single frame image.\n @param image   The image.\n @param type    The destination image type.\n @param quality Image quality, 0.0~1.0.\n @return The image data, or nil if an error occurs.\n */\n+ (nullable NSData *)encodeImage:(UIImage *)image type:(YYImageType)type quality:(CGFloat)quality;\n\n/**\n Convenience method to encode image from a decoder.\n @param decoder The image decoder.\n @param type    The destination image type;\n @param quality Image quality, 0.0~1.0.\n @return The image data, or nil if an error occurs.\n */\n+ (nullable NSData *)encodeImageWithDecoder:(YYImageDecoder *)decoder type:(YYImageType)type quality:(CGFloat)quality;\n\n@end\n\n\n#pragma mark - UIImage\n\n@interface UIImage (YYImageCoder)\n\n/**\n Decompress this image to bitmap, so when the image is displayed on screen, \n the main thread won't be blocked by additional decode. If the image has already\n been decoded or unable to decode, it just returns itself.\n \n @return an image decoded, or just return itself if no needed.\n @see yy_isDecodedForDisplay\n */\n- (instancetype)yy_imageByDecoded;\n\n/**\n Wherher the image can be display on screen without additional decoding.\n @warning It just a hint for your code, change it has no other effect.\n */\n@property (nonatomic) BOOL yy_isDecodedForDisplay;\n\n/**\n Saves this image to iOS Photos Album. \n \n @discussion  This method attempts to save the original data to album if the\n image is created from an animated GIF/APNG, otherwise, it will save the image \n as JPEG or PNG (based on the alpha information).\n \n @param completionBlock The block invoked (in main thread) after the save operation completes.\n */\n- (void)yy_saveToAlbumWithCompletionBlock:(void(^)(BOOL success, id asset)) completionBlock;\n/**\n Return a 'best' data representation for this image.\n \n @discussion The convertion based on these rule:\n 1. If the image is created from an animated GIF/APNG/WebP, it returns the original data.\n 2. It returns PNG or JPEG(0.9) representation based on the alpha information.\n \n @return Image data, or nil if an error occurs.\n */\n- (nullable NSData *)yy_imageDataRepresentation;\n\n@end\n\n\n\n#pragma mark - Helper\n\n/// Detect a data's image type by reading the data's header 16 bytes (very fast).\nCG_EXTERN YYImageType YYImageDetectType(CFDataRef data);\n\n/// Convert YYImageType to UTI (such as kUTTypeJPEG).\nCG_EXTERN CFStringRef _Nullable YYImageTypeToUTType(YYImageType type);\n\n/// Convert UTI (such as kUTTypeJPEG) to YYImageType.\nCG_EXTERN YYImageType YYImageTypeFromUTType(CFStringRef uti);\n\n/// Get image type's file extension (such as @\"jpg\").\nCG_EXTERN NSString *_Nullable YYImageTypeGetExtension(YYImageType type);\n\n\n\n/// Returns the shared DeviceRGB color space.\nCG_EXTERN CGColorSpaceRef YYCGColorSpaceGetDeviceRGB(void);\n\n/// Returns the shared DeviceGray color space.\nCG_EXTERN CGColorSpaceRef YYCGColorSpaceGetDeviceGray(void);\n\n/// Returns whether a color space is DeviceRGB.\nCG_EXTERN BOOL YYCGColorSpaceIsDeviceRGB(CGColorSpaceRef space);\n\n/// Returns whether a color space is DeviceGray.\nCG_EXTERN BOOL YYCGColorSpaceIsDeviceGray(CGColorSpaceRef space);\n\n\n\n/// Convert EXIF orientation value to UIImageOrientation.\nCG_EXTERN UIImageOrientation YYUIImageOrientationFromEXIFValue(NSInteger value);\n\n/// Convert UIImageOrientation to EXIF orientation value.\nCG_EXTERN NSInteger YYUIImageOrientationToEXIFValue(UIImageOrientation orientation);\n\n\n\n/**\n Create a decoded image.\n \n @discussion If the source image is created from a compressed image data (such as\n PNG or JPEG), you can use this method to decode the image. After decoded, you can\n access the decoded bytes with CGImageGetDataProvider() and CGDataProviderCopyData()\n without additional decode process. If the image has already decoded, this method\n just copy the decoded bytes to the new image.\n \n @param imageRef          The source image.\n @param decodeForDisplay  If YES, this method will decode the image and convert\n          it to BGRA8888 (premultiplied) or BGRX8888 format for CALayer display.\n \n @return A decoded image, or NULL if an error occurs.\n */\nCG_EXTERN CGImageRef _Nullable YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decodeForDisplay);\n\n/**\n Create an image copy with an orientation.\n \n @param imageRef       Source image\n @param orientation    Image orientation which will applied to the image.\n @param destBitmapInfo Destimation image bitmap, only support 32bit format (such as ARGB8888).\n @return A new image, or NULL if an error occurs.\n */\nCG_EXTERN CGImageRef _Nullable YYCGImageCreateCopyWithOrientation(CGImageRef imageRef,\n                                                                  UIImageOrientation orientation,\n                                                                  CGBitmapInfo destBitmapInfo);\n\n/**\n Create an image copy with CGAffineTransform.\n \n @param imageRef       Source image.\n @param transform      Transform applied to image (left-bottom based coordinate system).\n @param destSize       Destination image size\n @param destBitmapInfo Destimation image bitmap, only support 32bit format (such as ARGB8888).\n @return A new image, or NULL if an error occurs.\n */\nCG_EXTERN CGImageRef _Nullable YYCGImageCreateAffineTransformCopy(CGImageRef imageRef,\n                                                                  CGAffineTransform transform,\n                                                                  CGSize destSize,\n                                                                  CGBitmapInfo destBitmapInfo);\n\n/**\n Encode an image to data with CGImageDestination.\n \n @param imageRef  The image.\n @param type      The image destination data type.\n @param quality   The quality (0.0~1.0)\n @return A new image data, or nil if an error occurs.\n */\nCG_EXTERN CFDataRef _Nullable YYCGImageCreateEncodedData(CGImageRef imageRef, YYImageType type, CGFloat quality);\n\n\n/**\n Whether WebP is available in YYImage.\n */\nCG_EXTERN BOOL YYImageWebPAvailable(void);\n\n/**\n Get a webp image frame count;\n \n @param webpData WebP data.\n @return Image frame count, or 0 if an error occurs.\n */\nCG_EXTERN NSUInteger YYImageGetWebPFrameCount(CFDataRef webpData);\n\n/**\n Decode an image from WebP data, returns NULL if an error occurs.\n \n @param webpData          The WebP data.\n @param decodeForDisplay  If YES, this method will decode the image and convert it\n                            to BGRA8888 (premultiplied) format for CALayer display.\n @param useThreads        YES to enable multi-thread decode.\n                            (speed up, but cost more CPU)\n @param bypassFiltering   YES to skip the in-loop filtering.\n                            (speed up, but may lose some smooth)\n @param noFancyUpsampling YES to use faster pointwise upsampler.\n                            (speed down, and may lose some details).\n @return The decoded image, or NULL if an error occurs.\n */\nCG_EXTERN CGImageRef _Nullable YYCGImageCreateWithWebPData(CFDataRef webpData,\n                                                           BOOL decodeForDisplay,\n                                                           BOOL useThreads,\n                                                           BOOL bypassFiltering,\n                                                           BOOL noFancyUpsampling);\n\ntypedef NS_ENUM(NSUInteger, YYImagePreset) {\n    YYImagePresetDefault = 0,  ///< default preset.\n    YYImagePresetPicture,      ///< digital picture, like portrait, inner shot\n    YYImagePresetPhoto,        ///< outdoor photograph, with natural lighting\n    YYImagePresetDrawing,      ///< hand or line drawing, with high-contrast details\n    YYImagePresetIcon,         ///< small-sized colorful images\n    YYImagePresetText          ///< text-like\n};\n\n/**\n Encode a CGImage to WebP data\n \n @param imageRef      image\n @param lossless      YES=lossless (similar to PNG), NO=lossy (similar to JPEG)\n @param quality       0.0~1.0 (0=smallest file, 1.0=biggest file)\n                      For lossless image, try the value near 1.0; for lossy, try the value near 0.8.\n @param compressLevel 0~6 (0=fast, 6=slower-better). Default is 4.\n @param preset        Preset for different image type, default is YYImagePresetDefault.\n @return WebP data, or nil if an error occurs.\n */\nCG_EXTERN CFDataRef _Nullable YYCGImageCreateEncodedWebPData(CGImageRef imageRef,\n                                                             BOOL lossless,\n                                                             CGFloat quality,\n                                                             int compressLevel,\n                                                             YYImagePreset preset);\n\nNS_ASSUME_NONNULL_END\n"
  },
  {
    "path": "YYImage/YYImageCoder.m",
    "content": "//\n//  YYImageCoder.m\n//  YYImage <https://github.com/ibireme/YYImage>\n//\n//  Created by ibireme on 15/5/13.\n//  Copyright (c) 2015 ibireme.\n//\n//  This source code is licensed under the MIT-style license found in the\n//  LICENSE file in the root directory of this source tree.\n//\n\n#import \"YYImageCoder.h\"\n#import \"YYImage.h\"\n#import <CoreFoundation/CoreFoundation.h>\n#import <ImageIO/ImageIO.h>\n#import <Accelerate/Accelerate.h>\n#import <QuartzCore/QuartzCore.h>\n\n#if __has_include(<MobileCoreServices/MobileCoreServices.h>)\n#import <MobileCoreServices/MobileCoreServices.h>\n#else\n#import <CoreServices/CoreServices.h>\n#endif\n\n#if TARGET_OS_IOS\n#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0\n#import <AssetsLibrary/AssetsLibrary.h>\n#else\n#import <Photos/Photos.h>\n#endif\n#endif\n#import <objc/runtime.h>\n#import <pthread.h>\n#import <zlib.h>\n\n\n#if !TARGET_OS_MACCATALYST\n#ifndef YYIMAGE_WEBP_ENABLED\n#if __has_include(<WebP/decode.h>) && __has_include(<WebP/encode.h>) && \\\n    __has_include(<WebP/demux.h>)  && __has_include(<WebP/mux.h>)\n#define YYIMAGE_WEBP_ENABLED 1\n#import <WebP/decode.h>\n#import <WebP/encode.h>\n#import <WebP/demux.h>\n#import <WebP/mux.h>\n#elif __has_include(\"webp/decode.h\") && __has_include(\"webp/encode.h\") && \\\n      __has_include(\"webp/demux.h\")  && __has_include(\"webp/mux.h\")\n#define YYIMAGE_WEBP_ENABLED 1\n#import \"webp/decode.h\"\n#import \"webp/encode.h\"\n#import \"webp/demux.h\"\n#import \"webp/mux.h\"\n#else\n#define YYIMAGE_WEBP_ENABLED 0\n#endif\n#endif\n#else\n#define YYIMAGE_WEBP_ENABLED 0\n#endif\n\n\n\n\n////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Utility (for little endian platform)\n\n#define YY_FOUR_CC(c1,c2,c3,c4) ((uint32_t)(((c4) << 24) | ((c3) << 16) | ((c2) << 8) | (c1)))\n#define YY_TWO_CC(c1,c2) ((uint16_t)(((c2) << 8) | (c1)))\n\nstatic inline uint16_t yy_swap_endian_uint16(uint16_t value) {\n    return\n    (uint16_t) ((value & 0x00FF) << 8) |\n    (uint16_t) ((value & 0xFF00) >> 8) ;\n}\n\nstatic inline uint32_t yy_swap_endian_uint32(uint32_t value) {\n    return\n    (uint32_t)((value & 0x000000FFU) << 24) |\n    (uint32_t)((value & 0x0000FF00U) <<  8) |\n    (uint32_t)((value & 0x00FF0000U) >>  8) |\n    (uint32_t)((value & 0xFF000000U) >> 24) ;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n#pragma mark - APNG\n\n/*\n PNG  spec: http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html\n APNG spec: https://wiki.mozilla.org/APNG_Specification\n \n ===============================================================================\n PNG format:\n header (8): 89 50 4e 47 0d 0a 1a 0a\n chunk, chunk, chunk, ...\n \n ===============================================================================\n chunk format:\n length (4): uint32_t big endian\n fourcc (4): chunk type code\n data   (length): data\n crc32  (4): uint32_t big endian crc32(fourcc + data)\n \n ===============================================================================\n PNG chunk define:\n \n IHDR (Image Header) required, must appear first, 13 bytes\n width              (4) pixel count, should not be zero\n height             (4) pixel count, should not be zero\n bit depth          (1) expected: 1, 2, 4, 8, 16\n color type         (1) 1<<0 (palette used), 1<<1 (color used), 1<<2 (alpha channel used)\n compression method (1) 0 (deflate/inflate)\n filter method      (1) 0 (adaptive filtering with five basic filter types)\n interlace method   (1) 0 (no interlace) or 1 (Adam7 interlace)\n \n IDAT (Image Data) required, must appear consecutively if there's multiple 'IDAT' chunk\n \n IEND (End) required, must appear last, 0 bytes\n \n ===============================================================================\n APNG chunk define:\n \n acTL (Animation Control) required, must appear before 'IDAT', 8 bytes\n num frames     (4) number of frames\n num plays      (4) number of times to loop, 0 indicates infinite looping\n \n fcTL (Frame Control) required, must appear before the 'IDAT' or 'fdAT' chunks of the frame to which it applies, 26 bytes\n sequence number   (4) sequence number of the animation chunk, starting from 0\n width             (4) width of the following frame\n height            (4) height of the following frame\n x offset          (4) x position at which to render the following frame\n y offset          (4) y position at which to render the following frame\n delay num         (2) frame delay fraction numerator\n delay den         (2) frame delay fraction denominator\n dispose op        (1) type of frame area disposal to be done after rendering this frame (0:none, 1:background 2:previous)\n blend op          (1) type of frame area rendering for this frame (0:source, 1:over)\n \n fdAT (Frame Data) required\n sequence number   (4) sequence number of the animation chunk\n frame data        (x) frame data for this frame (same as 'IDAT')\n \n ===============================================================================\n `dispose_op` specifies how the output buffer should be changed at the end of the delay \n (before rendering the next frame).\n \n * NONE: no disposal is done on this frame before rendering the next; the contents\n    of the output buffer are left as is.\n * BACKGROUND: the frame's region of the output buffer is to be cleared to fully\n    transparent black before rendering the next frame.\n * PREVIOUS: the frame's region of the output buffer is to be reverted to the previous\n    contents before rendering the next frame.\n\n `blend_op` specifies whether the frame is to be alpha blended into the current output buffer\n content, or whether it should completely replace its region in the output buffer.\n \n * SOURCE: all color components of the frame, including alpha, overwrite the current contents\n    of the frame's output buffer region. \n * OVER: the frame should be composited onto the output buffer based on its alpha,\n    using a simple OVER operation as described in the \"Alpha Channel Processing\" section\n    of the PNG specification\n */\n\ntypedef enum {\n    YY_PNG_ALPHA_TYPE_PALEETE = 1 << 0,\n    YY_PNG_ALPHA_TYPE_COLOR = 1 << 1,\n    YY_PNG_ALPHA_TYPE_ALPHA = 1 << 2,\n} yy_png_alpha_type;\n\ntypedef enum {\n    YY_PNG_DISPOSE_OP_NONE = 0,\n    YY_PNG_DISPOSE_OP_BACKGROUND = 1,\n    YY_PNG_DISPOSE_OP_PREVIOUS = 2,\n} yy_png_dispose_op;\n\ntypedef enum {\n    YY_PNG_BLEND_OP_SOURCE = 0,\n    YY_PNG_BLEND_OP_OVER = 1,\n} yy_png_blend_op;\n\ntypedef struct {\n    uint32_t width;             ///< pixel count, should not be zero\n    uint32_t height;            ///< pixel count, should not be zero\n    uint8_t bit_depth;          ///< expected: 1, 2, 4, 8, 16\n    uint8_t color_type;         ///< see yy_png_alpha_type\n    uint8_t compression_method; ///< 0 (deflate/inflate)\n    uint8_t filter_method;      ///< 0 (adaptive filtering with five basic filter types)\n    uint8_t interlace_method;   ///< 0 (no interlace) or 1 (Adam7 interlace)\n} yy_png_chunk_IHDR;\n\ntypedef struct {\n    uint32_t sequence_number;  ///< sequence number of the animation chunk, starting from 0\n    uint32_t width;            ///< width of the following frame\n    uint32_t height;           ///< height of the following frame\n    uint32_t x_offset;         ///< x position at which to render the following frame\n    uint32_t y_offset;         ///< y position at which to render the following frame\n    uint16_t delay_num;        ///< frame delay fraction numerator\n    uint16_t delay_den;        ///< frame delay fraction denominator\n    uint8_t dispose_op;        ///< see yy_png_dispose_op\n    uint8_t blend_op;          ///< see yy_png_blend_op\n} yy_png_chunk_fcTL;\n\ntypedef struct {\n    uint32_t offset; ///< chunk offset in PNG data\n    uint32_t fourcc; ///< chunk fourcc\n    uint32_t length; ///< chunk data length\n    uint32_t crc32;  ///< chunk crc32\n} yy_png_chunk_info;\n\ntypedef struct {\n    uint32_t chunk_index; ///< the first `fdAT`/`IDAT` chunk index\n    uint32_t chunk_num;   ///< the `fdAT`/`IDAT` chunk count\n    uint32_t chunk_size;  ///< the `fdAT`/`IDAT` chunk bytes\n    yy_png_chunk_fcTL frame_control;\n} yy_png_frame_info;\n\ntypedef struct {\n    yy_png_chunk_IHDR header;   ///< png header\n    yy_png_chunk_info *chunks;      ///< chunks\n    uint32_t chunk_num;          ///< count of chunks\n    \n    yy_png_frame_info *apng_frames; ///< frame info, NULL if not apng\n    uint32_t apng_frame_num;     ///< 0 if not apng\n    uint32_t apng_loop_num;      ///< 0 indicates infinite looping\n    \n    uint32_t *apng_shared_chunk_indexs; ///< shared chunk index\n    uint32_t apng_shared_chunk_num;     ///< shared chunk count\n    uint32_t apng_shared_chunk_size;    ///< shared chunk bytes\n    uint32_t apng_shared_insert_index;  ///< shared chunk insert index\n    bool apng_first_frame_is_cover;     ///< the first frame is same as png (cover)\n} yy_png_info;\n\nstatic void yy_png_chunk_IHDR_read(yy_png_chunk_IHDR *IHDR, const uint8_t *data) {\n    IHDR->width = yy_swap_endian_uint32(*((uint32_t *)(data)));\n    IHDR->height = yy_swap_endian_uint32(*((uint32_t *)(data + 4)));\n    IHDR->bit_depth = data[8];\n    IHDR->color_type = data[9];\n    IHDR->compression_method = data[10];\n    IHDR->filter_method = data[11];\n    IHDR->interlace_method = data[12];\n}\n\nstatic void yy_png_chunk_IHDR_write(yy_png_chunk_IHDR *IHDR, uint8_t *data) {\n    *((uint32_t *)(data)) = yy_swap_endian_uint32(IHDR->width);\n    *((uint32_t *)(data + 4)) = yy_swap_endian_uint32(IHDR->height);\n    data[8] = IHDR->bit_depth;\n    data[9] = IHDR->color_type;\n    data[10] = IHDR->compression_method;\n    data[11] = IHDR->filter_method;\n    data[12] = IHDR->interlace_method;\n}\n\nstatic void yy_png_chunk_fcTL_read(yy_png_chunk_fcTL *fcTL, const uint8_t *data) {\n    fcTL->sequence_number = yy_swap_endian_uint32(*((uint32_t *)(data)));\n    fcTL->width = yy_swap_endian_uint32(*((uint32_t *)(data + 4)));\n    fcTL->height = yy_swap_endian_uint32(*((uint32_t *)(data + 8)));\n    fcTL->x_offset = yy_swap_endian_uint32(*((uint32_t *)(data + 12)));\n    fcTL->y_offset = yy_swap_endian_uint32(*((uint32_t *)(data + 16)));\n    fcTL->delay_num = yy_swap_endian_uint16(*((uint16_t *)(data + 20)));\n    fcTL->delay_den = yy_swap_endian_uint16(*((uint16_t *)(data + 22)));\n    fcTL->dispose_op = data[24];\n    fcTL->blend_op = data[25];\n}\n\nstatic void yy_png_chunk_fcTL_write(yy_png_chunk_fcTL *fcTL, uint8_t *data) {\n    *((uint32_t *)(data)) = yy_swap_endian_uint32(fcTL->sequence_number);\n    *((uint32_t *)(data + 4)) = yy_swap_endian_uint32(fcTL->width);\n    *((uint32_t *)(data + 8)) = yy_swap_endian_uint32(fcTL->height);\n    *((uint32_t *)(data + 12)) = yy_swap_endian_uint32(fcTL->x_offset);\n    *((uint32_t *)(data + 16)) = yy_swap_endian_uint32(fcTL->y_offset);\n    *((uint16_t *)(data + 20)) = yy_swap_endian_uint16(fcTL->delay_num);\n    *((uint16_t *)(data + 22)) = yy_swap_endian_uint16(fcTL->delay_den);\n    data[24] = fcTL->dispose_op;\n    data[25] = fcTL->blend_op;\n}\n\n// convert double value to fraction\nstatic void yy_png_delay_to_fraction(double duration, uint16_t *num, uint16_t *den) {\n    if (duration >= 0xFF) {\n        *num = 0xFF;\n        *den = 1;\n    } else if (duration <= 1.0 / (double)0xFF) {\n        *num = 1;\n        *den = 0xFF;\n    } else {\n        // Use continued fraction to calculate the num and den.\n        long MAX = 10;\n        double eps = (0.5 / (double)0xFF);\n        long p[MAX], q[MAX], a[MAX], i, numl = 0, denl = 0;\n        // The first two convergents are 0/1 and 1/0\n        p[0] = 0; q[0] = 1;\n        p[1] = 1; q[1] = 0;\n        // The rest of the convergents (and continued fraction)\n        for (i = 2; i < MAX; i++) {\n            a[i] = lrint(floor(duration));\n            p[i] = a[i] * p[i - 1] + p[i - 2];\n            q[i] = a[i] * q[i - 1] + q[i - 2];\n            if (p[i] <= 0xFF && q[i] <= 0xFF) { // uint16_t\n                numl = p[i];\n                denl = q[i];\n            } else break;\n            if (fabs(duration - a[i]) < eps) break;\n            duration = 1.0 / (duration - a[i]);\n        }\n        \n        if (numl != 0 && denl != 0) {\n            *num = numl;\n            *den = denl;\n        } else {\n            *num = 1;\n            *den = 100;\n        }\n    }\n}\n\n// convert fraction to double value\nstatic double yy_png_delay_to_seconds(uint16_t num, uint16_t den) {\n    if (den == 0) {\n        return num / 100.0;\n    } else {\n        return (double)num / (double)den;\n    }\n}\n\nstatic bool yy_png_validate_animation_chunk_order(yy_png_chunk_info *chunks,  /* input */\n                                                  uint32_t chunk_num,         /* input */\n                                                  uint32_t *first_idat_index, /* output */\n                                                  bool *first_frame_is_cover  /* output */) {\n    /*\n     PNG at least contains 3 chunks: IHDR, IDAT, IEND.\n     `IHDR` must appear first.\n     `IDAT` must appear consecutively.\n     `IEND` must appear end.\n     \n     APNG must contains one `acTL` and at least one 'fcTL' and `fdAT`.\n     `fdAT` must appear consecutively.\n     `fcTL` must appear before `IDAT` or `fdAT`.\n     */\n    if (chunk_num <= 2) return false;\n    if (chunks->fourcc != YY_FOUR_CC('I', 'H', 'D', 'R')) return false;\n    if ((chunks + chunk_num - 1)->fourcc != YY_FOUR_CC('I', 'E', 'N', 'D')) return false;\n    \n    uint32_t prev_fourcc = 0;\n    uint32_t IHDR_num = 0;\n    uint32_t IDAT_num = 0;\n    uint32_t acTL_num = 0;\n    uint32_t fcTL_num = 0;\n    uint32_t first_IDAT = 0;\n    bool first_frame_cover = false;\n    for (uint32_t i = 0; i < chunk_num; i++) {\n        yy_png_chunk_info *chunk = chunks + i;\n        switch (chunk->fourcc) {\n            case YY_FOUR_CC('I', 'H', 'D', 'R'): {  // png header\n                if (i != 0) return false;\n                if (IHDR_num > 0) return false;\n                IHDR_num++;\n            } break;\n            case YY_FOUR_CC('I', 'D', 'A', 'T'): {  // png data\n                if (prev_fourcc != YY_FOUR_CC('I', 'D', 'A', 'T')) {\n                    if (IDAT_num == 0)\n                        first_IDAT = i;\n                    else\n                        return false;\n                }\n                IDAT_num++;\n            } break;\n            case YY_FOUR_CC('a', 'c', 'T', 'L'): {  // apng control\n                if (acTL_num > 0) return false;\n                acTL_num++;\n            } break;\n            case YY_FOUR_CC('f', 'c', 'T', 'L'): {  // apng frame control\n                if (i + 1 == chunk_num) return false;\n                if ((chunk + 1)->fourcc != YY_FOUR_CC('f', 'd', 'A', 'T') &&\n                    (chunk + 1)->fourcc != YY_FOUR_CC('I', 'D', 'A', 'T')) {\n                    return false;\n                }\n                if (fcTL_num == 0) {\n                    if ((chunk + 1)->fourcc == YY_FOUR_CC('I', 'D', 'A', 'T')) {\n                        first_frame_cover = true;\n                    }\n                }\n                fcTL_num++;\n            } break;\n            case YY_FOUR_CC('f', 'd', 'A', 'T'): {  // apng data\n                if (prev_fourcc != YY_FOUR_CC('f', 'd', 'A', 'T') && prev_fourcc != YY_FOUR_CC('f', 'c', 'T', 'L')) {\n                    return false;\n                }\n            } break;\n        }\n        prev_fourcc = chunk->fourcc;\n    }\n    if (IHDR_num != 1) return false;\n    if (IDAT_num == 0) return false;\n    if (acTL_num != 1) return false;\n    if (fcTL_num < acTL_num) return false;\n    *first_idat_index = first_IDAT;\n    *first_frame_is_cover = first_frame_cover;\n    return true;\n}\n\nstatic void yy_png_info_release(yy_png_info *info) {\n    if (info) {\n        if (info->chunks) free(info->chunks);\n        if (info->apng_frames) free(info->apng_frames);\n        if (info->apng_shared_chunk_indexs) free(info->apng_shared_chunk_indexs);\n        free(info);\n    }\n}\n\n/**\n Create a png info from a png file. See struct png_info for more information.\n \n @param data   png/apng file data.\n @param length the data's length in bytes.\n @return A png info object, you may call yy_png_info_release() to release it.\n Returns NULL if an error occurs.\n */\nstatic yy_png_info *yy_png_info_create(const uint8_t *data, uint32_t length) {\n    if (length < 32) return NULL;\n    if (*((uint32_t *)data) != YY_FOUR_CC(0x89, 0x50, 0x4E, 0x47)) return NULL;\n    if (*((uint32_t *)(data + 4)) != YY_FOUR_CC(0x0D, 0x0A, 0x1A, 0x0A)) return NULL;\n    \n    uint32_t chunk_realloc_num = 16;\n    yy_png_chunk_info *chunks = malloc(sizeof(yy_png_chunk_info) * chunk_realloc_num);\n    if (!chunks) return NULL;\n    \n    // parse png chunks\n    uint32_t offset = 8;\n    uint32_t chunk_num = 0;\n    uint32_t chunk_capacity = chunk_realloc_num;\n    uint32_t apng_loop_num = 0;\n    int32_t apng_sequence_index = -1;\n    int32_t apng_frame_index = 0;\n    int32_t apng_frame_number = -1;\n    bool apng_chunk_error = false;\n    do {\n        if (chunk_num >= chunk_capacity) {\n            yy_png_chunk_info *new_chunks = realloc(chunks, sizeof(yy_png_chunk_info) * (chunk_capacity + chunk_realloc_num));\n            if (!new_chunks) {\n                free(chunks);\n                return NULL;\n            }\n            chunks = new_chunks;\n            chunk_capacity += chunk_realloc_num;\n        }\n        yy_png_chunk_info *chunk = chunks + chunk_num;\n        const uint8_t *chunk_data = data + offset;\n        chunk->offset = offset;\n        chunk->length = yy_swap_endian_uint32(*((uint32_t *)chunk_data));\n        if ((uint64_t)chunk->offset + (uint64_t)chunk->length + 12 > length) {\n            free(chunks);\n            return NULL;\n        }\n        \n        chunk->fourcc = *((uint32_t *)(chunk_data + 4));\n        if ((uint64_t)chunk->offset + 4 + chunk->length + 4 > (uint64_t)length) break;\n        chunk->crc32 = yy_swap_endian_uint32(*((uint32_t *)(chunk_data + 8 + chunk->length)));\n        chunk_num++;\n        offset += 12 + chunk->length;\n        \n        switch (chunk->fourcc) {\n            case YY_FOUR_CC('a', 'c', 'T', 'L') : {\n                if (chunk->length == 8) {\n                    apng_frame_number = yy_swap_endian_uint32(*((uint32_t *)(chunk_data + 8)));\n                    apng_loop_num = yy_swap_endian_uint32(*((uint32_t *)(chunk_data + 12)));\n                } else {\n                    apng_chunk_error = true;\n                }\n            } break;\n            case YY_FOUR_CC('f', 'c', 'T', 'L') :\n            case YY_FOUR_CC('f', 'd', 'A', 'T') : {\n                if (chunk->fourcc == YY_FOUR_CC('f', 'c', 'T', 'L')) {\n                    if (chunk->length != 26) {\n                        apng_chunk_error = true;\n                    } else {\n                        apng_frame_index++;\n                    }\n                }\n                if (chunk->length > 4) {\n                    uint32_t sequence = yy_swap_endian_uint32(*((uint32_t *)(chunk_data + 8)));\n                    if (apng_sequence_index + 1 == sequence) {\n                        apng_sequence_index++;\n                    } else {\n                        apng_chunk_error = true;\n                    }\n                } else {\n                    apng_chunk_error = true;\n                }\n            } break;\n            case YY_FOUR_CC('I', 'E', 'N', 'D') : {\n                offset = length; // end, break do-while loop\n            } break;\n        }\n    } while (offset + 12 <= length);\n    \n    if (chunk_num < 3 ||\n        chunks->fourcc != YY_FOUR_CC('I', 'H', 'D', 'R') ||\n        chunks->length != 13) {\n        free(chunks);\n        return NULL;\n    }\n    \n    // png info\n    yy_png_info *info = calloc(1, sizeof(yy_png_info));\n    if (!info) {\n        free(chunks);\n        return NULL;\n    }\n    info->chunks = chunks;\n    info->chunk_num = chunk_num;\n    yy_png_chunk_IHDR_read(&info->header, data + chunks->offset + 8);\n    \n    // apng info\n    if (!apng_chunk_error && apng_frame_number == apng_frame_index && apng_frame_number >= 1) {\n        bool first_frame_is_cover = false;\n        uint32_t first_IDAT_index = 0;\n        if (!yy_png_validate_animation_chunk_order(info->chunks, info->chunk_num, &first_IDAT_index, &first_frame_is_cover)) {\n            return info; // ignore apng chunk\n        }\n        \n        info->apng_loop_num = apng_loop_num;\n        info->apng_frame_num = apng_frame_number;\n        info->apng_first_frame_is_cover = first_frame_is_cover;\n        info->apng_shared_insert_index = first_IDAT_index;\n        info->apng_frames = calloc(apng_frame_number, sizeof(yy_png_frame_info));\n        if (!info->apng_frames) {\n            yy_png_info_release(info);\n            return NULL;\n        }\n        info->apng_shared_chunk_indexs = calloc(info->chunk_num, sizeof(uint32_t));\n        if (!info->apng_shared_chunk_indexs) {\n            yy_png_info_release(info);\n            return NULL;\n        }\n        \n        int32_t frame_index = -1;\n        uint32_t *shared_chunk_index = info->apng_shared_chunk_indexs;\n        for (int32_t i = 0; i < info->chunk_num; i++) {\n            yy_png_chunk_info *chunk = info->chunks + i;\n            switch (chunk->fourcc) {\n                case YY_FOUR_CC('I', 'D', 'A', 'T'): {\n                    if (info->apng_shared_insert_index == 0) {\n                        info->apng_shared_insert_index = i;\n                    }\n                    if (first_frame_is_cover) {\n                        yy_png_frame_info *frame = info->apng_frames + frame_index;\n                        frame->chunk_num++;\n                        frame->chunk_size += chunk->length + 12;\n                    }\n                } break;\n                case YY_FOUR_CC('a', 'c', 'T', 'L'): {\n                } break;\n                case YY_FOUR_CC('f', 'c', 'T', 'L'): {\n                    frame_index++;\n                    yy_png_frame_info *frame = info->apng_frames + frame_index;\n                    frame->chunk_index = i + 1;\n                    yy_png_chunk_fcTL_read(&frame->frame_control, data + chunk->offset + 8);\n                } break;\n                case YY_FOUR_CC('f', 'd', 'A', 'T'): {\n                    yy_png_frame_info *frame = info->apng_frames + frame_index;\n                    frame->chunk_num++;\n                    frame->chunk_size += chunk->length + 12;\n                } break;\n                default: {\n                    *shared_chunk_index = i;\n                    shared_chunk_index++;\n                    info->apng_shared_chunk_size += chunk->length + 12;\n                    info->apng_shared_chunk_num++;\n                } break;\n            }\n        }\n    }\n    return info;\n}\n\n/**\n Copy a png frame data from an apng file.\n \n @param data  apng file data\n @param info  png info\n @param index frame index (zero-based)\n @param size  output, the size of the frame data\n @return A frame data (single-frame png file), call free() to release the data.\n Returns NULL if an error occurs.\n */\nstatic uint8_t *yy_png_copy_frame_data_at_index(const uint8_t *data,\n                                                const yy_png_info *info,\n                                                const uint32_t index,\n                                                uint32_t *size) {\n    if (index >= info->apng_frame_num) return NULL;\n    \n    yy_png_frame_info *frame_info = info->apng_frames + index;\n    uint32_t frame_remux_size = 8 /* PNG Header */ + info->apng_shared_chunk_size + frame_info->chunk_size;\n    if (!(info->apng_first_frame_is_cover && index == 0)) {\n        frame_remux_size -= frame_info->chunk_num * 4; // remove fdAT sequence number\n    }\n    uint8_t *frame_data = malloc(frame_remux_size);\n    if (!frame_data) return NULL;\n    *size = frame_remux_size;\n    \n    uint32_t data_offset = 0;\n    bool inserted = false;\n    memcpy(frame_data, data, 8); // PNG File Header\n    data_offset += 8;\n    for (uint32_t i = 0; i < info->apng_shared_chunk_num; i++) {\n        uint32_t shared_chunk_index = info->apng_shared_chunk_indexs[i];\n        yy_png_chunk_info *shared_chunk_info = info->chunks + shared_chunk_index;\n        \n        if (shared_chunk_index >= info->apng_shared_insert_index && !inserted) { // replace IDAT with fdAT\n            inserted = true;\n            for (uint32_t c = 0; c < frame_info->chunk_num; c++) {\n                yy_png_chunk_info *insert_chunk_info = info->chunks + frame_info->chunk_index + c;\n                if (insert_chunk_info->fourcc == YY_FOUR_CC('f', 'd', 'A', 'T')) {\n                    *((uint32_t *)(frame_data + data_offset)) = yy_swap_endian_uint32(insert_chunk_info->length - 4);\n                    *((uint32_t *)(frame_data + data_offset + 4)) = YY_FOUR_CC('I', 'D', 'A', 'T');\n                    memcpy(frame_data + data_offset + 8, data + insert_chunk_info->offset + 12, insert_chunk_info->length - 4);\n                    uint32_t crc = (uint32_t)crc32(0, frame_data + data_offset + 4, insert_chunk_info->length);\n                    *((uint32_t *)(frame_data + data_offset + insert_chunk_info->length + 4)) = yy_swap_endian_uint32(crc);\n                    data_offset += insert_chunk_info->length + 8;\n                } else { // IDAT\n                    memcpy(frame_data + data_offset, data + insert_chunk_info->offset, insert_chunk_info->length + 12);\n                    data_offset += insert_chunk_info->length + 12;\n                }\n            }\n        }\n        \n        if (shared_chunk_info->fourcc == YY_FOUR_CC('I', 'H', 'D', 'R')) {\n            uint8_t tmp[25] = {0};\n            memcpy(tmp, data + shared_chunk_info->offset, 25);\n            yy_png_chunk_IHDR IHDR = info->header;\n            IHDR.width = frame_info->frame_control.width;\n            IHDR.height = frame_info->frame_control.height;\n            yy_png_chunk_IHDR_write(&IHDR, tmp + 8);\n            *((uint32_t *)(tmp + 21)) = yy_swap_endian_uint32((uint32_t)crc32(0, tmp + 4, 17));\n            memcpy(frame_data + data_offset, tmp, 25);\n            data_offset += 25;\n        } else {\n            memcpy(frame_data + data_offset, data + shared_chunk_info->offset, shared_chunk_info->length + 12);\n            data_offset += shared_chunk_info->length + 12;\n        }\n    }\n    return frame_data;\n}\n\n\n\n////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Helper\n\n/// Returns byte-aligned size.\nstatic inline size_t YYImageByteAlign(size_t size, size_t alignment) {\n    return ((size + (alignment - 1)) / alignment) * alignment;\n}\n\n/// Convert degree to radians\nstatic inline CGFloat YYImageDegreesToRadians(CGFloat degrees) {\n    return degrees * M_PI / 180;\n}\n\nCGColorSpaceRef YYCGColorSpaceGetDeviceRGB() {\n    static CGColorSpaceRef space;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        space = CGColorSpaceCreateDeviceRGB();\n    });\n    return space;\n}\n\nCGColorSpaceRef YYCGColorSpaceGetDeviceGray() {\n    static CGColorSpaceRef space;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        space = CGColorSpaceCreateDeviceGray();\n    });\n    return space;\n}\n\nBOOL YYCGColorSpaceIsDeviceRGB(CGColorSpaceRef space) {\n    return space && CFEqual(space, YYCGColorSpaceGetDeviceRGB());\n}\n\nBOOL YYCGColorSpaceIsDeviceGray(CGColorSpaceRef space) {\n    return space && CFEqual(space, YYCGColorSpaceGetDeviceGray());\n}\n\n/**\n A callback used in CGDataProviderCreateWithData() to release data.\n \n Example:\n \n void *data = malloc(size);\n CGDataProviderRef provider = CGDataProviderCreateWithData(data, data, size, YYCGDataProviderReleaseDataCallback);\n */\nstatic void YYCGDataProviderReleaseDataCallback(void *info, const void *data, size_t size) {\n    if (info) free(info);\n}\n\n/**\n Decode an image to bitmap buffer with the specified format.\n \n @param srcImage   Source image.\n @param dest       Destination buffer. It should be zero before call this method.\n                   If decode succeed, you should release the dest->data using free().\n @param destFormat Destination bitmap format.\n \n @return Whether succeed.\n \n @warning This method support iOS7.0 and later. If call it on iOS6, it just returns NO.\n CG_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0)\n */\nstatic BOOL YYCGImageDecodeToBitmapBufferWithAnyFormat(CGImageRef srcImage, vImage_Buffer *dest, vImage_CGImageFormat *destFormat) {\n    if (!srcImage || (((long)vImageConvert_AnyToAny) + 1 == 1) || !destFormat || !dest) return NO;\n    size_t width = CGImageGetWidth(srcImage);\n    size_t height = CGImageGetHeight(srcImage);\n    if (width == 0 || height == 0) return NO;\n    dest->data = NULL;\n    \n    vImage_Error error = kvImageNoError;\n    CFDataRef srcData = NULL;\n    vImageConverterRef convertor = NULL;\n    vImage_CGImageFormat srcFormat = {0};\n    srcFormat.bitsPerComponent = (uint32_t)CGImageGetBitsPerComponent(srcImage);\n    srcFormat.bitsPerPixel = (uint32_t)CGImageGetBitsPerPixel(srcImage);\n    srcFormat.colorSpace = CGImageGetColorSpace(srcImage);\n    srcFormat.bitmapInfo = CGImageGetBitmapInfo(srcImage) | CGImageGetAlphaInfo(srcImage);\n    \n    convertor = vImageConverter_CreateWithCGImageFormat(&srcFormat, destFormat, NULL, kvImageNoFlags, NULL);\n    if (!convertor) goto fail;\n    \n    CGDataProviderRef srcProvider = CGImageGetDataProvider(srcImage);\n    srcData = srcProvider ? CGDataProviderCopyData(srcProvider) : NULL; // decode\n    size_t srcLength = srcData ? CFDataGetLength(srcData) : 0;\n    const void *srcBytes = srcData ? CFDataGetBytePtr(srcData) : NULL;\n    if (srcLength == 0 || !srcBytes) goto fail;\n    \n    vImage_Buffer src = {0};\n    src.data = (void *)srcBytes;\n    src.width = width;\n    src.height = height;\n    src.rowBytes = CGImageGetBytesPerRow(srcImage);\n    \n    error = vImageBuffer_Init(dest, height, width, 32, kvImageNoFlags);\n    if (error != kvImageNoError) goto fail;\n    \n    error = vImageConvert_AnyToAny(convertor, &src, dest, NULL, kvImageNoFlags); // convert\n    if (error != kvImageNoError) goto fail;\n    \n    CFRelease(convertor);\n    CFRelease(srcData);\n    return YES;\n    \nfail:\n    if (convertor) CFRelease(convertor);\n    if (srcData) CFRelease(srcData);\n    if (dest->data) free(dest->data);\n    dest->data = NULL;\n    return NO;\n}\n\n/**\n Decode an image to bitmap buffer with the 32bit format (such as ARGB8888).\n \n @param srcImage   Source image.\n @param dest       Destination buffer. It should be zero before call this method.\n                   If decode succeed, you should release the dest->data using free().\n @param bitmapInfo Destination bitmap format.\n \n @return Whether succeed.\n */\nstatic BOOL YYCGImageDecodeToBitmapBufferWith32BitFormat(CGImageRef srcImage, vImage_Buffer *dest, CGBitmapInfo bitmapInfo) {\n    if (!srcImage || !dest) return NO;\n    size_t width = CGImageGetWidth(srcImage);\n    size_t height = CGImageGetHeight(srcImage);\n    if (width == 0 || height == 0) return NO;\n    \n    BOOL hasAlpha = NO;\n    BOOL alphaFirst = NO;\n    BOOL alphaPremultiplied = NO;\n    BOOL byteOrderNormal = NO;\n    \n    switch (bitmapInfo & kCGBitmapAlphaInfoMask) {\n        case kCGImageAlphaPremultipliedLast: {\n            hasAlpha = YES;\n            alphaPremultiplied = YES;\n        } break;\n        case kCGImageAlphaPremultipliedFirst: {\n            hasAlpha = YES;\n            alphaPremultiplied = YES;\n            alphaFirst = YES;\n        } break;\n        case kCGImageAlphaLast: {\n            hasAlpha = YES;\n        } break;\n        case kCGImageAlphaFirst: {\n            hasAlpha = YES;\n            alphaFirst = YES;\n        } break;\n        case kCGImageAlphaNoneSkipLast: {\n        } break;\n        case kCGImageAlphaNoneSkipFirst: {\n            alphaFirst = YES;\n        } break;\n        default: {\n            return NO;\n        } break;\n    }\n    \n    switch (bitmapInfo & kCGBitmapByteOrderMask) {\n        case kCGBitmapByteOrderDefault: {\n            byteOrderNormal = YES;\n        } break;\n        case kCGBitmapByteOrder32Little: {\n        } break;\n        case kCGBitmapByteOrder32Big: {\n            byteOrderNormal = YES;\n        } break;\n        default: {\n            return NO;\n        } break;\n    }\n    \n    /*\n     Try convert with vImageConvert_AnyToAny() (avaliable since iOS 7.0).\n     If fail, try decode with CGContextDrawImage().\n     CGBitmapContext use a premultiplied alpha format, unpremultiply may lose precision.\n     */\n    vImage_CGImageFormat destFormat = {0};\n    destFormat.bitsPerComponent = 8;\n    destFormat.bitsPerPixel = 32;\n    destFormat.colorSpace = YYCGColorSpaceGetDeviceRGB();\n    destFormat.bitmapInfo = bitmapInfo;\n    dest->data = NULL;\n    if (YYCGImageDecodeToBitmapBufferWithAnyFormat(srcImage, dest, &destFormat)) return YES;\n    \n    CGBitmapInfo contextBitmapInfo = bitmapInfo & kCGBitmapByteOrderMask;\n    if (!hasAlpha || alphaPremultiplied) {\n        contextBitmapInfo |= (bitmapInfo & kCGBitmapAlphaInfoMask);\n    } else {\n        contextBitmapInfo |= alphaFirst ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaPremultipliedLast;\n    }\n    CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, YYCGColorSpaceGetDeviceRGB(), contextBitmapInfo);\n    if (!context) goto fail;\n    \n    CGContextDrawImage(context, CGRectMake(0, 0, width, height), srcImage); // decode and convert\n    size_t bytesPerRow = CGBitmapContextGetBytesPerRow(context);\n    size_t length = height * bytesPerRow;\n    void *data = CGBitmapContextGetData(context);\n    if (length == 0 || !data) goto fail;\n    \n    dest->data = malloc(length);\n    dest->width = width;\n    dest->height = height;\n    dest->rowBytes = bytesPerRow;\n    if (!dest->data) goto fail;\n    \n    if (hasAlpha && !alphaPremultiplied) {\n        vImage_Buffer tmpSrc = {0};\n        tmpSrc.data = data;\n        tmpSrc.width = width;\n        tmpSrc.height = height;\n        tmpSrc.rowBytes = bytesPerRow;\n        vImage_Error error;\n        if (alphaFirst && byteOrderNormal) {\n            error = vImageUnpremultiplyData_ARGB8888(&tmpSrc, dest, kvImageNoFlags);\n        } else {\n            error = vImageUnpremultiplyData_RGBA8888(&tmpSrc, dest, kvImageNoFlags);\n        }\n        if (error != kvImageNoError) goto fail;\n    } else {\n        memcpy(dest->data, data, length);\n    }\n    \n    CFRelease(context);\n    return YES;\n    \nfail:\n    if (context) CFRelease(context);\n    if (dest->data) free(dest->data);\n    dest->data = NULL;\n    return NO;\n    return NO;\n}\n\nCGImageRef YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decodeForDisplay) {\n    if (!imageRef) return NULL;\n    size_t width = CGImageGetWidth(imageRef);\n    size_t height = CGImageGetHeight(imageRef);\n    if (width == 0 || height == 0) return NULL;\n    \n    if (decodeForDisplay) { //decode with redraw (may lose some precision)\n        CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef) & kCGBitmapAlphaInfoMask;\n        BOOL hasAlpha = NO;\n        if (alphaInfo == kCGImageAlphaPremultipliedLast ||\n            alphaInfo == kCGImageAlphaPremultipliedFirst ||\n            alphaInfo == kCGImageAlphaLast ||\n            alphaInfo == kCGImageAlphaFirst) {\n            hasAlpha = YES;\n        }\n        // BGRA8888 (premultiplied) or BGRX8888\n        // same as UIGraphicsBeginImageContext() and -[UIView drawRect:]\n        CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;\n        bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;\n        CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, YYCGColorSpaceGetDeviceRGB(), bitmapInfo);\n        if (!context) return NULL;\n        CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); // decode\n        CGImageRef newImage = CGBitmapContextCreateImage(context);\n        CFRelease(context);\n        return newImage;\n        \n    } else {\n        CGColorSpaceRef space = CGImageGetColorSpace(imageRef);\n        size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);\n        size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);\n        size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);\n        CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);\n        if (bytesPerRow == 0 || width == 0 || height == 0) return NULL;\n        \n        CGDataProviderRef dataProvider = CGImageGetDataProvider(imageRef);\n        if (!dataProvider) return NULL;\n        CFDataRef data = CGDataProviderCopyData(dataProvider); // decode\n        if (!data) return NULL;\n        \n        CGDataProviderRef newProvider = CGDataProviderCreateWithCFData(data);\n        CFRelease(data);\n        if (!newProvider) return NULL;\n        \n        CGImageRef newImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, space, bitmapInfo, newProvider, NULL, false, kCGRenderingIntentDefault);\n        CFRelease(newProvider);\n        return newImage;\n    }\n}\n\nCGImageRef YYCGImageCreateAffineTransformCopy(CGImageRef imageRef, CGAffineTransform transform, CGSize destSize, CGBitmapInfo destBitmapInfo) {\n    if (!imageRef) return NULL;\n    size_t srcWidth = CGImageGetWidth(imageRef);\n    size_t srcHeight = CGImageGetHeight(imageRef);\n    size_t destWidth = round(destSize.width);\n    size_t destHeight = round(destSize.height);\n    if (srcWidth == 0 || srcHeight == 0 || destWidth == 0 || destHeight == 0) return NULL;\n    \n    CGDataProviderRef tmpProvider = NULL, destProvider = NULL;\n    CGImageRef tmpImage = NULL, destImage = NULL;\n    vImage_Buffer src = {0}, tmp = {0}, dest = {0};\n    if(!YYCGImageDecodeToBitmapBufferWith32BitFormat(imageRef, &src, kCGImageAlphaFirst | kCGBitmapByteOrderDefault)) return NULL;\n    \n    size_t destBytesPerRow = YYImageByteAlign(destWidth * 4, 32);\n    tmp.data = malloc(destHeight * destBytesPerRow);\n    if (!tmp.data) goto fail;\n    \n    tmp.width = destWidth;\n    tmp.height = destHeight;\n    tmp.rowBytes = destBytesPerRow;\n    vImage_CGAffineTransform vTransform = *((vImage_CGAffineTransform *)&transform);\n    uint8_t backColor[4] = {0};\n    vImage_Error error = vImageAffineWarpCG_ARGB8888(&src, &tmp, NULL, &vTransform, backColor, kvImageBackgroundColorFill);\n    if (error != kvImageNoError) goto fail;\n    free(src.data);\n    src.data = NULL;\n    \n    tmpProvider = CGDataProviderCreateWithData(tmp.data, tmp.data, destHeight * destBytesPerRow, YYCGDataProviderReleaseDataCallback);\n    if (!tmpProvider) goto fail;\n    tmp.data = NULL; // hold by provider\n    tmpImage = CGImageCreate(destWidth, destHeight, 8, 32, destBytesPerRow, YYCGColorSpaceGetDeviceRGB(), kCGImageAlphaFirst | kCGBitmapByteOrderDefault, tmpProvider, NULL, false, kCGRenderingIntentDefault);\n    if (!tmpImage) goto fail;\n    CFRelease(tmpProvider);\n    tmpProvider = NULL;\n    \n    if ((destBitmapInfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaFirst &&\n        (destBitmapInfo & kCGBitmapByteOrderMask) != kCGBitmapByteOrder32Little) {\n        return tmpImage;\n    }\n    \n    if (!YYCGImageDecodeToBitmapBufferWith32BitFormat(tmpImage, &dest, destBitmapInfo)) goto fail;\n    CFRelease(tmpImage);\n    tmpImage = NULL;\n    \n    destProvider = CGDataProviderCreateWithData(dest.data, dest.data, destHeight * destBytesPerRow, YYCGDataProviderReleaseDataCallback);\n    if (!destProvider) goto fail;\n    dest.data = NULL; // hold by provider\n    destImage = CGImageCreate(destWidth, destHeight, 8, 32, destBytesPerRow, YYCGColorSpaceGetDeviceRGB(), destBitmapInfo, destProvider, NULL, false, kCGRenderingIntentDefault);\n    if (!destImage) goto fail;\n    CFRelease(destProvider);\n    destProvider = NULL;\n    \n    return destImage;\n    \nfail:\n    if (src.data) free(src.data);\n    if (tmp.data) free(tmp.data);\n    if (dest.data) free(dest.data);\n    if (tmpProvider) CFRelease(tmpProvider);\n    if (tmpImage) CFRelease(tmpImage);\n    if (destProvider) CFRelease(destProvider);\n    return NULL;\n}\n\nUIImageOrientation YYUIImageOrientationFromEXIFValue(NSInteger value) {\n    switch (value) {\n        case kCGImagePropertyOrientationUp: return UIImageOrientationUp;\n        case kCGImagePropertyOrientationDown: return UIImageOrientationDown;\n        case kCGImagePropertyOrientationLeft: return UIImageOrientationLeft;\n        case kCGImagePropertyOrientationRight: return UIImageOrientationRight;\n        case kCGImagePropertyOrientationUpMirrored: return UIImageOrientationUpMirrored;\n        case kCGImagePropertyOrientationDownMirrored: return UIImageOrientationDownMirrored;\n        case kCGImagePropertyOrientationLeftMirrored: return UIImageOrientationLeftMirrored;\n        case kCGImagePropertyOrientationRightMirrored: return UIImageOrientationRightMirrored;\n        default: return UIImageOrientationUp;\n    }\n}\n\nNSInteger YYUIImageOrientationToEXIFValue(UIImageOrientation orientation) {\n    switch (orientation) {\n        case UIImageOrientationUp: return kCGImagePropertyOrientationUp;\n        case UIImageOrientationDown: return kCGImagePropertyOrientationDown;\n        case UIImageOrientationLeft: return kCGImagePropertyOrientationLeft;\n        case UIImageOrientationRight: return kCGImagePropertyOrientationRight;\n        case UIImageOrientationUpMirrored: return kCGImagePropertyOrientationUpMirrored;\n        case UIImageOrientationDownMirrored: return kCGImagePropertyOrientationDownMirrored;\n        case UIImageOrientationLeftMirrored: return kCGImagePropertyOrientationLeftMirrored;\n        case UIImageOrientationRightMirrored: return kCGImagePropertyOrientationRightMirrored;\n        default: return kCGImagePropertyOrientationUp;\n    }\n}\n\nCGImageRef YYCGImageCreateCopyWithOrientation(CGImageRef imageRef, UIImageOrientation orientation, CGBitmapInfo destBitmapInfo) {\n    if (!imageRef) return NULL;\n    if (orientation == UIImageOrientationUp) return (CGImageRef)CFRetain(imageRef);\n    \n    size_t width = CGImageGetWidth(imageRef);\n    size_t height = CGImageGetHeight(imageRef);\n    \n    CGAffineTransform transform = CGAffineTransformIdentity;\n    BOOL swapWidthAndHeight = NO;\n    switch (orientation) {\n        case UIImageOrientationDown: {\n            transform = CGAffineTransformMakeRotation(YYImageDegreesToRadians(180));\n            transform = CGAffineTransformTranslate(transform, -(CGFloat)width, -(CGFloat)height);\n        } break;\n        case UIImageOrientationLeft: {\n            transform = CGAffineTransformMakeRotation(YYImageDegreesToRadians(90));\n            transform = CGAffineTransformTranslate(transform, -(CGFloat)0, -(CGFloat)height);\n            swapWidthAndHeight = YES;\n        } break;\n        case UIImageOrientationRight: {\n            transform = CGAffineTransformMakeRotation(YYImageDegreesToRadians(-90));\n            transform = CGAffineTransformTranslate(transform, -(CGFloat)width, (CGFloat)0);\n            swapWidthAndHeight = YES;\n        } break;\n        case UIImageOrientationUpMirrored: {\n            transform = CGAffineTransformTranslate(transform, (CGFloat)width, 0);\n            transform = CGAffineTransformScale(transform, -1, 1);\n        } break;\n        case UIImageOrientationDownMirrored: {\n            transform = CGAffineTransformTranslate(transform, 0, (CGFloat)height);\n            transform = CGAffineTransformScale(transform, 1, -1);\n        } break;\n        case UIImageOrientationLeftMirrored: {\n            transform = CGAffineTransformMakeRotation(YYImageDegreesToRadians(-90));\n            transform = CGAffineTransformScale(transform, 1, -1);\n            transform = CGAffineTransformTranslate(transform, -(CGFloat)width, -(CGFloat)height);\n            swapWidthAndHeight = YES;\n        } break;\n        case UIImageOrientationRightMirrored: {\n            transform = CGAffineTransformMakeRotation(YYImageDegreesToRadians(90));\n            transform = CGAffineTransformScale(transform, 1, -1);\n            swapWidthAndHeight = YES;\n        } break;\n        default: break;\n    }\n    if (CGAffineTransformIsIdentity(transform)) return (CGImageRef)CFRetain(imageRef);\n    \n    CGSize destSize = {width, height};\n    if (swapWidthAndHeight) {\n        destSize.width = height;\n        destSize.height = width;\n    }\n    \n    return YYCGImageCreateAffineTransformCopy(imageRef, transform, destSize, destBitmapInfo);\n}\n\nYYImageType YYImageDetectType(CFDataRef data) {\n    if (!data) return YYImageTypeUnknown;\n    uint64_t length = CFDataGetLength(data);\n    if (length < 16) return YYImageTypeUnknown;\n    \n    const char *bytes = (char *)CFDataGetBytePtr(data);\n    \n    uint32_t magic4 = *((uint32_t *)bytes);\n    switch (magic4) {\n        case YY_FOUR_CC(0x4D, 0x4D, 0x00, 0x2A): { // big endian TIFF\n            return YYImageTypeTIFF;\n        } break;\n            \n        case YY_FOUR_CC(0x49, 0x49, 0x2A, 0x00): { // little endian TIFF\n            return YYImageTypeTIFF;\n        } break;\n            \n        case YY_FOUR_CC(0x00, 0x00, 0x01, 0x00): { // ICO\n            return YYImageTypeICO;\n        } break;\n            \n        case YY_FOUR_CC(0x00, 0x00, 0x02, 0x00): { // CUR\n            return YYImageTypeICO;\n        } break;\n            \n        case YY_FOUR_CC('i', 'c', 'n', 's'): { // ICNS\n            return YYImageTypeICNS;\n        } break;\n            \n        case YY_FOUR_CC('G', 'I', 'F', '8'): { // GIF\n            return YYImageTypeGIF;\n        } break;\n            \n        case YY_FOUR_CC(0x89, 'P', 'N', 'G'): {  // PNG\n            uint32_t tmp = *((uint32_t *)(bytes + 4));\n            if (tmp == YY_FOUR_CC('\\r', '\\n', 0x1A, '\\n')) {\n                return YYImageTypePNG;\n            }\n        } break;\n            \n        case YY_FOUR_CC('R', 'I', 'F', 'F'): { // WebP\n            uint32_t tmp = *((uint32_t *)(bytes + 8));\n            if (tmp == YY_FOUR_CC('W', 'E', 'B', 'P')) {\n                return YYImageTypeWebP;\n            }\n        } break;\n        /*\n        case YY_FOUR_CC('B', 'P', 'G', 0xFB): { // BPG\n            return YYImageTypeBPG;\n        } break;\n        */\n    }\n    \n    uint16_t magic2 = *((uint16_t *)bytes);\n    switch (magic2) {\n        case YY_TWO_CC('B', 'A'):\n        case YY_TWO_CC('B', 'M'):\n        case YY_TWO_CC('I', 'C'):\n        case YY_TWO_CC('P', 'I'):\n        case YY_TWO_CC('C', 'I'):\n        case YY_TWO_CC('C', 'P'): { // BMP\n            return YYImageTypeBMP;\n        }\n        case YY_TWO_CC(0xFF, 0x4F): { // JPEG2000\n            return YYImageTypeJPEG2000;\n        }\n    }\n    \n    // JPG             FF D8 FF\n    if (memcmp(bytes,\"\\377\\330\\377\",3) == 0) return YYImageTypeJPEG;\n    \n    // JP2\n    if (memcmp(bytes + 4, \"\\152\\120\\040\\040\\015\", 5) == 0) return YYImageTypeJPEG2000;\n    \n    return YYImageTypeUnknown;\n}\n\nCFStringRef YYImageTypeToUTType(YYImageType type) {\n    switch (type) {\n        case YYImageTypeJPEG: return kUTTypeJPEG;\n        case YYImageTypeJPEG2000: return kUTTypeJPEG2000;\n        case YYImageTypeTIFF: return kUTTypeTIFF;\n        case YYImageTypeBMP: return kUTTypeBMP;\n        case YYImageTypeICO: return kUTTypeICO;\n        case YYImageTypeICNS: return kUTTypeAppleICNS;\n        case YYImageTypeGIF: return kUTTypeGIF;\n        case YYImageTypePNG: return kUTTypePNG;\n        default: return NULL;\n    }\n}\n\nYYImageType YYImageTypeFromUTType(CFStringRef uti) {\n    static NSDictionary *dic;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        dic = @{(id)kUTTypeJPEG : @(YYImageTypeJPEG),\n                (id)kUTTypeJPEG2000 : @(YYImageTypeJPEG2000),\n                (id)kUTTypeTIFF : @(YYImageTypeTIFF),\n                (id)kUTTypeBMP : @(YYImageTypeBMP),\n                (id)kUTTypeICO : @(YYImageTypeICO),\n                (id)kUTTypeAppleICNS : @(YYImageTypeICNS),\n                (id)kUTTypeGIF : @(YYImageTypeGIF),\n                (id)kUTTypePNG : @(YYImageTypePNG)};\n    });\n    if (!uti) return YYImageTypeUnknown;\n    NSNumber *num = dic[(__bridge __strong id)(uti)];\n    return num.unsignedIntegerValue;\n}\n\nNSString *YYImageTypeGetExtension(YYImageType type) {\n    switch (type) {\n        case YYImageTypeJPEG: return @\"jpg\";\n        case YYImageTypeJPEG2000: return @\"jp2\";\n        case YYImageTypeTIFF: return @\"tiff\";\n        case YYImageTypeBMP: return @\"bmp\";\n        case YYImageTypeICO: return @\"ico\";\n        case YYImageTypeICNS: return @\"icns\";\n        case YYImageTypeGIF: return @\"gif\";\n        case YYImageTypePNG: return @\"png\";\n        case YYImageTypeWebP: return @\"webp\";\n        default: return nil;\n    }\n}\n\nCFDataRef YYCGImageCreateEncodedData(CGImageRef imageRef, YYImageType type, CGFloat quality) {\n    if (!imageRef) return nil;\n    quality = quality < 0 ? 0 : quality > 1 ? 1 : quality;\n    \n    if (type == YYImageTypeWebP) {\n#if YYIMAGE_WEBP_ENABLED\n        if (quality == 1) {\n            return YYCGImageCreateEncodedWebPData(imageRef, YES, quality, 4, YYImagePresetDefault);\n        } else {\n            return YYCGImageCreateEncodedWebPData(imageRef, NO, quality, 4, YYImagePresetDefault);\n        }\n#else\n        return NULL;\n#endif\n    }\n    \n    CFStringRef uti = YYImageTypeToUTType(type);\n    if (!uti) return nil;\n    \n    CFMutableDataRef data = CFDataCreateMutable(CFAllocatorGetDefault(), 0);\n    if (!data) return NULL;\n    CGImageDestinationRef dest = CGImageDestinationCreateWithData(data, uti, 1, NULL);\n    if (!dest) {\n        CFRelease(data);\n        return NULL;\n    }\n    NSDictionary *options = @{(id)kCGImageDestinationLossyCompressionQuality : @(quality) };\n    CGImageDestinationAddImage(dest, imageRef, (CFDictionaryRef)options);\n    if (!CGImageDestinationFinalize(dest)) {\n        CFRelease(data);\n        CFRelease(dest);\n        return nil;\n    }\n    CFRelease(dest);\n    \n    if (CFDataGetLength(data) == 0) {\n        CFRelease(data);\n        return NULL;\n    }\n    return data;\n}\n\n#if YYIMAGE_WEBP_ENABLED\n\nBOOL YYImageWebPAvailable() {\n    return YES;\n}\n\nCFDataRef YYCGImageCreateEncodedWebPData(CGImageRef imageRef, BOOL lossless, CGFloat quality, int compressLevel, YYImagePreset preset) {\n    if (!imageRef) return nil;\n    size_t width = CGImageGetWidth(imageRef);\n    size_t height = CGImageGetHeight(imageRef);\n    if (width == 0 || width > WEBP_MAX_DIMENSION) return nil;\n    if (height == 0 || height > WEBP_MAX_DIMENSION) return nil;\n    \n    vImage_Buffer buffer = {0};\n    if(!YYCGImageDecodeToBitmapBufferWith32BitFormat(imageRef, &buffer, kCGImageAlphaLast | kCGBitmapByteOrderDefault)) return nil;\n    \n    WebPConfig config = {0};\n    WebPPicture picture = {0};\n    WebPMemoryWriter writer = {0};\n    CFDataRef webpData = NULL;\n    BOOL pictureNeedFree = NO;\n    \n    quality = quality < 0 ? 0 : quality > 1 ? 1 : quality;\n    preset = preset > YYImagePresetText ? YYImagePresetDefault : preset;\n    compressLevel = compressLevel < 0 ? 0 : compressLevel > 6 ? 6 : compressLevel;\n    if (!WebPConfigPreset(&config, (WebPPreset)preset, quality)) goto fail;\n    \n    config.quality = round(quality * 100.0);\n    config.lossless = lossless;\n    config.method = compressLevel;\n    switch ((WebPPreset)preset) {\n        case WEBP_PRESET_DEFAULT: {\n            config.image_hint = WEBP_HINT_DEFAULT;\n        } break;\n        case WEBP_PRESET_PICTURE: {\n            config.image_hint = WEBP_HINT_PICTURE;\n        } break;\n        case WEBP_PRESET_PHOTO: {\n            config.image_hint = WEBP_HINT_PHOTO;\n        } break;\n        case WEBP_PRESET_DRAWING:\n        case WEBP_PRESET_ICON:\n        case WEBP_PRESET_TEXT: {\n            config.image_hint = WEBP_HINT_GRAPH;\n        } break;\n    }\n    if (!WebPValidateConfig(&config)) goto fail;\n    \n    if (!WebPPictureInit(&picture)) goto fail;\n    pictureNeedFree = YES;\n    picture.width = (int)buffer.width;\n    picture.height = (int)buffer.height;\n    picture.use_argb = lossless;\n    if(!WebPPictureImportRGBA(&picture, buffer.data, (int)buffer.rowBytes)) goto fail;\n    \n    WebPMemoryWriterInit(&writer);\n    picture.writer = WebPMemoryWrite;\n    picture.custom_ptr = &writer;\n    if(!WebPEncode(&config, &picture)) goto fail;\n    \n    webpData = CFDataCreate(CFAllocatorGetDefault(), writer.mem, writer.size);\n    free(writer.mem);\n    WebPPictureFree(&picture);\n    free(buffer.data);\n    return webpData;\n    \nfail:\n    if (buffer.data) free(buffer.data);\n    if (pictureNeedFree) WebPPictureFree(&picture);\n    return nil;\n}\n\nNSUInteger YYImageGetWebPFrameCount(CFDataRef webpData) {\n    if (!webpData || CFDataGetLength(webpData) == 0) return 0;\n    \n    WebPData data = {CFDataGetBytePtr(webpData), CFDataGetLength(webpData)};\n    WebPDemuxer *demuxer = WebPDemux(&data);\n    if (!demuxer) return 0;\n    NSUInteger webpFrameCount = WebPDemuxGetI(demuxer, WEBP_FF_FRAME_COUNT);\n    WebPDemuxDelete(demuxer);\n    return webpFrameCount;\n}\n\nCGImageRef YYCGImageCreateWithWebPData(CFDataRef webpData,\n                                       BOOL decodeForDisplay,\n                                       BOOL useThreads,\n                                       BOOL bypassFiltering,\n                                       BOOL noFancyUpsampling) {\n    /*\n     Call WebPDecode() on a multi-frame webp data will get an error (VP8_STATUS_UNSUPPORTED_FEATURE).\n     Use WebPDemuxer to unpack it first.\n     */\n    WebPData data = {0};\n    WebPDemuxer *demuxer = NULL;\n    \n    int frameCount = 0, canvasWidth = 0, canvasHeight = 0;\n    WebPIterator iter = {0};\n    BOOL iterInited = NO;\n    const uint8_t *payload = NULL;\n    size_t payloadSize = 0;\n    WebPDecoderConfig config = {0};\n    \n    BOOL hasAlpha = NO;\n    size_t bitsPerComponent = 0, bitsPerPixel = 0, bytesPerRow = 0, destLength = 0;\n    CGBitmapInfo bitmapInfo = 0;\n    WEBP_CSP_MODE colorspace = 0;\n    void *destBytes = NULL;\n    CGDataProviderRef provider = NULL;\n    CGImageRef imageRef = NULL;\n    \n    if (!webpData || CFDataGetLength(webpData) == 0) return NULL;\n    data.bytes = CFDataGetBytePtr(webpData);\n    data.size = CFDataGetLength(webpData);\n    demuxer = WebPDemux(&data);\n    if (!demuxer) goto fail;\n    \n    frameCount = WebPDemuxGetI(demuxer, WEBP_FF_FRAME_COUNT);\n    if (frameCount == 0) {\n        goto fail;\n        \n    } else if (frameCount == 1) { // single-frame\n        payload = data.bytes;\n        payloadSize = data.size;\n        if (!WebPInitDecoderConfig(&config)) goto fail;\n        if (WebPGetFeatures(payload , payloadSize, &config.input) != VP8_STATUS_OK) goto fail;\n        canvasWidth = config.input.width;\n        canvasHeight = config.input.height;\n        \n    } else { // multi-frame\n        canvasWidth = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_WIDTH);\n        canvasHeight = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_HEIGHT);\n        if (canvasWidth < 1 || canvasHeight < 1) goto fail;\n        \n        if (!WebPDemuxGetFrame(demuxer, 1, &iter)) goto fail;\n        iterInited = YES;\n        \n        if (iter.width > canvasWidth || iter.height > canvasHeight) goto fail;\n        payload = iter.fragment.bytes;\n        payloadSize = iter.fragment.size;\n        \n        if (!WebPInitDecoderConfig(&config)) goto fail;\n        if (WebPGetFeatures(payload , payloadSize, &config.input) != VP8_STATUS_OK) goto fail;\n    }\n    if (payload == NULL || payloadSize == 0) goto fail;\n    \n    hasAlpha = config.input.has_alpha;\n    bitsPerComponent = 8;\n    bitsPerPixel = 32;\n    bytesPerRow = YYImageByteAlign(bitsPerPixel / 8 * canvasWidth, 32);\n    destLength = bytesPerRow * canvasHeight;\n    if (decodeForDisplay) {\n        bitmapInfo = kCGBitmapByteOrder32Host;\n        bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;\n        colorspace = MODE_bgrA; // small endian\n    } else {\n        bitmapInfo = kCGBitmapByteOrderDefault;\n        bitmapInfo |= hasAlpha ? kCGImageAlphaLast : kCGImageAlphaNoneSkipLast;\n        colorspace = MODE_RGBA;\n    }\n    destBytes = calloc(1, destLength);\n    if (!destBytes) goto fail;\n    \n    config.options.use_threads = useThreads; //speed up 23%\n    config.options.bypass_filtering = bypassFiltering; //speed up 11%, cause some banding\n    config.options.no_fancy_upsampling = noFancyUpsampling; //speed down 16%, lose some details\n    config.output.colorspace = colorspace;\n    config.output.is_external_memory = 1;\n    config.output.u.RGBA.rgba = destBytes;\n    config.output.u.RGBA.stride = (int)bytesPerRow;\n    config.output.u.RGBA.size = destLength;\n    \n    VP8StatusCode result = WebPDecode(payload, payloadSize, &config);\n    if ((result != VP8_STATUS_OK) && (result != VP8_STATUS_NOT_ENOUGH_DATA)) goto fail;\n    \n    if (iter.x_offset != 0 || iter.y_offset != 0) {\n        void *tmp = calloc(1, destLength);\n        if (tmp) {\n            vImage_Buffer src = {destBytes, canvasHeight, canvasWidth, bytesPerRow};\n            vImage_Buffer dest = {tmp, canvasHeight, canvasWidth, bytesPerRow};\n            vImage_CGAffineTransform transform = {1, 0, 0, 1, iter.x_offset, -iter.y_offset};\n            uint8_t backColor[4] = {0};\n            vImageAffineWarpCG_ARGB8888(&src, &dest, NULL, &transform, backColor, kvImageBackgroundColorFill);\n            memcpy(destBytes, tmp, destLength);\n            free(tmp);\n        }\n    }\n    \n    provider = CGDataProviderCreateWithData(destBytes, destBytes, destLength, YYCGDataProviderReleaseDataCallback);\n    if (!provider) goto fail;\n    destBytes = NULL; // hold by provider\n    \n    imageRef = CGImageCreate(canvasWidth, canvasHeight, bitsPerComponent, bitsPerPixel, bytesPerRow, YYCGColorSpaceGetDeviceRGB(), bitmapInfo, provider, NULL, false, kCGRenderingIntentDefault);\n    \n    CFRelease(provider);\n    if (iterInited) WebPDemuxReleaseIterator(&iter);\n    WebPDemuxDelete(demuxer);\n    \n    return imageRef;\n    \nfail:\n    if (destBytes) free(destBytes);\n    if (provider) CFRelease(provider);\n    if (iterInited) WebPDemuxReleaseIterator(&iter);\n    if (demuxer) WebPDemuxDelete(demuxer);\n    return NULL;\n}\n\n#else\n\nBOOL YYImageWebPAvailable() {\n    return NO;\n}\n\nCFDataRef YYCGImageCreateEncodedWebPData(CGImageRef imageRef, BOOL lossless, CGFloat quality, int compressLevel, YYImagePreset preset) {\n    NSLog(@\"WebP decoder is disabled\");\n    return NULL;\n}\n\nNSUInteger YYImageGetWebPFrameCount(CFDataRef webpData) {\n    NSLog(@\"WebP decoder is disabled\");\n    return 0;\n}\n\nCGImageRef YYCGImageCreateWithWebPData(CFDataRef webpData,\n                                       BOOL decodeForDisplay,\n                                       BOOL useThreads,\n                                       BOOL bypassFiltering,\n                                       BOOL noFancyUpsampling) {\n    NSLog(@\"WebP decoder is disabled\");\n    return NULL;\n}\n\n#endif\n\n\n////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Decoder\n\n@implementation YYImageFrame\n+ (instancetype)frameWithImage:(UIImage *)image {\n    YYImageFrame *frame = [self new];\n    frame.image = image;\n    return frame;\n}\n- (id)copyWithZone:(NSZone *)zone {\n    YYImageFrame *frame = [self.class new];\n    frame.index = _index;\n    frame.width = _width;\n    frame.height = _height;\n    frame.offsetX = _offsetX;\n    frame.offsetY = _offsetY;\n    frame.duration = _duration;\n    frame.dispose = _dispose;\n    frame.blend = _blend;\n    frame.image = _image.copy;\n    return frame;\n}\n@end\n\n// Internal frame object.\n@interface _YYImageDecoderFrame : YYImageFrame\n@property (nonatomic, assign) BOOL hasAlpha;                ///< Whether frame has alpha.\n@property (nonatomic, assign) BOOL isFullSize;              ///< Whether frame fill the canvas.\n@property (nonatomic, assign) NSUInteger blendFromIndex;    ///< Blend from frame index to current frame.\n@end\n\n@implementation _YYImageDecoderFrame\n- (id)copyWithZone:(NSZone *)zone {\n    _YYImageDecoderFrame *frame = [super copyWithZone:zone];\n    frame.hasAlpha = _hasAlpha;\n    frame.isFullSize = _isFullSize;\n    frame.blendFromIndex = _blendFromIndex;\n    return frame;\n}\n@end\n\n\n@implementation YYImageDecoder {\n    pthread_mutex_t _lock; // recursive lock\n    \n    BOOL _sourceTypeDetected;\n    CGImageSourceRef _source;\n    yy_png_info *_apngSource;\n#if YYIMAGE_WEBP_ENABLED\n    WebPDemuxer *_webpSource;\n#endif\n    \n    UIImageOrientation _orientation;\n    dispatch_semaphore_t _framesLock;\n    NSArray *_frames; ///< Array<GGImageDecoderFrame>, without image\n    BOOL _needBlend;\n    NSUInteger _blendFrameIndex;\n    CGContextRef _blendCanvas;\n}\n\n- (void)dealloc {\n    if (_source) CFRelease(_source);\n    if (_apngSource) yy_png_info_release(_apngSource);\n#if YYIMAGE_WEBP_ENABLED\n    if (_webpSource) WebPDemuxDelete(_webpSource);\n#endif\n    if (_blendCanvas) CFRelease(_blendCanvas);\n    pthread_mutex_destroy(&_lock);\n}\n\n+ (instancetype)decoderWithData:(NSData *)data scale:(CGFloat)scale {\n    if (!data) return nil;\n    YYImageDecoder *decoder = [[YYImageDecoder alloc] initWithScale:scale];\n    [decoder updateData:data final:YES];\n    if (decoder.frameCount == 0) return nil;\n    return decoder;\n}\n\n- (instancetype)init {\n    return [self initWithScale:[UIScreen mainScreen].scale];\n}\n\n- (instancetype)initWithScale:(CGFloat)scale {\n    self = [super init];\n    if (scale <= 0) scale = 1;\n    _scale = scale;\n    _framesLock = dispatch_semaphore_create(1);\n    \n    pthread_mutexattr_t attr;\n    pthread_mutexattr_init (&attr);\n    pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);\n    pthread_mutex_init (&_lock, &attr);\n    pthread_mutexattr_destroy (&attr);\n    \n    return self;\n}\n\n- (BOOL)updateData:(NSData *)data final:(BOOL)final {\n    BOOL result = NO;\n    pthread_mutex_lock(&_lock);\n    result = [self _updateData:data final:final];\n    pthread_mutex_unlock(&_lock);\n    return result;\n}\n\n- (YYImageFrame *)frameAtIndex:(NSUInteger)index decodeForDisplay:(BOOL)decodeForDisplay {\n    YYImageFrame *result = nil;\n    pthread_mutex_lock(&_lock);\n    result = [self _frameAtIndex:index decodeForDisplay:decodeForDisplay];\n    pthread_mutex_unlock(&_lock);\n    return result;\n}\n\n- (NSTimeInterval)frameDurationAtIndex:(NSUInteger)index {\n    NSTimeInterval result = 0;\n    dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER);\n    if (index < _frames.count) {\n        result = ((_YYImageDecoderFrame *)_frames[index]).duration;\n    }\n    dispatch_semaphore_signal(_framesLock);\n    return result;\n}\n\n- (NSDictionary *)framePropertiesAtIndex:(NSUInteger)index {\n    NSDictionary *result = nil;\n    pthread_mutex_lock(&_lock);\n    result = [self _framePropertiesAtIndex:index];\n    pthread_mutex_unlock(&_lock);\n    return result;\n}\n\n- (NSDictionary *)imageProperties {\n    NSDictionary *result = nil;\n    pthread_mutex_lock(&_lock);\n    result = [self _imageProperties];\n    pthread_mutex_unlock(&_lock);\n    return result;\n}\n\n#pragma private (wrap)\n\n- (BOOL)_updateData:(NSData *)data final:(BOOL)final {\n    if (_finalized) return NO;\n    if (data.length < _data.length) return NO;\n    _finalized = final;\n    _data = data;\n    \n    YYImageType type = YYImageDetectType((__bridge CFDataRef)data);\n    if (_sourceTypeDetected) {\n        if (_type != type) {\n            return NO;\n        } else {\n            [self _updateSource];\n        }\n    } else {\n        if (_data.length > 16) {\n            _type = type;\n            _sourceTypeDetected = YES;\n            [self _updateSource];\n        }\n    }\n    return YES;\n}\n\n- (YYImageFrame *)_frameAtIndex:(NSUInteger)index decodeForDisplay:(BOOL)decodeForDisplay {\n    if (index >= _frames.count) return 0;\n    _YYImageDecoderFrame *frame = [(_YYImageDecoderFrame *)_frames[index] copy];\n    BOOL decoded = NO;\n    BOOL extendToCanvas = NO;\n    if (_type != YYImageTypeICO && decodeForDisplay) { // ICO contains multi-size frame and should not extend to canvas.\n        extendToCanvas = YES;\n    }\n    \n    if (!_needBlend) {\n        CGImageRef imageRef = [self _newUnblendedImageAtIndex:index extendToCanvas:extendToCanvas decoded:&decoded];\n        if (!imageRef) return nil;\n        if (decodeForDisplay && !decoded) {\n            CGImageRef imageRefDecoded = YYCGImageCreateDecodedCopy(imageRef, YES);\n            if (imageRefDecoded) {\n                CFRelease(imageRef);\n                imageRef = imageRefDecoded;\n                decoded = YES;\n            }\n        }\n        UIImage *image = [UIImage imageWithCGImage:imageRef scale:_scale orientation:_orientation];\n        CFRelease(imageRef);\n        if (!image) return nil;\n        image.yy_isDecodedForDisplay = decoded;\n        frame.image = image;\n        return frame;\n    }\n    \n    // blend\n    if (![self _createBlendContextIfNeeded]) return nil;\n    CGImageRef imageRef = NULL;\n    \n    if (_blendFrameIndex + 1 == frame.index) {\n        imageRef = [self _newBlendedImageWithFrame:frame];\n        _blendFrameIndex = index;\n    } else { // should draw canvas from previous frame\n        _blendFrameIndex = NSNotFound;\n        CGContextClearRect(_blendCanvas, CGRectMake(0, 0, _width, _height));\n        \n        if (frame.blendFromIndex == frame.index) {\n            CGImageRef unblendedImage = [self _newUnblendedImageAtIndex:index extendToCanvas:NO decoded:NULL];\n            if (unblendedImage) {\n                CGContextDrawImage(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height), unblendedImage);\n                CFRelease(unblendedImage);\n            }\n            imageRef = CGBitmapContextCreateImage(_blendCanvas);\n            if (frame.dispose == YYImageDisposeBackground) {\n                CGContextClearRect(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height));\n            }\n            _blendFrameIndex = index;\n        } else { // canvas is not ready\n            for (uint32_t i = (uint32_t)frame.blendFromIndex; i <= (uint32_t)frame.index; i++) {\n                if (i == frame.index) {\n                    if (!imageRef) imageRef = [self _newBlendedImageWithFrame:frame];\n                } else {\n                    [self _blendImageWithFrame:_frames[i]];\n                }\n            }\n            _blendFrameIndex = index;\n        }\n    }\n    \n    if (!imageRef) return nil;\n    UIImage *image = [UIImage imageWithCGImage:imageRef scale:_scale orientation:_orientation];\n    CFRelease(imageRef);\n    if (!image) return nil;\n    \n    image.yy_isDecodedForDisplay = YES;\n    frame.image = image;\n    if (extendToCanvas) {\n        frame.width = _width;\n        frame.height = _height;\n        frame.offsetX = 0;\n        frame.offsetY = 0;\n        frame.dispose = YYImageDisposeNone;\n        frame.blend = YYImageBlendNone;\n    }\n    return frame;\n}\n\n- (NSDictionary *)_framePropertiesAtIndex:(NSUInteger)index {\n    if (index >= _frames.count) return nil;\n    if (!_source) return nil;\n    CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(_source, index, NULL);\n    if (!properties) return nil;\n    return CFBridgingRelease(properties);\n}\n\n- (NSDictionary *)_imageProperties {\n    if (!_source) return nil;\n    CFDictionaryRef properties = CGImageSourceCopyProperties(_source, NULL);\n    if (!properties) return nil;\n    return CFBridgingRelease(properties);\n}\n\n#pragma private\n\n- (void)_updateSource {\n    switch (_type) {\n        case YYImageTypeWebP: {\n            [self _updateSourceWebP];\n        } break;\n            \n        case YYImageTypePNG: {\n            [self _updateSourceAPNG];\n        } break;\n            \n        default: {\n            [self _updateSourceImageIO];\n        } break;\n    }\n}\n\n- (void)_updateSourceWebP {\n#if YYIMAGE_WEBP_ENABLED\n    _width = 0;\n    _height = 0;\n    _loopCount = 0;\n    if (_webpSource) WebPDemuxDelete(_webpSource);\n    _webpSource = NULL;\n    dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER);\n    _frames = nil;\n    dispatch_semaphore_signal(_framesLock);\n    \n    /*\n     https://developers.google.com/speed/webp/docs/api\n     The documentation said we can use WebPIDecoder to decode webp progressively, \n     but currently it can only returns an empty image (not same as progressive jpegs),\n     so we don't use progressive decoding.\n     \n     When using WebPDecode() to decode multi-frame webp, we will get the error\n     \"VP8_STATUS_UNSUPPORTED_FEATURE\", so we first use WebPDemuxer to unpack it.\n     */\n    \n    WebPData webPData = {0};\n    webPData.bytes = _data.bytes;\n    webPData.size = _data.length;\n    WebPDemuxer *demuxer = WebPDemux(&webPData);\n    if (!demuxer) return;\n    \n    uint32_t webpFrameCount = WebPDemuxGetI(demuxer, WEBP_FF_FRAME_COUNT);\n    uint32_t webpLoopCount =  WebPDemuxGetI(demuxer, WEBP_FF_LOOP_COUNT);\n    uint32_t canvasWidth = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_WIDTH);\n    uint32_t canvasHeight = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_HEIGHT);\n    if (webpFrameCount == 0 || canvasWidth < 1 || canvasHeight < 1) {\n        WebPDemuxDelete(demuxer);\n        return;\n    }\n    \n    NSMutableArray *frames = [NSMutableArray new];\n    BOOL needBlend = NO;\n    uint32_t iterIndex = 0;\n    uint32_t lastBlendIndex = 0;\n    WebPIterator iter = {0};\n    if (WebPDemuxGetFrame(demuxer, 1, &iter)) { // one-based index...\n        do {\n            _YYImageDecoderFrame *frame = [_YYImageDecoderFrame new];\n            [frames addObject:frame];\n            if (iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {\n                frame.dispose = YYImageDisposeBackground;\n            }\n            if (iter.blend_method == WEBP_MUX_BLEND) {\n                frame.blend = YYImageBlendOver;\n            }\n            \n            int canvasWidth = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_WIDTH);\n            int canvasHeight = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_HEIGHT);\n            frame.index = iterIndex;\n            frame.duration = iter.duration / 1000.0;\n            frame.width = iter.width;\n            frame.height = iter.height;\n            frame.hasAlpha = iter.has_alpha;\n            frame.blend = iter.blend_method == WEBP_MUX_BLEND;\n            frame.offsetX = iter.x_offset;\n            frame.offsetY = canvasHeight - iter.y_offset - iter.height;\n            \n            BOOL sizeEqualsToCanvas = (iter.width == canvasWidth && iter.height == canvasHeight);\n            BOOL offsetIsZero = (iter.x_offset == 0 && iter.y_offset == 0);\n            frame.isFullSize = (sizeEqualsToCanvas && offsetIsZero);\n            \n            if ((!frame.blend || !frame.hasAlpha) && frame.isFullSize) {\n                frame.blendFromIndex = lastBlendIndex = iterIndex;\n            } else {\n                if (frame.dispose && frame.isFullSize) {\n                    frame.blendFromIndex = lastBlendIndex;\n                    lastBlendIndex = iterIndex + 1;\n                } else {\n                    frame.blendFromIndex = lastBlendIndex;\n                }\n            }\n            if (frame.index != frame.blendFromIndex) needBlend = YES;\n            iterIndex++;\n        } while (WebPDemuxNextFrame(&iter));\n        WebPDemuxReleaseIterator(&iter);\n    }\n    if (frames.count != webpFrameCount) {\n        WebPDemuxDelete(demuxer);\n        return;\n    }\n    \n    _width = canvasWidth;\n    _height = canvasHeight;\n    _frameCount = frames.count;\n    _loopCount = webpLoopCount;\n    _needBlend = needBlend;\n    _webpSource = demuxer;\n    dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER);\n    _frames = frames;\n    dispatch_semaphore_signal(_framesLock);\n#else\n    static const char *func = __FUNCTION__;\n    static const int line = __LINE__;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        NSLog(@\"[%s: %d] WebP is not available, check the documentation to see how to install WebP component: https://github.com/ibireme/YYImage#installation\", func, line);\n    });\n#endif\n}\n\n- (void)_updateSourceAPNG {\n    /*\n     APNG extends PNG format to support animation, it was supported by ImageIO\n     since iOS 8.\n     \n     We use a custom APNG decoder to make APNG available in old system, so we\n     ignore the ImageIO's APNG frame info. Typically the custom decoder is a bit\n     faster than ImageIO.\n     */\n    \n    yy_png_info_release(_apngSource);\n    _apngSource = nil;\n    \n    [self _updateSourceImageIO]; // decode first frame\n    if (_frameCount == 0) return; // png decode failed\n    if (!_finalized) return; // ignore multi-frame before finalized\n    \n    yy_png_info *apng = yy_png_info_create(_data.bytes, (uint32_t)_data.length);\n    if (!apng) return; // apng decode failed\n    if (apng->apng_frame_num == 0 ||\n        (apng->apng_frame_num == 1 && apng->apng_first_frame_is_cover)) {\n        yy_png_info_release(apng);\n        return; // no animation\n    }\n    if (_source) { // apng decode succeed, no longer need image souce\n        CFRelease(_source);\n        _source = NULL;\n    }\n    \n    uint32_t canvasWidth = apng->header.width;\n    uint32_t canvasHeight = apng->header.height;\n    NSMutableArray *frames = [NSMutableArray new];\n    BOOL needBlend = NO;\n    uint32_t lastBlendIndex = 0;\n    for (uint32_t i = 0; i < apng->apng_frame_num; i++) {\n        _YYImageDecoderFrame *frame = [_YYImageDecoderFrame new];\n        [frames addObject:frame];\n        \n        yy_png_frame_info *fi = apng->apng_frames + i;\n        frame.index = i;\n        frame.duration = yy_png_delay_to_seconds(fi->frame_control.delay_num, fi->frame_control.delay_den);\n        frame.hasAlpha = YES;\n        frame.width = fi->frame_control.width;\n        frame.height = fi->frame_control.height;\n        frame.offsetX = fi->frame_control.x_offset;\n        frame.offsetY = canvasHeight - fi->frame_control.y_offset - fi->frame_control.height;\n        \n        BOOL sizeEqualsToCanvas = (frame.width == canvasWidth && frame.height == canvasHeight);\n        BOOL offsetIsZero = (fi->frame_control.x_offset == 0 && fi->frame_control.y_offset == 0);\n        frame.isFullSize = (sizeEqualsToCanvas && offsetIsZero);\n        \n        switch (fi->frame_control.dispose_op) {\n            case YY_PNG_DISPOSE_OP_BACKGROUND: {\n                frame.dispose = YYImageDisposeBackground;\n            } break;\n            case YY_PNG_DISPOSE_OP_PREVIOUS: {\n                frame.dispose = YYImageDisposePrevious;\n            } break;\n            default: {\n                frame.dispose = YYImageDisposeNone;\n            } break;\n        }\n        switch (fi->frame_control.blend_op) {\n            case YY_PNG_BLEND_OP_OVER: {\n                frame.blend = YYImageBlendOver;\n            } break;\n                \n            default: {\n                frame.blend = YYImageBlendNone;\n            } break;\n        }\n        \n        if (frame.blend == YYImageBlendNone && frame.isFullSize) {\n            frame.blendFromIndex  = i;\n            if (frame.dispose != YYImageDisposePrevious) lastBlendIndex = i;\n        } else {\n            if (frame.dispose == YYImageDisposeBackground && frame.isFullSize) {\n                frame.blendFromIndex = lastBlendIndex;\n                lastBlendIndex = i + 1;\n            } else {\n                frame.blendFromIndex = lastBlendIndex;\n            }\n        }\n        if (frame.index != frame.blendFromIndex) needBlend = YES;\n    }\n    \n    _width = canvasWidth;\n    _height = canvasHeight;\n    _frameCount = frames.count;\n    _loopCount = apng->apng_loop_num;\n    _needBlend = needBlend;\n    _apngSource = apng;\n    dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER);\n    _frames = frames;\n    dispatch_semaphore_signal(_framesLock);\n}\n\n- (void)_updateSourceImageIO {\n    _width = 0;\n    _height = 0;\n    _orientation = UIImageOrientationUp;\n    _loopCount = 0;\n    dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER);\n    _frames = nil;\n    dispatch_semaphore_signal(_framesLock);\n    \n    if (!_source) {\n        if (_finalized) {\n            _source = CGImageSourceCreateWithData((__bridge CFDataRef)_data, NULL);\n        } else {\n            _source = CGImageSourceCreateIncremental(NULL);\n            if (_source) CGImageSourceUpdateData(_source, (__bridge CFDataRef)_data, false);\n        }\n    } else {\n        CGImageSourceUpdateData(_source, (__bridge CFDataRef)_data, _finalized);\n    }\n    if (!_source) return;\n    \n    _frameCount = CGImageSourceGetCount(_source);\n    if (_frameCount == 0) return;\n    \n    if (!_finalized) { // ignore multi-frame before finalized\n        _frameCount = 1;\n    } else {\n        if (_type == YYImageTypePNG) { // use custom apng decoder and ignore multi-frame\n            _frameCount = 1;\n        }\n        if (_type == YYImageTypeGIF) { // get gif loop count\n            CFDictionaryRef properties = CGImageSourceCopyProperties(_source, NULL);\n            if (properties) {\n                CFDictionaryRef gif = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);\n                if (gif) {\n                    CFTypeRef loop = CFDictionaryGetValue(gif, kCGImagePropertyGIFLoopCount);\n                    if (loop) CFNumberGetValue(loop, kCFNumberNSIntegerType, &_loopCount);\n                }\n                CFRelease(properties);\n            }\n        }\n    }\n\n    /*\n     ICO, GIF, APNG may contains multi-frame.\n     */\n    NSMutableArray *frames = [NSMutableArray new];\n    for (NSUInteger i = 0; i < _frameCount; i++) {\n        _YYImageDecoderFrame *frame = [_YYImageDecoderFrame new];\n        frame.index = i;\n        frame.blendFromIndex = i;\n        frame.hasAlpha = YES;\n        frame.isFullSize = YES;\n        [frames addObject:frame];\n        \n        CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(_source, i, NULL);\n        if (properties) {\n            NSTimeInterval duration = 0;\n            NSInteger orientationValue = 0, width = 0, height = 0;\n            CFTypeRef value = NULL;\n            \n            value = CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth);\n            if (value) CFNumberGetValue(value, kCFNumberNSIntegerType, &width);\n            value = CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight);\n            if (value) CFNumberGetValue(value, kCFNumberNSIntegerType, &height);\n            if (_type == YYImageTypeGIF) {\n                CFDictionaryRef gif = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);\n                if (gif) {\n                    // Use the unclamped frame delay if it exists.\n                    value = CFDictionaryGetValue(gif, kCGImagePropertyGIFUnclampedDelayTime);\n                    if (!value) {\n                        // Fall back to the clamped frame delay if the unclamped frame delay does not exist.\n                        value = CFDictionaryGetValue(gif, kCGImagePropertyGIFDelayTime);\n                    }\n                    if (value) CFNumberGetValue(value, kCFNumberDoubleType, &duration);\n                }\n            }\n            \n            frame.width = width;\n            frame.height = height;\n            frame.duration = duration;\n            \n            if (i == 0 && _width + _height == 0) { // init first frame\n                _width = width;\n                _height = height;\n                value = CFDictionaryGetValue(properties, kCGImagePropertyOrientation);\n                if (value) {\n                    CFNumberGetValue(value, kCFNumberNSIntegerType, &orientationValue);\n                    _orientation = YYUIImageOrientationFromEXIFValue(orientationValue);\n                }\n            }\n            CFRelease(properties);\n        }\n    }\n    dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER);\n    _frames = frames;\n    dispatch_semaphore_signal(_framesLock);\n}\n\n- (CGImageRef)_newUnblendedImageAtIndex:(NSUInteger)index\n                         extendToCanvas:(BOOL)extendToCanvas\n                                decoded:(BOOL *)decoded CF_RETURNS_RETAINED {\n    \n    if (!_finalized && index > 0) return NULL;\n    if (_frames.count <= index) return NULL;\n    _YYImageDecoderFrame *frame = _frames[index];\n    \n    if (_source) {\n        CGImageRef imageRef = CGImageSourceCreateImageAtIndex(_source, index, (CFDictionaryRef)@{(id)kCGImageSourceShouldCache:@(YES)});\n        if (imageRef && extendToCanvas) {\n            size_t width = CGImageGetWidth(imageRef);\n            size_t height = CGImageGetHeight(imageRef);\n            if (width == _width && height == _height) {\n                CGImageRef imageRefExtended = YYCGImageCreateDecodedCopy(imageRef, YES);\n                if (imageRefExtended) {\n                    CFRelease(imageRef);\n                    imageRef = imageRefExtended;\n                    if (decoded) *decoded = YES;\n                }\n            } else {\n                CGContextRef context = CGBitmapContextCreate(NULL, _width, _height, 8, 0, YYCGColorSpaceGetDeviceRGB(), kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);\n                if (context) {\n                    CGContextDrawImage(context, CGRectMake(0, _height - height, width, height), imageRef);\n                    CGImageRef imageRefExtended = CGBitmapContextCreateImage(context);\n                    CFRelease(context);\n                    if (imageRefExtended) {\n                        CFRelease(imageRef);\n                        imageRef = imageRefExtended;\n                        if (decoded) *decoded = YES;\n                    }\n                }\n            }\n        }\n        return imageRef;\n    }\n    \n    if (_apngSource) {\n        uint32_t size = 0;\n        uint8_t *bytes = yy_png_copy_frame_data_at_index(_data.bytes, _apngSource, (uint32_t)index, &size);\n        if (!bytes) return NULL;\n        CGDataProviderRef provider = CGDataProviderCreateWithData(bytes, bytes, size, YYCGDataProviderReleaseDataCallback);\n        if (!provider) {\n            free(bytes);\n            return NULL;\n        }\n        bytes = NULL; // hold by provider\n        \n        CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, NULL);\n        if (!source) {\n            CFRelease(provider);\n            return NULL;\n        }\n        CFRelease(provider);\n        \n        if(CGImageSourceGetCount(source) < 1) {\n            CFRelease(source);\n            return NULL;\n        }\n        \n        CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, 0, (CFDictionaryRef)@{(id)kCGImageSourceShouldCache:@(YES)});\n        CFRelease(source);\n        if (!imageRef) return NULL;\n        if (extendToCanvas) {\n            CGContextRef context = CGBitmapContextCreate(NULL, _width, _height, 8, 0, YYCGColorSpaceGetDeviceRGB(), kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst); //bgrA\n            if (context) {\n                CGContextDrawImage(context, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height), imageRef);\n                CFRelease(imageRef);\n                imageRef = CGBitmapContextCreateImage(context);\n                CFRelease(context);\n                if (decoded) *decoded = YES;\n            }\n        }\n        return imageRef;\n    }\n    \n#if YYIMAGE_WEBP_ENABLED\n    if (_webpSource) {\n        WebPIterator iter;\n        if (!WebPDemuxGetFrame(_webpSource, (int)(index + 1), &iter)) return NULL; // demux webp frame data\n        // frame numbers are one-based in webp -----------^\n        \n        int frameWidth = iter.width;\n        int frameHeight = iter.height;\n        if (frameWidth < 1 || frameHeight < 1) return NULL;\n        \n        int width = extendToCanvas ? (int)_width : frameWidth;\n        int height = extendToCanvas ? (int)_height : frameHeight;\n        if (width > _width || height > _height) return NULL;\n        \n        const uint8_t *payload = iter.fragment.bytes;\n        size_t payloadSize = iter.fragment.size;\n        \n        WebPDecoderConfig config;\n        if (!WebPInitDecoderConfig(&config)) {\n            WebPDemuxReleaseIterator(&iter);\n            return NULL;\n        }\n        if (WebPGetFeatures(payload , payloadSize, &config.input) != VP8_STATUS_OK) {\n            WebPDemuxReleaseIterator(&iter);\n            return NULL;\n        }\n        \n        size_t bitsPerComponent = 8;\n        size_t bitsPerPixel = 32;\n        size_t bytesPerRow = YYImageByteAlign(bitsPerPixel / 8 * width, 32);\n        size_t length = bytesPerRow * height;\n        CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst; //bgrA\n        \n        void *pixels = calloc(1, length);\n        if (!pixels) {\n            WebPDemuxReleaseIterator(&iter);\n            return NULL;\n        }\n        \n        config.output.colorspace = MODE_bgrA;\n        config.output.is_external_memory = 1;\n        config.output.u.RGBA.rgba = pixels;\n        config.output.u.RGBA.stride = (int)bytesPerRow;\n        config.output.u.RGBA.size = length;\n        VP8StatusCode result = WebPDecode(payload, payloadSize, &config); // decode\n        if ((result != VP8_STATUS_OK) && (result != VP8_STATUS_NOT_ENOUGH_DATA)) {\n            WebPDemuxReleaseIterator(&iter);\n            free(pixels);\n            return NULL;\n        }\n        WebPDemuxReleaseIterator(&iter);\n        \n        if (extendToCanvas && (iter.x_offset != 0 || iter.y_offset != 0)) {\n            void *tmp = calloc(1, length);\n            if (tmp) {\n                vImage_Buffer src = {pixels, height, width, bytesPerRow};\n                vImage_Buffer dest = {tmp, height, width, bytesPerRow};\n                vImage_CGAffineTransform transform = {1, 0, 0, 1, iter.x_offset, -iter.y_offset};\n                uint8_t backColor[4] = {0};\n                vImage_Error error = vImageAffineWarpCG_ARGB8888(&src, &dest, NULL, &transform, backColor, kvImageBackgroundColorFill);\n                if (error == kvImageNoError) {\n                    memcpy(pixels, tmp, length);\n                }\n                free(tmp);\n            }\n        }\n        \n        CGDataProviderRef provider = CGDataProviderCreateWithData(pixels, pixels, length, YYCGDataProviderReleaseDataCallback);\n        if (!provider) {\n            free(pixels);\n            return NULL;\n        }\n        pixels = NULL; // hold by provider\n        \n        CGImageRef image = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, YYCGColorSpaceGetDeviceRGB(), bitmapInfo, provider, NULL, false, kCGRenderingIntentDefault);\n        CFRelease(provider);\n        if (decoded) *decoded = YES;\n        return image;\n    }\n#endif\n    \n    return NULL;\n}\n\n- (BOOL)_createBlendContextIfNeeded {\n    if (!_blendCanvas) {\n        _blendFrameIndex = NSNotFound;\n        _blendCanvas = CGBitmapContextCreate(NULL, _width, _height, 8, 0, YYCGColorSpaceGetDeviceRGB(), kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);\n    }\n    BOOL suc = _blendCanvas != NULL;\n    return suc;\n}\n\n- (void)_blendImageWithFrame:(_YYImageDecoderFrame *)frame {\n    if (frame.dispose == YYImageDisposePrevious) {\n        // nothing\n    } else if (frame.dispose == YYImageDisposeBackground) {\n        CGContextClearRect(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height));\n    } else { // no dispose\n        if (frame.blend == YYImageBlendOver) {\n            CGImageRef unblendImage = [self _newUnblendedImageAtIndex:frame.index extendToCanvas:NO decoded:NULL];\n            if (unblendImage) {\n                CGContextDrawImage(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height), unblendImage);\n                CFRelease(unblendImage);\n            }\n        } else {\n            CGContextClearRect(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height));\n            CGImageRef unblendImage = [self _newUnblendedImageAtIndex:frame.index extendToCanvas:NO decoded:NULL];\n            if (unblendImage) {\n                CGContextDrawImage(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height), unblendImage);\n                CFRelease(unblendImage);\n            }\n        }\n    }\n}\n\n- (CGImageRef)_newBlendedImageWithFrame:(_YYImageDecoderFrame *)frame CF_RETURNS_RETAINED{\n    CGImageRef imageRef = NULL;\n    if (frame.dispose == YYImageDisposePrevious) {\n        if (frame.blend == YYImageBlendOver) {\n            CGImageRef previousImage = CGBitmapContextCreateImage(_blendCanvas);\n            CGImageRef unblendImage = [self _newUnblendedImageAtIndex:frame.index extendToCanvas:NO decoded:NULL];\n            if (unblendImage) {\n                CGContextDrawImage(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height), unblendImage);\n                CFRelease(unblendImage);\n            }\n            imageRef = CGBitmapContextCreateImage(_blendCanvas);\n            CGContextClearRect(_blendCanvas, CGRectMake(0, 0, _width, _height));\n            if (previousImage) {\n                CGContextDrawImage(_blendCanvas, CGRectMake(0, 0, _width, _height), previousImage);\n                CFRelease(previousImage);\n            }\n        } else {\n            CGImageRef previousImage = CGBitmapContextCreateImage(_blendCanvas);\n            CGImageRef unblendImage = [self _newUnblendedImageAtIndex:frame.index extendToCanvas:NO decoded:NULL];\n            if (unblendImage) {\n                CGContextClearRect(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height));\n                CGContextDrawImage(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height), unblendImage);\n                CFRelease(unblendImage);\n            }\n            imageRef = CGBitmapContextCreateImage(_blendCanvas);\n            CGContextClearRect(_blendCanvas, CGRectMake(0, 0, _width, _height));\n            if (previousImage) {\n                CGContextDrawImage(_blendCanvas, CGRectMake(0, 0, _width, _height), previousImage);\n                CFRelease(previousImage);\n            }\n        }\n    } else if (frame.dispose == YYImageDisposeBackground) {\n        if (frame.blend == YYImageBlendOver) {\n            CGImageRef unblendImage = [self _newUnblendedImageAtIndex:frame.index extendToCanvas:NO decoded:NULL];\n            if (unblendImage) {\n                CGContextDrawImage(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height), unblendImage);\n                CFRelease(unblendImage);\n            }\n            imageRef = CGBitmapContextCreateImage(_blendCanvas);\n            CGContextClearRect(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height));\n        } else {\n            CGImageRef unblendImage = [self _newUnblendedImageAtIndex:frame.index extendToCanvas:NO decoded:NULL];\n            if (unblendImage) {\n                CGContextClearRect(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height));\n                CGContextDrawImage(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height), unblendImage);\n                CFRelease(unblendImage);\n            }\n            imageRef = CGBitmapContextCreateImage(_blendCanvas);\n            CGContextClearRect(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height));\n        }\n    } else { // no dispose\n        if (frame.blend == YYImageBlendOver) {\n            CGImageRef unblendImage = [self _newUnblendedImageAtIndex:frame.index extendToCanvas:NO decoded:NULL];\n            if (unblendImage) {\n                CGContextDrawImage(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height), unblendImage);\n                CFRelease(unblendImage);\n            }\n            imageRef = CGBitmapContextCreateImage(_blendCanvas);\n        } else {\n            CGImageRef unblendImage = [self _newUnblendedImageAtIndex:frame.index extendToCanvas:NO decoded:NULL];\n            if (unblendImage) {\n                CGContextClearRect(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height));\n                CGContextDrawImage(_blendCanvas, CGRectMake(frame.offsetX, frame.offsetY, frame.width, frame.height), unblendImage);\n                CFRelease(unblendImage);\n            }\n            imageRef = CGBitmapContextCreateImage(_blendCanvas);\n        }\n    }\n    return imageRef;\n}\n\n@end\n\n\n////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Encoder\n\n@implementation YYImageEncoder {\n    NSMutableArray *_images;\n    NSMutableArray *_durations;\n}\n\n- (instancetype)init {\n    @throw [NSException exceptionWithName:@\"YYImageEncoder init error\" reason:@\"YYImageEncoder must be initialized with a type. Use 'initWithType:' instead.\" userInfo:nil];\n    return [self initWithType:YYImageTypeUnknown];\n}\n\n- (instancetype)initWithType:(YYImageType)type {\n    if (type == YYImageTypeUnknown || type >= YYImageTypeOther) {\n        NSLog(@\"[%s: %d] Unsupported image type:%d\",__FUNCTION__, __LINE__, (int)type);\n        return nil;\n    }\n    \n#if !YYIMAGE_WEBP_ENABLED\n    if (type == YYImageTypeWebP) {\n        NSLog(@\"[%s: %d] WebP is not available, check the documentation to see how to install WebP component: https://github.com/ibireme/YYImage#installation\", __FUNCTION__, __LINE__);\n        return nil;\n    }\n#endif\n    \n    self = [super init];\n    if (!self) return nil;\n    _type = type;\n    _images = [NSMutableArray new];\n    _durations = [NSMutableArray new];\n\n    switch (type) {\n        case YYImageTypeJPEG:\n        case YYImageTypeJPEG2000: {\n            _quality = 0.9;\n        } break;\n        case YYImageTypeTIFF:\n        case YYImageTypeBMP:\n        case YYImageTypeGIF:\n        case YYImageTypeICO:\n        case YYImageTypeICNS:\n        case YYImageTypePNG: {\n            _quality = 1;\n            _lossless = YES;\n        } break;\n        case YYImageTypeWebP: {\n            _quality = 0.8;\n        } break;\n        default:\n            break;\n    }\n    \n    return self;\n}\n\n- (void)setQuality:(CGFloat)quality {\n    _quality = quality < 0 ? 0 : quality > 1 ? 1 : quality;\n}\n\n- (void)addImage:(UIImage *)image duration:(NSTimeInterval)duration {\n    if (!image.CGImage) return;\n    duration = duration < 0 ? 0 : duration;\n    [_images addObject:image];\n    [_durations addObject:@(duration)];\n}\n\n- (void)addImageWithData:(NSData *)data duration:(NSTimeInterval)duration {\n    if (data.length == 0) return;\n    duration = duration < 0 ? 0 : duration;\n    [_images addObject:data];\n    [_durations addObject:@(duration)];\n}\n\n- (void)addImageWithFile:(NSString *)path duration:(NSTimeInterval)duration {\n    if (path.length == 0) return;\n    duration = duration < 0 ? 0 : duration;\n    NSURL *url = [NSURL URLWithString:path];\n    if (!url) return;\n    [_images addObject:url];\n    [_durations addObject:@(duration)];\n}\n\n- (BOOL)_imageIOAvaliable {\n    switch (_type) {\n        case YYImageTypeJPEG:\n        case YYImageTypeJPEG2000:\n        case YYImageTypeTIFF:\n        case YYImageTypeBMP:\n        case YYImageTypeICO:\n        case YYImageTypeICNS:\n        case YYImageTypeGIF: {\n            return _images.count > 0;\n        } break;\n        case YYImageTypePNG: {\n            return _images.count == 1;\n        } break;\n        case YYImageTypeWebP: {\n            return NO;\n        } break;\n        default: return NO;\n    }\n}\n\n- (CGImageDestinationRef)_newImageDestination:(id)dest imageCount:(NSUInteger)count CF_RETURNS_RETAINED {\n    if (!dest) return nil;\n    CGImageDestinationRef destination = NULL;\n    if ([dest isKindOfClass:[NSString class]]) {\n        NSURL *url = [[NSURL alloc] initFileURLWithPath:dest];\n        if (url) {\n            destination = CGImageDestinationCreateWithURL((CFURLRef)url, YYImageTypeToUTType(_type), count, NULL);\n        }\n    } else if ([dest isKindOfClass:[NSMutableData class]]) {\n        destination = CGImageDestinationCreateWithData((CFMutableDataRef)dest, YYImageTypeToUTType(_type), count, NULL);\n    }\n    return destination;\n}\n\n- (void)_encodeImageWithDestination:(CGImageDestinationRef)destination imageCount:(NSUInteger)count {\n    if (_type == YYImageTypeGIF) {\n        NSDictionary *gifProperty = @{(__bridge id)kCGImagePropertyGIFDictionary:\n                                        @{(__bridge id)kCGImagePropertyGIFLoopCount: @(_loopCount)}};\n        CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)gifProperty);\n    }\n    \n    for (int i = 0; i < count; i++) {\n        @autoreleasepool {\n            id imageSrc = _images[i];\n            NSDictionary *frameProperty = NULL;\n            if (_type == YYImageTypeGIF && count > 1) {\n                frameProperty = @{(NSString *)kCGImagePropertyGIFDictionary : @{(NSString *) kCGImagePropertyGIFDelayTime:_durations[i]}};\n            } else {\n                frameProperty = @{(id)kCGImageDestinationLossyCompressionQuality : @(_quality)};\n            }\n            \n            if ([imageSrc isKindOfClass:[UIImage class]]) {\n                UIImage *image = imageSrc;\n                if (image.imageOrientation != UIImageOrientationUp && image.CGImage) {\n                    CGBitmapInfo info = CGImageGetBitmapInfo(image.CGImage) | CGImageGetAlphaInfo(image.CGImage);\n                    CGImageRef rotated = YYCGImageCreateCopyWithOrientation(image.CGImage, image.imageOrientation, info);\n                    if (rotated) {\n                        image = [UIImage imageWithCGImage:rotated];\n                        CFRelease(rotated);\n                    }\n                }\n                if (image.CGImage) CGImageDestinationAddImage(destination, ((UIImage *)imageSrc).CGImage, (CFDictionaryRef)frameProperty);\n            } else if ([imageSrc isKindOfClass:[NSURL class]]) {\n                CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)imageSrc, NULL);\n                if (source) {\n                    CGImageDestinationAddImageFromSource(destination, source, 0, (CFDictionaryRef)frameProperty);\n                    CFRelease(source);\n                }\n            } else if ([imageSrc isKindOfClass:[NSData class]]) {\n                CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imageSrc, NULL);\n                if (source) {\n                    CGImageDestinationAddImageFromSource(destination, source, 0, (CFDictionaryRef)frameProperty);\n                    CFRelease(source);\n                }\n            }\n        }\n    }\n}\n\n- (CGImageRef)_newCGImageFromIndex:(NSUInteger)index decoded:(BOOL)decoded CF_RETURNS_RETAINED {\n    UIImage *image = nil;\n    id imageSrc= _images[index];\n    if ([imageSrc isKindOfClass:[UIImage class]]) {\n        image = imageSrc;\n    } else if ([imageSrc isKindOfClass:[NSURL class]]) {\n        image = [UIImage imageWithContentsOfFile:((NSURL *)imageSrc).absoluteString];\n    } else if ([imageSrc isKindOfClass:[NSData class]]) {\n        image = [UIImage imageWithData:imageSrc];\n    }\n    if (!image) return NULL;\n    CGImageRef imageRef = image.CGImage;\n    if (!imageRef) return NULL;\n    if (image.imageOrientation != UIImageOrientationUp) {\n        return YYCGImageCreateCopyWithOrientation(imageRef, image.imageOrientation, kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);\n    }\n    if (decoded) {\n        return YYCGImageCreateDecodedCopy(imageRef, YES);\n    }\n    return (CGImageRef)CFRetain(imageRef);\n}\n\n- (NSData *)_encodeWithImageIO {\n    NSMutableData *data = [NSMutableData new];\n    NSUInteger count = _type == YYImageTypeGIF ? _images.count : 1;\n    CGImageDestinationRef destination = [self _newImageDestination:data imageCount:count];\n    BOOL suc = NO;\n    if (destination) {\n        [self _encodeImageWithDestination:destination imageCount:count];\n        suc = CGImageDestinationFinalize(destination);\n        CFRelease(destination);\n    }\n    if (suc && data.length > 0) {\n        return data;\n    } else {\n        return nil;\n    }\n}\n\n- (BOOL)_encodeWithImageIO:(NSString *)path {\n    NSUInteger count = _type == YYImageTypeGIF ? _images.count : 1;\n    CGImageDestinationRef destination = [self _newImageDestination:path imageCount:count];\n    BOOL suc = NO;\n    if (destination) {\n        [self _encodeImageWithDestination:destination imageCount:count];\n        suc = CGImageDestinationFinalize(destination);\n        CFRelease(destination);\n    }\n    return suc;\n}\n\n- (NSData *)_encodeAPNG {\n    // encode APNG (ImageIO doesn't support APNG encoding, so we use a custom encoder)\n    NSMutableArray *pngDatas = [NSMutableArray new];\n    NSMutableArray *pngSizes = [NSMutableArray new];\n    NSUInteger canvasWidth = 0, canvasHeight = 0;\n    for (int i = 0; i < _images.count; i++) {\n        CGImageRef decoded = [self _newCGImageFromIndex:i decoded:YES];\n        if (!decoded) return nil;\n        CGSize size = CGSizeMake(CGImageGetWidth(decoded), CGImageGetHeight(decoded));\n        [pngSizes addObject:[NSValue valueWithCGSize:size]];\n        if (canvasWidth < size.width) canvasWidth = size.width;\n        if (canvasHeight < size.height) canvasHeight = size.height;\n        CFDataRef frameData = YYCGImageCreateEncodedData(decoded, YYImageTypePNG, 1);\n        CFRelease(decoded);\n        if (!frameData) return nil;\n        [pngDatas addObject:(__bridge id)(frameData)];\n        CFRelease(frameData);\n        if (size.width < 1 || size.height < 1) return nil;\n    }\n    CGSize firstFrameSize = [(NSValue *)[pngSizes firstObject] CGSizeValue];\n    if (firstFrameSize.width < canvasWidth || firstFrameSize.height < canvasHeight) {\n        CGImageRef decoded = [self _newCGImageFromIndex:0 decoded:YES];\n        if (!decoded) return nil;\n        CGContextRef context = CGBitmapContextCreate(NULL, canvasWidth, canvasHeight, 8,\n                                                     0, YYCGColorSpaceGetDeviceRGB(), kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);\n        if (!context) {\n            CFRelease(decoded);\n            return nil;\n        }\n        CGContextDrawImage(context, CGRectMake(0, canvasHeight - firstFrameSize.height, firstFrameSize.width, firstFrameSize.height), decoded);\n        CFRelease(decoded);\n        CGImageRef extendedImage = CGBitmapContextCreateImage(context);\n        CFRelease(context);\n        if (!extendedImage) return nil;\n        CFDataRef frameData = YYCGImageCreateEncodedData(extendedImage, YYImageTypePNG, 1);\n        if (!frameData) {\n            CFRelease(extendedImage);\n            return nil;\n        }\n        CFRelease(extendedImage);\n        pngDatas[0] = (__bridge id)(frameData);\n        CFRelease(frameData);\n    }\n    \n    NSData *firstFrameData = pngDatas[0];\n    yy_png_info *info = yy_png_info_create(firstFrameData.bytes, (uint32_t)firstFrameData.length);\n    if (!info) return nil;\n    NSMutableData *result = [NSMutableData new];\n    BOOL insertBefore = NO, insertAfter = NO;\n    uint32_t apngSequenceIndex = 0;\n    \n    uint32_t png_header[2];\n    png_header[0] = YY_FOUR_CC(0x89, 0x50, 0x4E, 0x47);\n    png_header[1] = YY_FOUR_CC(0x0D, 0x0A, 0x1A, 0x0A);\n    \n    [result appendBytes:png_header length:8];\n    \n    for (int i = 0; i < info->chunk_num; i++) {\n        yy_png_chunk_info *chunk = info->chunks + i;\n        \n        if (!insertBefore && chunk->fourcc == YY_FOUR_CC('I', 'D', 'A', 'T')) {\n            insertBefore = YES;\n            // insert acTL (APNG Control)\n            uint32_t acTL[5] = {0};\n            acTL[0] = yy_swap_endian_uint32(8); //length\n            acTL[1] = YY_FOUR_CC('a', 'c', 'T', 'L'); // fourcc\n            acTL[2] = yy_swap_endian_uint32((uint32_t)pngDatas.count); // num frames\n            acTL[3] = yy_swap_endian_uint32((uint32_t)_loopCount); // num plays\n            acTL[4] = yy_swap_endian_uint32((uint32_t)crc32(0, (const Bytef *)(acTL + 1), 12)); //crc32\n            [result appendBytes:acTL length:20];\n            \n            // insert fcTL (first frame control)\n            yy_png_chunk_fcTL chunk_fcTL = {0};\n            chunk_fcTL.sequence_number = apngSequenceIndex;\n            chunk_fcTL.width = (uint32_t)firstFrameSize.width;\n            chunk_fcTL.height = (uint32_t)firstFrameSize.height;\n            yy_png_delay_to_fraction([(NSNumber *)_durations[0] doubleValue], &chunk_fcTL.delay_num, &chunk_fcTL.delay_den);\n            chunk_fcTL.delay_num = chunk_fcTL.delay_num;\n            chunk_fcTL.delay_den = chunk_fcTL.delay_den;\n            chunk_fcTL.dispose_op = YY_PNG_DISPOSE_OP_BACKGROUND;\n            chunk_fcTL.blend_op = YY_PNG_BLEND_OP_SOURCE;\n            \n            uint8_t fcTL[38] = {0};\n            *((uint32_t *)fcTL) = yy_swap_endian_uint32(26); //length\n            *((uint32_t *)(fcTL + 4)) = YY_FOUR_CC('f', 'c', 'T', 'L'); // fourcc\n            yy_png_chunk_fcTL_write(&chunk_fcTL, fcTL + 8);\n            *((uint32_t *)(fcTL + 34)) = yy_swap_endian_uint32((uint32_t)crc32(0, (const Bytef *)(fcTL + 4), 30));\n            [result appendBytes:fcTL length:38];\n            \n            apngSequenceIndex++;\n        }\n        \n        if (!insertAfter && insertBefore && chunk->fourcc != YY_FOUR_CC('I', 'D', 'A', 'T')) {\n            insertAfter = YES;\n            // insert fcTL and fdAT (APNG frame control and data)\n            \n            for (int i = 1; i < pngDatas.count; i++) {\n                NSData *frameData = pngDatas[i];\n                yy_png_info *frame = yy_png_info_create(frameData.bytes, (uint32_t)frameData.length);\n                if (!frame) {\n                    yy_png_info_release(info);\n                    return nil;\n                }\n                \n                // insert fcTL (first frame control)\n                yy_png_chunk_fcTL chunk_fcTL = {0};\n                chunk_fcTL.sequence_number = apngSequenceIndex;\n                chunk_fcTL.width = frame->header.width;\n                chunk_fcTL.height = frame->header.height;\n                yy_png_delay_to_fraction([(NSNumber *)_durations[i] doubleValue], &chunk_fcTL.delay_num, &chunk_fcTL.delay_den);\n                chunk_fcTL.delay_num = chunk_fcTL.delay_num;\n                chunk_fcTL.delay_den = chunk_fcTL.delay_den;\n                chunk_fcTL.dispose_op = YY_PNG_DISPOSE_OP_BACKGROUND;\n                chunk_fcTL.blend_op = YY_PNG_BLEND_OP_SOURCE;\n                \n                uint8_t fcTL[38] = {0};\n                *((uint32_t *)fcTL) = yy_swap_endian_uint32(26); //length\n                *((uint32_t *)(fcTL + 4)) = YY_FOUR_CC('f', 'c', 'T', 'L'); // fourcc\n                yy_png_chunk_fcTL_write(&chunk_fcTL, fcTL + 8);\n                *((uint32_t *)(fcTL + 34)) = yy_swap_endian_uint32((uint32_t)crc32(0, (const Bytef *)(fcTL + 4), 30));\n                [result appendBytes:fcTL length:38];\n                \n                apngSequenceIndex++;\n                \n                // insert fdAT (frame data)\n                for (int d = 0; d < frame->chunk_num; d++) {\n                    yy_png_chunk_info *dchunk = frame->chunks + d;\n                    if (dchunk->fourcc == YY_FOUR_CC('I', 'D', 'A', 'T')) {\n                        uint32_t length = yy_swap_endian_uint32(dchunk->length + 4);\n                        [result appendBytes:&length length:4]; //length\n                        uint32_t fourcc = YY_FOUR_CC('f', 'd', 'A', 'T');\n                        [result appendBytes:&fourcc length:4]; //fourcc\n                        uint32_t sq = yy_swap_endian_uint32(apngSequenceIndex);\n                        [result appendBytes:&sq length:4]; //data (sq)\n                        [result appendBytes:(((uint8_t *)frameData.bytes) + dchunk->offset + 8) length:dchunk->length]; //data\n                        uint8_t *bytes = ((uint8_t *)result.bytes) + result.length - dchunk->length - 8;\n                        uint32_t crc = yy_swap_endian_uint32((uint32_t)crc32(0, bytes, dchunk->length + 8));\n                        [result appendBytes:&crc length:4]; //crc\n                        \n                        apngSequenceIndex++;\n                    }\n                }\n                yy_png_info_release(frame);\n            }\n        }\n        \n        [result appendBytes:((uint8_t *)firstFrameData.bytes) + chunk->offset length:chunk->length + 12];\n    }\n    yy_png_info_release(info);\n    return result;\n}\n\n- (NSData *)_encodeWebP {\n#if YYIMAGE_WEBP_ENABLED\n    // encode webp\n    NSMutableArray *webpDatas = [NSMutableArray new];\n    for (NSUInteger i = 0; i < _images.count; i++) {\n        CGImageRef image = [self _newCGImageFromIndex:i decoded:NO];\n        if (!image) return nil;\n        CFDataRef frameData = YYCGImageCreateEncodedWebPData(image, _lossless, _quality, 4, YYImagePresetDefault);\n        CFRelease(image);\n        if (!frameData) return nil;\n        [webpDatas addObject:(__bridge id)frameData];\n        CFRelease(frameData);\n    }\n    if (webpDatas.count == 1) {\n        return webpDatas.firstObject;\n    } else {\n        // multi-frame webp\n        WebPMux *mux = WebPMuxNew();\n        if (!mux) return nil;\n        for (NSUInteger i = 0; i < _images.count; i++) {\n            NSData *data = webpDatas[i];\n            NSNumber *duration = _durations[i];\n            WebPMuxFrameInfo frame = {0};\n            frame.bitstream.bytes = data.bytes;\n            frame.bitstream.size = data.length;\n            frame.duration = (int)(duration.floatValue * 1000.0);\n            frame.id = WEBP_CHUNK_ANMF;\n            frame.dispose_method = WEBP_MUX_DISPOSE_BACKGROUND;\n            frame.blend_method = WEBP_MUX_NO_BLEND;\n            if (WebPMuxPushFrame(mux, &frame, 0) != WEBP_MUX_OK) {\n                WebPMuxDelete(mux);\n                return nil;\n            }\n        }\n        \n        WebPMuxAnimParams params = {(uint32_t)0, (int)_loopCount};\n        if (WebPMuxSetAnimationParams(mux, &params) != WEBP_MUX_OK) {\n            WebPMuxDelete(mux);\n            return nil;\n        }\n        \n        WebPData output_data;\n        WebPMuxError error = WebPMuxAssemble(mux, &output_data);\n        WebPMuxDelete(mux);\n        if (error != WEBP_MUX_OK) {\n            return nil;\n        }\n        NSData *result = [NSData dataWithBytes:output_data.bytes length:output_data.size];\n        WebPDataClear(&output_data);\n        return result.length ? result : nil;\n    }\n#else\n    return nil;\n#endif\n}\n- (NSData *)encode {\n    if (_images.count == 0) return nil;\n    \n    if ([self _imageIOAvaliable]) return [self _encodeWithImageIO];\n    if (_type == YYImageTypePNG) return [self _encodeAPNG];\n    if (_type == YYImageTypeWebP) return [self _encodeWebP];\n    return nil;\n}\n\n- (BOOL)encodeToFile:(NSString *)path {\n    if (_images.count == 0 || path.length == 0) return NO;\n    \n    if ([self _imageIOAvaliable]) return [self _encodeWithImageIO:path];\n    NSData *data = [self encode];\n    if (!data) return NO;\n    return [data writeToFile:path atomically:YES];\n}\n\n+ (NSData *)encodeImage:(UIImage *)image type:(YYImageType)type quality:(CGFloat)quality {\n    YYImageEncoder *encoder = [[YYImageEncoder alloc] initWithType:type];\n    encoder.quality = quality;\n    [encoder addImage:image duration:0];\n    return [encoder encode];\n}\n\n+ (NSData *)encodeImageWithDecoder:(YYImageDecoder *)decoder type:(YYImageType)type quality:(CGFloat)quality {\n    if (!decoder || decoder.frameCount == 0) return nil;\n    YYImageEncoder *encoder = [[YYImageEncoder alloc] initWithType:type];\n    encoder.quality = quality;\n    for (int i = 0; i < decoder.frameCount; i++) {\n        UIImage *frame = [decoder frameAtIndex:i decodeForDisplay:YES].image;\n        [encoder addImageWithData:UIImagePNGRepresentation(frame) duration:[decoder frameDurationAtIndex:i]];\n    }\n    return encoder.encode;\n}\n\n@end\n\n\n@implementation UIImage (YYImageCoder)\n\n- (instancetype)yy_imageByDecoded {\n    if (self.yy_isDecodedForDisplay) return self;\n    CGImageRef imageRef = self.CGImage;\n    if (!imageRef) return self;\n    CGImageRef newImageRef = YYCGImageCreateDecodedCopy(imageRef, YES);\n    if (!newImageRef) return self;\n    UIImage *newImage = [[self.class alloc] initWithCGImage:newImageRef scale:self.scale orientation:self.imageOrientation];\n    CGImageRelease(newImageRef);\n    if (!newImage) newImage = self; // decode failed, return self.\n    newImage.yy_isDecodedForDisplay = YES;\n    return newImage;\n}\n\n- (BOOL)yy_isDecodedForDisplay {\n    if (self.images.count > 1 || [self isKindOfClass:[YYSpriteSheetImage class]]) return YES;\n    NSNumber *num = objc_getAssociatedObject(self, @selector(yy_isDecodedForDisplay));\n    return [num boolValue];\n}\n\n- (void)setYy_isDecodedForDisplay:(BOOL)isDecodedForDisplay {\n    objc_setAssociatedObject(self, @selector(yy_isDecodedForDisplay), @(isDecodedForDisplay), OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n}\n\n#if TARGET_OS_IOS &&  __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0\n- (PHAsset *)_getAssetFromlocalIdentifier:(NSString *)localIdentifier{\n    if(localIdentifier == nil){\n        NSLog(@\"Cannot get asset from localID because it is nil\");\n        return nil;\n    }\n    PHFetchResult *result = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil];\n    if(result.count){\n        return result[0];\n    }\n    return nil;\n}\n#endif\n\n- (void)yy_saveToAlbumWithCompletionBlock:(void(^)(BOOL success, id asset)) completionBlock {\n#if TARGET_OS_IOS\n    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n        NSData *data = [self _yy_dataRepresentationForSystem:YES];\n        #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0\n        ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];\n        [library writeImageDataToSavedPhotosAlbum:data metadata:nil completionBlock:^(NSURL *assetURL, NSError *error){\n            BOOL success = YES;\n            PHAsset *asset = nil;\n            if (error) {\n                success = NO;\n            } else {\n                PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[assetURL] options:nil];\n                asset = [result firstObject];\n            }\n            \n            if (!completionBlock) return;\n            if (pthread_main_np()) {\n                completionBlock(success, asset);\n            } else {\n                dispatch_async(dispatch_get_main_queue(), ^{\n                    completionBlock(success, asset);\n                });\n            }\n        }];\n        #else\n        __block PHObjectPlaceholder *placeholderAsset=nil;\n        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{\n            if (@available(iOS 9, *)) {\n                PHAssetCreationRequest *newAssetRequest = [PHAssetCreationRequest creationRequestForAsset];\n                [newAssetRequest addResourceWithType:PHAssetResourceTypePhoto data:data options:nil];\n                placeholderAsset = newAssetRequest.placeholderForCreatedAsset;\n            } else {\n                PHAssetChangeRequest *newAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:[UIImage imageWithData:data]];\n                placeholderAsset = newAssetRequest.placeholderForCreatedAsset;\n            }\n        } completionHandler:^(BOOL success, NSError * _Nullable error) {\n            dispatch_async(dispatch_get_main_queue(), ^{\n                if (success) {\n                    PHAsset *asset = [self _getAssetFromlocalIdentifier:placeholderAsset.localIdentifier];\n                    if (completionBlock) completionBlock(YES, asset);\n                } else {\n                    if (completionBlock) completionBlock(NO, nil);\n                }\n            });\n        }];\n        #endif\n    });\n#else\n    NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : @\"yy_saveToAlbumWithCompletionBlock failed: operation unavailable on Apple TV.\" };\n    completionBlock(nil, [NSError errorWithDomain:@\"com.ibireme.webimage\" code:-1 userInfo:userInfo]);\n#endif\n}\n- (NSData *)yy_imageDataRepresentation {\n    return [self _yy_dataRepresentationForSystem:NO];\n}\n\n/// @param forSystem YES: used for system album (PNG/JPEG/GIF), NO: used for YYImage (PNG/JPEG/GIF/WebP)\n- (NSData *)_yy_dataRepresentationForSystem:(BOOL)forSystem {\n    NSData *data = nil;\n    if ([self isKindOfClass:[YYImage class]]) {\n        YYImage *image = (id)self;\n        if (image.animatedImageData) {\n            if (forSystem) { // system only support GIF and PNG\n                if (image.animatedImageType == YYImageTypeGIF ||\n                    image.animatedImageType == YYImageTypePNG) {\n                    data = image.animatedImageData;\n                }\n            } else {\n                data = image.animatedImageData;\n            }\n        }\n    }\n    if (!data) {\n        CGImageRef imageRef = self.CGImage ? (CGImageRef)CFRetain(self.CGImage) : nil;\n        if (imageRef) {\n            CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);\n            CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef) & kCGBitmapAlphaInfoMask;\n            BOOL hasAlpha = NO;\n            if (alphaInfo == kCGImageAlphaPremultipliedLast ||\n                alphaInfo == kCGImageAlphaPremultipliedFirst ||\n                alphaInfo == kCGImageAlphaLast ||\n                alphaInfo == kCGImageAlphaFirst) {\n                hasAlpha = YES;\n            }\n            if (self.imageOrientation != UIImageOrientationUp) {\n                CGImageRef rotated = YYCGImageCreateCopyWithOrientation(imageRef, self.imageOrientation, bitmapInfo | alphaInfo);\n                if (rotated) {\n                    CFRelease(imageRef);\n                    imageRef = rotated;\n                }\n            }\n            @autoreleasepool {\n                UIImage *newImage = [UIImage imageWithCGImage:imageRef];\n                if (newImage) {\n                    if (hasAlpha) {\n                        data = UIImagePNGRepresentation([UIImage imageWithCGImage:imageRef]);\n                    } else {\n                        data = UIImageJPEGRepresentation([UIImage imageWithCGImage:imageRef], 0.9); // same as Apple's example\n                    }\n                }\n            }\n            CFRelease(imageRef);\n        }\n    }\n    if (!data) {\n        data = UIImagePNGRepresentation(self);\n    }\n    return data;\n}\n\n@end\n"
  },
  {
    "path": "YYImage/YYSpriteSheetImage.h",
    "content": "//\n//  YYSpriteImage.h\n//  YYImage <https://github.com/ibireme/YYImage>\n//\n//  Created by ibireme on 15/4/21.\n//  Copyright (c) 2015 ibireme.\n//\n//  This source code is licensed under the MIT-style license found in the\n//  LICENSE file in the root directory of this source tree.\n//\n\n#import <UIKit/UIKit.h>\n\n#if __has_include(<YYImage/YYImage.h>)\n#import <YYImage/YYAnimatedImageView.h>\n#elif __has_include(<YYWebImage/YYImage.h>)\n#import <YYWebImage/YYAnimatedImageView.h>\n#else\n#import \"YYAnimatedImageView.h\"\n#endif\n\nNS_ASSUME_NONNULL_BEGIN\n\n/**\n An image to display sprite sheet animation.\n \n @discussion It is a fully compatible `UIImage` subclass.\n The animation can be played by YYAnimatedImageView.\n \n Sample Code:\n  \n    // 8 * 12 sprites in a single sheet image\n    UIImage *spriteSheet = [UIImage imageNamed:@\"sprite-sheet\"];\n    NSMutableArray *contentRects = [NSMutableArray new];\n    NSMutableArray *durations = [NSMutableArray new];\n    for (int j = 0; j < 12; j++) {\n        for (int i = 0; i < 8; i++) {\n            CGRect rect;\n            rect.size = CGSizeMake(img.size.width / 8, img.size.height / 12);\n            rect.origin.x = img.size.width / 8 * i;\n            rect.origin.y = img.size.height / 12 * j;\n            [contentRects addObject:[NSValue valueWithCGRect:rect]];\n            [durations addObject:@(1 / 60.0)];\n        }\n    }\n    YYSpriteSheetImage *sprite;\n    sprite = [[YYSpriteSheetImage alloc] initWithSpriteSheetImage:img\n                                                     contentRects:contentRects\n                                                   frameDurations:durations\n                                                        loopCount:0];\n    YYAnimatedImageView *imgView = [YYAnimatedImageView new];\n    imgView.size = CGSizeMake(img.size.width / 8, img.size.height / 12);\n    imgView.image = sprite;\n \n \n \n @discussion It can also be used to display single frame in sprite sheet image.\n Sample Code:\n \n    YYSpriteSheetImage *sheet = ...;\n    UIImageView *imageView = ...;\n    imageView.image = sheet;\n    imageView.layer.contentsRect = [sheet contentsRectForCALayerAtIndex:6];\n \n */\n@interface YYSpriteSheetImage : UIImage <YYAnimatedImage>\n\n/**\n Creates and returns an image object.\n \n @param image          The sprite sheet image (contains all frames).\n \n @param contentRects   The sprite sheet image frame rects in the image coordinates.\n     The rectangle should not outside the image's bounds. The objects in this array\n     should be created with [NSValue valueWithCGRect:].\n \n @param frameDurations The sprite sheet image frame's durations in seconds. \n     The objects in this array should be NSNumber.\n \n @param loopCount      Animation loop count, 0 means infinite looping.\n \n @return An image object, or nil if an error occurs.\n */\n- (nullable instancetype)initWithSpriteSheetImage:(UIImage *)image\n                                     contentRects:(NSArray<NSValue *> *)contentRects\n                                   frameDurations:(NSArray<NSNumber *> *)frameDurations\n                                        loopCount:(NSUInteger)loopCount;\n\n@property (nonatomic, readonly) NSArray<NSValue *> *contentRects;\n@property (nonatomic, readonly) NSArray<NSValue *> *frameDurations;\n@property (nonatomic, readonly) NSUInteger loopCount;\n\n/**\n Get the contents rect for CALayer.\n See \"contentsRect\" property in CALayer for more information.\n \n @param index Index of frame.\n @return Contents Rect.\n */\n- (CGRect)contentsRectForCALayerAtIndex:(NSUInteger)index;\n\n@end\n\nNS_ASSUME_NONNULL_END\n"
  },
  {
    "path": "YYImage/YYSpriteSheetImage.m",
    "content": "//\n//  YYSpriteImage.m\n//  YYImage <https://github.com/ibireme/YYImage>\n//\n//  Created by ibireme on 15/4/21.\n//  Copyright (c) 2015 ibireme.\n//\n//  This source code is licensed under the MIT-style license found in the\n//  LICENSE file in the root directory of this source tree.\n//\n\n#import \"YYSpriteSheetImage.h\"\n\n@implementation YYSpriteSheetImage\n\n- (instancetype)initWithSpriteSheetImage:(UIImage *)image\n                            contentRects:(NSArray *)contentRects\n                          frameDurations:(NSArray *)frameDurations\n                               loopCount:(NSUInteger)loopCount {\n    if (!image.CGImage) return nil;\n    if (contentRects.count < 1 || frameDurations.count < 1) return nil;\n    if (contentRects.count != frameDurations.count) return nil;\n    \n    self = [super initWithCGImage:image.CGImage scale:image.scale orientation:image.imageOrientation];\n    if (!self) return nil;\n    \n    _contentRects = contentRects.copy;\n    _frameDurations = frameDurations.copy;\n    _loopCount = loopCount;\n    return self;\n}\n\n- (CGRect)contentsRectForCALayerAtIndex:(NSUInteger)index {\n    CGRect layerRect = CGRectMake(0, 0, 1, 1);\n    if (index >= _contentRects.count) return layerRect;\n    \n    CGSize imageSize = self.size;\n    CGRect rect = [self animatedImageContentsRectAtIndex:index];\n    if (imageSize.width > 0.01 && imageSize.height > 0.01) {\n        layerRect.origin.x = rect.origin.x / imageSize.width;\n        layerRect.origin.y = rect.origin.y / imageSize.height;\n        layerRect.size.width = rect.size.width / imageSize.width;\n        layerRect.size.height = rect.size.height / imageSize.height;\n        layerRect = CGRectIntersection(layerRect, CGRectMake(0, 0, 1, 1));\n        if (CGRectIsNull(layerRect) || CGRectIsEmpty(layerRect)) {\n            layerRect = CGRectMake(0, 0, 1, 1);\n        }\n    }\n    return layerRect;\n}\n\n#pragma mark @protocol YYAnimatedImage\n\n- (NSUInteger)animatedImageFrameCount {\n    return _contentRects.count;\n}\n\n- (NSUInteger)animatedImageLoopCount {\n    return _loopCount;\n}\n\n- (NSUInteger)animatedImageBytesPerFrame {\n    return 0;\n}\n\n- (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index {\n    return self;\n}\n\n- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index {\n    if (index >= _frameDurations.count) return 0;\n    return ((NSNumber *)_frameDurations[index]).doubleValue;\n}\n\n- (CGRect)animatedImageContentsRectAtIndex:(NSUInteger)index {\n    if (index >= _contentRects.count) return CGRectZero;\n    return ((NSValue *)_contentRects[index]).CGRectValue;\n}\n\n@end\n"
  },
  {
    "path": "build-scripts/BUILD",
    "content": "388"
  },
  {
    "path": "build-scripts/VERSION",
    "content": "4.33\n"
  },
  {
    "path": "build-scripts/ace-modes.js",
    "content": "var data = {\n    \"abap\": {\n        \"name\": \"abap\",\n        \"caption\": \"ABAP\",\n        \"mode\": \"ace/mode/abap\",\n        \"extensions\": \"abap\",\n        \"extRe\": {}\n    },\n    \"abc\": {\n        \"name\": \"abc\",\n        \"caption\": \"ABC\",\n        \"mode\": \"ace/mode/abc\",\n        \"extensions\": \"abc\",\n        \"extRe\": {}\n    },\n    \"actionscript\": {\n        \"name\": \"actionscript\",\n        \"caption\": \"ActionScript\",\n        \"mode\": \"ace/mode/actionscript\",\n        \"extensions\": \"as\",\n        \"extRe\": {}\n    },\n    \"ada\": {\n        \"name\": \"ada\",\n        \"caption\": \"ADA\",\n        \"mode\": \"ace/mode/ada\",\n        \"extensions\": \"ada|adb\",\n        \"extRe\": {}\n    },\n    \"apache_conf\": {\n        \"name\": \"apache_conf\",\n        \"caption\": \"Apache Conf\",\n        \"mode\": \"ace/mode/apache_conf\",\n        \"extensions\": \"^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd\",\n        \"extRe\": {}\n    },\n    \"asciidoc\": {\n        \"name\": \"asciidoc\",\n        \"caption\": \"AsciiDoc\",\n        \"mode\": \"ace/mode/asciidoc\",\n        \"extensions\": \"asciidoc|adoc\",\n        \"extRe\": {}\n    },\n    \"assembly_x86\": {\n        \"name\": \"assembly_x86\",\n        \"caption\": \"Assembly x86\",\n        \"mode\": \"ace/mode/assembly_x86\",\n        \"extensions\": \"asm|a\",\n        \"extRe\": {}\n    },\n    \"autohotkey\": {\n        \"name\": \"autohotkey\",\n        \"caption\": \"AutoHotKey\",\n        \"mode\": \"ace/mode/autohotkey\",\n        \"extensions\": \"ahk\",\n        \"extRe\": {}\n    },\n    \"batchfile\": {\n        \"name\": \"batchfile\",\n        \"caption\": \"BatchFile\",\n        \"mode\": \"ace/mode/batchfile\",\n        \"extensions\": \"bat|cmd\",\n        \"extRe\": {}\n    },\n    \"bro\": {\n        \"name\": \"bro\",\n        \"caption\": \"Bro\",\n        \"mode\": \"ace/mode/bro\",\n        \"extensions\": \"bro\",\n        \"extRe\": {}\n    },\n    \"c_cpp\": {\n        \"name\": \"c_cpp\",\n        \"caption\": \"C and C++\",\n        \"mode\": \"ace/mode/c_cpp\",\n        \"extensions\": \"cpp|c|cc|cxx|h|hh|hpp|ino\",\n        \"extRe\": {}\n    },\n    \"c9search\": {\n        \"name\": \"c9search\",\n        \"caption\": \"C9Search\",\n        \"mode\": \"ace/mode/c9search\",\n        \"extensions\": \"c9search_results\",\n        \"extRe\": {}\n    },\n    \"cirru\": {\n        \"name\": \"cirru\",\n        \"caption\": \"Cirru\",\n        \"mode\": \"ace/mode/cirru\",\n        \"extensions\": \"cirru|cr\",\n        \"extRe\": {}\n    },\n    \"clojure\": {\n        \"name\": \"clojure\",\n        \"caption\": \"Clojure\",\n        \"mode\": \"ace/mode/clojure\",\n        \"extensions\": \"clj|cljs\",\n        \"extRe\": {}\n    },\n    \"cobol\": {\n        \"name\": \"cobol\",\n        \"caption\": \"Cobol\",\n        \"mode\": \"ace/mode/cobol\",\n        \"extensions\": \"CBL|COB\",\n        \"extRe\": {}\n    },\n    \"coffee\": {\n        \"name\": \"coffee\",\n        \"caption\": \"CoffeeScript\",\n        \"mode\": \"ace/mode/coffee\",\n        \"extensions\": \"coffee|cf|cson|^Cakefile\",\n        \"extRe\": {}\n    },\n    \"coldfusion\": {\n        \"name\": \"coldfusion\",\n        \"caption\": \"ColdFusion\",\n        \"mode\": \"ace/mode/coldfusion\",\n        \"extensions\": \"cfm\",\n        \"extRe\": {}\n    },\n    \"csharp\": {\n        \"name\": \"csharp\",\n        \"caption\": \"C#\",\n        \"mode\": \"ace/mode/csharp\",\n        \"extensions\": \"cs\",\n        \"extRe\": {}\n    },\n    \"csound_document\": {\n        \"name\": \"csound_document\",\n        \"caption\": \"Csound Document\",\n        \"mode\": \"ace/mode/csound_document\",\n        \"extensions\": \"csd\",\n        \"extRe\": {}\n    },\n    \"csound_orchestra\": {\n        \"name\": \"csound_orchestra\",\n        \"caption\": \"Csound\",\n        \"mode\": \"ace/mode/csound_orchestra\",\n        \"extensions\": \"orc\",\n        \"extRe\": {}\n    },\n    \"csound_score\": {\n        \"name\": \"csound_score\",\n        \"caption\": \"Csound Score\",\n        \"mode\": \"ace/mode/csound_score\",\n        \"extensions\": \"sco\",\n        \"extRe\": {}\n    },\n    \"css\": {\n        \"name\": \"css\",\n        \"caption\": \"CSS\",\n        \"mode\": \"ace/mode/css\",\n        \"extensions\": \"css\",\n        \"extRe\": {}\n    },\n    \"curly\": {\n        \"name\": \"curly\",\n        \"caption\": \"Curly\",\n        \"mode\": \"ace/mode/curly\",\n        \"extensions\": \"curly\",\n        \"extRe\": {}\n    },\n    \"d\": {\n        \"name\": \"d\",\n        \"caption\": \"D\",\n        \"mode\": \"ace/mode/d\",\n        \"extensions\": \"d|di\",\n        \"extRe\": {}\n    },\n    \"dart\": {\n        \"name\": \"dart\",\n        \"caption\": \"Dart\",\n        \"mode\": \"ace/mode/dart\",\n        \"extensions\": \"dart\",\n        \"extRe\": {}\n    },\n    \"diff\": {\n        \"name\": \"diff\",\n        \"caption\": \"Diff\",\n        \"mode\": \"ace/mode/diff\",\n        \"extensions\": \"diff|patch\",\n        \"extRe\": {}\n    },\n    \"dockerfile\": {\n        \"name\": \"dockerfile\",\n        \"caption\": \"Dockerfile\",\n        \"mode\": \"ace/mode/dockerfile\",\n        \"extensions\": \"^Dockerfile\",\n        \"extRe\": {}\n    },\n    \"dot\": {\n        \"name\": \"dot\",\n        \"caption\": \"Dot\",\n        \"mode\": \"ace/mode/dot\",\n        \"extensions\": \"dot\",\n        \"extRe\": {}\n    },\n    \"drools\": {\n        \"name\": \"drools\",\n        \"caption\": \"Drools\",\n        \"mode\": \"ace/mode/drools\",\n        \"extensions\": \"drl\",\n        \"extRe\": {}\n    },\n    \"dummy\": {\n        \"name\": \"dummy\",\n        \"caption\": \"Dummy\",\n        \"mode\": \"ace/mode/dummy\",\n        \"extensions\": \"dummy\",\n        \"extRe\": {}\n    },\n    \"dummysyntax\": {\n        \"name\": \"dummysyntax\",\n        \"caption\": \"DummySyntax\",\n        \"mode\": \"ace/mode/dummysyntax\",\n        \"extensions\": \"dummy\",\n        \"extRe\": {}\n    },\n    \"eiffel\": {\n        \"name\": \"eiffel\",\n        \"caption\": \"Eiffel\",\n        \"mode\": \"ace/mode/eiffel\",\n        \"extensions\": \"e|ge\",\n        \"extRe\": {}\n    },\n    \"ejs\": {\n        \"name\": \"ejs\",\n        \"caption\": \"EJS\",\n        \"mode\": \"ace/mode/ejs\",\n        \"extensions\": \"ejs\",\n        \"extRe\": {}\n    },\n    \"elixir\": {\n        \"name\": \"elixir\",\n        \"caption\": \"Elixir\",\n        \"mode\": \"ace/mode/elixir\",\n        \"extensions\": \"ex|exs\",\n        \"extRe\": {}\n    },\n    \"elm\": {\n        \"name\": \"elm\",\n        \"caption\": \"Elm\",\n        \"mode\": \"ace/mode/elm\",\n        \"extensions\": \"elm\",\n        \"extRe\": {}\n    },\n    \"erlang\": {\n        \"name\": \"erlang\",\n        \"caption\": \"Erlang\",\n        \"mode\": \"ace/mode/erlang\",\n        \"extensions\": \"erl|hrl\",\n        \"extRe\": {}\n    },\n    \"forth\": {\n        \"name\": \"forth\",\n        \"caption\": \"Forth\",\n        \"mode\": \"ace/mode/forth\",\n        \"extensions\": \"frt|fs|ldr|fth|4th\",\n        \"extRe\": {}\n    },\n    \"fortran\": {\n        \"name\": \"fortran\",\n        \"caption\": \"Fortran\",\n        \"mode\": \"ace/mode/fortran\",\n        \"extensions\": \"f|f90\",\n        \"extRe\": {}\n    },\n    \"ftl\": {\n        \"name\": \"ftl\",\n        \"caption\": \"FreeMarker\",\n        \"mode\": \"ace/mode/ftl\",\n        \"extensions\": \"ftl\",\n        \"extRe\": {}\n    },\n    \"gcode\": {\n        \"name\": \"gcode\",\n        \"caption\": \"Gcode\",\n        \"mode\": \"ace/mode/gcode\",\n        \"extensions\": \"gcode\",\n        \"extRe\": {}\n    },\n    \"gherkin\": {\n        \"name\": \"gherkin\",\n        \"caption\": \"Gherkin\",\n        \"mode\": \"ace/mode/gherkin\",\n        \"extensions\": \"feature\",\n        \"extRe\": {}\n    },\n    \"gitignore\": {\n        \"name\": \"gitignore\",\n        \"caption\": \"Gitignore\",\n        \"mode\": \"ace/mode/gitignore\",\n        \"extensions\": \"^.gitignore\",\n        \"extRe\": {}\n    },\n    \"glsl\": {\n        \"name\": \"glsl\",\n        \"caption\": \"Glsl\",\n        \"mode\": \"ace/mode/glsl\",\n        \"extensions\": \"glsl|frag|vert\",\n        \"extRe\": {}\n    },\n    \"gobstones\": {\n        \"name\": \"gobstones\",\n        \"caption\": \"Gobstones\",\n        \"mode\": \"ace/mode/gobstones\",\n        \"extensions\": \"gbs\",\n        \"extRe\": {}\n    },\n    \"golang\": {\n        \"name\": \"golang\",\n        \"caption\": \"Go\",\n        \"mode\": \"ace/mode/golang\",\n        \"extensions\": \"go\",\n        \"extRe\": {}\n    },\n    \"graphqlschema\": {\n        \"name\": \"graphqlschema\",\n        \"caption\": \"GraphQLSchema\",\n        \"mode\": \"ace/mode/graphqlschema\",\n        \"extensions\": \"gql\",\n        \"extRe\": {}\n    },\n    \"groovy\": {\n        \"name\": \"groovy\",\n        \"caption\": \"Groovy\",\n        \"mode\": \"ace/mode/groovy\",\n        \"extensions\": \"groovy\",\n        \"extRe\": {}\n    },\n    \"haml\": {\n        \"name\": \"haml\",\n        \"caption\": \"HAML\",\n        \"mode\": \"ace/mode/haml\",\n        \"extensions\": \"haml\",\n        \"extRe\": {}\n    },\n    \"handlebars\": {\n        \"name\": \"handlebars\",\n        \"caption\": \"Handlebars\",\n        \"mode\": \"ace/mode/handlebars\",\n        \"extensions\": \"hbs|handlebars|tpl|mustache\",\n        \"extRe\": {}\n    },\n    \"haskell\": {\n        \"name\": \"haskell\",\n        \"caption\": \"Haskell\",\n        \"mode\": \"ace/mode/haskell\",\n        \"extensions\": \"hs\",\n        \"extRe\": {}\n    },\n    \"haskell_cabal\": {\n        \"name\": \"haskell_cabal\",\n        \"caption\": \"Haskell Cabal\",\n        \"mode\": \"ace/mode/haskell_cabal\",\n        \"extensions\": \"cabal\",\n        \"extRe\": {}\n    },\n    \"haxe\": {\n        \"name\": \"haxe\",\n        \"caption\": \"haXe\",\n        \"mode\": \"ace/mode/haxe\",\n        \"extensions\": \"hx\",\n        \"extRe\": {}\n    },\n    \"hjson\": {\n        \"name\": \"hjson\",\n        \"caption\": \"Hjson\",\n        \"mode\": \"ace/mode/hjson\",\n        \"extensions\": \"hjson\",\n        \"extRe\": {}\n    },\n    \"html\": {\n        \"name\": \"html\",\n        \"caption\": \"HTML\",\n        \"mode\": \"ace/mode/html\",\n        \"extensions\": \"html|htm|xhtml|vue|we|wpy\",\n        \"extRe\": {}\n    },\n    \"html_elixir\": {\n        \"name\": \"html_elixir\",\n        \"caption\": \"HTML (Elixir)\",\n        \"mode\": \"ace/mode/html_elixir\",\n        \"extensions\": \"eex|html.eex\",\n        \"extRe\": {}\n    },\n    \"html_ruby\": {\n        \"name\": \"html_ruby\",\n        \"caption\": \"HTML (Ruby)\",\n        \"mode\": \"ace/mode/html_ruby\",\n        \"extensions\": \"erb|rhtml|html.erb\",\n        \"extRe\": {}\n    },\n    \"ini\": {\n        \"name\": \"ini\",\n        \"caption\": \"INI\",\n        \"mode\": \"ace/mode/ini\",\n        \"extensions\": \"ini|conf|cfg|prefs\",\n        \"extRe\": {}\n    },\n    \"io\": {\n        \"name\": \"io\",\n        \"caption\": \"Io\",\n        \"mode\": \"ace/mode/io\",\n        \"extensions\": \"io\",\n        \"extRe\": {}\n    },\n    \"jack\": {\n        \"name\": \"jack\",\n        \"caption\": \"Jack\",\n        \"mode\": \"ace/mode/jack\",\n        \"extensions\": \"jack\",\n        \"extRe\": {}\n    },\n    \"jade\": {\n        \"name\": \"jade\",\n        \"caption\": \"Jade\",\n        \"mode\": \"ace/mode/jade\",\n        \"extensions\": \"jade|pug\",\n        \"extRe\": {}\n    },\n    \"java\": {\n        \"name\": \"java\",\n        \"caption\": \"Java\",\n        \"mode\": \"ace/mode/java\",\n        \"extensions\": \"java\",\n        \"extRe\": {}\n    },\n    \"javascript\": {\n        \"name\": \"javascript\",\n        \"caption\": \"JavaScript\",\n        \"mode\": \"ace/mode/javascript\",\n        \"extensions\": \"js|jsm|jsx\",\n        \"extRe\": {}\n    },\n    \"json\": {\n        \"name\": \"json\",\n        \"caption\": \"JSON\",\n        \"mode\": \"ace/mode/json\",\n        \"extensions\": \"json\",\n        \"extRe\": {}\n    },\n    \"jsoniq\": {\n        \"name\": \"jsoniq\",\n        \"caption\": \"JSONiq\",\n        \"mode\": \"ace/mode/jsoniq\",\n        \"extensions\": \"jq\",\n        \"extRe\": {}\n    },\n    \"jsp\": {\n        \"name\": \"jsp\",\n        \"caption\": \"JSP\",\n        \"mode\": \"ace/mode/jsp\",\n        \"extensions\": \"jsp\",\n        \"extRe\": {}\n    },\n    \"jssm\": {\n        \"name\": \"jssm\",\n        \"caption\": \"JSSM\",\n        \"mode\": \"ace/mode/jssm\",\n        \"extensions\": \"jssm|jssm_state\",\n        \"extRe\": {}\n    },\n    \"jsx\": {\n        \"name\": \"jsx\",\n        \"caption\": \"JSX\",\n        \"mode\": \"ace/mode/jsx\",\n        \"extensions\": \"jsx\",\n        \"extRe\": {}\n    },\n    \"julia\": {\n        \"name\": \"julia\",\n        \"caption\": \"Julia\",\n        \"mode\": \"ace/mode/julia\",\n        \"extensions\": \"jl\",\n        \"extRe\": {}\n    },\n    \"kotlin\": {\n        \"name\": \"kotlin\",\n        \"caption\": \"Kotlin\",\n        \"mode\": \"ace/mode/kotlin\",\n        \"extensions\": \"kt|kts\",\n        \"extRe\": {}\n    },\n    \"latex\": {\n        \"name\": \"latex\",\n        \"caption\": \"LaTeX\",\n        \"mode\": \"ace/mode/latex\",\n        \"extensions\": \"tex|latex|ltx|bib\",\n        \"extRe\": {}\n    },\n    \"less\": {\n        \"name\": \"less\",\n        \"caption\": \"LESS\",\n        \"mode\": \"ace/mode/less\",\n        \"extensions\": \"less\",\n        \"extRe\": {}\n    },\n    \"liquid\": {\n        \"name\": \"liquid\",\n        \"caption\": \"Liquid\",\n        \"mode\": \"ace/mode/liquid\",\n        \"extensions\": \"liquid\",\n        \"extRe\": {}\n    },\n    \"lisp\": {\n        \"name\": \"lisp\",\n        \"caption\": \"Lisp\",\n        \"mode\": \"ace/mode/lisp\",\n        \"extensions\": \"lisp\",\n        \"extRe\": {}\n    },\n    \"livescript\": {\n        \"name\": \"livescript\",\n        \"caption\": \"LiveScript\",\n        \"mode\": \"ace/mode/livescript\",\n        \"extensions\": \"ls\",\n        \"extRe\": {}\n    },\n    \"logiql\": {\n        \"name\": \"logiql\",\n        \"caption\": \"LogiQL\",\n        \"mode\": \"ace/mode/logiql\",\n        \"extensions\": \"logic|lql\",\n        \"extRe\": {}\n    },\n    \"lsl\": {\n        \"name\": \"lsl\",\n        \"caption\": \"LSL\",\n        \"mode\": \"ace/mode/lsl\",\n        \"extensions\": \"lsl\",\n        \"extRe\": {}\n    },\n    \"lua\": {\n        \"name\": \"lua\",\n        \"caption\": \"Lua\",\n        \"mode\": \"ace/mode/lua\",\n        \"extensions\": \"lua\",\n        \"extRe\": {}\n    },\n    \"luapage\": {\n        \"name\": \"luapage\",\n        \"caption\": \"LuaPage\",\n        \"mode\": \"ace/mode/luapage\",\n        \"extensions\": \"lp\",\n        \"extRe\": {}\n    },\n    \"lucene\": {\n        \"name\": \"lucene\",\n        \"caption\": \"Lucene\",\n        \"mode\": \"ace/mode/lucene\",\n        \"extensions\": \"lucene\",\n        \"extRe\": {}\n    },\n    \"makefile\": {\n        \"name\": \"makefile\",\n        \"caption\": \"Makefile\",\n        \"mode\": \"ace/mode/makefile\",\n        \"extensions\": \"^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make\",\n        \"extRe\": {}\n    },\n    \"markdown\": {\n        \"name\": \"markdown\",\n        \"caption\": \"Markdown\",\n        \"mode\": \"ace/mode/markdown\",\n        \"extensions\": \"md|markdown\",\n        \"extRe\": {}\n    },\n    \"mask\": {\n        \"name\": \"mask\",\n        \"caption\": \"Mask\",\n        \"mode\": \"ace/mode/mask\",\n        \"extensions\": \"mask\",\n        \"extRe\": {}\n    },\n    \"matlab\": {\n        \"name\": \"matlab\",\n        \"caption\": \"MATLAB\",\n        \"mode\": \"ace/mode/matlab\",\n        \"extensions\": \"matlab\",\n        \"extRe\": {}\n    },\n    \"maze\": {\n        \"name\": \"maze\",\n        \"caption\": \"Maze\",\n        \"mode\": \"ace/mode/maze\",\n        \"extensions\": \"mz\",\n        \"extRe\": {}\n    },\n    \"mel\": {\n        \"name\": \"mel\",\n        \"caption\": \"MEL\",\n        \"mode\": \"ace/mode/mel\",\n        \"extensions\": \"mel\",\n        \"extRe\": {}\n    },\n    \"mushcode\": {\n        \"name\": \"mushcode\",\n        \"caption\": \"MUSHCode\",\n        \"mode\": \"ace/mode/mushcode\",\n        \"extensions\": \"mc|mush\",\n        \"extRe\": {}\n    },\n    \"mysql\": {\n        \"name\": \"mysql\",\n        \"caption\": \"MySQL\",\n        \"mode\": \"ace/mode/mysql\",\n        \"extensions\": \"mysql\",\n        \"extRe\": {}\n    },\n    \"nix\": {\n        \"name\": \"nix\",\n        \"caption\": \"Nix\",\n        \"mode\": \"ace/mode/nix\",\n        \"extensions\": \"nix\",\n        \"extRe\": {}\n    },\n    \"nsis\": {\n        \"name\": \"nsis\",\n        \"caption\": \"NSIS\",\n        \"mode\": \"ace/mode/nsis\",\n        \"extensions\": \"nsi|nsh\",\n        \"extRe\": {}\n    },\n    \"objectivec\": {\n        \"name\": \"objectivec\",\n        \"caption\": \"Objective-C\",\n        \"mode\": \"ace/mode/objectivec\",\n        \"extensions\": \"m|mm\",\n        \"extRe\": {}\n    },\n    \"ocaml\": {\n        \"name\": \"ocaml\",\n        \"caption\": \"OCaml\",\n        \"mode\": \"ace/mode/ocaml\",\n        \"extensions\": \"ml|mli\",\n        \"extRe\": {}\n    },\n    \"pascal\": {\n        \"name\": \"pascal\",\n        \"caption\": \"Pascal\",\n        \"mode\": \"ace/mode/pascal\",\n        \"extensions\": \"pas|p\",\n        \"extRe\": {}\n    },\n    \"perl\": {\n        \"name\": \"perl\",\n        \"caption\": \"Perl\",\n        \"mode\": \"ace/mode/perl\",\n        \"extensions\": \"pl|pm\",\n        \"extRe\": {}\n    },\n    \"pgsql\": {\n        \"name\": \"pgsql\",\n        \"caption\": \"pgSQL\",\n        \"mode\": \"ace/mode/pgsql\",\n        \"extensions\": \"pgsql\",\n        \"extRe\": {}\n    },\n    \"php\": {\n        \"name\": \"php\",\n        \"caption\": \"PHP\",\n        \"mode\": \"ace/mode/php\",\n        \"extensions\": \"php|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp|module\",\n        \"extRe\": {}\n    },\n    \"pig\": {\n        \"name\": \"pig\",\n        \"caption\": \"Pig\",\n        \"mode\": \"ace/mode/pig\",\n        \"extensions\": \"pig\",\n        \"extRe\": {}\n    },\n    \"powershell\": {\n        \"name\": \"powershell\",\n        \"caption\": \"Powershell\",\n        \"mode\": \"ace/mode/powershell\",\n        \"extensions\": \"ps1\",\n        \"extRe\": {}\n    },\n    \"praat\": {\n        \"name\": \"praat\",\n        \"caption\": \"Praat\",\n        \"mode\": \"ace/mode/praat\",\n        \"extensions\": \"praat|praatscript|psc|proc\",\n        \"extRe\": {}\n    },\n    \"prolog\": {\n        \"name\": \"prolog\",\n        \"caption\": \"Prolog\",\n        \"mode\": \"ace/mode/prolog\",\n        \"extensions\": \"plg|prolog\",\n        \"extRe\": {}\n    },\n    \"properties\": {\n        \"name\": \"properties\",\n        \"caption\": \"Properties\",\n        \"mode\": \"ace/mode/properties\",\n        \"extensions\": \"properties\",\n        \"extRe\": {}\n    },\n    \"protobuf\": {\n        \"name\": \"protobuf\",\n        \"caption\": \"Protobuf\",\n        \"mode\": \"ace/mode/protobuf\",\n        \"extensions\": \"proto\",\n        \"extRe\": {}\n    },\n    \"python\": {\n        \"name\": \"python\",\n        \"caption\": \"Python\",\n        \"mode\": \"ace/mode/python\",\n        \"extensions\": \"py\",\n        \"extRe\": {}\n    },\n    \"r\": {\n        \"name\": \"r\",\n        \"caption\": \"R\",\n        \"mode\": \"ace/mode/r\",\n        \"extensions\": \"r\",\n        \"extRe\": {}\n    },\n    \"razor\": {\n        \"name\": \"razor\",\n        \"caption\": \"Razor\",\n        \"mode\": \"ace/mode/razor\",\n        \"extensions\": \"cshtml|asp\",\n        \"extRe\": {}\n    },\n    \"rdoc\": {\n        \"name\": \"rdoc\",\n        \"caption\": \"RDoc\",\n        \"mode\": \"ace/mode/rdoc\",\n        \"extensions\": \"Rd\",\n        \"extRe\": {}\n    },\n    \"red\": {\n        \"name\": \"red\",\n        \"caption\": \"Red\",\n        \"mode\": \"ace/mode/red\",\n        \"extensions\": \"red|reds\",\n        \"extRe\": {}\n    },\n    \"rhtml\": {\n        \"name\": \"rhtml\",\n        \"caption\": \"RHTML\",\n        \"mode\": \"ace/mode/rhtml\",\n        \"extensions\": \"Rhtml\",\n        \"extRe\": {}\n    },\n    \"rst\": {\n        \"name\": \"rst\",\n        \"caption\": \"RST\",\n        \"mode\": \"ace/mode/rst\",\n        \"extensions\": \"rst\",\n        \"extRe\": {}\n    },\n    \"ruby\": {\n        \"name\": \"ruby\",\n        \"caption\": \"Ruby\",\n        \"mode\": \"ace/mode/ruby\",\n        \"extensions\": \"rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile\",\n        \"extRe\": {}\n    },\n    \"rust\": {\n        \"name\": \"rust\",\n        \"caption\": \"Rust\",\n        \"mode\": \"ace/mode/rust\",\n        \"extensions\": \"rs\",\n        \"extRe\": {}\n    },\n    \"sass\": {\n        \"name\": \"sass\",\n        \"caption\": \"SASS\",\n        \"mode\": \"ace/mode/sass\",\n        \"extensions\": \"sass\",\n        \"extRe\": {}\n    },\n    \"scad\": {\n        \"name\": \"scad\",\n        \"caption\": \"SCAD\",\n        \"mode\": \"ace/mode/scad\",\n        \"extensions\": \"scad\",\n        \"extRe\": {}\n    },\n    \"scala\": {\n        \"name\": \"scala\",\n        \"caption\": \"Scala\",\n        \"mode\": \"ace/mode/scala\",\n        \"extensions\": \"scala\",\n        \"extRe\": {}\n    },\n    \"scheme\": {\n        \"name\": \"scheme\",\n        \"caption\": \"Scheme\",\n        \"mode\": \"ace/mode/scheme\",\n        \"extensions\": \"scm|sm|rkt|oak|scheme\",\n        \"extRe\": {}\n    },\n    \"scss\": {\n        \"name\": \"scss\",\n        \"caption\": \"SCSS\",\n        \"mode\": \"ace/mode/scss\",\n        \"extensions\": \"scss\",\n        \"extRe\": {}\n    },\n    \"sh\": {\n        \"name\": \"sh\",\n        \"caption\": \"SH\",\n        \"mode\": \"ace/mode/sh\",\n        \"extensions\": \"sh|bash|^.bashrc\",\n        \"extRe\": {}\n    },\n    \"sjs\": {\n        \"name\": \"sjs\",\n        \"caption\": \"SJS\",\n        \"mode\": \"ace/mode/sjs\",\n        \"extensions\": \"sjs\",\n        \"extRe\": {}\n    },\n    \"smarty\": {\n        \"name\": \"smarty\",\n        \"caption\": \"Smarty\",\n        \"mode\": \"ace/mode/smarty\",\n        \"extensions\": \"smarty|tpl\",\n        \"extRe\": {}\n    },\n    \"snippets\": {\n        \"name\": \"snippets\",\n        \"caption\": \"snippets\",\n        \"mode\": \"ace/mode/snippets\",\n        \"extensions\": \"snippets\",\n        \"extRe\": {}\n    },\n    \"soy_template\": {\n        \"name\": \"soy_template\",\n        \"caption\": \"Soy Template\",\n        \"mode\": \"ace/mode/soy_template\",\n        \"extensions\": \"soy\",\n        \"extRe\": {}\n    },\n    \"space\": {\n        \"name\": \"space\",\n        \"caption\": \"Space\",\n        \"mode\": \"ace/mode/space\",\n        \"extensions\": \"space\",\n        \"extRe\": {}\n    },\n    \"sql\": {\n        \"name\": \"sql\",\n        \"caption\": \"SQL\",\n        \"mode\": \"ace/mode/sql\",\n        \"extensions\": \"sql\",\n        \"extRe\": {}\n    },\n    \"sqlserver\": {\n        \"name\": \"sqlserver\",\n        \"caption\": \"SQLServer\",\n        \"mode\": \"ace/mode/sqlserver\",\n        \"extensions\": \"sqlserver\",\n        \"extRe\": {}\n    },\n    \"stylus\": {\n        \"name\": \"stylus\",\n        \"caption\": \"Stylus\",\n        \"mode\": \"ace/mode/stylus\",\n        \"extensions\": \"styl|stylus\",\n        \"extRe\": {}\n    },\n    \"svg\": {\n        \"name\": \"svg\",\n        \"caption\": \"SVG\",\n        \"mode\": \"ace/mode/svg\",\n        \"extensions\": \"svg\",\n        \"extRe\": {}\n    },\n    \"swift\": {\n        \"name\": \"swift\",\n        \"caption\": \"Swift\",\n        \"mode\": \"ace/mode/swift\",\n        \"extensions\": \"swift\",\n        \"extRe\": {}\n    },\n    \"tcl\": {\n        \"name\": \"tcl\",\n        \"caption\": \"Tcl\",\n        \"mode\": \"ace/mode/tcl\",\n        \"extensions\": \"tcl\",\n        \"extRe\": {}\n    },\n    \"tex\": {\n        \"name\": \"tex\",\n        \"caption\": \"Tex\",\n        \"mode\": \"ace/mode/tex\",\n        \"extensions\": \"tex\",\n        \"extRe\": {}\n    },\n    \"text\": {\n        \"name\": \"text\",\n        \"caption\": \"Text\",\n        \"mode\": \"ace/mode/text\",\n        \"extensions\": \"txt\",\n        \"extRe\": {},\n        \"path\": \"ace/mode/text\"\n    },\n    \"textile\": {\n        \"name\": \"textile\",\n        \"caption\": \"Textile\",\n        \"mode\": \"ace/mode/textile\",\n        \"extensions\": \"textile\",\n        \"extRe\": {}\n    },\n    \"toml\": {\n        \"name\": \"toml\",\n        \"caption\": \"Toml\",\n        \"mode\": \"ace/mode/toml\",\n        \"extensions\": \"toml\",\n        \"extRe\": {}\n    },\n    \"tsx\": {\n        \"name\": \"tsx\",\n        \"caption\": \"TSX\",\n        \"mode\": \"ace/mode/tsx\",\n        \"extensions\": \"tsx\",\n        \"extRe\": {}\n    },\n    \"twig\": {\n        \"name\": \"twig\",\n        \"caption\": \"Twig\",\n        \"mode\": \"ace/mode/twig\",\n        \"extensions\": \"twig|swig\",\n        \"extRe\": {}\n    },\n    \"typescript\": {\n        \"name\": \"typescript\",\n        \"caption\": \"Typescript\",\n        \"mode\": \"ace/mode/typescript\",\n        \"extensions\": \"ts|typescript|str\",\n        \"extRe\": {}\n    },\n    \"vala\": {\n        \"name\": \"vala\",\n        \"caption\": \"Vala\",\n        \"mode\": \"ace/mode/vala\",\n        \"extensions\": \"vala\",\n        \"extRe\": {}\n    },\n    \"vbscript\": {\n        \"name\": \"vbscript\",\n        \"caption\": \"VBScript\",\n        \"mode\": \"ace/mode/vbscript\",\n        \"extensions\": \"vbs|vb\",\n        \"extRe\": {}\n    },\n    \"velocity\": {\n        \"name\": \"velocity\",\n        \"caption\": \"Velocity\",\n        \"mode\": \"ace/mode/velocity\",\n        \"extensions\": \"vm\",\n        \"extRe\": {}\n    },\n    \"verilog\": {\n        \"name\": \"verilog\",\n        \"caption\": \"Verilog\",\n        \"mode\": \"ace/mode/verilog\",\n        \"extensions\": \"v|vh|sv|svh\",\n        \"extRe\": {}\n    },\n    \"vhdl\": {\n        \"name\": \"vhdl\",\n        \"caption\": \"VHDL\",\n        \"mode\": \"ace/mode/vhdl\",\n        \"extensions\": \"vhd|vhdl\",\n        \"extRe\": {}\n    },\n    \"wollok\": {\n        \"name\": \"wollok\",\n        \"caption\": \"Wollok\",\n        \"mode\": \"ace/mode/wollok\",\n        \"extensions\": \"wlk|wpgm|wtest\",\n        \"extRe\": {}\n    },\n    \"xml\": {\n        \"name\": \"xml\",\n        \"caption\": \"XML\",\n        \"mode\": \"ace/mode/xml\",\n        \"extensions\": \"xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml\",\n        \"extRe\": {}\n    },\n    \"xquery\": {\n        \"name\": \"xquery\",\n        \"caption\": \"XQuery\",\n        \"mode\": \"ace/mode/xquery\",\n        \"extensions\": \"xq\",\n        \"extRe\": {}\n    },\n    \"yaml\": {\n        \"name\": \"yaml\",\n        \"caption\": \"YAML\",\n        \"mode\": \"ace/mode/yaml\",\n        \"extensions\": \"yaml|yml\",\n        \"extRe\": {}\n    },\n    \"django\": {\n        \"name\": \"django\",\n        \"caption\": \"Django\",\n        \"mode\": \"ace/mode/django\",\n        \"extensions\": \"html\",\n        \"extRe\": {}\n    }\n}\n\nfor(var key in data) {\n    console.log('@\"' + data[key]['caption'] + '\": [NSRegularExpression regularExpressionWithPattern:@\"' + data[key]['extensions'] + '\" options:NSRegularExpressionCaseInsensitive error:nil],')\n}\n\nconsole.log('')\nconsole.log('')\nconsole.log('')\n\nfor(var key in data) {\n    console.log('@{@\"name\": @\"' + data[key]['caption'] + '\", @\"extension\": @\"' + data[key]['extensions'].split('|')[0].replace(/^\\^\\.?/, '') +'\"},')\n}\n"
  },
  {
    "path": "build-scripts/emocode-data.js",
    "content": "var data = {\n    \"0023-fe0f-20e3\":[[\"\\u0023\\uFE0F\\u20E3\"],\"Symbols\",1556,[\"hash\"],0,0,\"0.6\",\"keycap\"],\n    \"002a-fe0f-20e3\":[[\"\\u002A\\uFE0F\\u20E3\"],\"Symbols\",1557,[\"keycap_star\"],0,1,\"2.0\",\"keycap\"],\n    \"0030-fe0f-20e3\":[[\"\\u0030\\uFE0F\\u20E3\"],\"Symbols\",1558,[\"zero\"],0,2,\"0.6\",\"keycap\"],\n    \"0031-fe0f-20e3\":[[\"\\u0031\\uFE0F\\u20E3\"],\"Symbols\",1559,[\"one\"],0,3,\"0.6\",\"keycap\"],\n    \"0032-fe0f-20e3\":[[\"\\u0032\\uFE0F\\u20E3\"],\"Symbols\",1560,[\"two\"],0,4,\"0.6\",\"keycap\"],\n    \"0033-fe0f-20e3\":[[\"\\u0033\\uFE0F\\u20E3\"],\"Symbols\",1561,[\"three\"],0,5,\"0.6\",\"keycap\"],\n    \"0034-fe0f-20e3\":[[\"\\u0034\\uFE0F\\u20E3\"],\"Symbols\",1562,[\"four\"],0,6,\"0.6\",\"keycap\"],\n    \"0035-fe0f-20e3\":[[\"\\u0035\\uFE0F\\u20E3\"],\"Symbols\",1563,[\"five\"],0,7,\"0.6\",\"keycap\"],\n    \"0036-fe0f-20e3\":[[\"\\u0036\\uFE0F\\u20E3\"],\"Symbols\",1564,[\"six\"],0,8,\"0.6\",\"keycap\"],\n    \"0037-fe0f-20e3\":[[\"\\u0037\\uFE0F\\u20E3\"],\"Symbols\",1565,[\"seven\"],0,9,\"0.6\",\"keycap\"],\n    \"0038-fe0f-20e3\":[[\"\\u0038\\uFE0F\\u20E3\"],\"Symbols\",1566,[\"eight\"],0,10,\"0.6\",\"keycap\"],\n    \"0039-fe0f-20e3\":[[\"\\u0039\\uFE0F\\u20E3\"],\"Symbols\",1567,[\"nine\"],0,11,\"0.6\",\"keycap\"],\n    \"00a9-fe0f\":[[\"\\u00A9\\uFE0F\"],\"Symbols\",1552,[\"copyright\"],0,12,\"0.6\",\"other-symbol\"],\n    \"00ae-fe0f\":[[\"\\u00AE\\uFE0F\"],\"Symbols\",1553,[\"registered\"],0,13,\"0.6\",\"other-symbol\"],\n    \"1f004\":[[\"\\uD83C\\uDC04\"],\"Activities\",1145,[\"mahjong\"],0,14,\"0.6\",\"game\"],\n    \"1f0cf\":[[\"\\uD83C\\uDCCF\"],\"Activities\",1144,[\"black_joker\"],0,15,\"0.6\",\"game\"],\n    \"1f170-fe0f\":[[\"\\uD83C\\uDD70\\uFE0F\"],\"Symbols\",1574,[\"a\"],0,16,\"0.6\",\"alphanum\"],\n    \"1f171-fe0f\":[[\"\\uD83C\\uDD71\\uFE0F\"],\"Symbols\",1576,[\"b\"],0,17,\"0.6\",\"alphanum\"],\n    \"1f17e-fe0f\":[[\"\\uD83C\\uDD7E\\uFE0F\"],\"Symbols\",1585,[\"o2\"],0,18,\"0.6\",\"alphanum\"],\n    \"1f17f-fe0f\":[[\"\\uD83C\\uDD7F\\uFE0F\"],\"Symbols\",1587,[\"parking\"],0,19,\"0.6\",\"alphanum\"],\n    \"1f18e\":[[\"\\uD83C\\uDD8E\"],\"Symbols\",1575,[\"ab\"],0,20,\"0.6\",\"alphanum\"],\n    \"1f191\":[[\"\\uD83C\\uDD91\"],\"Symbols\",1577,[\"cl\"],0,21,\"0.6\",\"alphanum\"],\n    \"1f192\":[[\"\\uD83C\\uDD92\"],\"Symbols\",1578,[\"cool\"],0,22,\"0.6\",\"alphanum\"],\n    \"1f193\":[[\"\\uD83C\\uDD93\"],\"Symbols\",1579,[\"free\"],0,23,\"0.6\",\"alphanum\"],\n    \"1f194\":[[\"\\uD83C\\uDD94\"],\"Symbols\",1581,[\"id\"],0,24,\"0.6\",\"alphanum\"],\n    \"1f195\":[[\"\\uD83C\\uDD95\"],\"Symbols\",1583,[\"new\"],0,25,\"0.6\",\"alphanum\"],\n    \"1f196\":[[\"\\uD83C\\uDD96\"],\"Symbols\",1584,[\"ng\"],0,26,\"0.6\",\"alphanum\"],\n    \"1f197\":[[\"\\uD83C\\uDD97\"],\"Symbols\",1586,[\"ok\"],0,27,\"0.6\",\"alphanum\"],\n    \"1f198\":[[\"\\uD83C\\uDD98\"],\"Symbols\",1588,[\"sos\"],0,28,\"0.6\",\"alphanum\"],\n    \"1f199\":[[\"\\uD83C\\uDD99\"],\"Symbols\",1589,[\"up\"],0,29,\"0.6\",\"alphanum\"],\n    \"1f19a\":[[\"\\uD83C\\uDD9A\"],\"Symbols\",1590,[\"vs\"],0,30,\"0.6\",\"alphanum\"],\n    \"1f1e6-1f1e8\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDE8\"],\"Flags\",1650,[\"flag-ac\"],0,31,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1e9\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDE9\"],\"Flags\",1651,[\"flag-ad\"],0,32,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1ea\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDEA\"],\"Flags\",1652,[\"flag-ae\"],0,33,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1eb\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDEB\"],\"Flags\",1653,[\"flag-af\"],0,34,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1ec\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDEC\"],\"Flags\",1654,[\"flag-ag\"],0,35,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1ee\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDEE\"],\"Flags\",1655,[\"flag-ai\"],0,36,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1f1\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDF1\"],\"Flags\",1656,[\"flag-al\"],0,37,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1f2\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDF2\"],\"Flags\",1657,[\"flag-am\"],0,38,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1f4\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDF4\"],\"Flags\",1658,[\"flag-ao\"],0,39,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1f6\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDF6\"],\"Flags\",1659,[\"flag-aq\"],0,40,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1f7\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDF7\"],\"Flags\",1660,[\"flag-ar\"],0,41,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1f8\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDF8\"],\"Flags\",1661,[\"flag-as\"],0,42,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1f9\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDF9\"],\"Flags\",1662,[\"flag-at\"],0,43,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1fa\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDFA\"],\"Flags\",1663,[\"flag-au\"],0,44,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1fc\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDFC\"],\"Flags\",1664,[\"flag-aw\"],0,45,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1fd\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDFD\"],\"Flags\",1665,[\"flag-ax\"],0,46,\"2.0\",\"country-flag\"],\n    \"1f1e6-1f1ff\":[[\"\\uD83C\\uDDE6\\uD83C\\uDDFF\"],\"Flags\",1666,[\"flag-az\"],0,47,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1e6\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDE6\"],\"Flags\",1667,[\"flag-ba\"],0,48,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1e7\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDE7\"],\"Flags\",1668,[\"flag-bb\"],0,49,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1e9\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDE9\"],\"Flags\",1669,[\"flag-bd\"],0,50,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1ea\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDEA\"],\"Flags\",1670,[\"flag-be\"],0,51,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1eb\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDEB\"],\"Flags\",1671,[\"flag-bf\"],0,52,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1ec\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDEC\"],\"Flags\",1672,[\"flag-bg\"],0,53,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1ed\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDED\"],\"Flags\",1673,[\"flag-bh\"],0,54,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1ee\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDEE\"],\"Flags\",1674,[\"flag-bi\"],0,55,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1ef\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDEF\"],\"Flags\",1675,[\"flag-bj\"],0,56,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1f1\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDF1\"],\"Flags\",1676,[\"flag-bl\"],0,57,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1f2\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDF2\"],\"Flags\",1677,[\"flag-bm\"],0,58,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1f3\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDF3\"],\"Flags\",1678,[\"flag-bn\"],0,59,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1f4\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDF4\"],\"Flags\",1679,[\"flag-bo\"],0,60,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1f6\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDF6\"],\"Flags\",1680,[\"flag-bq\"],0,61,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1f7\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDF7\"],\"Flags\",1681,[\"flag-br\"],1,0,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1f8\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDF8\"],\"Flags\",1682,[\"flag-bs\"],1,1,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1f9\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDF9\"],\"Flags\",1683,[\"flag-bt\"],1,2,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1fb\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDFB\"],\"Flags\",1684,[\"flag-bv\"],1,3,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1fc\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDFC\"],\"Flags\",1685,[\"flag-bw\"],1,4,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1fe\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDFE\"],\"Flags\",1686,[\"flag-by\"],1,5,\"2.0\",\"country-flag\"],\n    \"1f1e7-1f1ff\":[[\"\\uD83C\\uDDE7\\uD83C\\uDDFF\"],\"Flags\",1687,[\"flag-bz\"],1,6,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1e6\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDE6\"],\"Flags\",1688,[\"flag-ca\"],1,7,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1e8\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDE8\"],\"Flags\",1689,[\"flag-cc\"],1,8,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1e9\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDE9\"],\"Flags\",1690,[\"flag-cd\"],1,9,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1eb\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDEB\"],\"Flags\",1691,[\"flag-cf\"],1,10,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1ec\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDEC\"],\"Flags\",1692,[\"flag-cg\"],1,11,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1ed\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDED\"],\"Flags\",1693,[\"flag-ch\"],1,12,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1ee\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDEE\"],\"Flags\",1694,[\"flag-ci\"],1,13,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1f0\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDF0\"],\"Flags\",1695,[\"flag-ck\"],1,14,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1f1\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDF1\"],\"Flags\",1696,[\"flag-cl\"],1,15,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1f2\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDF2\"],\"Flags\",1697,[\"flag-cm\"],1,16,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1f3\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDF3\"],\"Flags\",1698,[\"cn\",\"flag-cn\"],1,17,\"0.6\",\"country-flag\"],\n    \"1f1e8-1f1f4\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDF4\"],\"Flags\",1699,[\"flag-co\"],1,18,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1f5\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDF5\"],\"Flags\",1700,[\"flag-cp\"],1,19,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1f6\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDF6\"],\"Flags\",1701,[\"flag-sark\"],1,20,\"16.0\",\"country-flag\"],\n    \"1f1e8-1f1f7\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDF7\"],\"Flags\",1702,[\"flag-cr\"],1,21,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1fa\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDFA\"],\"Flags\",1703,[\"flag-cu\"],1,22,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1fb\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDFB\"],\"Flags\",1704,[\"flag-cv\"],1,23,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1fc\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDFC\"],\"Flags\",1705,[\"flag-cw\"],1,24,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1fd\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDFD\"],\"Flags\",1706,[\"flag-cx\"],1,25,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1fe\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDFE\"],\"Flags\",1707,[\"flag-cy\"],1,26,\"2.0\",\"country-flag\"],\n    \"1f1e8-1f1ff\":[[\"\\uD83C\\uDDE8\\uD83C\\uDDFF\"],\"Flags\",1708,[\"flag-cz\"],1,27,\"2.0\",\"country-flag\"],\n    \"1f1e9-1f1ea\":[[\"\\uD83C\\uDDE9\\uD83C\\uDDEA\"],\"Flags\",1709,[\"de\",\"flag-de\"],1,28,\"0.6\",\"country-flag\"],\n    \"1f1e9-1f1ec\":[[\"\\uD83C\\uDDE9\\uD83C\\uDDEC\"],\"Flags\",1710,[\"flag-dg\"],1,29,\"2.0\",\"country-flag\"],\n    \"1f1e9-1f1ef\":[[\"\\uD83C\\uDDE9\\uD83C\\uDDEF\"],\"Flags\",1711,[\"flag-dj\"],1,30,\"2.0\",\"country-flag\"],\n    \"1f1e9-1f1f0\":[[\"\\uD83C\\uDDE9\\uD83C\\uDDF0\"],\"Flags\",1712,[\"flag-dk\"],1,31,\"2.0\",\"country-flag\"],\n    \"1f1e9-1f1f2\":[[\"\\uD83C\\uDDE9\\uD83C\\uDDF2\"],\"Flags\",1713,[\"flag-dm\"],1,32,\"2.0\",\"country-flag\"],\n    \"1f1e9-1f1f4\":[[\"\\uD83C\\uDDE9\\uD83C\\uDDF4\"],\"Flags\",1714,[\"flag-do\"],1,33,\"2.0\",\"country-flag\"],\n    \"1f1e9-1f1ff\":[[\"\\uD83C\\uDDE9\\uD83C\\uDDFF\"],\"Flags\",1715,[\"flag-dz\"],1,34,\"2.0\",\"country-flag\"],\n    \"1f1ea-1f1e6\":[[\"\\uD83C\\uDDEA\\uD83C\\uDDE6\"],\"Flags\",1716,[\"flag-ea\"],1,35,\"2.0\",\"country-flag\"],\n    \"1f1ea-1f1e8\":[[\"\\uD83C\\uDDEA\\uD83C\\uDDE8\"],\"Flags\",1717,[\"flag-ec\"],1,36,\"2.0\",\"country-flag\"],\n    \"1f1ea-1f1ea\":[[\"\\uD83C\\uDDEA\\uD83C\\uDDEA\"],\"Flags\",1718,[\"flag-ee\"],1,37,\"2.0\",\"country-flag\"],\n    \"1f1ea-1f1ec\":[[\"\\uD83C\\uDDEA\\uD83C\\uDDEC\"],\"Flags\",1719,[\"flag-eg\"],1,38,\"2.0\",\"country-flag\"],\n    \"1f1ea-1f1ed\":[[\"\\uD83C\\uDDEA\\uD83C\\uDDED\"],\"Flags\",1720,[\"flag-eh\"],1,39,\"2.0\",\"country-flag\"],\n    \"1f1ea-1f1f7\":[[\"\\uD83C\\uDDEA\\uD83C\\uDDF7\"],\"Flags\",1721,[\"flag-er\"],1,40,\"2.0\",\"country-flag\"],\n    \"1f1ea-1f1f8\":[[\"\\uD83C\\uDDEA\\uD83C\\uDDF8\"],\"Flags\",1722,[\"es\",\"flag-es\"],1,41,\"0.6\",\"country-flag\"],\n    \"1f1ea-1f1f9\":[[\"\\uD83C\\uDDEA\\uD83C\\uDDF9\"],\"Flags\",1723,[\"flag-et\"],1,42,\"2.0\",\"country-flag\"],\n    \"1f1ea-1f1fa\":[[\"\\uD83C\\uDDEA\\uD83C\\uDDFA\"],\"Flags\",1724,[\"flag-eu\"],1,43,\"2.0\",\"country-flag\"],\n    \"1f1eb-1f1ee\":[[\"\\uD83C\\uDDEB\\uD83C\\uDDEE\"],\"Flags\",1725,[\"flag-fi\"],1,44,\"2.0\",\"country-flag\"],\n    \"1f1eb-1f1ef\":[[\"\\uD83C\\uDDEB\\uD83C\\uDDEF\"],\"Flags\",1726,[\"flag-fj\"],1,45,\"2.0\",\"country-flag\"],\n    \"1f1eb-1f1f0\":[[\"\\uD83C\\uDDEB\\uD83C\\uDDF0\"],\"Flags\",1727,[\"flag-fk\"],1,46,\"2.0\",\"country-flag\"],\n    \"1f1eb-1f1f2\":[[\"\\uD83C\\uDDEB\\uD83C\\uDDF2\"],\"Flags\",1728,[\"flag-fm\"],1,47,\"2.0\",\"country-flag\"],\n    \"1f1eb-1f1f4\":[[\"\\uD83C\\uDDEB\\uD83C\\uDDF4\"],\"Flags\",1729,[\"flag-fo\"],1,48,\"2.0\",\"country-flag\"],\n    \"1f1eb-1f1f7\":[[\"\\uD83C\\uDDEB\\uD83C\\uDDF7\"],\"Flags\",1730,[\"fr\",\"flag-fr\"],1,49,\"0.6\",\"country-flag\"],\n    \"1f1ec-1f1e6\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDE6\"],\"Flags\",1731,[\"flag-ga\"],1,50,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1e7\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDE7\"],\"Flags\",1732,[\"gb\",\"uk\",\"flag-gb\"],1,51,\"0.6\",\"country-flag\"],\n    \"1f1ec-1f1e9\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDE9\"],\"Flags\",1733,[\"flag-gd\"],1,52,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1ea\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDEA\"],\"Flags\",1734,[\"flag-ge\"],1,53,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1eb\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDEB\"],\"Flags\",1735,[\"flag-gf\"],1,54,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1ec\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDEC\"],\"Flags\",1736,[\"flag-gg\"],1,55,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1ed\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDED\"],\"Flags\",1737,[\"flag-gh\"],1,56,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1ee\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDEE\"],\"Flags\",1738,[\"flag-gi\"],1,57,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1f1\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDF1\"],\"Flags\",1739,[\"flag-gl\"],1,58,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1f2\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDF2\"],\"Flags\",1740,[\"flag-gm\"],1,59,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1f3\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDF3\"],\"Flags\",1741,[\"flag-gn\"],1,60,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1f5\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDF5\"],\"Flags\",1742,[\"flag-gp\"],1,61,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1f6\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDF6\"],\"Flags\",1743,[\"flag-gq\"],2,0,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1f7\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDF7\"],\"Flags\",1744,[\"flag-gr\"],2,1,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1f8\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDF8\"],\"Flags\",1745,[\"flag-gs\"],2,2,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1f9\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDF9\"],\"Flags\",1746,[\"flag-gt\"],2,3,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1fa\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDFA\"],\"Flags\",1747,[\"flag-gu\"],2,4,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1fc\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDFC\"],\"Flags\",1748,[\"flag-gw\"],2,5,\"2.0\",\"country-flag\"],\n    \"1f1ec-1f1fe\":[[\"\\uD83C\\uDDEC\\uD83C\\uDDFE\"],\"Flags\",1749,[\"flag-gy\"],2,6,\"2.0\",\"country-flag\"],\n    \"1f1ed-1f1f0\":[[\"\\uD83C\\uDDED\\uD83C\\uDDF0\"],\"Flags\",1750,[\"flag-hk\"],2,7,\"2.0\",\"country-flag\"],\n    \"1f1ed-1f1f2\":[[\"\\uD83C\\uDDED\\uD83C\\uDDF2\"],\"Flags\",1751,[\"flag-hm\"],2,8,\"2.0\",\"country-flag\"],\n    \"1f1ed-1f1f3\":[[\"\\uD83C\\uDDED\\uD83C\\uDDF3\"],\"Flags\",1752,[\"flag-hn\"],2,9,\"2.0\",\"country-flag\"],\n    \"1f1ed-1f1f7\":[[\"\\uD83C\\uDDED\\uD83C\\uDDF7\"],\"Flags\",1753,[\"flag-hr\"],2,10,\"2.0\",\"country-flag\"],\n    \"1f1ed-1f1f9\":[[\"\\uD83C\\uDDED\\uD83C\\uDDF9\"],\"Flags\",1754,[\"flag-ht\"],2,11,\"2.0\",\"country-flag\"],\n    \"1f1ed-1f1fa\":[[\"\\uD83C\\uDDED\\uD83C\\uDDFA\"],\"Flags\",1755,[\"flag-hu\"],2,12,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1e8\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDE8\"],\"Flags\",1756,[\"flag-ic\"],2,13,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1e9\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDE9\"],\"Flags\",1757,[\"flag-id\"],2,14,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1ea\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDEA\"],\"Flags\",1758,[\"flag-ie\"],2,15,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1f1\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDF1\"],\"Flags\",1759,[\"flag-il\"],2,16,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1f2\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDF2\"],\"Flags\",1760,[\"flag-im\"],2,17,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1f3\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDF3\"],\"Flags\",1761,[\"flag-in\"],2,18,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1f4\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDF4\"],\"Flags\",1762,[\"flag-io\"],2,19,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1f6\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDF6\"],\"Flags\",1763,[\"flag-iq\"],2,20,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1f7\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDF7\"],\"Flags\",1764,[\"flag-ir\"],2,21,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1f8\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDF8\"],\"Flags\",1765,[\"flag-is\"],2,22,\"2.0\",\"country-flag\"],\n    \"1f1ee-1f1f9\":[[\"\\uD83C\\uDDEE\\uD83C\\uDDF9\"],\"Flags\",1766,[\"it\",\"flag-it\"],2,23,\"0.6\",\"country-flag\"],\n    \"1f1ef-1f1ea\":[[\"\\uD83C\\uDDEF\\uD83C\\uDDEA\"],\"Flags\",1767,[\"flag-je\"],2,24,\"2.0\",\"country-flag\"],\n    \"1f1ef-1f1f2\":[[\"\\uD83C\\uDDEF\\uD83C\\uDDF2\"],\"Flags\",1768,[\"flag-jm\"],2,25,\"2.0\",\"country-flag\"],\n    \"1f1ef-1f1f4\":[[\"\\uD83C\\uDDEF\\uD83C\\uDDF4\"],\"Flags\",1769,[\"flag-jo\"],2,26,\"2.0\",\"country-flag\"],\n    \"1f1ef-1f1f5\":[[\"\\uD83C\\uDDEF\\uD83C\\uDDF5\"],\"Flags\",1770,[\"jp\",\"flag-jp\"],2,27,\"0.6\",\"country-flag\"],\n    \"1f1f0-1f1ea\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDEA\"],\"Flags\",1771,[\"flag-ke\"],2,28,\"2.0\",\"country-flag\"],\n    \"1f1f0-1f1ec\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDEC\"],\"Flags\",1772,[\"flag-kg\"],2,29,\"2.0\",\"country-flag\"],\n    \"1f1f0-1f1ed\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDED\"],\"Flags\",1773,[\"flag-kh\"],2,30,\"2.0\",\"country-flag\"],\n    \"1f1f0-1f1ee\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDEE\"],\"Flags\",1774,[\"flag-ki\"],2,31,\"2.0\",\"country-flag\"],\n    \"1f1f0-1f1f2\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDF2\"],\"Flags\",1775,[\"flag-km\"],2,32,\"2.0\",\"country-flag\"],\n    \"1f1f0-1f1f3\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDF3\"],\"Flags\",1776,[\"flag-kn\"],2,33,\"2.0\",\"country-flag\"],\n    \"1f1f0-1f1f5\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDF5\"],\"Flags\",1777,[\"flag-kp\"],2,34,\"2.0\",\"country-flag\"],\n    \"1f1f0-1f1f7\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDF7\"],\"Flags\",1778,[\"kr\",\"flag-kr\"],2,35,\"0.6\",\"country-flag\"],\n    \"1f1f0-1f1fc\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDFC\"],\"Flags\",1779,[\"flag-kw\"],2,36,\"2.0\",\"country-flag\"],\n    \"1f1f0-1f1fe\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDFE\"],\"Flags\",1780,[\"flag-ky\"],2,37,\"2.0\",\"country-flag\"],\n    \"1f1f0-1f1ff\":[[\"\\uD83C\\uDDF0\\uD83C\\uDDFF\"],\"Flags\",1781,[\"flag-kz\"],2,38,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1e6\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDE6\"],\"Flags\",1782,[\"flag-la\"],2,39,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1e7\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDE7\"],\"Flags\",1783,[\"flag-lb\"],2,40,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1e8\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDE8\"],\"Flags\",1784,[\"flag-lc\"],2,41,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1ee\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDEE\"],\"Flags\",1785,[\"flag-li\"],2,42,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1f0\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDF0\"],\"Flags\",1786,[\"flag-lk\"],2,43,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1f7\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDF7\"],\"Flags\",1787,[\"flag-lr\"],2,44,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1f8\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDF8\"],\"Flags\",1788,[\"flag-ls\"],2,45,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1f9\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDF9\"],\"Flags\",1789,[\"flag-lt\"],2,46,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1fa\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDFA\"],\"Flags\",1790,[\"flag-lu\"],2,47,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1fb\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDFB\"],\"Flags\",1791,[\"flag-lv\"],2,48,\"2.0\",\"country-flag\"],\n    \"1f1f1-1f1fe\":[[\"\\uD83C\\uDDF1\\uD83C\\uDDFE\"],\"Flags\",1792,[\"flag-ly\"],2,49,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1e6\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDE6\"],\"Flags\",1793,[\"flag-ma\"],2,50,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1e8\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDE8\"],\"Flags\",1794,[\"flag-mc\"],2,51,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1e9\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDE9\"],\"Flags\",1795,[\"flag-md\"],2,52,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1ea\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDEA\"],\"Flags\",1796,[\"flag-me\"],2,53,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1eb\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDEB\"],\"Flags\",1797,[\"flag-mf\"],2,54,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1ec\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDEC\"],\"Flags\",1798,[\"flag-mg\"],2,55,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1ed\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDED\"],\"Flags\",1799,[\"flag-mh\"],2,56,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1f0\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDF0\"],\"Flags\",1800,[\"flag-mk\"],2,57,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1f1\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDF1\"],\"Flags\",1801,[\"flag-ml\"],2,58,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1f2\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDF2\"],\"Flags\",1802,[\"flag-mm\"],2,59,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1f3\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDF3\"],\"Flags\",1803,[\"flag-mn\"],2,60,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1f4\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDF4\"],\"Flags\",1804,[\"flag-mo\"],2,61,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1f5\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDF5\"],\"Flags\",1805,[\"flag-mp\"],3,0,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1f6\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDF6\"],\"Flags\",1806,[\"flag-mq\"],3,1,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1f7\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDF7\"],\"Flags\",1807,[\"flag-mr\"],3,2,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1f8\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDF8\"],\"Flags\",1808,[\"flag-ms\"],3,3,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1f9\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDF9\"],\"Flags\",1809,[\"flag-mt\"],3,4,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1fa\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDFA\"],\"Flags\",1810,[\"flag-mu\"],3,5,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1fb\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDFB\"],\"Flags\",1811,[\"flag-mv\"],3,6,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1fc\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDFC\"],\"Flags\",1812,[\"flag-mw\"],3,7,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1fd\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDFD\"],\"Flags\",1813,[\"flag-mx\"],3,8,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1fe\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDFE\"],\"Flags\",1814,[\"flag-my\"],3,9,\"2.0\",\"country-flag\"],\n    \"1f1f2-1f1ff\":[[\"\\uD83C\\uDDF2\\uD83C\\uDDFF\"],\"Flags\",1815,[\"flag-mz\"],3,10,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1e6\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDE6\"],\"Flags\",1816,[\"flag-na\"],3,11,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1e8\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDE8\"],\"Flags\",1817,[\"flag-nc\"],3,12,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1ea\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDEA\"],\"Flags\",1818,[\"flag-ne\"],3,13,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1eb\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDEB\"],\"Flags\",1819,[\"flag-nf\"],3,14,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1ec\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDEC\"],\"Flags\",1820,[\"flag-ng\"],3,15,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1ee\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDEE\"],\"Flags\",1821,[\"flag-ni\"],3,16,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1f1\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDF1\"],\"Flags\",1822,[\"flag-nl\"],3,17,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1f4\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDF4\"],\"Flags\",1823,[\"flag-no\"],3,18,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1f5\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDF5\"],\"Flags\",1824,[\"flag-np\"],3,19,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1f7\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDF7\"],\"Flags\",1825,[\"flag-nr\"],3,20,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1fa\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDFA\"],\"Flags\",1826,[\"flag-nu\"],3,21,\"2.0\",\"country-flag\"],\n    \"1f1f3-1f1ff\":[[\"\\uD83C\\uDDF3\\uD83C\\uDDFF\"],\"Flags\",1827,[\"flag-nz\"],3,22,\"2.0\",\"country-flag\"],\n    \"1f1f4-1f1f2\":[[\"\\uD83C\\uDDF4\\uD83C\\uDDF2\"],\"Flags\",1828,[\"flag-om\"],3,23,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1e6\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDE6\"],\"Flags\",1829,[\"flag-pa\"],3,24,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1ea\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDEA\"],\"Flags\",1830,[\"flag-pe\"],3,25,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1eb\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDEB\"],\"Flags\",1831,[\"flag-pf\"],3,26,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1ec\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDEC\"],\"Flags\",1832,[\"flag-pg\"],3,27,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1ed\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDED\"],\"Flags\",1833,[\"flag-ph\"],3,28,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1f0\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDF0\"],\"Flags\",1834,[\"flag-pk\"],3,29,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1f1\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDF1\"],\"Flags\",1835,[\"flag-pl\"],3,30,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1f2\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDF2\"],\"Flags\",1836,[\"flag-pm\"],3,31,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1f3\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDF3\"],\"Flags\",1837,[\"flag-pn\"],3,32,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1f7\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDF7\"],\"Flags\",1838,[\"flag-pr\"],3,33,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1f8\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDF8\"],\"Flags\",1839,[\"flag-ps\"],3,34,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1f9\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDF9\"],\"Flags\",1840,[\"flag-pt\"],3,35,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1fc\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDFC\"],\"Flags\",1841,[\"flag-pw\"],3,36,\"2.0\",\"country-flag\"],\n    \"1f1f5-1f1fe\":[[\"\\uD83C\\uDDF5\\uD83C\\uDDFE\"],\"Flags\",1842,[\"flag-py\"],3,37,\"2.0\",\"country-flag\"],\n    \"1f1f6-1f1e6\":[[\"\\uD83C\\uDDF6\\uD83C\\uDDE6\"],\"Flags\",1843,[\"flag-qa\"],3,38,\"2.0\",\"country-flag\"],\n    \"1f1f7-1f1ea\":[[\"\\uD83C\\uDDF7\\uD83C\\uDDEA\"],\"Flags\",1844,[\"flag-re\"],3,39,\"2.0\",\"country-flag\"],\n    \"1f1f7-1f1f4\":[[\"\\uD83C\\uDDF7\\uD83C\\uDDF4\"],\"Flags\",1845,[\"flag-ro\"],3,40,\"2.0\",\"country-flag\"],\n    \"1f1f7-1f1f8\":[[\"\\uD83C\\uDDF7\\uD83C\\uDDF8\"],\"Flags\",1846,[\"flag-rs\"],3,41,\"2.0\",\"country-flag\"],\n    \"1f1f7-1f1fa\":[[\"\\uD83C\\uDDF7\\uD83C\\uDDFA\"],\"Flags\",1847,[\"ru\",\"flag-ru\"],3,42,\"0.6\",\"country-flag\"],\n    \"1f1f7-1f1fc\":[[\"\\uD83C\\uDDF7\\uD83C\\uDDFC\"],\"Flags\",1848,[\"flag-rw\"],3,43,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1e6\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDE6\"],\"Flags\",1849,[\"flag-sa\"],3,44,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1e7\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDE7\"],\"Flags\",1850,[\"flag-sb\"],3,45,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1e8\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDE8\"],\"Flags\",1851,[\"flag-sc\"],3,46,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1e9\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDE9\"],\"Flags\",1852,[\"flag-sd\"],3,47,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1ea\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDEA\"],\"Flags\",1853,[\"flag-se\"],3,48,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1ec\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDEC\"],\"Flags\",1854,[\"flag-sg\"],3,49,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1ed\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDED\"],\"Flags\",1855,[\"flag-sh\"],3,50,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1ee\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDEE\"],\"Flags\",1856,[\"flag-si\"],3,51,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1ef\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDEF\"],\"Flags\",1857,[\"flag-sj\"],3,52,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1f0\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDF0\"],\"Flags\",1858,[\"flag-sk\"],3,53,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1f1\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDF1\"],\"Flags\",1859,[\"flag-sl\"],3,54,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1f2\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDF2\"],\"Flags\",1860,[\"flag-sm\"],3,55,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1f3\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDF3\"],\"Flags\",1861,[\"flag-sn\"],3,56,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1f4\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDF4\"],\"Flags\",1862,[\"flag-so\"],3,57,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1f7\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDF7\"],\"Flags\",1863,[\"flag-sr\"],3,58,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1f8\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDF8\"],\"Flags\",1864,[\"flag-ss\"],3,59,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1f9\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDF9\"],\"Flags\",1865,[\"flag-st\"],3,60,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1fb\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDFB\"],\"Flags\",1866,[\"flag-sv\"],3,61,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1fd\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDFD\"],\"Flags\",1867,[\"flag-sx\"],4,0,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1fe\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDFE\"],\"Flags\",1868,[\"flag-sy\"],4,1,\"2.0\",\"country-flag\"],\n    \"1f1f8-1f1ff\":[[\"\\uD83C\\uDDF8\\uD83C\\uDDFF\"],\"Flags\",1869,[\"flag-sz\"],4,2,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1e6\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDE6\"],\"Flags\",1870,[\"flag-ta\"],4,3,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1e8\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDE8\"],\"Flags\",1871,[\"flag-tc\"],4,4,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1e9\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDE9\"],\"Flags\",1872,[\"flag-td\"],4,5,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1eb\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDEB\"],\"Flags\",1873,[\"flag-tf\"],4,6,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1ec\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDEC\"],\"Flags\",1874,[\"flag-tg\"],4,7,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1ed\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDED\"],\"Flags\",1875,[\"flag-th\"],4,8,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1ef\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDEF\"],\"Flags\",1876,[\"flag-tj\"],4,9,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1f0\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDF0\"],\"Flags\",1877,[\"flag-tk\"],4,10,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1f1\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDF1\"],\"Flags\",1878,[\"flag-tl\"],4,11,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1f2\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDF2\"],\"Flags\",1879,[\"flag-tm\"],4,12,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1f3\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDF3\"],\"Flags\",1880,[\"flag-tn\"],4,13,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1f4\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDF4\"],\"Flags\",1881,[\"flag-to\"],4,14,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1f7\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDF7\"],\"Flags\",1882,[\"flag-tr\"],4,15,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1f9\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDF9\"],\"Flags\",1883,[\"flag-tt\"],4,16,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1fb\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDFB\"],\"Flags\",1884,[\"flag-tv\"],4,17,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1fc\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDFC\"],\"Flags\",1885,[\"flag-tw\"],4,18,\"2.0\",\"country-flag\"],\n    \"1f1f9-1f1ff\":[[\"\\uD83C\\uDDF9\\uD83C\\uDDFF\"],\"Flags\",1886,[\"flag-tz\"],4,19,\"2.0\",\"country-flag\"],\n    \"1f1fa-1f1e6\":[[\"\\uD83C\\uDDFA\\uD83C\\uDDE6\"],\"Flags\",1887,[\"flag-ua\"],4,20,\"2.0\",\"country-flag\"],\n    \"1f1fa-1f1ec\":[[\"\\uD83C\\uDDFA\\uD83C\\uDDEC\"],\"Flags\",1888,[\"flag-ug\"],4,21,\"2.0\",\"country-flag\"],\n    \"1f1fa-1f1f2\":[[\"\\uD83C\\uDDFA\\uD83C\\uDDF2\"],\"Flags\",1889,[\"flag-um\"],4,22,\"2.0\",\"country-flag\"],\n    \"1f1fa-1f1f3\":[[\"\\uD83C\\uDDFA\\uD83C\\uDDF3\"],\"Flags\",1890,[\"flag-un\"],4,23,\"4.0\",\"country-flag\"],\n    \"1f1fa-1f1f8\":[[\"\\uD83C\\uDDFA\\uD83C\\uDDF8\"],\"Flags\",1891,[\"us\",\"flag-us\"],4,24,\"0.6\",\"country-flag\"],\n    \"1f1fa-1f1fe\":[[\"\\uD83C\\uDDFA\\uD83C\\uDDFE\"],\"Flags\",1892,[\"flag-uy\"],4,25,\"2.0\",\"country-flag\"],\n    \"1f1fa-1f1ff\":[[\"\\uD83C\\uDDFA\\uD83C\\uDDFF\"],\"Flags\",1893,[\"flag-uz\"],4,26,\"2.0\",\"country-flag\"],\n    \"1f1fb-1f1e6\":[[\"\\uD83C\\uDDFB\\uD83C\\uDDE6\"],\"Flags\",1894,[\"flag-va\"],4,27,\"2.0\",\"country-flag\"],\n    \"1f1fb-1f1e8\":[[\"\\uD83C\\uDDFB\\uD83C\\uDDE8\"],\"Flags\",1895,[\"flag-vc\"],4,28,\"2.0\",\"country-flag\"],\n    \"1f1fb-1f1ea\":[[\"\\uD83C\\uDDFB\\uD83C\\uDDEA\"],\"Flags\",1896,[\"flag-ve\"],4,29,\"2.0\",\"country-flag\"],\n    \"1f1fb-1f1ec\":[[\"\\uD83C\\uDDFB\\uD83C\\uDDEC\"],\"Flags\",1897,[\"flag-vg\"],4,30,\"2.0\",\"country-flag\"],\n    \"1f1fb-1f1ee\":[[\"\\uD83C\\uDDFB\\uD83C\\uDDEE\"],\"Flags\",1898,[\"flag-vi\"],4,31,\"2.0\",\"country-flag\"],\n    \"1f1fb-1f1f3\":[[\"\\uD83C\\uDDFB\\uD83C\\uDDF3\"],\"Flags\",1899,[\"flag-vn\"],4,32,\"2.0\",\"country-flag\"],\n    \"1f1fb-1f1fa\":[[\"\\uD83C\\uDDFB\\uD83C\\uDDFA\"],\"Flags\",1900,[\"flag-vu\"],4,33,\"2.0\",\"country-flag\"],\n    \"1f1fc-1f1eb\":[[\"\\uD83C\\uDDFC\\uD83C\\uDDEB\"],\"Flags\",1901,[\"flag-wf\"],4,34,\"2.0\",\"country-flag\"],\n    \"1f1fc-1f1f8\":[[\"\\uD83C\\uDDFC\\uD83C\\uDDF8\"],\"Flags\",1902,[\"flag-ws\"],4,35,\"2.0\",\"country-flag\"],\n    \"1f1fd-1f1f0\":[[\"\\uD83C\\uDDFD\\uD83C\\uDDF0\"],\"Flags\",1903,[\"flag-xk\"],4,36,\"2.0\",\"country-flag\"],\n    \"1f1fe-1f1ea\":[[\"\\uD83C\\uDDFE\\uD83C\\uDDEA\"],\"Flags\",1904,[\"flag-ye\"],4,37,\"2.0\",\"country-flag\"],\n    \"1f1fe-1f1f9\":[[\"\\uD83C\\uDDFE\\uD83C\\uDDF9\"],\"Flags\",1905,[\"flag-yt\"],4,38,\"2.0\",\"country-flag\"],\n    \"1f1ff-1f1e6\":[[\"\\uD83C\\uDDFF\\uD83C\\uDDE6\"],\"Flags\",1906,[\"flag-za\"],4,39,\"2.0\",\"country-flag\"],\n    \"1f1ff-1f1f2\":[[\"\\uD83C\\uDDFF\\uD83C\\uDDF2\"],\"Flags\",1907,[\"flag-zm\"],4,40,\"2.0\",\"country-flag\"],\n    \"1f1ff-1f1fc\":[[\"\\uD83C\\uDDFF\\uD83C\\uDDFC\"],\"Flags\",1908,[\"flag-zw\"],4,41,\"2.0\",\"country-flag\"],\n    \"1f201\":[[\"\\uD83C\\uDE01\"],\"Symbols\",1591,[\"koko\"],4,42,\"0.6\",\"alphanum\"],\n    \"1f202-fe0f\":[[\"\\uD83C\\uDE02\\uFE0F\"],\"Symbols\",1592,[\"sa\"],4,43,\"0.6\",\"alphanum\"],\n    \"1f21a\":[[\"\\uD83C\\uDE1A\"],\"Symbols\",1598,[\"u7121\"],4,44,\"0.6\",\"alphanum\"],\n    \"1f22f\":[[\"\\uD83C\\uDE2F\"],\"Symbols\",1595,[\"u6307\"],4,45,\"0.6\",\"alphanum\"],\n    \"1f232\":[[\"\\uD83C\\uDE32\"],\"Symbols\",1599,[\"u7981\"],4,46,\"0.6\",\"alphanum\"],\n    \"1f233\":[[\"\\uD83C\\uDE33\"],\"Symbols\",1603,[\"u7a7a\"],4,47,\"0.6\",\"alphanum\"],\n    \"1f234\":[[\"\\uD83C\\uDE34\"],\"Symbols\",1602,[\"u5408\"],4,48,\"0.6\",\"alphanum\"],\n    \"1f235\":[[\"\\uD83C\\uDE35\"],\"Symbols\",1607,[\"u6e80\"],4,49,\"0.6\",\"alphanum\"],\n    \"1f236\":[[\"\\uD83C\\uDE36\"],\"Symbols\",1594,[\"u6709\"],4,50,\"0.6\",\"alphanum\"],\n    \"1f237-fe0f\":[[\"\\uD83C\\uDE37\\uFE0F\"],\"Symbols\",1593,[\"u6708\"],4,51,\"0.6\",\"alphanum\"],\n    \"1f238\":[[\"\\uD83C\\uDE38\"],\"Symbols\",1601,[\"u7533\"],4,52,\"0.6\",\"alphanum\"],\n    \"1f239\":[[\"\\uD83C\\uDE39\"],\"Symbols\",1597,[\"u5272\"],4,53,\"0.6\",\"alphanum\"],\n    \"1f23a\":[[\"\\uD83C\\uDE3A\"],\"Symbols\",1606,[\"u55b6\"],4,54,\"0.6\",\"alphanum\"],\n    \"1f250\":[[\"\\uD83C\\uDE50\"],\"Symbols\",1596,[\"ideograph_advantage\"],4,55,\"0.6\",\"alphanum\"],\n    \"1f251\":[[\"\\uD83C\\uDE51\"],\"Symbols\",1600,[\"accept\"],4,56,\"0.6\",\"alphanum\"],\n    \"1f300\":[[\"\\uD83C\\uDF00\"],\"Travel & Places\",1055,[\"cyclone\"],4,57,\"0.6\",\"sky & weather\"],\n    \"1f301\":[[\"\\uD83C\\uDF01\"],\"Travel & Places\",902,[\"foggy\"],4,58,\"0.6\",\"place-other\"],\n    \"1f302\":[[\"\\uD83C\\uDF02\"],\"Travel & Places\",1057,[\"closed_umbrella\"],4,59,\"0.6\",\"sky & weather\"],\n    \"1f303\":[[\"\\uD83C\\uDF03\"],\"Travel & Places\",903,[\"night_with_stars\"],4,60,\"0.6\",\"place-other\"],\n    \"1f304\":[[\"\\uD83C\\uDF04\"],\"Travel & Places\",905,[\"sunrise_over_mountains\"],4,61,\"0.6\",\"place-other\"],\n    \"1f305\":[[\"\\uD83C\\uDF05\"],\"Travel & Places\",906,[\"sunrise\"],5,0,\"0.6\",\"place-other\"],\n    \"1f306\":[[\"\\uD83C\\uDF06\"],\"Travel & Places\",907,[\"city_sunset\"],5,1,\"0.6\",\"place-other\"],\n    \"1f307\":[[\"\\uD83C\\uDF07\"],\"Travel & Places\",908,[\"city_sunrise\"],5,2,\"0.6\",\"place-other\"],\n    \"1f308\":[[\"\\uD83C\\uDF08\"],\"Travel & Places\",1056,[\"rainbow\"],5,3,\"0.6\",\"sky & weather\"],\n    \"1f309\":[[\"\\uD83C\\uDF09\"],\"Travel & Places\",909,[\"bridge_at_night\"],5,4,\"0.6\",\"place-other\"],\n    \"1f30a\":[[\"\\uD83C\\uDF0A\"],\"Travel & Places\",1068,[\"ocean\"],5,5,\"0.6\",\"sky & weather\"],\n    \"1f30b\":[[\"\\uD83C\\uDF0B\"],\"Travel & Places\",860,[\"volcano\"],5,6,\"0.6\",\"place-geographic\"],\n    \"1f30c\":[[\"\\uD83C\\uDF0C\"],\"Travel & Places\",1042,[\"milky_way\"],5,7,\"0.6\",\"sky & weather\"],\n    \"1f30d\":[[\"\\uD83C\\uDF0D\"],\"Travel & Places\",851,[\"earth_africa\"],5,8,\"0.7\",\"place-map\"],\n    \"1f30e\":[[\"\\uD83C\\uDF0E\"],\"Travel & Places\",852,[\"earth_americas\"],5,9,\"0.7\",\"place-map\"],\n    \"1f30f\":[[\"\\uD83C\\uDF0F\"],\"Travel & Places\",853,[\"earth_asia\"],5,10,\"0.6\",\"place-map\"],\n    \"1f310\":[[\"\\uD83C\\uDF10\"],\"Travel & Places\",854,[\"globe_with_meridians\"],5,11,\"1.0\",\"place-map\"],\n    \"1f311\":[[\"\\uD83C\\uDF11\"],\"Travel & Places\",1022,[\"new_moon\"],5,12,\"0.6\",\"sky & weather\"],\n    \"1f312\":[[\"\\uD83C\\uDF12\"],\"Travel & Places\",1023,[\"waxing_crescent_moon\"],5,13,\"1.0\",\"sky & weather\"],\n    \"1f313\":[[\"\\uD83C\\uDF13\"],\"Travel & Places\",1024,[\"first_quarter_moon\"],5,14,\"0.6\",\"sky & weather\"],\n    \"1f314\":[[\"\\uD83C\\uDF14\"],\"Travel & Places\",1025,[\"moon\",\"waxing_gibbous_moon\"],5,15,\"0.6\",\"sky & weather\"],\n    \"1f315\":[[\"\\uD83C\\uDF15\"],\"Travel & Places\",1026,[\"full_moon\"],5,16,\"0.6\",\"sky & weather\"],\n    \"1f316\":[[\"\\uD83C\\uDF16\"],\"Travel & Places\",1027,[\"waning_gibbous_moon\"],5,17,\"1.0\",\"sky & weather\"],\n    \"1f317\":[[\"\\uD83C\\uDF17\"],\"Travel & Places\",1028,[\"last_quarter_moon\"],5,18,\"1.0\",\"sky & weather\"],\n    \"1f318\":[[\"\\uD83C\\uDF18\"],\"Travel & Places\",1029,[\"waning_crescent_moon\"],5,19,\"1.0\",\"sky & weather\"],\n    \"1f319\":[[\"\\uD83C\\uDF19\"],\"Travel & Places\",1030,[\"crescent_moon\"],5,20,\"0.6\",\"sky & weather\"],\n    \"1f31a\":[[\"\\uD83C\\uDF1A\"],\"Travel & Places\",1031,[\"new_moon_with_face\"],5,21,\"1.0\",\"sky & weather\"],\n    \"1f31b\":[[\"\\uD83C\\uDF1B\"],\"Travel & Places\",1032,[\"first_quarter_moon_with_face\"],5,22,\"0.6\",\"sky & weather\"],\n    \"1f31c\":[[\"\\uD83C\\uDF1C\"],\"Travel & Places\",1033,[\"last_quarter_moon_with_face\"],5,23,\"0.7\",\"sky & weather\"],\n    \"1f31d\":[[\"\\uD83C\\uDF1D\"],\"Travel & Places\",1036,[\"full_moon_with_face\"],5,24,\"1.0\",\"sky & weather\"],\n    \"1f31e\":[[\"\\uD83C\\uDF1E\"],\"Travel & Places\",1037,[\"sun_with_face\"],5,25,\"1.0\",\"sky & weather\"],\n    \"1f31f\":[[\"\\uD83C\\uDF1F\"],\"Travel & Places\",1040,[\"star2\"],5,26,\"0.6\",\"sky & weather\"],\n    \"1f320\":[[\"\\uD83C\\uDF20\"],\"Travel & Places\",1041,[\"stars\"],5,27,\"0.6\",\"sky & weather\"],\n    \"1f321-fe0f\":[[\"\\uD83C\\uDF21\\uFE0F\"],\"Travel & Places\",1034,[\"thermometer\"],5,28,\"0.7\",\"sky & weather\"],\n    \"1f324-fe0f\":[[\"\\uD83C\\uDF24\\uFE0F\"],\"Travel & Places\",1046,[\"mostly_sunny\",\"sun_small_cloud\"],5,29,\"0.7\",\"sky & weather\"],\n    \"1f325-fe0f\":[[\"\\uD83C\\uDF25\\uFE0F\"],\"Travel & Places\",1047,[\"barely_sunny\",\"sun_behind_cloud\"],5,30,\"0.7\",\"sky & weather\"],\n    \"1f326-fe0f\":[[\"\\uD83C\\uDF26\\uFE0F\"],\"Travel & Places\",1048,[\"partly_sunny_rain\",\"sun_behind_rain_cloud\"],5,31,\"0.7\",\"sky & weather\"],\n    \"1f327-fe0f\":[[\"\\uD83C\\uDF27\\uFE0F\"],\"Travel & Places\",1049,[\"rain_cloud\"],5,32,\"0.7\",\"sky & weather\"],\n    \"1f328-fe0f\":[[\"\\uD83C\\uDF28\\uFE0F\"],\"Travel & Places\",1050,[\"snow_cloud\"],5,33,\"0.7\",\"sky & weather\"],\n    \"1f329-fe0f\":[[\"\\uD83C\\uDF29\\uFE0F\"],\"Travel & Places\",1051,[\"lightning\",\"lightning_cloud\"],5,34,\"0.7\",\"sky & weather\"],\n    \"1f32a-fe0f\":[[\"\\uD83C\\uDF2A\\uFE0F\"],\"Travel & Places\",1052,[\"tornado\",\"tornado_cloud\"],5,35,\"0.7\",\"sky & weather\"],\n    \"1f32b-fe0f\":[[\"\\uD83C\\uDF2B\\uFE0F\"],\"Travel & Places\",1053,[\"fog\"],5,36,\"0.7\",\"sky & weather\"],\n    \"1f32c-fe0f\":[[\"\\uD83C\\uDF2C\\uFE0F\"],\"Travel & Places\",1054,[\"wind_blowing_face\"],5,37,\"0.7\",\"sky & weather\"],\n    \"1f32d\":[[\"\\uD83C\\uDF2D\"],\"Food & Drink\",775,[\"hotdog\"],5,38,\"1.0\",\"food-prepared\"],\n    \"1f32e\":[[\"\\uD83C\\uDF2E\"],\"Food & Drink\",777,[\"taco\"],5,39,\"1.0\",\"food-prepared\"],\n    \"1f32f\":[[\"\\uD83C\\uDF2F\"],\"Food & Drink\",778,[\"burrito\"],5,40,\"1.0\",\"food-prepared\"],\n    \"1f330\":[[\"\\uD83C\\uDF30\"],\"Food & Drink\",754,[\"chestnut\"],5,41,\"0.6\",\"food-vegetable\"],\n    \"1f331\":[[\"\\uD83C\\uDF31\"],\"Animals & Nature\",703,[\"seedling\"],5,42,\"0.6\",\"plant-other\"],\n    \"1f332\":[[\"\\uD83C\\uDF32\"],\"Animals & Nature\",705,[\"evergreen_tree\"],5,43,\"1.0\",\"plant-other\"],\n    \"1f333\":[[\"\\uD83C\\uDF33\"],\"Animals & Nature\",706,[\"deciduous_tree\"],5,44,\"1.0\",\"plant-other\"],\n    \"1f334\":[[\"\\uD83C\\uDF34\"],\"Animals & Nature\",707,[\"palm_tree\"],5,45,\"0.6\",\"plant-other\"],\n    \"1f335\":[[\"\\uD83C\\uDF35\"],\"Animals & Nature\",708,[\"cactus\"],5,46,\"0.6\",\"plant-other\"],\n    \"1f336-fe0f\":[[\"\\uD83C\\uDF36\\uFE0F\"],\"Food & Drink\",745,[\"hot_pepper\"],5,47,\"0.7\",\"food-vegetable\"],\n    \"1f337\":[[\"\\uD83C\\uDF37\"],\"Animals & Nature\",701,[\"tulip\"],5,48,\"0.6\",\"plant-flower\"],\n    \"1f338\":[[\"\\uD83C\\uDF38\"],\"Animals & Nature\",692,[\"cherry_blossom\"],5,49,\"0.6\",\"plant-flower\"],\n    \"1f339\":[[\"\\uD83C\\uDF39\"],\"Animals & Nature\",696,[\"rose\"],5,50,\"0.6\",\"plant-flower\"],\n    \"1f33a\":[[\"\\uD83C\\uDF3A\"],\"Animals & Nature\",698,[\"hibiscus\"],5,51,\"0.6\",\"plant-flower\"],\n    \"1f33b\":[[\"\\uD83C\\uDF3B\"],\"Animals & Nature\",699,[\"sunflower\"],5,52,\"0.6\",\"plant-flower\"],\n    \"1f33c\":[[\"\\uD83C\\uDF3C\"],\"Animals & Nature\",700,[\"blossom\"],5,53,\"0.6\",\"plant-flower\"],\n    \"1f33d\":[[\"\\uD83C\\uDF3D\"],\"Food & Drink\",744,[\"corn\"],5,54,\"0.6\",\"food-vegetable\"],\n    \"1f33e\":[[\"\\uD83C\\uDF3E\"],\"Animals & Nature\",709,[\"ear_of_rice\"],5,55,\"0.6\",\"plant-other\"],\n    \"1f33f\":[[\"\\uD83C\\uDF3F\"],\"Animals & Nature\",710,[\"herb\"],5,56,\"0.6\",\"plant-other\"],\n    \"1f340\":[[\"\\uD83C\\uDF40\"],\"Animals & Nature\",712,[\"four_leaf_clover\"],5,57,\"0.6\",\"plant-other\"],\n    \"1f341\":[[\"\\uD83C\\uDF41\"],\"Animals & Nature\",713,[\"maple_leaf\"],5,58,\"0.6\",\"plant-other\"],\n    \"1f342\":[[\"\\uD83C\\uDF42\"],\"Animals & Nature\",714,[\"fallen_leaf\"],5,59,\"0.6\",\"plant-other\"],\n    \"1f343\":[[\"\\uD83C\\uDF43\"],\"Animals & Nature\",715,[\"leaves\"],5,60,\"0.6\",\"plant-other\"],\n    \"1f344-200d-1f7eb\":[[\"\\uD83C\\uDF44\\u200D\\uD83D\\uDFEB\"],\"Food & Drink\",757,[\"brown_mushroom\"],5,61,\"15.1\",\"food-vegetable\"],\n    \"1f344\":[[\"\\uD83C\\uDF44\"],\"Animals & Nature\",718,[\"mushroom\"],6,0,\"0.6\",\"plant-other\"],\n    \"1f345\":[[\"\\uD83C\\uDF45\"],\"Food & Drink\",737,[\"tomato\"],6,1,\"0.6\",\"food-fruit\"],\n    \"1f346\":[[\"\\uD83C\\uDF46\"],\"Food & Drink\",741,[\"eggplant\"],6,2,\"0.6\",\"food-vegetable\"],\n    \"1f347\":[[\"\\uD83C\\uDF47\"],\"Food & Drink\",720,[\"grapes\"],6,3,\"0.6\",\"food-fruit\"],\n    \"1f348\":[[\"\\uD83C\\uDF48\"],\"Food & Drink\",721,[\"melon\"],6,4,\"0.6\",\"food-fruit\"],\n    \"1f349\":[[\"\\uD83C\\uDF49\"],\"Food & Drink\",722,[\"watermelon\"],6,5,\"0.6\",\"food-fruit\"],\n    \"1f34a\":[[\"\\uD83C\\uDF4A\"],\"Food & Drink\",723,[\"tangerine\"],6,6,\"0.6\",\"food-fruit\"],\n    \"1f34b-200d-1f7e9\":[[\"\\uD83C\\uDF4B\\u200D\\uD83D\\uDFE9\"],\"Food & Drink\",725,[\"lime\"],6,7,\"15.1\",\"food-fruit\"],\n    \"1f34b\":[[\"\\uD83C\\uDF4B\"],\"Food & Drink\",724,[\"lemon\"],6,8,\"1.0\",\"food-fruit\"],\n    \"1f34c\":[[\"\\uD83C\\uDF4C\"],\"Food & Drink\",726,[\"banana\"],6,9,\"0.6\",\"food-fruit\"],\n    \"1f34d\":[[\"\\uD83C\\uDF4D\"],\"Food & Drink\",727,[\"pineapple\"],6,10,\"0.6\",\"food-fruit\"],\n    \"1f34e\":[[\"\\uD83C\\uDF4E\"],\"Food & Drink\",729,[\"apple\"],6,11,\"0.6\",\"food-fruit\"],\n    \"1f34f\":[[\"\\uD83C\\uDF4F\"],\"Food & Drink\",730,[\"green_apple\"],6,12,\"0.6\",\"food-fruit\"],\n    \"1f350\":[[\"\\uD83C\\uDF50\"],\"Food & Drink\",731,[\"pear\"],6,13,\"1.0\",\"food-fruit\"],\n    \"1f351\":[[\"\\uD83C\\uDF51\"],\"Food & Drink\",732,[\"peach\"],6,14,\"0.6\",\"food-fruit\"],\n    \"1f352\":[[\"\\uD83C\\uDF52\"],\"Food & Drink\",733,[\"cherries\"],6,15,\"0.6\",\"food-fruit\"],\n    \"1f353\":[[\"\\uD83C\\uDF53\"],\"Food & Drink\",734,[\"strawberry\"],6,16,\"0.6\",\"food-fruit\"],\n    \"1f354\":[[\"\\uD83C\\uDF54\"],\"Food & Drink\",772,[\"hamburger\"],6,17,\"0.6\",\"food-prepared\"],\n    \"1f355\":[[\"\\uD83C\\uDF55\"],\"Food & Drink\",774,[\"pizza\"],6,18,\"0.6\",\"food-prepared\"],\n    \"1f356\":[[\"\\uD83C\\uDF56\"],\"Food & Drink\",768,[\"meat_on_bone\"],6,19,\"0.6\",\"food-prepared\"],\n    \"1f357\":[[\"\\uD83C\\uDF57\"],\"Food & Drink\",769,[\"poultry_leg\"],6,20,\"0.6\",\"food-prepared\"],\n    \"1f358\":[[\"\\uD83C\\uDF58\"],\"Food & Drink\",794,[\"rice_cracker\"],6,21,\"0.6\",\"food-asian\"],\n    \"1f359\":[[\"\\uD83C\\uDF59\"],\"Food & Drink\",795,[\"rice_ball\"],6,22,\"0.6\",\"food-asian\"],\n    \"1f35a\":[[\"\\uD83C\\uDF5A\"],\"Food & Drink\",796,[\"rice\"],6,23,\"0.6\",\"food-asian\"],\n    \"1f35b\":[[\"\\uD83C\\uDF5B\"],\"Food & Drink\",797,[\"curry\"],6,24,\"0.6\",\"food-asian\"],\n    \"1f35c\":[[\"\\uD83C\\uDF5C\"],\"Food & Drink\",798,[\"ramen\"],6,25,\"0.6\",\"food-asian\"],\n    \"1f35d\":[[\"\\uD83C\\uDF5D\"],\"Food & Drink\",799,[\"spaghetti\"],6,26,\"0.6\",\"food-asian\"],\n    \"1f35e\":[[\"\\uD83C\\uDF5E\"],\"Food & Drink\",759,[\"bread\"],6,27,\"0.6\",\"food-prepared\"],\n    \"1f35f\":[[\"\\uD83C\\uDF5F\"],\"Food & Drink\",773,[\"fries\"],6,28,\"0.6\",\"food-prepared\"],\n    \"1f360\":[[\"\\uD83C\\uDF60\"],\"Food & Drink\",800,[\"sweet_potato\"],6,29,\"0.6\",\"food-asian\"],\n    \"1f361\":[[\"\\uD83C\\uDF61\"],\"Food & Drink\",806,[\"dango\"],6,30,\"0.6\",\"food-asian\"],\n    \"1f362\":[[\"\\uD83C\\uDF62\"],\"Food & Drink\",801,[\"oden\"],6,31,\"0.6\",\"food-asian\"],\n    \"1f363\":[[\"\\uD83C\\uDF63\"],\"Food & Drink\",802,[\"sushi\"],6,32,\"0.6\",\"food-asian\"],\n    \"1f364\":[[\"\\uD83C\\uDF64\"],\"Food & Drink\",803,[\"fried_shrimp\"],6,33,\"0.6\",\"food-asian\"],\n    \"1f365\":[[\"\\uD83C\\uDF65\"],\"Food & Drink\",804,[\"fish_cake\"],6,34,\"0.6\",\"food-asian\"],\n    \"1f366\":[[\"\\uD83C\\uDF66\"],\"Food & Drink\",810,[\"icecream\"],6,35,\"0.6\",\"food-sweet\"],\n    \"1f367\":[[\"\\uD83C\\uDF67\"],\"Food & Drink\",811,[\"shaved_ice\"],6,36,\"0.6\",\"food-sweet\"],\n    \"1f368\":[[\"\\uD83C\\uDF68\"],\"Food & Drink\",812,[\"ice_cream\"],6,37,\"0.6\",\"food-sweet\"],\n    \"1f369\":[[\"\\uD83C\\uDF69\"],\"Food & Drink\",813,[\"doughnut\"],6,38,\"0.6\",\"food-sweet\"],\n    \"1f36a\":[[\"\\uD83C\\uDF6A\"],\"Food & Drink\",814,[\"cookie\"],6,39,\"0.6\",\"food-sweet\"],\n    \"1f36b\":[[\"\\uD83C\\uDF6B\"],\"Food & Drink\",819,[\"chocolate_bar\"],6,40,\"0.6\",\"food-sweet\"],\n    \"1f36c\":[[\"\\uD83C\\uDF6C\"],\"Food & Drink\",820,[\"candy\"],6,41,\"0.6\",\"food-sweet\"],\n    \"1f36d\":[[\"\\uD83C\\uDF6D\"],\"Food & Drink\",821,[\"lollipop\"],6,42,\"0.6\",\"food-sweet\"],\n    \"1f36e\":[[\"\\uD83C\\uDF6E\"],\"Food & Drink\",822,[\"custard\"],6,43,\"0.6\",\"food-sweet\"],\n    \"1f36f\":[[\"\\uD83C\\uDF6F\"],\"Food & Drink\",823,[\"honey_pot\"],6,44,\"0.6\",\"food-sweet\"],\n    \"1f370\":[[\"\\uD83C\\uDF70\"],\"Food & Drink\",816,[\"cake\"],6,45,\"0.6\",\"food-sweet\"],\n    \"1f371\":[[\"\\uD83C\\uDF71\"],\"Food & Drink\",793,[\"bento\"],6,46,\"0.6\",\"food-asian\"],\n    \"1f372\":[[\"\\uD83C\\uDF72\"],\"Food & Drink\",785,[\"stew\"],6,47,\"0.6\",\"food-prepared\"],\n    \"1f373\":[[\"\\uD83C\\uDF73\"],\"Food & Drink\",783,[\"fried_egg\",\"cooking\"],6,48,\"0.6\",\"food-prepared\"],\n    \"1f374\":[[\"\\uD83C\\uDF74\"],\"Food & Drink\",846,[\"fork_and_knife\"],6,49,\"0.6\",\"dishware\"],\n    \"1f375\":[[\"\\uD83C\\uDF75\"],\"Food & Drink\",828,[\"tea\"],6,50,\"0.6\",\"drink\"],\n    \"1f376\":[[\"\\uD83C\\uDF76\"],\"Food & Drink\",829,[\"sake\"],6,51,\"0.6\",\"drink\"],\n    \"1f377\":[[\"\\uD83C\\uDF77\"],\"Food & Drink\",831,[\"wine_glass\"],6,52,\"0.6\",\"drink\"],\n    \"1f378\":[[\"\\uD83C\\uDF78\"],\"Food & Drink\",832,[\"cocktail\"],6,53,\"0.6\",\"drink\"],\n    \"1f379\":[[\"\\uD83C\\uDF79\"],\"Food & Drink\",833,[\"tropical_drink\"],6,54,\"0.6\",\"drink\"],\n    \"1f37a\":[[\"\\uD83C\\uDF7A\"],\"Food & Drink\",834,[\"beer\"],6,55,\"0.6\",\"drink\"],\n    \"1f37b\":[[\"\\uD83C\\uDF7B\"],\"Food & Drink\",835,[\"beers\"],6,56,\"0.6\",\"drink\"],\n    \"1f37c\":[[\"\\uD83C\\uDF7C\"],\"Food & Drink\",824,[\"baby_bottle\"],6,57,\"1.0\",\"drink\"],\n    \"1f37d-fe0f\":[[\"\\uD83C\\uDF7D\\uFE0F\"],\"Food & Drink\",845,[\"knife_fork_plate\"],6,58,\"0.7\",\"dishware\"],\n    \"1f37e\":[[\"\\uD83C\\uDF7E\"],\"Food & Drink\",830,[\"champagne\"],6,59,\"1.0\",\"drink\"],\n    \"1f37f\":[[\"\\uD83C\\uDF7F\"],\"Food & Drink\",789,[\"popcorn\"],6,60,\"1.0\",\"food-prepared\"],\n    \"1f380\":[[\"\\uD83C\\uDF80\"],\"Activities\",1085,[\"ribbon\"],6,61,\"0.6\",\"event\"],\n    \"1f381\":[[\"\\uD83C\\uDF81\"],\"Activities\",1086,[\"gift\"],7,0,\"0.6\",\"event\"],\n    \"1f382\":[[\"\\uD83C\\uDF82\"],\"Food & Drink\",815,[\"birthday\"],7,1,\"0.6\",\"food-sweet\"],\n    \"1f383\":[[\"\\uD83C\\uDF83\"],\"Activities\",1069,[\"jack_o_lantern\"],7,2,\"0.6\",\"event\"],\n    \"1f384\":[[\"\\uD83C\\uDF84\"],\"Activities\",1070,[\"christmas_tree\"],7,3,\"0.6\",\"event\"],\n    \"1f385\":[[\"\\uD83C\\uDF85\"],\"People & Body\",372,[\"santa\"],7,4,\"0.6\",\"person-fantasy\"],\n    \"1f386\":[[\"\\uD83C\\uDF86\"],\"Activities\",1071,[\"fireworks\"],7,10,\"0.6\",\"event\"],\n    \"1f387\":[[\"\\uD83C\\uDF87\"],\"Activities\",1072,[\"sparkler\"],7,11,\"0.6\",\"event\"],\n    \"1f388\":[[\"\\uD83C\\uDF88\"],\"Activities\",1075,[\"balloon\"],7,12,\"0.6\",\"event\"],\n    \"1f389\":[[\"\\uD83C\\uDF89\"],\"Activities\",1076,[\"tada\"],7,13,\"0.6\",\"event\"],\n    \"1f38a\":[[\"\\uD83C\\uDF8A\"],\"Activities\",1077,[\"confetti_ball\"],7,14,\"0.6\",\"event\"],\n    \"1f38b\":[[\"\\uD83C\\uDF8B\"],\"Activities\",1078,[\"tanabata_tree\"],7,15,\"0.6\",\"event\"],\n    \"1f38c\":[[\"\\uD83C\\uDF8C\"],\"Flags\",1644,[\"crossed_flags\"],7,16,\"0.6\",\"flag\"],\n    \"1f38d\":[[\"\\uD83C\\uDF8D\"],\"Activities\",1079,[\"bamboo\"],7,17,\"0.6\",\"event\"],\n    \"1f38e\":[[\"\\uD83C\\uDF8E\"],\"Activities\",1080,[\"dolls\"],7,18,\"0.6\",\"event\"],\n    \"1f38f\":[[\"\\uD83C\\uDF8F\"],\"Activities\",1081,[\"flags\"],7,19,\"0.6\",\"event\"],\n    \"1f390\":[[\"\\uD83C\\uDF90\"],\"Activities\",1082,[\"wind_chime\"],7,20,\"0.6\",\"event\"],\n    \"1f391\":[[\"\\uD83C\\uDF91\"],\"Activities\",1083,[\"rice_scene\"],7,21,\"0.6\",\"event\"],\n    \"1f392\":[[\"\\uD83C\\uDF92\"],\"Objects\",1179,[\"school_satchel\"],7,22,\"0.6\",\"clothing\"],\n    \"1f393\":[[\"\\uD83C\\uDF93\"],\"Objects\",1193,[\"mortar_board\"],7,23,\"0.6\",\"clothing\"],\n    \"1f396-fe0f\":[[\"\\uD83C\\uDF96\\uFE0F\"],\"Activities\",1090,[\"medal\"],7,24,\"0.7\",\"award-medal\"],\n    \"1f397-fe0f\":[[\"\\uD83C\\uDF97\\uFE0F\"],\"Activities\",1087,[\"reminder_ribbon\"],7,25,\"0.7\",\"event\"],\n    \"1f399-fe0f\":[[\"\\uD83C\\uDF99\\uFE0F\"],\"Objects\",1213,[\"studio_microphone\"],7,26,\"0.7\",\"music\"],\n    \"1f39a-fe0f\":[[\"\\uD83C\\uDF9A\\uFE0F\"],\"Objects\",1214,[\"level_slider\"],7,27,\"0.7\",\"music\"],\n    \"1f39b-fe0f\":[[\"\\uD83C\\uDF9B\\uFE0F\"],\"Objects\",1215,[\"control_knobs\"],7,28,\"0.7\",\"music\"],\n    \"1f39e-fe0f\":[[\"\\uD83C\\uDF9E\\uFE0F\"],\"Objects\",1252,[\"film_frames\"],7,29,\"0.7\",\"light & video\"],\n    \"1f39f-fe0f\":[[\"\\uD83C\\uDF9F\\uFE0F\"],\"Activities\",1088,[\"admission_tickets\"],7,30,\"0.7\",\"event\"],\n    \"1f3a0\":[[\"\\uD83C\\uDFA0\"],\"Travel & Places\",911,[\"carousel_horse\"],7,31,\"0.6\",\"place-other\"],\n    \"1f3a1\":[[\"\\uD83C\\uDFA1\"],\"Travel & Places\",913,[\"ferris_wheel\"],7,32,\"0.6\",\"place-other\"],\n    \"1f3a2\":[[\"\\uD83C\\uDFA2\"],\"Travel & Places\",914,[\"roller_coaster\"],7,33,\"0.6\",\"place-other\"],\n    \"1f3a3\":[[\"\\uD83C\\uDFA3\"],\"Activities\",1117,[\"fishing_pole_and_fish\"],7,34,\"0.6\",\"sport\"],\n    \"1f3a4\":[[\"\\uD83C\\uDFA4\"],\"Objects\",1216,[\"microphone\"],7,35,\"0.6\",\"music\"],\n    \"1f3a5\":[[\"\\uD83C\\uDFA5\"],\"Objects\",1251,[\"movie_camera\"],7,36,\"0.6\",\"light & video\"],\n    \"1f3a6\":[[\"\\uD83C\\uDFA6\"],\"Symbols\",1509,[\"cinema\"],7,37,\"0.6\",\"av-symbol\"],\n    \"1f3a7\":[[\"\\uD83C\\uDFA7\"],\"Objects\",1217,[\"headphones\"],7,38,\"0.6\",\"music\"],\n    \"1f3a8\":[[\"\\uD83C\\uDFA8\"],\"Activities\",1149,[\"art\"],7,39,\"0.6\",\"arts & crafts\"],\n    \"1f3a9\":[[\"\\uD83C\\uDFA9\"],\"Objects\",1192,[\"tophat\"],7,40,\"0.6\",\"clothing\"],\n    \"1f3aa\":[[\"\\uD83C\\uDFAA\"],\"Travel & Places\",916,[\"circus_tent\"],7,41,\"0.6\",\"place-other\"],\n    \"1f3ab\":[[\"\\uD83C\\uDFAB\"],\"Activities\",1089,[\"ticket\"],7,42,\"0.6\",\"event\"],\n    \"1f3ac\":[[\"\\uD83C\\uDFAC\"],\"Objects\",1254,[\"clapper\"],7,43,\"0.6\",\"light & video\"],\n    \"1f3ad\":[[\"\\uD83C\\uDFAD\"],\"Activities\",1147,[\"performing_arts\"],7,44,\"0.6\",\"arts & crafts\"],\n    \"1f3ae\":[[\"\\uD83C\\uDFAE\"],\"Activities\",1130,[\"video_game\"],7,45,\"0.6\",\"game\"],\n    \"1f3af\":[[\"\\uD83C\\uDFAF\"],\"Activities\",1123,[\"dart\"],7,46,\"0.6\",\"game\"],\n    \"1f3b0\":[[\"\\uD83C\\uDFB0\"],\"Activities\",1132,[\"slot_machine\"],7,47,\"0.6\",\"game\"],\n    \"1f3b1\":[[\"\\uD83C\\uDFB1\"],\"Activities\",1127,[\"8ball\"],7,48,\"0.6\",\"game\"],\n    \"1f3b2\":[[\"\\uD83C\\uDFB2\"],\"Activities\",1133,[\"game_die\"],7,49,\"0.6\",\"game\"],\n    \"1f3b3\":[[\"\\uD83C\\uDFB3\"],\"Activities\",1105,[\"bowling\"],7,50,\"0.6\",\"sport\"],\n    \"1f3b4\":[[\"\\uD83C\\uDFB4\"],\"Activities\",1146,[\"flower_playing_cards\"],7,51,\"0.6\",\"game\"],\n    \"1f3b5\":[[\"\\uD83C\\uDFB5\"],\"Objects\",1211,[\"musical_note\"],7,52,\"0.6\",\"music\"],\n    \"1f3b6\":[[\"\\uD83C\\uDFB6\"],\"Objects\",1212,[\"notes\"],7,53,\"0.6\",\"music\"],\n    \"1f3b7\":[[\"\\uD83C\\uDFB7\"],\"Objects\",1219,[\"saxophone\"],7,54,\"0.6\",\"musical-instrument\"],\n    \"1f3b8\":[[\"\\uD83C\\uDFB8\"],\"Objects\",1221,[\"guitar\"],7,55,\"0.6\",\"musical-instrument\"],\n    \"1f3b9\":[[\"\\uD83C\\uDFB9\"],\"Objects\",1222,[\"musical_keyboard\"],7,56,\"0.6\",\"musical-instrument\"],\n    \"1f3ba\":[[\"\\uD83C\\uDFBA\"],\"Objects\",1223,[\"trumpet\"],7,57,\"0.6\",\"musical-instrument\"],\n    \"1f3bb\":[[\"\\uD83C\\uDFBB\"],\"Objects\",1224,[\"violin\"],7,58,\"0.6\",\"musical-instrument\"],\n    \"1f3bc\":[[\"\\uD83C\\uDFBC\"],\"Objects\",1210,[\"musical_score\"],7,59,\"0.6\",\"music\"],\n    \"1f3bd\":[[\"\\uD83C\\uDFBD\"],\"Activities\",1119,[\"running_shirt_with_sash\"],7,60,\"0.6\",\"sport\"],\n    \"1f3be\":[[\"\\uD83C\\uDFBE\"],\"Activities\",1103,[\"tennis\"],7,61,\"0.6\",\"sport\"],\n    \"1f3bf\":[[\"\\uD83C\\uDFBF\"],\"Activities\",1120,[\"ski\"],8,0,\"0.6\",\"sport\"],\n    \"1f3c0\":[[\"\\uD83C\\uDFC0\"],\"Activities\",1099,[\"basketball\"],8,1,\"0.6\",\"sport\"],\n    \"1f3c1\":[[\"\\uD83C\\uDFC1\"],\"Flags\",1642,[\"checkered_flag\"],8,2,\"0.6\",\"flag\"],\n    \"1f3c2\":[[\"\\uD83C\\uDFC2\"],\"People & Body\",463,[\"snowboarder\"],8,3,\"0.6\",\"person-sport\"],\n    \"1f3c3-200d-2640-fe0f\":[[\"\\uD83C\\uDFC3\\u200D\\u2640\\uFE0F\"],\"People & Body\",444,[\"woman-running\"],8,9,\"4.0\",\"person-activity\"],\n    \"1f3c3-200d-2640-fe0f-200d-27a1-fe0f\":[[\"\\uD83C\\uDFC3\\u200D\\u2640\\uFE0F\\u200D\\u27A1\\uFE0F\"],\"People & Body\",446,[\"woman_running_facing_right\"],8,15,\"15.1\",\"person-activity\"],\n    \"1f3c3-200d-2642-fe0f\":[[\"\\uD83C\\uDFC3\\u200D\\u2642\\uFE0F\",\"\\uD83C\\uDFC3\"],\"People & Body\",443,[\"man-running\",\"runner\",\"running\"],8,21,\"4.0\",\"person-activity\"],\n    \"1f3c3-200d-2642-fe0f-200d-27a1-fe0f\":[[\"\\uD83C\\uDFC3\\u200D\\u2642\\uFE0F\\u200D\\u27A1\\uFE0F\"],\"People & Body\",447,[\"man_running_facing_right\"],8,27,\"15.1\",\"person-activity\"],\n    \"1f3c3-200d-27a1-fe0f\":[[\"\\uD83C\\uDFC3\\u200D\\u27A1\\uFE0F\"],\"People & Body\",445,[\"person_running_facing_right\"],8,33,\"15.1\",\"person-activity\"],\n    \"1f3c4-200d-2640-fe0f\":[[\"\\uD83C\\uDFC4\\u200D\\u2640\\uFE0F\"],\"People & Body\",469,[\"woman-surfing\"],8,45,\"4.0\",\"person-sport\"],\n    \"1f3c4-200d-2642-fe0f\":[[\"\\uD83C\\uDFC4\\u200D\\u2642\\uFE0F\",\"\\uD83C\\uDFC4\"],\"People & Body\",468,[\"man-surfing\",\"surfer\"],8,51,\"4.0\",\"person-sport\"],\n    \"1f3c5\":[[\"\\uD83C\\uDFC5\"],\"Activities\",1092,[\"sports_medal\"],9,1,\"1.0\",\"award-medal\"],\n    \"1f3c6\":[[\"\\uD83C\\uDFC6\"],\"Activities\",1091,[\"trophy\"],9,2,\"0.6\",\"award-medal\"],\n    \"1f3c7\":[[\"\\uD83C\\uDFC7\"],\"People & Body\",461,[\"horse_racing\"],9,3,\"1.0\",\"person-sport\"],\n    \"1f3c8\":[[\"\\uD83C\\uDFC8\"],\"Activities\",1101,[\"football\"],9,9,\"0.6\",\"sport\"],\n    \"1f3c9\":[[\"\\uD83C\\uDFC9\"],\"Activities\",1102,[\"rugby_football\"],9,10,\"1.0\",\"sport\"],\n    \"1f3ca-200d-2640-fe0f\":[[\"\\uD83C\\uDFCA\\u200D\\u2640\\uFE0F\"],\"People & Body\",475,[\"woman-swimming\"],9,11,\"4.0\",\"person-sport\"],\n    \"1f3ca-200d-2642-fe0f\":[[\"\\uD83C\\uDFCA\\u200D\\u2642\\uFE0F\",\"\\uD83C\\uDFCA\"],\"People & Body\",474,[\"man-swimming\",\"swimmer\"],9,17,\"4.0\",\"person-sport\"],\n    \"1f3cb-fe0f-200d-2640-fe0f\":[[\"\\uD83C\\uDFCB\\uFE0F\\u200D\\u2640\\uFE0F\"],\"People & Body\",481,[\"woman-lifting-weights\"],9,29,\"4.0\",\"person-sport\"],\n    \"1f3cb-fe0f-200d-2642-fe0f\":[[\"\\uD83C\\uDFCB\\uFE0F\\u200D\\u2642\\uFE0F\",\"\\uD83C\\uDFCB\\uFE0F\"],\"People & Body\",480,[\"man-lifting-weights\",\"weight_lifter\"],9,35,\"4.0\",\"person-sport\"],\n    \"1f3cc-fe0f-200d-2640-fe0f\":[[\"\\uD83C\\uDFCC\\uFE0F\\u200D\\u2640\\uFE0F\"],\"People & Body\",466,[\"woman-golfing\"],9,47,\"4.0\",\"person-sport\"],\n    \"1f3cc-fe0f-200d-2642-fe0f\":[[\"\\uD83C\\uDFCC\\uFE0F\\u200D\\u2642\\uFE0F\",\"\\uD83C\\uDFCC\\uFE0F\"],\"People & Body\",465,[\"man-golfing\",\"golfer\"],9,53,\"4.0\",\"person-sport\"],\n    \"1f3cd-fe0f\":[[\"\\uD83C\\uDFCD\\uFE0F\"],\"Travel & Places\",947,[\"racing_motorcycle\"],10,3,\"0.7\",\"transport-ground\"],\n    \"1f3ce-fe0f\":[[\"\\uD83C\\uDFCE\\uFE0F\"],\"Travel & Places\",946,[\"racing_car\"],10,4,\"0.7\",\"transport-ground\"],\n    \"1f3cf\":[[\"\\uD83C\\uDFCF\"],\"Activities\",1106,[\"cricket_bat_and_ball\"],10,5,\"1.0\",\"sport\"],\n    \"1f3d0\":[[\"\\uD83C\\uDFD0\"],\"Activities\",1100,[\"volleyball\"],10,6,\"1.0\",\"sport\"],\n    \"1f3d1\":[[\"\\uD83C\\uDFD1\"],\"Activities\",1107,[\"field_hockey_stick_and_ball\"],10,7,\"1.0\",\"sport\"],\n    \"1f3d2\":[[\"\\uD83C\\uDFD2\"],\"Activities\",1108,[\"ice_hockey_stick_and_puck\"],10,8,\"1.0\",\"sport\"],\n    \"1f3d3\":[[\"\\uD83C\\uDFD3\"],\"Activities\",1110,[\"table_tennis_paddle_and_ball\"],10,9,\"1.0\",\"sport\"],\n    \"1f3d4-fe0f\":[[\"\\uD83C\\uDFD4\\uFE0F\"],\"Travel & Places\",858,[\"snow_capped_mountain\"],10,10,\"0.7\",\"place-geographic\"],\n    \"1f3d5-fe0f\":[[\"\\uD83C\\uDFD5\\uFE0F\"],\"Travel & Places\",862,[\"camping\"],10,11,\"0.7\",\"place-geographic\"],\n    \"1f3d6-fe0f\":[[\"\\uD83C\\uDFD6\\uFE0F\"],\"Travel & Places\",863,[\"beach_with_umbrella\"],10,12,\"0.7\",\"place-geographic\"],\n    \"1f3d7-fe0f\":[[\"\\uD83C\\uDFD7\\uFE0F\"],\"Travel & Places\",869,[\"building_construction\"],10,13,\"0.7\",\"place-building\"],\n    \"1f3d8-fe0f\":[[\"\\uD83C\\uDFD8\\uFE0F\"],\"Travel & Places\",874,[\"house_buildings\"],10,14,\"0.7\",\"place-building\"],\n    \"1f3d9-fe0f\":[[\"\\uD83C\\uDFD9\\uFE0F\"],\"Travel & Places\",904,[\"cityscape\"],10,15,\"0.7\",\"place-other\"],\n    \"1f3da-fe0f\":[[\"\\uD83C\\uDFDA\\uFE0F\"],\"Travel & Places\",875,[\"derelict_house_building\"],10,16,\"0.7\",\"place-building\"],\n    \"1f3db-fe0f\":[[\"\\uD83C\\uDFDB\\uFE0F\"],\"Travel & Places\",868,[\"classical_building\"],10,17,\"0.7\",\"place-building\"],\n    \"1f3dc-fe0f\":[[\"\\uD83C\\uDFDC\\uFE0F\"],\"Travel & Places\",864,[\"desert\"],10,18,\"0.7\",\"place-geographic\"],\n    \"1f3dd-fe0f\":[[\"\\uD83C\\uDFDD\\uFE0F\"],\"Travel & Places\",865,[\"desert_island\"],10,19,\"0.7\",\"place-geographic\"],\n    \"1f3de-fe0f\":[[\"\\uD83C\\uDFDE\\uFE0F\"],\"Travel & Places\",866,[\"national_park\"],10,20,\"0.7\",\"place-geographic\"],\n    \"1f3df-fe0f\":[[\"\\uD83C\\uDFDF\\uFE0F\"],\"Travel & Places\",867,[\"stadium\"],10,21,\"0.7\",\"place-building\"],\n    \"1f3e0\":[[\"\\uD83C\\uDFE0\"],\"Travel & Places\",876,[\"house\"],10,22,\"0.6\",\"place-building\"],\n    \"1f3e1\":[[\"\\uD83C\\uDFE1\"],\"Travel & Places\",877,[\"house_with_garden\"],10,23,\"0.6\",\"place-building\"],\n    \"1f3e2\":[[\"\\uD83C\\uDFE2\"],\"Travel & Places\",878,[\"office\"],10,24,\"0.6\",\"place-building\"],\n    \"1f3e3\":[[\"\\uD83C\\uDFE3\"],\"Travel & Places\",879,[\"post_office\"],10,25,\"0.6\",\"place-building\"],\n    \"1f3e4\":[[\"\\uD83C\\uDFE4\"],\"Travel & Places\",880,[\"european_post_office\"],10,26,\"1.0\",\"place-building\"],\n    \"1f3e5\":[[\"\\uD83C\\uDFE5\"],\"Travel & Places\",881,[\"hospital\"],10,27,\"0.6\",\"place-building\"],\n    \"1f3e6\":[[\"\\uD83C\\uDFE6\"],\"Travel & Places\",882,[\"bank\"],10,28,\"0.6\",\"place-building\"],\n    \"1f3e7\":[[\"\\uD83C\\uDFE7\"],\"Symbols\",1418,[\"atm\"],10,29,\"0.6\",\"transport-sign\"],\n    \"1f3e8\":[[\"\\uD83C\\uDFE8\"],\"Travel & Places\",883,[\"hotel\"],10,30,\"0.6\",\"place-building\"],\n    \"1f3e9\":[[\"\\uD83C\\uDFE9\"],\"Travel & Places\",884,[\"love_hotel\"],10,31,\"0.6\",\"place-building\"],\n    \"1f3ea\":[[\"\\uD83C\\uDFEA\"],\"Travel & Places\",885,[\"convenience_store\"],10,32,\"0.6\",\"place-building\"],\n    \"1f3eb\":[[\"\\uD83C\\uDFEB\"],\"Travel & Places\",886,[\"school\"],10,33,\"0.6\",\"place-building\"],\n    \"1f3ec\":[[\"\\uD83C\\uDFEC\"],\"Travel & Places\",887,[\"department_store\"],10,34,\"0.6\",\"place-building\"],\n    \"1f3ed\":[[\"\\uD83C\\uDFED\"],\"Travel & Places\",888,[\"factory\"],10,35,\"0.6\",\"place-building\"],\n    \"1f3ee\":[[\"\\uD83C\\uDFEE\"],\"Objects\",1265,[\"izakaya_lantern\",\"lantern\"],10,36,\"0.6\",\"light & video\"],\n    \"1f3ef\":[[\"\\uD83C\\uDFEF\"],\"Travel & Places\",889,[\"japanese_castle\"],10,37,\"0.6\",\"place-building\"],\n    \"1f3f0\":[[\"\\uD83C\\uDFF0\"],\"Travel & Places\",890,[\"european_castle\"],10,38,\"0.6\",\"place-building\"],\n    \"1f3f3-fe0f-200d-1f308\":[[\"\\uD83C\\uDFF3\\uFE0F\\u200D\\uD83C\\uDF08\"],\"Flags\",1647,[\"rainbow-flag\"],10,39,\"4.0\",\"flag\"],\n    \"1f3f3-fe0f-200d-26a7-fe0f\":[[\"\\uD83C\\uDFF3\\uFE0F\\u200D\\u26A7\\uFE0F\"],\"Flags\",1648,[\"transgender_flag\"],10,40,\"13.0\",\"flag\"],\n    \"1f3f3-fe0f\":[[\"\\uD83C\\uDFF3\\uFE0F\"],\"Flags\",1646,[\"waving_white_flag\"],10,41,\"0.7\",\"flag\"],\n    \"1f3f4-200d-2620-fe0f\":[[\"\\uD83C\\uDFF4\\u200D\\u2620\\uFE0F\"],\"Flags\",1649,[\"pirate_flag\"],10,42,\"11.0\",\"flag\"],\n    \"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f\":[[\"\\uD83C\\uDFF4\\uDB40\\uDC67\\uDB40\\uDC62\\uDB40\\uDC65\\uDB40\\uDC6E\\uDB40\\uDC67\\uDB40\\uDC7F\"],\"Flags\",1909,[\"flag-england\"],10,43,\"5.0\",\"subdivision-flag\"],\n    \"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f\":[[\"\\uD83C\\uDFF4\\uDB40\\uDC67\\uDB40\\uDC62\\uDB40\\uDC73\\uDB40\\uDC63\\uDB40\\uDC74\\uDB40\\uDC7F\"],\"Flags\",1910,[\"flag-scotland\"],10,44,\"5.0\",\"subdivision-flag\"],\n    \"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f\":[[\"\\uD83C\\uDFF4\\uDB40\\uDC67\\uDB40\\uDC62\\uDB40\\uDC77\\uDB40\\uDC6C\\uDB40\\uDC73\\uDB40\\uDC7F\"],\"Flags\",1911,[\"flag-wales\"],10,45,\"5.0\",\"subdivision-flag\"],\n    \"1f3f4\":[[\"\\uD83C\\uDFF4\"],\"Flags\",1645,[\"waving_black_flag\"],10,46,\"1.0\",\"flag\"],\n    \"1f3f5-fe0f\":[[\"\\uD83C\\uDFF5\\uFE0F\"],\"Animals & Nature\",695,[\"rosette\"],10,47,\"0.7\",\"plant-flower\"],\n    \"1f3f7-fe0f\":[[\"\\uD83C\\uDFF7\\uFE0F\"],\"Objects\",1283,[\"label\"],10,48,\"0.7\",\"book-paper\"],\n    \"1f3f8\":[[\"\\uD83C\\uDFF8\"],\"Activities\",1111,[\"badminton_racquet_and_shuttlecock\"],10,49,\"1.0\",\"sport\"],\n    \"1f3f9\":[[\"\\uD83C\\uDFF9\"],\"Objects\",1352,[\"bow_and_arrow\"],10,50,\"1.0\",\"tool\"],\n    \"1f3fa\":[[\"\\uD83C\\uDFFA\"],\"Food & Drink\",850,[\"amphora\"],10,51,\"1.0\",\"dishware\"],\n    \"1f3fb\":[[\"\\uD83C\\uDFFB\"],\"Component\",556,[\"skin-tone-2\"],10,52,\"1.0\",\"skin-tone\"],\n    \"1f3fc\":[[\"\\uD83C\\uDFFC\"],\"Component\",557,[\"skin-tone-3\"],10,53,\"1.0\",\"skin-tone\"],\n    \"1f3fd\":[[\"\\uD83C\\uDFFD\"],\"Component\",558,[\"skin-tone-4\"],10,54,\"1.0\",\"skin-tone\"],\n    \"1f3fe\":[[\"\\uD83C\\uDFFE\"],\"Component\",559,[\"skin-tone-5\"],10,55,\"1.0\",\"skin-tone\"],\n    \"1f3ff\":[[\"\\uD83C\\uDFFF\"],\"Component\",560,[\"skin-tone-6\"],10,56,\"1.0\",\"skin-tone\"],\n    \"1f400\":[[\"\\uD83D\\uDC00\"],\"Animals & Nature\",609,[\"rat\"],10,57,\"1.0\",\"animal-mammal\"],\n    \"1f401\":[[\"\\uD83D\\uDC01\"],\"Animals & Nature\",608,[\"mouse2\"],10,58,\"1.0\",\"animal-mammal\"],\n    \"1f402\":[[\"\\uD83D\\uDC02\"],\"Animals & Nature\",589,[\"ox\"],10,59,\"1.0\",\"animal-mammal\"],\n    \"1f403\":[[\"\\uD83D\\uDC03\"],\"Animals & Nature\",590,[\"water_buffalo\"],10,60,\"1.0\",\"animal-mammal\"],\n    \"1f404\":[[\"\\uD83D\\uDC04\"],\"Animals & Nature\",591,[\"cow2\"],10,61,\"1.0\",\"animal-mammal\"],\n    \"1f405\":[[\"\\uD83D\\uDC05\"],\"Animals & Nature\",578,[\"tiger2\"],11,0,\"1.0\",\"animal-mammal\"],\n    \"1f406\":[[\"\\uD83D\\uDC06\"],\"Animals & Nature\",579,[\"leopard\"],11,1,\"1.0\",\"animal-mammal\"],\n    \"1f407\":[[\"\\uD83D\\uDC07\"],\"Animals & Nature\",612,[\"rabbit2\"],11,2,\"1.0\",\"animal-mammal\"],\n    \"1f408-200d-2b1b\":[[\"\\uD83D\\uDC08\\u200D\\u2B1B\"],\"Animals & Nature\",575,[\"black_cat\"],11,3,\"13.0\",\"animal-mammal\"],\n    \"1f408\":[[\"\\uD83D\\uDC08\"],\"Animals & Nature\",574,[\"cat2\"],11,4,\"0.7\",\"animal-mammal\"],\n    \"1f409\":[[\"\\uD83D\\uDC09\"],\"Animals & Nature\",655,[\"dragon\"],11,5,\"1.0\",\"animal-reptile\"],\n    \"1f40a\":[[\"\\uD83D\\uDC0A\"],\"Animals & Nature\",650,[\"crocodile\"],11,6,\"1.0\",\"animal-reptile\"],\n    \"1f40b\":[[\"\\uD83D\\uDC0B\"],\"Animals & Nature\",659,[\"whale2\"],11,7,\"1.0\",\"animal-marine\"],\n    \"1f40c\":[[\"\\uD83D\\uDC0C\"],\"Animals & Nature\",675,[\"snail\"],11,8,\"0.6\",\"animal-bug\"],\n    \"1f40d\":[[\"\\uD83D\\uDC0D\"],\"Animals & Nature\",653,[\"snake\"],11,9,\"0.6\",\"animal-reptile\"],\n    \"1f40e\":[[\"\\uD83D\\uDC0E\"],\"Animals & Nature\",583,[\"racehorse\"],11,10,\"0.6\",\"animal-mammal\"],\n    \"1f40f\":[[\"\\uD83D\\uDC0F\"],\"Animals & Nature\",596,[\"ram\"],11,11,\"1.0\",\"animal-mammal\"],\n    \"1f410\":[[\"\\uD83D\\uDC10\"],\"Animals & Nature\",598,[\"goat\"],11,12,\"1.0\",\"animal-mammal\"],\n    \"1f411\":[[\"\\uD83D\\uDC11\"],\"Animals & Nature\",597,[\"sheep\"],11,13,\"0.6\",\"animal-mammal\"],\n    \"1f412\":[[\"\\uD83D\\uDC12\"],\"Animals & Nature\",562,[\"monkey\"],11,14,\"0.6\",\"animal-mammal\"],\n    \"1f413\":[[\"\\uD83D\\uDC13\"],\"Animals & Nature\",629,[\"rooster\"],11,15,\"1.0\",\"animal-bird\"],\n    \"1f414\":[[\"\\uD83D\\uDC14\"],\"Animals & Nature\",628,[\"chicken\"],11,16,\"0.6\",\"animal-bird\"],\n    \"1f415-200d-1f9ba\":[[\"\\uD83D\\uDC15\\u200D\\uD83E\\uDDBA\"],\"Animals & Nature\",568,[\"service_dog\"],11,17,\"12.0\",\"animal-mammal\"],\n    \"1f415\":[[\"\\uD83D\\uDC15\"],\"Animals & Nature\",566,[\"dog2\"],11,18,\"0.7\",\"animal-mammal\"],\n    \"1f416\":[[\"\\uD83D\\uDC16\"],\"Animals & Nature\",593,[\"pig2\"],11,19,\"1.0\",\"animal-mammal\"],\n    \"1f417\":[[\"\\uD83D\\uDC17\"],\"Animals & Nature\",594,[\"boar\"],11,20,\"0.6\",\"animal-mammal\"],\n    \"1f418\":[[\"\\uD83D\\uDC18\"],\"Animals & Nature\",603,[\"elephant\"],11,21,\"0.6\",\"animal-mammal\"],\n    \"1f419\":[[\"\\uD83D\\uDC19\"],\"Animals & Nature\",666,[\"octopus\"],11,22,\"0.6\",\"animal-marine\"],\n    \"1f41a\":[[\"\\uD83D\\uDC1A\"],\"Animals & Nature\",667,[\"shell\"],11,23,\"0.6\",\"animal-marine\"],\n    \"1f41b\":[[\"\\uD83D\\uDC1B\"],\"Animals & Nature\",677,[\"bug\"],11,24,\"0.6\",\"animal-bug\"],\n    \"1f41c\":[[\"\\uD83D\\uDC1C\"],\"Animals & Nature\",678,[\"ant\"],11,25,\"0.6\",\"animal-bug\"],\n    \"1f41d\":[[\"\\uD83D\\uDC1D\"],\"Animals & Nature\",679,[\"bee\",\"honeybee\"],11,26,\"0.6\",\"animal-bug\"],\n    \"1f41e\":[[\"\\uD83D\\uDC1E\"],\"Animals & Nature\",681,[\"ladybug\",\"lady_beetle\"],11,27,\"0.6\",\"animal-bug\"],\n    \"1f41f\":[[\"\\uD83D\\uDC1F\"],\"Animals & Nature\",662,[\"fish\"],11,28,\"0.6\",\"animal-marine\"],\n    \"1f420\":[[\"\\uD83D\\uDC20\"],\"Animals & Nature\",663,[\"tropical_fish\"],11,29,\"0.6\",\"animal-marine\"],\n    \"1f421\":[[\"\\uD83D\\uDC21\"],\"Animals & Nature\",664,[\"blowfish\"],11,30,\"0.6\",\"animal-marine\"],\n    \"1f422\":[[\"\\uD83D\\uDC22\"],\"Animals & Nature\",651,[\"turtle\"],11,31,\"0.6\",\"animal-reptile\"],\n    \"1f423\":[[\"\\uD83D\\uDC23\"],\"Animals & Nature\",630,[\"hatching_chick\"],11,32,\"0.6\",\"animal-bird\"],\n    \"1f424\":[[\"\\uD83D\\uDC24\"],\"Animals & Nature\",631,[\"baby_chick\"],11,33,\"0.6\",\"animal-bird\"],\n    \"1f425\":[[\"\\uD83D\\uDC25\"],\"Animals & Nature\",632,[\"hatched_chick\"],11,34,\"0.6\",\"animal-bird\"],\n    \"1f426-200d-1f525\":[[\"\\uD83D\\uDC26\\u200D\\uD83D\\uDD25\"],\"Animals & Nature\",648,[\"phoenix\"],11,35,\"15.1\",\"animal-bird\"],\n    \"1f426-200d-2b1b\":[[\"\\uD83D\\uDC26\\u200D\\u2B1B\"],\"Animals & Nature\",646,[\"black_bird\"],11,36,\"15.0\",\"animal-bird\"],\n    \"1f426\":[[\"\\uD83D\\uDC26\"],\"Animals & Nature\",633,[\"bird\"],11,37,\"0.6\",\"animal-bird\"],\n    \"1f427\":[[\"\\uD83D\\uDC27\"],\"Animals & Nature\",634,[\"penguin\"],11,38,\"0.6\",\"animal-bird\"],\n    \"1f428\":[[\"\\uD83D\\uDC28\"],\"Animals & Nature\",619,[\"koala\"],11,39,\"0.6\",\"animal-mammal\"],\n    \"1f429\":[[\"\\uD83D\\uDC29\"],\"Animals & Nature\",569,[\"poodle\"],11,40,\"0.6\",\"animal-mammal\"],\n    \"1f42a\":[[\"\\uD83D\\uDC2A\"],\"Animals & Nature\",599,[\"dromedary_camel\"],11,41,\"1.0\",\"animal-mammal\"],\n    \"1f42b\":[[\"\\uD83D\\uDC2B\"],\"Animals & Nature\",600,[\"camel\"],11,42,\"0.6\",\"animal-mammal\"],\n    \"1f42c\":[[\"\\uD83D\\uDC2C\"],\"Animals & Nature\",660,[\"dolphin\",\"flipper\"],11,43,\"0.6\",\"animal-marine\"],\n    \"1f42d\":[[\"\\uD83D\\uDC2D\"],\"Animals & Nature\",607,[\"mouse\"],11,44,\"0.6\",\"animal-mammal\"],\n    \"1f42e\":[[\"\\uD83D\\uDC2E\"],\"Animals & Nature\",588,[\"cow\"],11,45,\"0.6\",\"animal-mammal\"],\n    \"1f42f\":[[\"\\uD83D\\uDC2F\"],\"Animals & Nature\",577,[\"tiger\"],11,46,\"0.6\",\"animal-mammal\"],\n    \"1f430\":[[\"\\uD83D\\uDC30\"],\"Animals & Nature\",611,[\"rabbit\"],11,47,\"0.6\",\"animal-mammal\"],\n    \"1f431\":[[\"\\uD83D\\uDC31\"],\"Animals & Nature\",573,[\"cat\"],11,48,\"0.6\",\"animal-mammal\"],\n    \"1f432\":[[\"\\uD83D\\uDC32\"],\"Animals & Nature\",654,[\"dragon_face\"],11,49,\"0.6\",\"animal-reptile\"],\n    \"1f433\":[[\"\\uD83D\\uDC33\"],\"Animals & Nature\",658,[\"whale\"],11,50,\"0.6\",\"animal-marine\"],\n    \"1f434\":[[\"\\uD83D\\uDC34\"],\"Animals & Nature\",580,[\"horse\"],11,51,\"0.6\",\"animal-mammal\"],\n    \"1f435\":[[\"\\uD83D\\uDC35\"],\"Animals & Nature\",561,[\"monkey_face\"],11,52,\"0.6\",\"animal-mammal\"],\n    \"1f436\":[[\"\\uD83D\\uDC36\"],\"Animals & Nature\",565,[\"dog\"],11,53,\"0.6\",\"animal-mammal\"],\n    \"1f437\":[[\"\\uD83D\\uDC37\"],\"Animals & Nature\",592,[\"pig\"],11,54,\"0.6\",\"animal-mammal\"],\n    \"1f438\":[[\"\\uD83D\\uDC38\"],\"Animals & Nature\",649,[\"frog\"],11,55,\"0.6\",\"animal-amphibian\"],\n    \"1f439\":[[\"\\uD83D\\uDC39\"],\"Animals & Nature\",610,[\"hamster\"],11,56,\"0.6\",\"animal-mammal\"],\n    \"1f43a\":[[\"\\uD83D\\uDC3A\"],\"Animals & Nature\",570,[\"wolf\"],11,57,\"0.6\",\"animal-mammal\"],\n    \"1f43b-200d-2744-fe0f\":[[\"\\uD83D\\uDC3B\\u200D\\u2744\\uFE0F\"],\"Animals & Nature\",618,[\"polar_bear\"],11,58,\"13.0\",\"animal-mammal\"],\n    \"1f43b\":[[\"\\uD83D\\uDC3B\"],\"Animals & Nature\",617,[\"bear\"],11,59,\"0.6\",\"animal-mammal\"],\n    \"1f43c\":[[\"\\uD83D\\uDC3C\"],\"Animals & Nature\",620,[\"panda_face\"],11,60,\"0.6\",\"animal-mammal\"],\n    \"1f43d\":[[\"\\uD83D\\uDC3D\"],\"Animals & Nature\",595,[\"pig_nose\"],11,61,\"0.6\",\"animal-mammal\"],\n    \"1f43e\":[[\"\\uD83D\\uDC3E\"],\"Animals & Nature\",626,[\"feet\",\"paw_prints\"],12,0,\"0.6\",\"animal-mammal\"],\n    \"1f43f-fe0f\":[[\"\\uD83D\\uDC3F\\uFE0F\"],\"Animals & Nature\",613,[\"chipmunk\"],12,1,\"0.7\",\"animal-mammal\"],\n    \"1f440\":[[\"\\uD83D\\uDC40\"],\"People & Body\",226,[\"eyes\"],12,2,\"0.6\",\"body-parts\"],\n    \"1f441-fe0f-200d-1f5e8-fe0f\":[[\"\\uD83D\\uDC41\\uFE0F\\u200D\\uD83D\\uDDE8\\uFE0F\"],\"Smileys & Emotion\",165,[\"eye-in-speech-bubble\"],12,3,\"2.0\",\"emotion\"],\n    \"1f441-fe0f\":[[\"\\uD83D\\uDC41\\uFE0F\"],\"People & Body\",227,[\"eye\"],12,4,\"0.7\",\"body-parts\"],\n    \"1f442\":[[\"\\uD83D\\uDC42\"],\"People & Body\",218,[\"ear\"],12,5,\"0.6\",\"body-parts\"],\n    \"1f443\":[[\"\\uD83D\\uDC43\"],\"People & Body\",220,[\"nose\"],12,11,\"0.6\",\"body-parts\"],\n    \"1f444\":[[\"\\uD83D\\uDC44\"],\"People & Body\",229,[\"lips\"],12,17,\"0.6\",\"body-parts\"],\n    \"1f445\":[[\"\\uD83D\\uDC45\"],\"People & Body\",228,[\"tongue\"],12,18,\"0.6\",\"body-parts\"],\n    \"1f446\":[[\"\\uD83D\\uDC46\"],\"People & Body\",192,[\"point_up_2\"],12,19,\"0.6\",\"hand-single-finger\"],\n    \"1f447\":[[\"\\uD83D\\uDC47\"],\"People & Body\",194,[\"point_down\"],12,25,\"0.6\",\"hand-single-finger\"],\n    \"1f448\":[[\"\\uD83D\\uDC48\"],\"People & Body\",190,[\"point_left\"],12,31,\"0.6\",\"hand-single-finger\"],\n    \"1f449\":[[\"\\uD83D\\uDC49\"],\"People & Body\",191,[\"point_right\"],12,37,\"0.6\",\"hand-single-finger\"],\n    \"1f44a\":[[\"\\uD83D\\uDC4A\"],\"People & Body\",200,[\"facepunch\",\"punch\"],12,43,\"0.6\",\"hand-fingers-closed\"],\n    \"1f44b\":[[\"\\uD83D\\uDC4B\"],\"People & Body\",170,[\"wave\"],12,49,\"0.6\",\"hand-fingers-open\"],\n    \"1f44c\":[[\"\\uD83D\\uDC4C\"],\"People & Body\",181,[\"ok_hand\"],12,55,\"0.6\",\"hand-fingers-partial\"],\n    \"1f44d\":[[\"\\uD83D\\uDC4D\"],\"People & Body\",197,[\"+1\",\"thumbsup\"],12,61,\"0.6\",\"hand-fingers-closed\"],\n    \"1f44e\":[[\"\\uD83D\\uDC4E\"],\"People & Body\",198,[\"-1\",\"thumbsdown\"],13,5,\"0.6\",\"hand-fingers-closed\"],\n    \"1f44f\":[[\"\\uD83D\\uDC4F\"],\"People & Body\",203,[\"clap\"],13,11,\"0.6\",\"hands\"],\n    \"1f450\":[[\"\\uD83D\\uDC50\"],\"People & Body\",206,[\"open_hands\"],13,17,\"0.6\",\"hands\"],\n    \"1f451\":[[\"\\uD83D\\uDC51\"],\"Objects\",1190,[\"crown\"],13,23,\"0.6\",\"clothing\"],\n    \"1f452\":[[\"\\uD83D\\uDC52\"],\"Objects\",1191,[\"womans_hat\"],13,24,\"0.6\",\"clothing\"],\n    \"1f453\":[[\"\\uD83D\\uDC53\"],\"Objects\",1154,[\"eyeglasses\"],13,25,\"0.6\",\"clothing\"],\n    \"1f454\":[[\"\\uD83D\\uDC54\"],\"Objects\",1159,[\"necktie\"],13,26,\"0.6\",\"clothing\"],\n    \"1f455\":[[\"\\uD83D\\uDC55\"],\"Objects\",1160,[\"shirt\",\"tshirt\"],13,27,\"0.6\",\"clothing\"],\n    \"1f456\":[[\"\\uD83D\\uDC56\"],\"Objects\",1161,[\"jeans\"],13,28,\"0.6\",\"clothing\"],\n    \"1f457\":[[\"\\uD83D\\uDC57\"],\"Objects\",1166,[\"dress\"],13,29,\"0.6\",\"clothing\"],\n    \"1f458\":[[\"\\uD83D\\uDC58\"],\"Objects\",1167,[\"kimono\"],13,30,\"0.6\",\"clothing\"],\n    \"1f459\":[[\"\\uD83D\\uDC59\"],\"Objects\",1172,[\"bikini\"],13,31,\"0.6\",\"clothing\"],\n    \"1f45a\":[[\"\\uD83D\\uDC5A\"],\"Objects\",1173,[\"womans_clothes\"],13,32,\"0.6\",\"clothing\"],\n    \"1f45b\":[[\"\\uD83D\\uDC5B\"],\"Objects\",1175,[\"purse\"],13,33,\"0.6\",\"clothing\"],\n    \"1f45c\":[[\"\\uD83D\\uDC5C\"],\"Objects\",1176,[\"handbag\"],13,34,\"0.6\",\"clothing\"],\n    \"1f45d\":[[\"\\uD83D\\uDC5D\"],\"Objects\",1177,[\"pouch\"],13,35,\"0.6\",\"clothing\"],\n    \"1f45e\":[[\"\\uD83D\\uDC5E\"],\"Objects\",1181,[\"mans_shoe\",\"shoe\"],13,36,\"0.6\",\"clothing\"],\n    \"1f45f\":[[\"\\uD83D\\uDC5F\"],\"Objects\",1182,[\"athletic_shoe\"],13,37,\"0.6\",\"clothing\"],\n    \"1f460\":[[\"\\uD83D\\uDC60\"],\"Objects\",1185,[\"high_heel\"],13,38,\"0.6\",\"clothing\"],\n    \"1f461\":[[\"\\uD83D\\uDC61\"],\"Objects\",1186,[\"sandal\"],13,39,\"0.6\",\"clothing\"],\n    \"1f462\":[[\"\\uD83D\\uDC62\"],\"Objects\",1188,[\"boot\"],13,40,\"0.6\",\"clothing\"],\n    \"1f463\":[[\"\\uD83D\\uDC63\"],\"People & Body\",554,[\"footprints\"],13,41,\"0.6\",\"person-symbol\"],\n    \"1f464\":[[\"\\uD83D\\uDC64\"],\"People & Body\",546,[\"bust_in_silhouette\"],13,42,\"0.6\",\"person-symbol\"],\n    \"1f465\":[[\"\\uD83D\\uDC65\"],\"People & Body\",547,[\"busts_in_silhouette\"],13,43,\"1.0\",\"person-symbol\"],\n    \"1f466\":[[\"\\uD83D\\uDC66\"],\"People & Body\",233,[\"boy\"],13,44,\"0.6\",\"person\"],\n    \"1f467\":[[\"\\uD83D\\uDC67\"],\"People & Body\",234,[\"girl\"],13,50,\"0.6\",\"person\"],\n    \"1f468-200d-1f33e\":[[\"\\uD83D\\uDC68\\u200D\\uD83C\\uDF3E\"],\"People & Body\",302,[\"male-farmer\"],13,56,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f373\":[[\"\\uD83D\\uDC68\\u200D\\uD83C\\uDF73\"],\"People & Body\",305,[\"male-cook\"],14,0,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f37c\":[[\"\\uD83D\\uDC68\\u200D\\uD83C\\uDF7C\"],\"People & Body\",369,[\"man_feeding_baby\"],14,6,\"13.0\",\"person-role\"],\n    \"1f468-200d-1f393\":[[\"\\uD83D\\uDC68\\u200D\\uD83C\\uDF93\"],\"People & Body\",293,[\"male-student\"],14,12,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f3a4\":[[\"\\uD83D\\uDC68\\u200D\\uD83C\\uDFA4\"],\"People & Body\",323,[\"male-singer\"],14,18,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f3a8\":[[\"\\uD83D\\uDC68\\u200D\\uD83C\\uDFA8\"],\"People & Body\",326,[\"male-artist\"],14,24,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f3eb\":[[\"\\uD83D\\uDC68\\u200D\\uD83C\\uDFEB\"],\"People & Body\",296,[\"male-teacher\"],14,30,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f3ed\":[[\"\\uD83D\\uDC68\\u200D\\uD83C\\uDFED\"],\"People & Body\",311,[\"male-factory-worker\"],14,36,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f466-200d-1f466\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66\"],\"People & Body\",536,[\"man-boy-boy\"],14,42,\"4.0\",\"family\"],\n    \"1f468-200d-1f466\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC66\"],\"People & Body\",535,[\"man-boy\"],14,43,\"4.0\",\"family\"],\n    \"1f468-200d-1f467-200d-1f466\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66\"],\"People & Body\",538,[\"man-girl-boy\"],14,44,\"4.0\",\"family\"],\n    \"1f468-200d-1f467-200d-1f467\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67\"],\"People & Body\",539,[\"man-girl-girl\"],14,45,\"4.0\",\"family\"],\n    \"1f468-200d-1f467\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC67\"],\"People & Body\",537,[\"man-girl\"],14,46,\"4.0\",\"family\"],\n    \"1f468-200d-1f468-200d-1f466\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC66\"],\"People & Body\",525,[\"man-man-boy\"],14,47,\"2.0\",\"family\"],\n    \"1f468-200d-1f468-200d-1f466-200d-1f466\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66\"],\"People & Body\",528,[\"man-man-boy-boy\"],14,48,\"2.0\",\"family\"],\n    \"1f468-200d-1f468-200d-1f467\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC67\"],\"People & Body\",526,[\"man-man-girl\"],14,49,\"2.0\",\"family\"],\n    \"1f468-200d-1f468-200d-1f467-200d-1f466\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66\"],\"People & Body\",527,[\"man-man-girl-boy\"],14,50,\"2.0\",\"family\"],\n    \"1f468-200d-1f468-200d-1f467-200d-1f467\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67\"],\"People & Body\",529,[\"man-man-girl-girl\"],14,51,\"2.0\",\"family\"],\n    \"1f468-200d-1f469-200d-1f466\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\",\"\\uD83D\\uDC6A\"],\"People & Body\",520,[\"man-woman-boy\",\"family\"],14,52,\"2.0\",\"family\"],\n    \"1f468-200d-1f469-200d-1f466-200d-1f466\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66\"],\"People & Body\",523,[\"man-woman-boy-boy\"],14,53,\"2.0\",\"family\"],\n    \"1f468-200d-1f469-200d-1f467\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\"],\"People & Body\",521,[\"man-woman-girl\"],14,54,\"2.0\",\"family\"],\n    \"1f468-200d-1f469-200d-1f467-200d-1f466\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66\"],\"People & Body\",522,[\"man-woman-girl-boy\"],14,55,\"2.0\",\"family\"],\n    \"1f468-200d-1f469-200d-1f467-200d-1f467\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67\"],\"People & Body\",524,[\"man-woman-girl-girl\"],14,56,\"2.0\",\"family\"],\n    \"1f468-200d-1f4bb\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDCBB\"],\"People & Body\",320,[\"male-technologist\"],14,57,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f4bc\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDCBC\"],\"People & Body\",314,[\"male-office-worker\"],15,1,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f527\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDD27\"],\"People & Body\",308,[\"male-mechanic\"],15,7,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f52c\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDD2C\"],\"People & Body\",317,[\"male-scientist\"],15,13,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f680\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDE80\"],\"People & Body\",332,[\"male-astronaut\"],15,19,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f692\":[[\"\\uD83D\\uDC68\\u200D\\uD83D\\uDE92\"],\"People & Body\",335,[\"male-firefighter\"],15,25,\"4.0\",\"person-role\"],\n    \"1f468-200d-1f9af-200d-27a1-fe0f\":[[\"\\uD83D\\uDC68\\u200D\\uD83E\\uDDAF\\u200D\\u27A1\\uFE0F\"],\"People & Body\",427,[\"man_with_white_cane_facing_right\"],15,31,\"15.1\",\"person-activity\"],\n    \"1f468-200d-1f9af\":[[\"\\uD83D\\uDC68\\u200D\\uD83E\\uDDAF\"],\"People & Body\",426,[\"man_with_probing_cane\"],15,37,\"12.0\",\"person-activity\"],\n    \"1f468-200d-1f9b0\":[[\"\\uD83D\\uDC68\\u200D\\uD83E\\uDDB0\"],\"People & Body\",241,[\"red_haired_man\"],15,43,\"11.0\",\"person\"],\n    \"1f468-200d-1f9b1\":[[\"\\uD83D\\uDC68\\u200D\\uD83E\\uDDB1\"],\"People & Body\",242,[\"curly_haired_man\"],15,49,\"11.0\",\"person\"],\n    \"1f468-200d-1f9b2\":[[\"\\uD83D\\uDC68\\u200D\\uD83E\\uDDB2\"],\"People & Body\",244,[\"bald_man\"],15,55,\"11.0\",\"person\"],\n    \"1f468-200d-1f9b3\":[[\"\\uD83D\\uDC68\\u200D\\uD83E\\uDDB3\"],\"People & Body\",243,[\"white_haired_man\"],15,61,\"11.0\",\"person\"],\n    \"1f468-200d-1f9bc-200d-27a1-fe0f\":[[\"\\uD83D\\uDC68\\u200D\\uD83E\\uDDBC\\u200D\\u27A1\\uFE0F\"],\"People & Body\",433,[\"man_in_motorized_wheelchair_facing_right\"],16,5,\"15.1\",\"person-activity\"],\n    \"1f468-200d-1f9bc\":[[\"\\uD83D\\uDC68\\u200D\\uD83E\\uDDBC\"],\"People & Body\",432,[\"man_in_motorized_wheelchair\"],16,11,\"12.0\",\"person-activity\"],\n    \"1f468-200d-1f9bd-200d-27a1-fe0f\":[[\"\\uD83D\\uDC68\\u200D\\uD83E\\uDDBD\\u200D\\u27A1\\uFE0F\"],\"People & Body\",439,[\"man_in_manual_wheelchair_facing_right\"],16,17,\"15.1\",\"person-activity\"],\n    \"1f468-200d-1f9bd\":[[\"\\uD83D\\uDC68\\u200D\\uD83E\\uDDBD\"],\"People & Body\",438,[\"man_in_manual_wheelchair\"],16,23,\"12.0\",\"person-activity\"],\n    \"1f468-200d-2695-fe0f\":[[\"\\uD83D\\uDC68\\u200D\\u2695\\uFE0F\"],\"People & Body\",290,[\"male-doctor\"],16,29,\"4.0\",\"person-role\"],\n    \"1f468-200d-2696-fe0f\":[[\"\\uD83D\\uDC68\\u200D\\u2696\\uFE0F\"],\"People & Body\",299,[\"male-judge\"],16,35,\"4.0\",\"person-role\"],\n    \"1f468-200d-2708-fe0f\":[[\"\\uD83D\\uDC68\\u200D\\u2708\\uFE0F\"],\"People & Body\",329,[\"male-pilot\"],16,41,\"4.0\",\"person-role\"],\n    \"1f468-200d-2764-fe0f-200d-1f468\":[[\"\\uD83D\\uDC68\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC68\"],\"People & Body\",518,[\"man-heart-man\"],16,47,\"2.0\",\"family\"],\n    \"1f468-200d-2764-fe0f-200d-1f48b-200d-1f468\":[[\"\\uD83D\\uDC68\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC8B\\u200D\\uD83D\\uDC68\"],\"People & Body\",514,[\"man-kiss-man\"],17,11,\"2.0\",\"family\"],\n    \"1f468\":[[\"\\uD83D\\uDC68\"],\"People & Body\",237,[\"man\"],17,37,\"0.6\",\"person\"],\n    \"1f469-200d-1f33e\":[[\"\\uD83D\\uDC69\\u200D\\uD83C\\uDF3E\"],\"People & Body\",303,[\"female-farmer\"],17,43,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f373\":[[\"\\uD83D\\uDC69\\u200D\\uD83C\\uDF73\"],\"People & Body\",306,[\"female-cook\"],17,49,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f37c\":[[\"\\uD83D\\uDC69\\u200D\\uD83C\\uDF7C\"],\"People & Body\",368,[\"woman_feeding_baby\"],17,55,\"13.0\",\"person-role\"],\n    \"1f469-200d-1f393\":[[\"\\uD83D\\uDC69\\u200D\\uD83C\\uDF93\"],\"People & Body\",294,[\"female-student\"],17,61,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f3a4\":[[\"\\uD83D\\uDC69\\u200D\\uD83C\\uDFA4\"],\"People & Body\",324,[\"female-singer\"],18,5,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f3a8\":[[\"\\uD83D\\uDC69\\u200D\\uD83C\\uDFA8\"],\"People & Body\",327,[\"female-artist\"],18,11,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f3eb\":[[\"\\uD83D\\uDC69\\u200D\\uD83C\\uDFEB\"],\"People & Body\",297,[\"female-teacher\"],18,17,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f3ed\":[[\"\\uD83D\\uDC69\\u200D\\uD83C\\uDFED\"],\"People & Body\",312,[\"female-factory-worker\"],18,23,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f466-200d-1f466\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66\"],\"People & Body\",541,[\"woman-boy-boy\"],18,29,\"4.0\",\"family\"],\n    \"1f469-200d-1f466\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\"],\"People & Body\",540,[\"woman-boy\"],18,30,\"4.0\",\"family\"],\n    \"1f469-200d-1f467-200d-1f466\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66\"],\"People & Body\",543,[\"woman-girl-boy\"],18,31,\"4.0\",\"family\"],\n    \"1f469-200d-1f467-200d-1f467\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67\"],\"People & Body\",544,[\"woman-girl-girl\"],18,32,\"4.0\",\"family\"],\n    \"1f469-200d-1f467\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\"],\"People & Body\",542,[\"woman-girl\"],18,33,\"4.0\",\"family\"],\n    \"1f469-200d-1f469-200d-1f466\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\"],\"People & Body\",530,[\"woman-woman-boy\"],18,34,\"2.0\",\"family\"],\n    \"1f469-200d-1f469-200d-1f466-200d-1f466\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66\"],\"People & Body\",533,[\"woman-woman-boy-boy\"],18,35,\"2.0\",\"family\"],\n    \"1f469-200d-1f469-200d-1f467\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\"],\"People & Body\",531,[\"woman-woman-girl\"],18,36,\"2.0\",\"family\"],\n    \"1f469-200d-1f469-200d-1f467-200d-1f466\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66\"],\"People & Body\",532,[\"woman-woman-girl-boy\"],18,37,\"2.0\",\"family\"],\n    \"1f469-200d-1f469-200d-1f467-200d-1f467\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67\"],\"People & Body\",534,[\"woman-woman-girl-girl\"],18,38,\"2.0\",\"family\"],\n    \"1f469-200d-1f4bb\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDCBB\"],\"People & Body\",321,[\"female-technologist\"],18,39,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f4bc\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDCBC\"],\"People & Body\",315,[\"female-office-worker\"],18,45,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f527\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDD27\"],\"People & Body\",309,[\"female-mechanic\"],18,51,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f52c\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDD2C\"],\"People & Body\",318,[\"female-scientist\"],18,57,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f680\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDE80\"],\"People & Body\",333,[\"female-astronaut\"],19,1,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f692\":[[\"\\uD83D\\uDC69\\u200D\\uD83D\\uDE92\"],\"People & Body\",336,[\"female-firefighter\"],19,7,\"4.0\",\"person-role\"],\n    \"1f469-200d-1f9af-200d-27a1-fe0f\":[[\"\\uD83D\\uDC69\\u200D\\uD83E\\uDDAF\\u200D\\u27A1\\uFE0F\"],\"People & Body\",429,[\"woman_with_white_cane_facing_right\"],19,13,\"15.1\",\"person-activity\"],\n    \"1f469-200d-1f9af\":[[\"\\uD83D\\uDC69\\u200D\\uD83E\\uDDAF\"],\"People & Body\",428,[\"woman_with_probing_cane\"],19,19,\"12.0\",\"person-activity\"],\n    \"1f469-200d-1f9b0\":[[\"\\uD83D\\uDC69\\u200D\\uD83E\\uDDB0\"],\"People & Body\",246,[\"red_haired_woman\"],19,25,\"11.0\",\"person\"],\n    \"1f469-200d-1f9b1\":[[\"\\uD83D\\uDC69\\u200D\\uD83E\\uDDB1\"],\"People & Body\",248,[\"curly_haired_woman\"],19,31,\"11.0\",\"person\"],\n    \"1f469-200d-1f9b2\":[[\"\\uD83D\\uDC69\\u200D\\uD83E\\uDDB2\"],\"People & Body\",252,[\"bald_woman\"],19,37,\"11.0\",\"person\"],\n    \"1f469-200d-1f9b3\":[[\"\\uD83D\\uDC69\\u200D\\uD83E\\uDDB3\"],\"People & Body\",250,[\"white_haired_woman\"],19,43,\"11.0\",\"person\"],\n    \"1f469-200d-1f9bc-200d-27a1-fe0f\":[[\"\\uD83D\\uDC69\\u200D\\uD83E\\uDDBC\\u200D\\u27A1\\uFE0F\"],\"People & Body\",435,[\"woman_in_motorized_wheelchair_facing_right\"],19,49,\"15.1\",\"person-activity\"],\n    \"1f469-200d-1f9bc\":[[\"\\uD83D\\uDC69\\u200D\\uD83E\\uDDBC\"],\"People & Body\",434,[\"woman_in_motorized_wheelchair\"],19,55,\"12.0\",\"person-activity\"],\n    \"1f469-200d-1f9bd-200d-27a1-fe0f\":[[\"\\uD83D\\uDC69\\u200D\\uD83E\\uDDBD\\u200D\\u27A1\\uFE0F\"],\"People & Body\",441,[\"woman_in_manual_wheelchair_facing_right\"],19,61,\"15.1\",\"person-activity\"],\n    \"1f469-200d-1f9bd\":[[\"\\uD83D\\uDC69\\u200D\\uD83E\\uDDBD\"],\"People & Body\",440,[\"woman_in_manual_wheelchair\"],20,5,\"12.0\",\"person-activity\"],\n    \"1f469-200d-2695-fe0f\":[[\"\\uD83D\\uDC69\\u200D\\u2695\\uFE0F\"],\"People & Body\",291,[\"female-doctor\"],20,11,\"4.0\",\"person-role\"],\n    \"1f469-200d-2696-fe0f\":[[\"\\uD83D\\uDC69\\u200D\\u2696\\uFE0F\"],\"People & Body\",300,[\"female-judge\"],20,17,\"4.0\",\"person-role\"],\n    \"1f469-200d-2708-fe0f\":[[\"\\uD83D\\uDC69\\u200D\\u2708\\uFE0F\"],\"People & Body\",330,[\"female-pilot\"],20,23,\"4.0\",\"person-role\"],\n    \"1f469-200d-2764-fe0f-200d-1f468\":[[\"\\uD83D\\uDC69\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC68\"],\"People & Body\",517,[\"woman-heart-man\"],20,29,\"2.0\",\"family\"],\n    \"1f469-200d-2764-fe0f-200d-1f469\":[[\"\\uD83D\\uDC69\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC69\"],\"People & Body\",519,[\"woman-heart-woman\"],20,55,\"2.0\",\"family\"],\n    \"1f469-200d-2764-fe0f-200d-1f48b-200d-1f468\":[[\"\\uD83D\\uDC69\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC8B\\u200D\\uD83D\\uDC68\"],\"People & Body\",513,[\"woman-kiss-man\"],21,19,\"2.0\",\"family\"],\n    \"1f469-200d-2764-fe0f-200d-1f48b-200d-1f469\":[[\"\\uD83D\\uDC69\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC8B\\u200D\\uD83D\\uDC69\"],\"People & Body\",515,[\"woman-kiss-woman\"],21,45,\"2.0\",\"family\"],\n    \"1f469\":[[\"\\uD83D\\uDC69\"],\"People & Body\",245,[\"woman\"],22,9,\"0.6\",\"person\"],\n    \"1f46b\":[[\"\\uD83D\\uDC6B\"],\"People & Body\",510,[\"man_and_woman_holding_hands\",\"woman_and_man_holding_hands\",\"couple\"],22,16,\"0.6\",\"family\"],\n    \"1f46c\":[[\"\\uD83D\\uDC6C\"],\"People & Body\",511,[\"two_men_holding_hands\",\"men_holding_hands\"],22,42,\"1.0\",\"family\"],\n    \"1f46d\":[[\"\\uD83D\\uDC6D\"],\"People & Body\",509,[\"two_women_holding_hands\",\"women_holding_hands\"],23,6,\"1.0\",\"family\"],\n    \"1f46e-200d-2640-fe0f\":[[\"\\uD83D\\uDC6E\\u200D\\u2640\\uFE0F\"],\"People & Body\",339,[\"female-police-officer\"],23,32,\"4.0\",\"person-role\"],\n    \"1f46e-200d-2642-fe0f\":[[\"\\uD83D\\uDC6E\\u200D\\u2642\\uFE0F\",\"\\uD83D\\uDC6E\"],\"People & Body\",338,[\"male-police-officer\",\"cop\"],23,38,\"4.0\",\"person-role\"],\n    \"1f46f-200d-2640-fe0f\":[[\"\\uD83D\\uDC6F\\u200D\\u2640\\uFE0F\",\"\\uD83D\\uDC6F\"],\"People & Body\",453,[\"women-with-bunny-ears-partying\",\"woman-with-bunny-ears-partying\",\"dancers\"],23,50,\"4.0\",\"person-activity\"],\n    \"1f46f-200d-2642-fe0f\":[[\"\\uD83D\\uDC6F\\u200D\\u2642\\uFE0F\"],\"People & Body\",452,[\"men-with-bunny-ears-partying\",\"man-with-bunny-ears-partying\"],23,51,\"4.0\",\"person-activity\"],\n    \"1f470-200d-2640-fe0f\":[[\"\\uD83D\\uDC70\\u200D\\u2640\\uFE0F\"],\"People & Body\",363,[\"woman_with_veil\"],23,53,\"13.0\",\"person-role\"],\n    \"1f470-200d-2642-fe0f\":[[\"\\uD83D\\uDC70\\u200D\\u2642\\uFE0F\"],\"People & Body\",362,[\"man_with_veil\"],23,59,\"13.0\",\"person-role\"],\n    \"1f470\":[[\"\\uD83D\\uDC70\"],\"People & Body\",361,[\"bride_with_veil\"],24,3,\"0.6\",\"person-role\"],\n    \"1f471-200d-2640-fe0f\":[[\"\\uD83D\\uDC71\\u200D\\u2640\\uFE0F\"],\"People & Body\",254,[\"blond-haired-woman\"],24,9,\"4.0\",\"person\"],\n    \"1f471-200d-2642-fe0f\":[[\"\\uD83D\\uDC71\\u200D\\u2642\\uFE0F\",\"\\uD83D\\uDC71\"],\"People & Body\",255,[\"blond-haired-man\",\"person_with_blond_hair\"],24,15,\"4.0\",\"person\"],\n    \"1f472\":[[\"\\uD83D\\uDC72\"],\"People & Body\",356,[\"man_with_gua_pi_mao\"],24,27,\"0.6\",\"person-role\"],\n    \"1f473-200d-2640-fe0f\":[[\"\\uD83D\\uDC73\\u200D\\u2640\\uFE0F\"],\"People & Body\",355,[\"woman-wearing-turban\"],24,33,\"4.0\",\"person-role\"],\n    \"1f473-200d-2642-fe0f\":[[\"\\uD83D\\uDC73\\u200D\\u2642\\uFE0F\",\"\\uD83D\\uDC73\"],\"People & Body\",354,[\"man-wearing-turban\",\"man_with_turban\"],24,39,\"4.0\",\"person-role\"],\n    \"1f474\":[[\"\\uD83D\\uDC74\"],\"People & Body\",257,[\"older_man\"],24,51,\"0.6\",\"person\"],\n    \"1f475\":[[\"\\uD83D\\uDC75\"],\"People & Body\",258,[\"older_woman\"],24,57,\"0.6\",\"person\"],\n    \"1f476\":[[\"\\uD83D\\uDC76\"],\"People & Body\",231,[\"baby\"],25,1,\"0.6\",\"person\"],\n    \"1f477-200d-2640-fe0f\":[[\"\\uD83D\\uDC77\\u200D\\u2640\\uFE0F\"],\"People & Body\",349,[\"female-construction-worker\"],25,7,\"4.0\",\"person-role\"],\n    \"1f477-200d-2642-fe0f\":[[\"\\uD83D\\uDC77\\u200D\\u2642\\uFE0F\",\"\\uD83D\\uDC77\"],\"People & Body\",348,[\"male-construction-worker\",\"construction_worker\"],25,13,\"4.0\",\"person-role\"],\n    \"1f478\":[[\"\\uD83D\\uDC78\"],\"People & Body\",352,[\"princess\"],25,25,\"0.6\",\"person-role\"],\n    \"1f479\":[[\"\\uD83D\\uDC79\"],\"Smileys & Emotion\",113,[\"japanese_ogre\"],25,31,\"0.6\",\"face-costume\"],\n    \"1f47a\":[[\"\\uD83D\\uDC7A\"],\"Smileys & Emotion\",114,[\"japanese_goblin\"],25,32,\"0.6\",\"face-costume\"],\n    \"1f47b\":[[\"\\uD83D\\uDC7B\"],\"Smileys & Emotion\",115,[\"ghost\"],25,33,\"0.6\",\"face-costume\"],\n    \"1f47c\":[[\"\\uD83D\\uDC7C\"],\"People & Body\",371,[\"angel\"],25,34,\"0.6\",\"person-fantasy\"],\n    \"1f47d\":[[\"\\uD83D\\uDC7D\"],\"Smileys & Emotion\",116,[\"alien\"],25,40,\"0.6\",\"face-costume\"],\n    \"1f47e\":[[\"\\uD83D\\uDC7E\"],\"Smileys & Emotion\",117,[\"space_invader\"],25,41,\"0.6\",\"face-costume\"],\n    \"1f47f\":[[\"\\uD83D\\uDC7F\"],\"Smileys & Emotion\",108,[\"imp\"],25,42,\"0.6\",\"face-negative\"],\n    \"1f480\":[[\"\\uD83D\\uDC80\"],\"Smileys & Emotion\",109,[\"skull\"],25,43,\"0.6\",\"face-negative\"],\n    \"1f481-200d-2640-fe0f\":[[\"\\uD83D\\uDC81\\u200D\\u2640\\uFE0F\",\"\\uD83D\\uDC81\"],\"People & Body\",273,[\"woman-tipping-hand\",\"information_desk_person\"],25,44,\"4.0\",\"person-gesture\"],\n    \"1f481-200d-2642-fe0f\":[[\"\\uD83D\\uDC81\\u200D\\u2642\\uFE0F\"],\"People & Body\",272,[\"man-tipping-hand\"],25,50,\"4.0\",\"person-gesture\"],\n    \"1f482-200d-2640-fe0f\":[[\"\\uD83D\\uDC82\\u200D\\u2640\\uFE0F\"],\"People & Body\",345,[\"female-guard\"],26,0,\"4.0\",\"person-role\"],\n    \"1f482-200d-2642-fe0f\":[[\"\\uD83D\\uDC82\\u200D\\u2642\\uFE0F\",\"\\uD83D\\uDC82\"],\"People & Body\",344,[\"male-guard\",\"guardsman\"],26,6,\"4.0\",\"person-role\"],\n    \"1f483\":[[\"\\uD83D\\uDC83\"],\"People & Body\",448,[\"dancer\"],26,18,\"0.6\",\"person-activity\"],\n    \"1f484\":[[\"\\uD83D\\uDC84\"],\"Objects\",1198,[\"lipstick\"],26,24,\"0.6\",\"clothing\"],\n    \"1f485\":[[\"\\uD83D\\uDC85\"],\"People & Body\",211,[\"nail_care\"],26,25,\"0.6\",\"hand-prop\"],\n    \"1f486-200d-2640-fe0f\":[[\"\\uD83D\\uDC86\\u200D\\u2640\\uFE0F\",\"\\uD83D\\uDC86\"],\"People & Body\",405,[\"woman-getting-massage\",\"massage\"],26,31,\"4.0\",\"person-activity\"],\n    \"1f486-200d-2642-fe0f\":[[\"\\uD83D\\uDC86\\u200D\\u2642\\uFE0F\"],\"People & Body\",404,[\"man-getting-massage\"],26,37,\"4.0\",\"person-activity\"],\n    \"1f487-200d-2640-fe0f\":[[\"\\uD83D\\uDC87\\u200D\\u2640\\uFE0F\",\"\\uD83D\\uDC87\"],\"People & Body\",408,[\"woman-getting-haircut\",\"haircut\"],26,49,\"4.0\",\"person-activity\"],\n    \"1f487-200d-2642-fe0f\":[[\"\\uD83D\\uDC87\\u200D\\u2642\\uFE0F\"],\"People & Body\",407,[\"man-getting-haircut\"],26,55,\"4.0\",\"person-activity\"],\n    \"1f488\":[[\"\\uD83D\\uDC88\"],\"Travel & Places\",915,[\"barber\"],27,5,\"0.6\",\"place-other\"],\n    \"1f489\":[[\"\\uD83D\\uDC89\"],\"Objects\",1377,[\"syringe\"],27,6,\"0.6\",\"medical\"],\n    \"1f48a\":[[\"\\uD83D\\uDC8A\"],\"Objects\",1379,[\"pill\"],27,7,\"0.6\",\"medical\"],\n    \"1f48b\":[[\"\\uD83D\\uDC8B\"],\"Smileys & Emotion\",156,[\"kiss\"],27,8,\"0.6\",\"emotion\"],\n    \"1f48c\":[[\"\\uD83D\\uDC8C\"],\"Smileys & Emotion\",131,[\"love_letter\"],27,9,\"0.6\",\"heart\"],\n    \"1f48d\":[[\"\\uD83D\\uDC8D\"],\"Objects\",1199,[\"ring\"],27,10,\"0.6\",\"clothing\"],\n    \"1f48e\":[[\"\\uD83D\\uDC8E\"],\"Objects\",1200,[\"gem\"],27,11,\"0.6\",\"clothing\"],\n    \"1f48f\":[[\"\\uD83D\\uDC8F\"],\"People & Body\",512,[\"couplekiss\"],27,12,\"0.6\",\"family\"],\n    \"1f490\":[[\"\\uD83D\\uDC90\"],\"Animals & Nature\",691,[\"bouquet\"],27,38,\"0.6\",\"plant-flower\"],\n    \"1f491\":[[\"\\uD83D\\uDC91\"],\"People & Body\",516,[\"couple_with_heart\"],27,39,\"0.6\",\"family\"],\n    \"1f492\":[[\"\\uD83D\\uDC92\"],\"Travel & Places\",891,[\"wedding\"],28,3,\"0.6\",\"place-building\"],\n    \"1f493\":[[\"\\uD83D\\uDC93\"],\"Smileys & Emotion\",136,[\"heartbeat\"],28,4,\"0.6\",\"heart\"],\n    \"1f494\":[[\"\\uD83D\\uDC94\"],\"Smileys & Emotion\",141,[\"broken_heart\"],28,5,\"0.6\",\"heart\",\"<\\/3\"],\n    \"1f495\":[[\"\\uD83D\\uDC95\"],\"Smileys & Emotion\",138,[\"two_hearts\"],28,6,\"0.6\",\"heart\"],\n    \"1f496\":[[\"\\uD83D\\uDC96\"],\"Smileys & Emotion\",134,[\"sparkling_heart\"],28,7,\"0.6\",\"heart\"],\n    \"1f497\":[[\"\\uD83D\\uDC97\"],\"Smileys & Emotion\",135,[\"heartpulse\"],28,8,\"0.6\",\"heart\"],\n    \"1f498\":[[\"\\uD83D\\uDC98\"],\"Smileys & Emotion\",132,[\"cupid\"],28,9,\"0.6\",\"heart\"],\n    \"1f499\":[[\"\\uD83D\\uDC99\"],\"Smileys & Emotion\",149,[\"blue_heart\"],28,10,\"0.6\",\"heart\",\"<3\"],\n    \"1f49a\":[[\"\\uD83D\\uDC9A\"],\"Smileys & Emotion\",148,[\"green_heart\"],28,11,\"0.6\",\"heart\",\"<3\"],\n    \"1f49b\":[[\"\\uD83D\\uDC9B\"],\"Smileys & Emotion\",147,[\"yellow_heart\"],28,12,\"0.6\",\"heart\",\"<3\"],\n    \"1f49c\":[[\"\\uD83D\\uDC9C\"],\"Smileys & Emotion\",151,[\"purple_heart\"],28,13,\"0.6\",\"heart\",\"<3\"],\n    \"1f49d\":[[\"\\uD83D\\uDC9D\"],\"Smileys & Emotion\",133,[\"gift_heart\"],28,14,\"0.6\",\"heart\"],\n    \"1f49e\":[[\"\\uD83D\\uDC9E\"],\"Smileys & Emotion\",137,[\"revolving_hearts\"],28,15,\"0.6\",\"heart\"],\n    \"1f49f\":[[\"\\uD83D\\uDC9F\"],\"Smileys & Emotion\",139,[\"heart_decoration\"],28,16,\"0.6\",\"heart\"],\n    \"1f4a0\":[[\"\\uD83D\\uDCA0\"],\"Symbols\",1638,[\"diamond_shape_with_a_dot_inside\"],28,17,\"0.6\",\"geometric\"],\n    \"1f4a1\":[[\"\\uD83D\\uDCA1\"],\"Objects\",1263,[\"bulb\"],28,18,\"0.6\",\"light & video\"],\n    \"1f4a2\":[[\"\\uD83D\\uDCA2\"],\"Smileys & Emotion\",158,[\"anger\"],28,19,\"0.6\",\"emotion\"],\n    \"1f4a3\":[[\"\\uD83D\\uDCA3\"],\"Objects\",1350,[\"bomb\"],28,20,\"0.6\",\"tool\"],\n    \"1f4a4\":[[\"\\uD83D\\uDCA4\"],\"Smileys & Emotion\",169,[\"zzz\"],28,21,\"0.6\",\"emotion\"],\n    \"1f4a5\":[[\"\\uD83D\\uDCA5\"],\"Smileys & Emotion\",159,[\"boom\",\"collision\"],28,22,\"0.6\",\"emotion\"],\n    \"1f4a6\":[[\"\\uD83D\\uDCA6\"],\"Smileys & Emotion\",161,[\"sweat_drops\"],28,23,\"0.6\",\"emotion\"],\n    \"1f4a7\":[[\"\\uD83D\\uDCA7\"],\"Travel & Places\",1067,[\"droplet\"],28,24,\"0.6\",\"sky & weather\"],\n    \"1f4a8\":[[\"\\uD83D\\uDCA8\"],\"Smileys & Emotion\",162,[\"dash\"],28,25,\"0.6\",\"emotion\"],\n    \"1f4a9\":[[\"\\uD83D\\uDCA9\"],\"Smileys & Emotion\",111,[\"pile_of_poo\", \"hankey\",\"poop\",\"shit\"],28,26,\"0.6\",\"face-costume\"],\n    \"1f4aa\":[[\"\\uD83D\\uDCAA\"],\"People & Body\",213,[\"muscle\"],28,27,\"0.6\",\"body-parts\"],\n    \"1f4ab\":[[\"\\uD83D\\uDCAB\"],\"Smileys & Emotion\",160,[\"dizzy\"],28,33,\"0.6\",\"emotion\"],\n    \"1f4ac\":[[\"\\uD83D\\uDCAC\"],\"Smileys & Emotion\",164,[\"speech_balloon\"],28,34,\"0.6\",\"emotion\"],\n    \"1f4ad\":[[\"\\uD83D\\uDCAD\"],\"Smileys & Emotion\",168,[\"thought_balloon\"],28,35,\"1.0\",\"emotion\"],\n    \"1f4ae\":[[\"\\uD83D\\uDCAE\"],\"Animals & Nature\",693,[\"white_flower\"],28,36,\"0.6\",\"plant-flower\"],\n    \"1f4af\":[[\"\\uD83D\\uDCAF\"],\"Smileys & Emotion\",157,[\"100\"],28,37,\"0.6\",\"emotion\"],\n    \"1f4b0\":[[\"\\uD83D\\uDCB0\"],\"Objects\",1284,[\"moneybag\"],28,38,\"0.6\",\"money\"],\n    \"1f4b1\":[[\"\\uD83D\\uDCB1\"],\"Symbols\",1532,[\"currency_exchange\"],28,39,\"0.6\",\"currency\"],\n    \"1f4b2\":[[\"\\uD83D\\uDCB2\"],\"Symbols\",1533,[\"heavy_dollar_sign\"],28,40,\"0.6\",\"currency\"],\n    \"1f4b3\":[[\"\\uD83D\\uDCB3\"],\"Objects\",1291,[\"credit_card\"],28,41,\"0.6\",\"money\"],\n    \"1f4b4\":[[\"\\uD83D\\uDCB4\"],\"Objects\",1286,[\"yen\"],28,42,\"0.6\",\"money\"],\n    \"1f4b5\":[[\"\\uD83D\\uDCB5\"],\"Objects\",1287,[\"dollar\"],28,43,\"0.6\",\"money\"],\n    \"1f4b6\":[[\"\\uD83D\\uDCB6\"],\"Objects\",1288,[\"euro\"],28,44,\"1.0\",\"money\"],\n    \"1f4b7\":[[\"\\uD83D\\uDCB7\"],\"Objects\",1289,[\"pound\"],28,45,\"1.0\",\"money\"],\n    \"1f4b8\":[[\"\\uD83D\\uDCB8\"],\"Objects\",1290,[\"money_with_wings\"],28,46,\"0.6\",\"money\"],\n    \"1f4b9\":[[\"\\uD83D\\uDCB9\"],\"Objects\",1293,[\"chart\"],28,47,\"0.6\",\"money\"],\n    \"1f4ba\":[[\"\\uD83D\\uDCBA\"],\"Travel & Places\",981,[\"seat\"],28,48,\"0.6\",\"transport-air\"],\n    \"1f4bb\":[[\"\\uD83D\\uDCBB\"],\"Objects\",1240,[\"computer\"],28,49,\"0.6\",\"computer\"],\n    \"1f4bc\":[[\"\\uD83D\\uDCBC\"],\"Objects\",1314,[\"briefcase\"],28,50,\"0.6\",\"office\"],\n    \"1f4bd\":[[\"\\uD83D\\uDCBD\"],\"Objects\",1246,[\"minidisc\"],28,51,\"0.6\",\"computer\"],\n    \"1f4be\":[[\"\\uD83D\\uDCBE\"],\"Objects\",1247,[\"floppy_disk\"],28,52,\"0.6\",\"computer\"],\n    \"1f4bf\":[[\"\\uD83D\\uDCBF\"],\"Objects\",1248,[\"cd\"],28,53,\"0.6\",\"computer\"],\n    \"1f4c0\":[[\"\\uD83D\\uDCC0\"],\"Objects\",1249,[\"dvd\"],28,54,\"0.6\",\"computer\"],\n    \"1f4c1\":[[\"\\uD83D\\uDCC1\"],\"Objects\",1315,[\"file_folder\"],28,55,\"0.6\",\"office\"],\n    \"1f4c2\":[[\"\\uD83D\\uDCC2\"],\"Objects\",1316,[\"open_file_folder\"],28,56,\"0.6\",\"office\"],\n    \"1f4c3\":[[\"\\uD83D\\uDCC3\"],\"Objects\",1276,[\"page_with_curl\"],28,57,\"0.6\",\"book-paper\"],\n    \"1f4c4\":[[\"\\uD83D\\uDCC4\"],\"Objects\",1278,[\"page_facing_up\"],28,58,\"0.6\",\"book-paper\"],\n    \"1f4c5\":[[\"\\uD83D\\uDCC5\"],\"Objects\",1318,[\"date\"],28,59,\"0.6\",\"office\"],\n    \"1f4c6\":[[\"\\uD83D\\uDCC6\"],\"Objects\",1319,[\"calendar\"],28,60,\"0.6\",\"office\"],\n    \"1f4c7\":[[\"\\uD83D\\uDCC7\"],\"Objects\",1322,[\"card_index\"],28,61,\"0.6\",\"office\"],\n    \"1f4c8\":[[\"\\uD83D\\uDCC8\"],\"Objects\",1323,[\"chart_with_upwards_trend\"],29,0,\"0.6\",\"office\"],\n    \"1f4c9\":[[\"\\uD83D\\uDCC9\"],\"Objects\",1324,[\"chart_with_downwards_trend\"],29,1,\"0.6\",\"office\"],\n    \"1f4ca\":[[\"\\uD83D\\uDCCA\"],\"Objects\",1325,[\"bar_chart\"],29,2,\"0.6\",\"office\"],\n    \"1f4cb\":[[\"\\uD83D\\uDCCB\"],\"Objects\",1326,[\"clipboard\"],29,3,\"0.6\",\"office\"],\n    \"1f4cc\":[[\"\\uD83D\\uDCCC\"],\"Objects\",1327,[\"pushpin\"],29,4,\"0.6\",\"office\"],\n    \"1f4cd\":[[\"\\uD83D\\uDCCD\"],\"Objects\",1328,[\"round_pushpin\"],29,5,\"0.6\",\"office\"],\n    \"1f4ce\":[[\"\\uD83D\\uDCCE\"],\"Objects\",1329,[\"paperclip\"],29,6,\"0.6\",\"office\"],\n    \"1f4cf\":[[\"\\uD83D\\uDCCF\"],\"Objects\",1331,[\"straight_ruler\"],29,7,\"0.6\",\"office\"],\n    \"1f4d0\":[[\"\\uD83D\\uDCD0\"],\"Objects\",1332,[\"triangular_ruler\"],29,8,\"0.6\",\"office\"],\n    \"1f4d1\":[[\"\\uD83D\\uDCD1\"],\"Objects\",1281,[\"bookmark_tabs\"],29,9,\"0.6\",\"book-paper\"],\n    \"1f4d2\":[[\"\\uD83D\\uDCD2\"],\"Objects\",1275,[\"ledger\"],29,10,\"0.6\",\"book-paper\"],\n    \"1f4d3\":[[\"\\uD83D\\uDCD3\"],\"Objects\",1274,[\"notebook\"],29,11,\"0.6\",\"book-paper\"],\n    \"1f4d4\":[[\"\\uD83D\\uDCD4\"],\"Objects\",1267,[\"notebook_with_decorative_cover\"],29,12,\"0.6\",\"book-paper\"],\n    \"1f4d5\":[[\"\\uD83D\\uDCD5\"],\"Objects\",1268,[\"closed_book\"],29,13,\"0.6\",\"book-paper\"],\n    \"1f4d6\":[[\"\\uD83D\\uDCD6\"],\"Objects\",1269,[\"book\",\"open_book\"],29,14,\"0.6\",\"book-paper\"],\n    \"1f4d7\":[[\"\\uD83D\\uDCD7\"],\"Objects\",1270,[\"green_book\"],29,15,\"0.6\",\"book-paper\"],\n    \"1f4d8\":[[\"\\uD83D\\uDCD8\"],\"Objects\",1271,[\"blue_book\"],29,16,\"0.6\",\"book-paper\"],\n    \"1f4d9\":[[\"\\uD83D\\uDCD9\"],\"Objects\",1272,[\"orange_book\"],29,17,\"0.6\",\"book-paper\"],\n    \"1f4da\":[[\"\\uD83D\\uDCDA\"],\"Objects\",1273,[\"books\"],29,18,\"0.6\",\"book-paper\"],\n    \"1f4db\":[[\"\\uD83D\\uDCDB\"],\"Symbols\",1538,[\"name_badge\"],29,19,\"0.6\",\"other-symbol\"],\n    \"1f4dc\":[[\"\\uD83D\\uDCDC\"],\"Objects\",1277,[\"scroll\"],29,20,\"0.6\",\"book-paper\"],\n    \"1f4dd\":[[\"\\uD83D\\uDCDD\"],\"Objects\",1313,[\"memo\",\"pencil\"],29,21,\"0.6\",\"writing\"],\n    \"1f4de\":[[\"\\uD83D\\uDCDE\"],\"Objects\",1234,[\"telephone_receiver\"],29,22,\"0.6\",\"phone\"],\n    \"1f4df\":[[\"\\uD83D\\uDCDF\"],\"Objects\",1235,[\"pager\"],29,23,\"0.6\",\"phone\"],\n    \"1f4e0\":[[\"\\uD83D\\uDCE0\"],\"Objects\",1236,[\"fax\"],29,24,\"0.6\",\"phone\"],\n    \"1f4e1\":[[\"\\uD83D\\uDCE1\"],\"Objects\",1376,[\"satellite_antenna\"],29,25,\"0.6\",\"science\"],\n    \"1f4e2\":[[\"\\uD83D\\uDCE2\"],\"Objects\",1205,[\"loudspeaker\"],29,26,\"0.6\",\"sound\"],\n    \"1f4e3\":[[\"\\uD83D\\uDCE3\"],\"Objects\",1206,[\"mega\"],29,27,\"0.6\",\"sound\"],\n    \"1f4e4\":[[\"\\uD83D\\uDCE4\"],\"Objects\",1298,[\"outbox_tray\"],29,28,\"0.6\",\"mail\"],\n    \"1f4e5\":[[\"\\uD83D\\uDCE5\"],\"Objects\",1299,[\"inbox_tray\"],29,29,\"0.6\",\"mail\"],\n    \"1f4e6\":[[\"\\uD83D\\uDCE6\"],\"Objects\",1300,[\"package\"],29,30,\"0.6\",\"mail\"],\n    \"1f4e7\":[[\"\\uD83D\\uDCE7\"],\"Objects\",1295,[\"e-mail\"],29,31,\"0.6\",\"mail\"],\n    \"1f4e8\":[[\"\\uD83D\\uDCE8\"],\"Objects\",1296,[\"incoming_envelope\"],29,32,\"0.6\",\"mail\"],\n    \"1f4e9\":[[\"\\uD83D\\uDCE9\"],\"Objects\",1297,[\"envelope_with_arrow\"],29,33,\"0.6\",\"mail\"],\n    \"1f4ea\":[[\"\\uD83D\\uDCEA\"],\"Objects\",1302,[\"mailbox_closed\"],29,34,\"0.6\",\"mail\"],\n    \"1f4eb\":[[\"\\uD83D\\uDCEB\"],\"Objects\",1301,[\"mailbox\"],29,35,\"0.6\",\"mail\"],\n    \"1f4ec\":[[\"\\uD83D\\uDCEC\"],\"Objects\",1303,[\"mailbox_with_mail\"],29,36,\"0.7\",\"mail\"],\n    \"1f4ed\":[[\"\\uD83D\\uDCED\"],\"Objects\",1304,[\"mailbox_with_no_mail\"],29,37,\"0.7\",\"mail\"],\n    \"1f4ee\":[[\"\\uD83D\\uDCEE\"],\"Objects\",1305,[\"postbox\"],29,38,\"0.6\",\"mail\"],\n    \"1f4ef\":[[\"\\uD83D\\uDCEF\"],\"Objects\",1207,[\"postal_horn\"],29,39,\"1.0\",\"sound\"],\n    \"1f4f0\":[[\"\\uD83D\\uDCF0\"],\"Objects\",1279,[\"newspaper\"],29,40,\"0.6\",\"book-paper\"],\n    \"1f4f1\":[[\"\\uD83D\\uDCF1\"],\"Objects\",1231,[\"iphone\"],29,41,\"0.6\",\"phone\"],\n    \"1f4f2\":[[\"\\uD83D\\uDCF2\"],\"Objects\",1232,[\"calling\"],29,42,\"0.6\",\"phone\"],\n    \"1f4f3\":[[\"\\uD83D\\uDCF3\"],\"Symbols\",1514,[\"vibration_mode\"],29,43,\"0.6\",\"av-symbol\"],\n    \"1f4f4\":[[\"\\uD83D\\uDCF4\"],\"Symbols\",1515,[\"mobile_phone_off\"],29,44,\"0.6\",\"av-symbol\"],\n    \"1f4f5\":[[\"\\uD83D\\uDCF5\"],\"Symbols\",1440,[\"no_mobile_phones\"],29,45,\"1.0\",\"warning\"],\n    \"1f4f6\":[[\"\\uD83D\\uDCF6\"],\"Symbols\",1512,[\"signal_strength\"],29,46,\"0.6\",\"av-symbol\"],\n    \"1f4f7\":[[\"\\uD83D\\uDCF7\"],\"Objects\",1256,[\"camera\"],29,47,\"0.6\",\"light & video\"],\n    \"1f4f8\":[[\"\\uD83D\\uDCF8\"],\"Objects\",1257,[\"camera_with_flash\"],29,48,\"1.0\",\"light & video\"],\n    \"1f4f9\":[[\"\\uD83D\\uDCF9\"],\"Objects\",1258,[\"video_camera\"],29,49,\"0.6\",\"light & video\"],\n    \"1f4fa\":[[\"\\uD83D\\uDCFA\"],\"Objects\",1255,[\"tv\"],29,50,\"0.6\",\"light & video\"],\n    \"1f4fb\":[[\"\\uD83D\\uDCFB\"],\"Objects\",1218,[\"radio\"],29,51,\"0.6\",\"music\"],\n    \"1f4fc\":[[\"\\uD83D\\uDCFC\"],\"Objects\",1259,[\"vhs\"],29,52,\"0.6\",\"light & video\"],\n    \"1f4fd-fe0f\":[[\"\\uD83D\\uDCFD\\uFE0F\"],\"Objects\",1253,[\"film_projector\"],29,53,\"0.7\",\"light & video\"],\n    \"1f4ff\":[[\"\\uD83D\\uDCFF\"],\"Objects\",1197,[\"prayer_beads\"],29,54,\"1.0\",\"clothing\"],\n    \"1f500\":[[\"\\uD83D\\uDD00\"],\"Symbols\",1491,[\"twisted_rightwards_arrows\"],29,55,\"1.0\",\"av-symbol\"],\n    \"1f501\":[[\"\\uD83D\\uDD01\"],\"Symbols\",1492,[\"repeat\"],29,56,\"1.0\",\"av-symbol\"],\n    \"1f502\":[[\"\\uD83D\\uDD02\"],\"Symbols\",1493,[\"repeat_one\"],29,57,\"1.0\",\"av-symbol\"],\n    \"1f503\":[[\"\\uD83D\\uDD03\"],\"Symbols\",1458,[\"arrows_clockwise\"],29,58,\"0.6\",\"arrow\"],\n    \"1f504\":[[\"\\uD83D\\uDD04\"],\"Symbols\",1459,[\"arrows_counterclockwise\"],29,59,\"1.0\",\"arrow\"],\n    \"1f505\":[[\"\\uD83D\\uDD05\"],\"Symbols\",1510,[\"low_brightness\"],29,60,\"1.0\",\"av-symbol\"],\n    \"1f506\":[[\"\\uD83D\\uDD06\"],\"Symbols\",1511,[\"high_brightness\"],29,61,\"1.0\",\"av-symbol\"],\n    \"1f507\":[[\"\\uD83D\\uDD07\"],\"Objects\",1201,[\"mute\"],30,0,\"1.0\",\"sound\"],\n    \"1f508\":[[\"\\uD83D\\uDD08\"],\"Objects\",1202,[\"speaker\"],30,1,\"0.7\",\"sound\"],\n    \"1f509\":[[\"\\uD83D\\uDD09\"],\"Objects\",1203,[\"sound\"],30,2,\"1.0\",\"sound\"],\n    \"1f50a\":[[\"\\uD83D\\uDD0A\"],\"Objects\",1204,[\"loud_sound\"],30,3,\"0.6\",\"sound\"],\n    \"1f50b\":[[\"\\uD83D\\uDD0B\"],\"Objects\",1237,[\"battery\"],30,4,\"0.6\",\"computer\"],\n    \"1f50c\":[[\"\\uD83D\\uDD0C\"],\"Objects\",1239,[\"electric_plug\"],30,5,\"0.6\",\"computer\"],\n    \"1f50d\":[[\"\\uD83D\\uDD0D\"],\"Objects\",1260,[\"mag\"],30,6,\"0.6\",\"light & video\"],\n    \"1f50e\":[[\"\\uD83D\\uDD0E\"],\"Objects\",1261,[\"mag_right\"],30,7,\"0.6\",\"light & video\"],\n    \"1f50f\":[[\"\\uD83D\\uDD0F\"],\"Objects\",1339,[\"lock_with_ink_pen\"],30,8,\"0.6\",\"lock\"],\n    \"1f510\":[[\"\\uD83D\\uDD10\"],\"Objects\",1340,[\"closed_lock_with_key\"],30,9,\"0.6\",\"lock\"],\n    \"1f511\":[[\"\\uD83D\\uDD11\"],\"Objects\",1341,[\"key\"],30,10,\"0.6\",\"lock\"],\n    \"1f512\":[[\"\\uD83D\\uDD12\"],\"Objects\",1337,[\"lock\"],30,11,\"0.6\",\"lock\"],\n    \"1f513\":[[\"\\uD83D\\uDD13\"],\"Objects\",1338,[\"unlock\"],30,12,\"0.6\",\"lock\"],\n    \"1f514\":[[\"\\uD83D\\uDD14\"],\"Objects\",1208,[\"bell\"],30,13,\"0.6\",\"sound\"],\n    \"1f515\":[[\"\\uD83D\\uDD15\"],\"Objects\",1209,[\"no_bell\"],30,14,\"1.0\",\"sound\"],\n    \"1f516\":[[\"\\uD83D\\uDD16\"],\"Objects\",1282,[\"bookmark\"],30,15,\"0.6\",\"book-paper\"],\n    \"1f517\":[[\"\\uD83D\\uDD17\"],\"Objects\",1362,[\"link\"],30,16,\"0.6\",\"tool\"],\n    \"1f518\":[[\"\\uD83D\\uDD18\"],\"Symbols\",1639,[\"radio_button\"],30,17,\"0.6\",\"geometric\"],\n    \"1f519\":[[\"\\uD83D\\uDD19\"],\"Symbols\",1460,[\"back\"],30,18,\"0.6\",\"arrow\"],\n    \"1f51a\":[[\"\\uD83D\\uDD1A\"],\"Symbols\",1461,[\"end\"],30,19,\"0.6\",\"arrow\"],\n    \"1f51b\":[[\"\\uD83D\\uDD1B\"],\"Symbols\",1462,[\"on\"],30,20,\"0.6\",\"arrow\"],\n    \"1f51c\":[[\"\\uD83D\\uDD1C\"],\"Symbols\",1463,[\"soon\"],30,21,\"0.6\",\"arrow\"],\n    \"1f51d\":[[\"\\uD83D\\uDD1D\"],\"Symbols\",1464,[\"top\"],30,22,\"0.6\",\"arrow\"],\n    \"1f51e\":[[\"\\uD83D\\uDD1E\"],\"Symbols\",1441,[\"underage\"],30,23,\"0.6\",\"warning\"],\n    \"1f51f\":[[\"\\uD83D\\uDD1F\"],\"Symbols\",1568,[\"keycap_ten\"],30,24,\"0.6\",\"keycap\"],\n    \"1f520\":[[\"\\uD83D\\uDD20\"],\"Symbols\",1569,[\"capital_abcd\"],30,25,\"0.6\",\"alphanum\"],\n    \"1f521\":[[\"\\uD83D\\uDD21\"],\"Symbols\",1570,[\"abcd\"],30,26,\"0.6\",\"alphanum\"],\n    \"1f522\":[[\"\\uD83D\\uDD22\"],\"Symbols\",1571,[\"1234\"],30,27,\"0.6\",\"alphanum\"],\n    \"1f523\":[[\"\\uD83D\\uDD23\"],\"Symbols\",1572,[\"symbols\"],30,28,\"0.6\",\"alphanum\"],\n    \"1f524\":[[\"\\uD83D\\uDD24\"],\"Symbols\",1573,[\"abc\"],30,29,\"0.6\",\"alphanum\"],\n    \"1f525\":[[\"\\uD83D\\uDD25\"],\"Travel & Places\",1066,[\"fire\"],30,30,\"0.6\",\"sky & weather\"],\n    \"1f526\":[[\"\\uD83D\\uDD26\"],\"Objects\",1264,[\"flashlight\"],30,31,\"0.6\",\"light & video\"],\n    \"1f527\":[[\"\\uD83D\\uDD27\"],\"Objects\",1355,[\"wrench\"],30,32,\"0.6\",\"tool\"],\n    \"1f528\":[[\"\\uD83D\\uDD28\"],\"Objects\",1343,[\"hammer\"],30,33,\"0.6\",\"tool\"],\n    \"1f529\":[[\"\\uD83D\\uDD29\"],\"Objects\",1357,[\"nut_and_bolt\"],30,34,\"0.6\",\"tool\"],\n    \"1f52a\":[[\"\\uD83D\\uDD2A\"],\"Food & Drink\",848,[\"hocho\",\"knife\"],30,35,\"0.6\",\"dishware\"],\n    \"1f52b\":[[\"\\uD83D\\uDD2B\"],\"Activities\",1126,[\"gun\"],30,36,\"0.6\",\"game\"],\n    \"1f52c\":[[\"\\uD83D\\uDD2C\"],\"Objects\",1374,[\"microscope\"],30,37,\"1.0\",\"science\"],\n    \"1f52d\":[[\"\\uD83D\\uDD2D\"],\"Objects\",1375,[\"telescope\"],30,38,\"1.0\",\"science\"],\n    \"1f52e\":[[\"\\uD83D\\uDD2E\"],\"Activities\",1128,[\"crystal_ball\"],30,39,\"0.6\",\"game\"],\n    \"1f52f\":[[\"\\uD83D\\uDD2F\"],\"Symbols\",1476,[\"six_pointed_star\"],30,40,\"0.6\",\"religion\"],\n    \"1f530\":[[\"\\uD83D\\uDD30\"],\"Symbols\",1539,[\"beginner\"],30,41,\"0.6\",\"other-symbol\"],\n    \"1f531\":[[\"\\uD83D\\uDD31\"],\"Symbols\",1537,[\"trident\"],30,42,\"0.6\",\"other-symbol\"],\n    \"1f532\":[[\"\\uD83D\\uDD32\"],\"Symbols\",1641,[\"black_square_button\"],30,43,\"0.6\",\"geometric\"],\n    \"1f533\":[[\"\\uD83D\\uDD33\"],\"Symbols\",1640,[\"white_square_button\"],30,44,\"0.6\",\"geometric\"],\n    \"1f534\":[[\"\\uD83D\\uDD34\"],\"Symbols\",1608,[\"red_circle\"],30,45,\"0.6\",\"geometric\"],\n    \"1f535\":[[\"\\uD83D\\uDD35\"],\"Symbols\",1612,[\"large_blue_circle\"],30,46,\"0.6\",\"geometric\"],\n    \"1f536\":[[\"\\uD83D\\uDD36\"],\"Symbols\",1632,[\"large_orange_diamond\"],30,47,\"0.6\",\"geometric\"],\n    \"1f537\":[[\"\\uD83D\\uDD37\"],\"Symbols\",1633,[\"large_blue_diamond\"],30,48,\"0.6\",\"geometric\"],\n    \"1f538\":[[\"\\uD83D\\uDD38\"],\"Symbols\",1634,[\"small_orange_diamond\"],30,49,\"0.6\",\"geometric\"],\n    \"1f539\":[[\"\\uD83D\\uDD39\"],\"Symbols\",1635,[\"small_blue_diamond\"],30,50,\"0.6\",\"geometric\"],\n    \"1f53a\":[[\"\\uD83D\\uDD3A\"],\"Symbols\",1636,[\"small_red_triangle\"],30,51,\"0.6\",\"geometric\"],\n    \"1f53b\":[[\"\\uD83D\\uDD3B\"],\"Symbols\",1637,[\"small_red_triangle_down\"],30,52,\"0.6\",\"geometric\"],\n    \"1f53c\":[[\"\\uD83D\\uDD3C\"],\"Symbols\",1501,[\"arrow_up_small\"],30,53,\"0.6\",\"av-symbol\"],\n    \"1f53d\":[[\"\\uD83D\\uDD3D\"],\"Symbols\",1503,[\"arrow_down_small\"],30,54,\"0.6\",\"av-symbol\"],\n    \"1f549-fe0f\":[[\"\\uD83D\\uDD49\\uFE0F\"],\"Symbols\",1467,[\"om_symbol\"],30,55,\"0.7\",\"religion\"],\n    \"1f54a-fe0f\":[[\"\\uD83D\\uDD4A\\uFE0F\"],\"Animals & Nature\",635,[\"dove_of_peace\"],30,56,\"0.7\",\"animal-bird\"],\n    \"1f54b\":[[\"\\uD83D\\uDD4B\"],\"Travel & Places\",899,[\"kaaba\"],30,57,\"1.0\",\"place-religious\"],\n    \"1f54c\":[[\"\\uD83D\\uDD4C\"],\"Travel & Places\",895,[\"mosque\"],30,58,\"1.0\",\"place-religious\"],\n    \"1f54d\":[[\"\\uD83D\\uDD4D\"],\"Travel & Places\",897,[\"synagogue\"],30,59,\"1.0\",\"place-religious\"],\n    \"1f54e\":[[\"\\uD83D\\uDD4E\"],\"Symbols\",1475,[\"menorah_with_nine_branches\"],30,60,\"1.0\",\"religion\"],\n    \"1f550\":[[\"\\uD83D\\uDD50\"],\"Travel & Places\",1000,[\"clock1\"],30,61,\"0.6\",\"time\"],\n    \"1f551\":[[\"\\uD83D\\uDD51\"],\"Travel & Places\",1002,[\"clock2\"],31,0,\"0.6\",\"time\"],\n    \"1f552\":[[\"\\uD83D\\uDD52\"],\"Travel & Places\",1004,[\"clock3\"],31,1,\"0.6\",\"time\"],\n    \"1f553\":[[\"\\uD83D\\uDD53\"],\"Travel & Places\",1006,[\"clock4\"],31,2,\"0.6\",\"time\"],\n    \"1f554\":[[\"\\uD83D\\uDD54\"],\"Travel & Places\",1008,[\"clock5\"],31,3,\"0.6\",\"time\"],\n    \"1f555\":[[\"\\uD83D\\uDD55\"],\"Travel & Places\",1010,[\"clock6\"],31,4,\"0.6\",\"time\"],\n    \"1f556\":[[\"\\uD83D\\uDD56\"],\"Travel & Places\",1012,[\"clock7\"],31,5,\"0.6\",\"time\"],\n    \"1f557\":[[\"\\uD83D\\uDD57\"],\"Travel & Places\",1014,[\"clock8\"],31,6,\"0.6\",\"time\"],\n    \"1f558\":[[\"\\uD83D\\uDD58\"],\"Travel & Places\",1016,[\"clock9\"],31,7,\"0.6\",\"time\"],\n    \"1f559\":[[\"\\uD83D\\uDD59\"],\"Travel & Places\",1018,[\"clock10\"],31,8,\"0.6\",\"time\"],\n    \"1f55a\":[[\"\\uD83D\\uDD5A\"],\"Travel & Places\",1020,[\"clock11\"],31,9,\"0.6\",\"time\"],\n    \"1f55b\":[[\"\\uD83D\\uDD5B\"],\"Travel & Places\",998,[\"clock12\"],31,10,\"0.6\",\"time\"],\n    \"1f55c\":[[\"\\uD83D\\uDD5C\"],\"Travel & Places\",1001,[\"clock130\"],31,11,\"0.7\",\"time\"],\n    \"1f55d\":[[\"\\uD83D\\uDD5D\"],\"Travel & Places\",1003,[\"clock230\"],31,12,\"0.7\",\"time\"],\n    \"1f55e\":[[\"\\uD83D\\uDD5E\"],\"Travel & Places\",1005,[\"clock330\"],31,13,\"0.7\",\"time\"],\n    \"1f55f\":[[\"\\uD83D\\uDD5F\"],\"Travel & Places\",1007,[\"clock430\"],31,14,\"0.7\",\"time\"],\n    \"1f560\":[[\"\\uD83D\\uDD60\"],\"Travel & Places\",1009,[\"clock530\"],31,15,\"0.7\",\"time\"],\n    \"1f561\":[[\"\\uD83D\\uDD61\"],\"Travel & Places\",1011,[\"clock630\"],31,16,\"0.7\",\"time\"],\n    \"1f562\":[[\"\\uD83D\\uDD62\"],\"Travel & Places\",1013,[\"clock730\"],31,17,\"0.7\",\"time\"],\n    \"1f563\":[[\"\\uD83D\\uDD63\"],\"Travel & Places\",1015,[\"clock830\"],31,18,\"0.7\",\"time\"],\n    \"1f564\":[[\"\\uD83D\\uDD64\"],\"Travel & Places\",1017,[\"clock930\"],31,19,\"0.7\",\"time\"],\n    \"1f565\":[[\"\\uD83D\\uDD65\"],\"Travel & Places\",1019,[\"clock1030\"],31,20,\"0.7\",\"time\"],\n    \"1f566\":[[\"\\uD83D\\uDD66\"],\"Travel & Places\",1021,[\"clock1130\"],31,21,\"0.7\",\"time\"],\n    \"1f567\":[[\"\\uD83D\\uDD67\"],\"Travel & Places\",999,[\"clock1230\"],31,22,\"0.7\",\"time\"],\n    \"1f56f-fe0f\":[[\"\\uD83D\\uDD6F\\uFE0F\"],\"Objects\",1262,[\"candle\"],31,23,\"0.7\",\"light & video\"],\n    \"1f570-fe0f\":[[\"\\uD83D\\uDD70\\uFE0F\"],\"Travel & Places\",997,[\"mantelpiece_clock\"],31,24,\"0.7\",\"time\"],\n    \"1f573-fe0f\":[[\"\\uD83D\\uDD73\\uFE0F\"],\"Smileys & Emotion\",163,[\"hole\"],31,25,\"0.7\",\"emotion\"],\n    \"1f574-fe0f\":[[\"\\uD83D\\uDD74\\uFE0F\"],\"People & Body\",450,[\"man_in_business_suit_levitating\"],31,26,\"0.7\",\"person-activity\"],\n    \"1f575-fe0f-200d-2640-fe0f\":[[\"\\uD83D\\uDD75\\uFE0F\\u200D\\u2640\\uFE0F\"],\"People & Body\",342,[\"female-detective\"],31,32,\"4.0\",\"person-role\"],\n    \"1f575-fe0f-200d-2642-fe0f\":[[\"\\uD83D\\uDD75\\uFE0F\\u200D\\u2642\\uFE0F\",\"\\uD83D\\uDD75\\uFE0F\"],\"People & Body\",341,[\"male-detective\",\"sleuth_or_spy\"],31,38,\"4.0\",\"person-role\"],\n    \"1f576-fe0f\":[[\"\\uD83D\\uDD76\\uFE0F\"],\"Objects\",1155,[\"dark_sunglasses\"],31,50,\"0.7\",\"clothing\"],\n    \"1f577-fe0f\":[[\"\\uD83D\\uDD77\\uFE0F\"],\"Animals & Nature\",684,[\"spider\"],31,51,\"0.7\",\"animal-bug\"],\n    \"1f578-fe0f\":[[\"\\uD83D\\uDD78\\uFE0F\"],\"Animals & Nature\",685,[\"spider_web\"],31,52,\"0.7\",\"animal-bug\"],\n    \"1f579-fe0f\":[[\"\\uD83D\\uDD79\\uFE0F\"],\"Activities\",1131,[\"joystick\"],31,53,\"0.7\",\"game\"],\n    \"1f57a\":[[\"\\uD83D\\uDD7A\"],\"People & Body\",449,[\"man_dancing\"],31,54,\"3.0\",\"person-activity\"],\n    \"1f587-fe0f\":[[\"\\uD83D\\uDD87\\uFE0F\"],\"Objects\",1330,[\"linked_paperclips\"],31,60,\"0.7\",\"office\"],\n    \"1f58a-fe0f\":[[\"\\uD83D\\uDD8A\\uFE0F\"],\"Objects\",1310,[\"lower_left_ballpoint_pen\"],31,61,\"0.7\",\"writing\"],\n    \"1f58b-fe0f\":[[\"\\uD83D\\uDD8B\\uFE0F\"],\"Objects\",1309,[\"lower_left_fountain_pen\"],32,0,\"0.7\",\"writing\"],\n    \"1f58c-fe0f\":[[\"\\uD83D\\uDD8C\\uFE0F\"],\"Objects\",1311,[\"lower_left_paintbrush\"],32,1,\"0.7\",\"writing\"],\n    \"1f58d-fe0f\":[[\"\\uD83D\\uDD8D\\uFE0F\"],\"Objects\",1312,[\"lower_left_crayon\"],32,2,\"0.7\",\"writing\"],\n    \"1f590-fe0f\":[[\"\\uD83D\\uDD90\\uFE0F\"],\"People & Body\",172,[\"raised_hand_with_fingers_splayed\"],32,3,\"0.7\",\"hand-fingers-open\"],\n    \"1f595\":[[\"\\uD83D\\uDD95\"],\"People & Body\",193,[\"middle_finger\",\"reversed_hand_with_middle_finger_extended\"],32,9,\"1.0\",\"hand-single-finger\"],\n    \"1f596\":[[\"\\uD83D\\uDD96\"],\"People & Body\",174,[\"spock-hand\"],32,15,\"1.0\",\"hand-fingers-open\"],\n    \"1f5a4\":[[\"\\uD83D\\uDDA4\"],\"Smileys & Emotion\",153,[\"black_heart\"],32,21,\"3.0\",\"heart\"],\n    \"1f5a5-fe0f\":[[\"\\uD83D\\uDDA5\\uFE0F\"],\"Objects\",1241,[\"desktop_computer\"],32,22,\"0.7\",\"computer\"],\n    \"1f5a8-fe0f\":[[\"\\uD83D\\uDDA8\\uFE0F\"],\"Objects\",1242,[\"printer\"],32,23,\"0.7\",\"computer\"],\n    \"1f5b1-fe0f\":[[\"\\uD83D\\uDDB1\\uFE0F\"],\"Objects\",1244,[\"three_button_mouse\"],32,24,\"0.7\",\"computer\"],\n    \"1f5b2-fe0f\":[[\"\\uD83D\\uDDB2\\uFE0F\"],\"Objects\",1245,[\"trackball\"],32,25,\"0.7\",\"computer\"],\n    \"1f5bc-fe0f\":[[\"\\uD83D\\uDDBC\\uFE0F\"],\"Activities\",1148,[\"frame_with_picture\"],32,26,\"0.7\",\"arts & crafts\"],\n    \"1f5c2-fe0f\":[[\"\\uD83D\\uDDC2\\uFE0F\"],\"Objects\",1317,[\"card_index_dividers\"],32,27,\"0.7\",\"office\"],\n    \"1f5c3-fe0f\":[[\"\\uD83D\\uDDC3\\uFE0F\"],\"Objects\",1334,[\"card_file_box\"],32,28,\"0.7\",\"office\"],\n    \"1f5c4-fe0f\":[[\"\\uD83D\\uDDC4\\uFE0F\"],\"Objects\",1335,[\"file_cabinet\"],32,29,\"0.7\",\"office\"],\n    \"1f5d1-fe0f\":[[\"\\uD83D\\uDDD1\\uFE0F\"],\"Objects\",1336,[\"wastebasket\"],32,30,\"0.7\",\"office\"],\n    \"1f5d2-fe0f\":[[\"\\uD83D\\uDDD2\\uFE0F\"],\"Objects\",1320,[\"spiral_note_pad\"],32,31,\"0.7\",\"office\"],\n    \"1f5d3-fe0f\":[[\"\\uD83D\\uDDD3\\uFE0F\"],\"Objects\",1321,[\"spiral_calendar_pad\"],32,32,\"0.7\",\"office\"],\n    \"1f5dc-fe0f\":[[\"\\uD83D\\uDDDC\\uFE0F\"],\"Objects\",1359,[\"compression\"],32,33,\"0.7\",\"tool\"],\n    \"1f5dd-fe0f\":[[\"\\uD83D\\uDDDD\\uFE0F\"],\"Objects\",1342,[\"old_key\"],32,34,\"0.7\",\"lock\"],\n    \"1f5de-fe0f\":[[\"\\uD83D\\uDDDE\\uFE0F\"],\"Objects\",1280,[\"rolled_up_newspaper\"],32,35,\"0.7\",\"book-paper\"],\n    \"1f5e1-fe0f\":[[\"\\uD83D\\uDDE1\\uFE0F\"],\"Objects\",1348,[\"dagger_knife\"],32,36,\"0.7\",\"tool\"],\n    \"1f5e3-fe0f\":[[\"\\uD83D\\uDDE3\\uFE0F\"],\"People & Body\",545,[\"speaking_head_in_silhouette\"],32,37,\"0.7\",\"person-symbol\"],\n    \"1f5e8-fe0f\":[[\"\\uD83D\\uDDE8\\uFE0F\"],\"Smileys & Emotion\",166,[\"left_speech_bubble\"],32,38,\"2.0\",\"emotion\"],\n    \"1f5ef-fe0f\":[[\"\\uD83D\\uDDEF\\uFE0F\"],\"Smileys & Emotion\",167,[\"right_anger_bubble\"],32,39,\"0.7\",\"emotion\"],\n    \"1f5f3-fe0f\":[[\"\\uD83D\\uDDF3\\uFE0F\"],\"Objects\",1306,[\"ballot_box_with_ballot\"],32,40,\"0.7\",\"mail\"],\n    \"1f5fa-fe0f\":[[\"\\uD83D\\uDDFA\\uFE0F\"],\"Travel & Places\",855,[\"world_map\"],32,41,\"0.7\",\"place-map\"],\n    \"1f5fb\":[[\"\\uD83D\\uDDFB\"],\"Travel & Places\",861,[\"mount_fuji\"],32,42,\"0.6\",\"place-geographic\"],\n    \"1f5fc\":[[\"\\uD83D\\uDDFC\"],\"Travel & Places\",892,[\"tokyo_tower\"],32,43,\"0.6\",\"place-building\"],\n    \"1f5fd\":[[\"\\uD83D\\uDDFD\"],\"Travel & Places\",893,[\"statue_of_liberty\"],32,44,\"0.6\",\"place-building\"],\n    \"1f5fe\":[[\"\\uD83D\\uDDFE\"],\"Travel & Places\",856,[\"japan\"],32,45,\"0.6\",\"place-map\"],\n    \"1f5ff\":[[\"\\uD83D\\uDDFF\"],\"Objects\",1415,[\"moyai\"],32,46,\"0.6\",\"other-object\"],\n    \"1f600\":[[\"\\uD83D\\uDE00\"],\"Smileys & Emotion\",1,[\"grinning\"],32,47,\"1.0\",\"face-smiling\",\":D\"],\n    \"1f601\":[[\"\\uD83D\\uDE01\"],\"Smileys & Emotion\",4,[\"grin\"],32,48,\"0.6\",\"face-smiling\"],\n    \"1f602\":[[\"\\uD83D\\uDE02\"],\"Smileys & Emotion\",8,[\"joy\"],32,49,\"0.6\",\"face-smiling\"],\n    \"1f603\":[[\"\\uD83D\\uDE03\"],\"Smileys & Emotion\",2,[\"smiley\"],32,50,\"0.6\",\"face-smiling\",\":)\"],\n    \"1f604\":[[\"\\uD83D\\uDE04\"],\"Smileys & Emotion\",3,[\"smile\"],32,51,\"0.6\",\"face-smiling\",\":)\"],\n    \"1f605\":[[\"\\uD83D\\uDE05\"],\"Smileys & Emotion\",6,[\"sweat_smile\"],32,52,\"0.6\",\"face-smiling\"],\n    \"1f606\":[[\"\\uD83D\\uDE06\"],\"Smileys & Emotion\",5,[\"laughing\",\"satisfied\"],32,53,\"0.6\",\"face-smiling\"],\n    \"1f607\":[[\"\\uD83D\\uDE07\"],\"Smileys & Emotion\",14,[\"innocent\"],32,54,\"1.0\",\"face-smiling\"],\n    \"1f608\":[[\"\\uD83D\\uDE08\"],\"Smileys & Emotion\",107,[\"smiling_imp\"],32,55,\"1.0\",\"face-negative\"],\n    \"1f609\":[[\"\\uD83D\\uDE09\"],\"Smileys & Emotion\",12,[\"wink\"],32,56,\"0.6\",\"face-smiling\",\";)\"],\n    \"1f60a\":[[\"\\uD83D\\uDE0A\"],\"Smileys & Emotion\",13,[\"blush\"],32,57,\"0.6\",\"face-smiling\",\":)\"],\n    \"1f60b\":[[\"\\uD83D\\uDE0B\"],\"Smileys & Emotion\",24,[\"yum\"],32,58,\"0.6\",\"face-tongue\"],\n    \"1f60c\":[[\"\\uD83D\\uDE0C\"],\"Smileys & Emotion\",53,[\"relieved\"],32,59,\"0.6\",\"face-sleepy\"],\n    \"1f60d\":[[\"\\uD83D\\uDE0D\"],\"Smileys & Emotion\",16,[\"heart_eyes\"],32,60,\"0.6\",\"face-affection\"],\n    \"1f60e\":[[\"\\uD83D\\uDE0E\"],\"Smileys & Emotion\",74,[\"sunglasses\"],32,61,\"1.0\",\"face-glasses\"],\n    \"1f60f\":[[\"\\uD83D\\uDE0F\"],\"Smileys & Emotion\",44,[\"smirk\"],33,0,\"0.6\",\"face-neutral-skeptical\"],\n    \"1f610\":[[\"\\uD83D\\uDE10\"],\"Smileys & Emotion\",39,[\"neutral_face\"],33,1,\"0.7\",\"face-neutral-skeptical\"],\n    \"1f611\":[[\"\\uD83D\\uDE11\"],\"Smileys & Emotion\",40,[\"expressionless\"],33,2,\"1.0\",\"face-neutral-skeptical\"],\n    \"1f612\":[[\"\\uD83D\\uDE12\"],\"Smileys & Emotion\",45,[\"unamused\"],33,3,\"0.6\",\"face-neutral-skeptical\",\":(\"],\n    \"1f613\":[[\"\\uD83D\\uDE13\"],\"Smileys & Emotion\",99,[\"sweat\"],33,4,\"0.6\",\"face-concerned\"],\n    \"1f614\":[[\"\\uD83D\\uDE14\"],\"Smileys & Emotion\",54,[\"pensive\"],33,5,\"0.6\",\"face-sleepy\"],\n    \"1f615\":[[\"\\uD83D\\uDE15\"],\"Smileys & Emotion\",77,[\"confused\"],33,6,\"1.0\",\"face-concerned\"],\n    \"1f616\":[[\"\\uD83D\\uDE16\"],\"Smileys & Emotion\",96,[\"confounded\"],33,7,\"0.6\",\"face-concerned\"],\n    \"1f617\":[[\"\\uD83D\\uDE17\"],\"Smileys & Emotion\",19,[\"kissing\"],33,8,\"1.0\",\"face-affection\"],\n    \"1f618\":[[\"\\uD83D\\uDE18\"],\"Smileys & Emotion\",18,[\"kissing_heart\"],33,9,\"0.6\",\"face-affection\"],\n    \"1f619\":[[\"\\uD83D\\uDE19\"],\"Smileys & Emotion\",22,[\"kissing_smiling_eyes\"],33,10,\"1.0\",\"face-affection\"],\n    \"1f61a\":[[\"\\uD83D\\uDE1A\"],\"Smileys & Emotion\",21,[\"kissing_closed_eyes\"],33,11,\"0.6\",\"face-affection\"],\n    \"1f61b\":[[\"\\uD83D\\uDE1B\"],\"Smileys & Emotion\",25,[\"stuck_out_tongue\"],33,12,\"1.0\",\"face-tongue\",\":p\"],\n    \"1f61c\":[[\"\\uD83D\\uDE1C\"],\"Smileys & Emotion\",26,[\"stuck_out_tongue_winking_eye\"],33,13,\"0.6\",\"face-tongue\",\";p\"],\n    \"1f61d\":[[\"\\uD83D\\uDE1D\"],\"Smileys & Emotion\",28,[\"stuck_out_tongue_closed_eyes\"],33,14,\"0.6\",\"face-tongue\"],\n    \"1f61e\":[[\"\\uD83D\\uDE1E\"],\"Smileys & Emotion\",98,[\"disappointed\"],33,15,\"0.6\",\"face-concerned\",\":(\"],\n    \"1f61f\":[[\"\\uD83D\\uDE1F\"],\"Smileys & Emotion\",79,[\"worried\"],33,16,\"1.0\",\"face-concerned\"],\n    \"1f620\":[[\"\\uD83D\\uDE20\"],\"Smileys & Emotion\",105,[\"angry\"],33,17,\"0.6\",\"face-negative\"],\n    \"1f621\":[[\"\\uD83D\\uDE21\"],\"Smileys & Emotion\",104,[\"rage\"],33,18,\"0.6\",\"face-negative\"],\n    \"1f622\":[[\"\\uD83D\\uDE22\"],\"Smileys & Emotion\",93,[\"cry\"],33,19,\"0.6\",\"face-concerned\",\":'(\"],\n    \"1f623\":[[\"\\uD83D\\uDE23\"],\"Smileys & Emotion\",97,[\"persevere\"],33,20,\"0.6\",\"face-concerned\"],\n    \"1f624\":[[\"\\uD83D\\uDE24\"],\"Smileys & Emotion\",103,[\"triumph\"],33,21,\"0.6\",\"face-negative\"],\n    \"1f625\":[[\"\\uD83D\\uDE25\"],\"Smileys & Emotion\",92,[\"disappointed_relieved\"],33,22,\"0.6\",\"face-concerned\"],\n    \"1f626\":[[\"\\uD83D\\uDE26\"],\"Smileys & Emotion\",88,[\"frowning\"],33,23,\"1.0\",\"face-concerned\"],\n    \"1f627\":[[\"\\uD83D\\uDE27\"],\"Smileys & Emotion\",89,[\"anguished\"],33,24,\"1.0\",\"face-concerned\"],\n    \"1f628\":[[\"\\uD83D\\uDE28\"],\"Smileys & Emotion\",90,[\"fearful\"],33,25,\"0.6\",\"face-concerned\"],\n    \"1f629\":[[\"\\uD83D\\uDE29\"],\"Smileys & Emotion\",100,[\"weary\"],33,26,\"0.6\",\"face-concerned\"],\n    \"1f62a\":[[\"\\uD83D\\uDE2A\"],\"Smileys & Emotion\",55,[\"sleepy\"],33,27,\"0.6\",\"face-sleepy\"],\n    \"1f62b\":[[\"\\uD83D\\uDE2B\"],\"Smileys & Emotion\",101,[\"tired_face\"],33,28,\"0.6\",\"face-concerned\"],\n    \"1f62c\":[[\"\\uD83D\\uDE2C\"],\"Smileys & Emotion\",47,[\"grimacing\"],33,29,\"1.0\",\"face-neutral-skeptical\"],\n    \"1f62d\":[[\"\\uD83D\\uDE2D\"],\"Smileys & Emotion\",94,[\"sob\"],33,30,\"0.6\",\"face-concerned\",\":'(\"],\n    \"1f62e-200d-1f4a8\":[[\"\\uD83D\\uDE2E\\u200D\\uD83D\\uDCA8\"],\"Smileys & Emotion\",48,[\"face_exhaling\"],33,31,\"13.1\",\"face-neutral-skeptical\"],\n    \"1f62e\":[[\"\\uD83D\\uDE2E\"],\"Smileys & Emotion\",82,[\"open_mouth\"],33,32,\"1.0\",\"face-concerned\"],\n    \"1f62f\":[[\"\\uD83D\\uDE2F\"],\"Smileys & Emotion\",83,[\"hushed\"],33,33,\"1.0\",\"face-concerned\"],\n    \"1f630\":[[\"\\uD83D\\uDE30\"],\"Smileys & Emotion\",91,[\"cold_sweat\"],33,34,\"0.6\",\"face-concerned\"],\n    \"1f631\":[[\"\\uD83D\\uDE31\"],\"Smileys & Emotion\",95,[\"scream\"],33,35,\"0.6\",\"face-concerned\"],\n    \"1f632\":[[\"\\uD83D\\uDE32\"],\"Smileys & Emotion\",84,[\"astonished\"],33,36,\"0.6\",\"face-concerned\"],\n    \"1f633\":[[\"\\uD83D\\uDE33\"],\"Smileys & Emotion\",85,[\"flushed\"],33,37,\"0.6\",\"face-concerned\"],\n    \"1f634\":[[\"\\uD83D\\uDE34\"],\"Smileys & Emotion\",57,[\"sleeping\"],33,38,\"1.0\",\"face-sleepy\"],\n    \"1f635-200d-1f4ab\":[[\"\\uD83D\\uDE35\\u200D\\uD83D\\uDCAB\"],\"Smileys & Emotion\",69,[\"face_with_spiral_eyes\"],33,39,\"13.1\",\"face-unwell\"],\n    \"1f635\":[[\"\\uD83D\\uDE35\"],\"Smileys & Emotion\",68,[\"dizzy_face\"],33,40,\"0.6\",\"face-unwell\"],\n    \"1f636-200d-1f32b-fe0f\":[[\"\\uD83D\\uDE36\\u200D\\uD83C\\uDF2B\\uFE0F\"],\"Smileys & Emotion\",43,[\"face_in_clouds\"],33,41,\"13.1\",\"face-neutral-skeptical\"],\n    \"1f636\":[[\"\\uD83D\\uDE36\"],\"Smileys & Emotion\",41,[\"no_mouth\"],33,42,\"1.0\",\"face-neutral-skeptical\"],\n    \"1f637\":[[\"\\uD83D\\uDE37\"],\"Smileys & Emotion\",59,[\"mask\"],33,43,\"0.6\",\"face-unwell\"],\n    \"1f638\":[[\"\\uD83D\\uDE38\"],\"Smileys & Emotion\",120,[\"smile_cat\"],33,44,\"0.6\",\"cat-face\"],\n    \"1f639\":[[\"\\uD83D\\uDE39\"],\"Smileys & Emotion\",121,[\"joy_cat\"],33,45,\"0.6\",\"cat-face\"],\n    \"1f63a\":[[\"\\uD83D\\uDE3A\"],\"Smileys & Emotion\",119,[\"smiley_cat\"],33,46,\"0.6\",\"cat-face\"],\n    \"1f63b\":[[\"\\uD83D\\uDE3B\"],\"Smileys & Emotion\",122,[\"heart_eyes_cat\"],33,47,\"0.6\",\"cat-face\"],\n    \"1f63c\":[[\"\\uD83D\\uDE3C\"],\"Smileys & Emotion\",123,[\"smirk_cat\"],33,48,\"0.6\",\"cat-face\"],\n    \"1f63d\":[[\"\\uD83D\\uDE3D\"],\"Smileys & Emotion\",124,[\"kissing_cat\"],33,49,\"0.6\",\"cat-face\"],\n    \"1f63e\":[[\"\\uD83D\\uDE3E\"],\"Smileys & Emotion\",127,[\"pouting_cat\"],33,50,\"0.6\",\"cat-face\"],\n    \"1f63f\":[[\"\\uD83D\\uDE3F\"],\"Smileys & Emotion\",126,[\"crying_cat_face\"],33,51,\"0.6\",\"cat-face\"],\n    \"1f640\":[[\"\\uD83D\\uDE40\"],\"Smileys & Emotion\",125,[\"scream_cat\"],33,52,\"0.6\",\"cat-face\"],\n    \"1f641\":[[\"\\uD83D\\uDE41\"],\"Smileys & Emotion\",80,[\"slightly_frowning_face\"],33,53,\"1.0\",\"face-concerned\"],\n    \"1f642-200d-2194-fe0f\":[[\"\\uD83D\\uDE42\\u200D\\u2194\\uFE0F\"],\"Smileys & Emotion\",51,[\"head_shaking_horizontally\"],33,54,\"15.1\",\"face-neutral-skeptical\"],\n    \"1f642-200d-2195-fe0f\":[[\"\\uD83D\\uDE42\\u200D\\u2195\\uFE0F\"],\"Smileys & Emotion\",52,[\"head_shaking_vertically\"],33,55,\"15.1\",\"face-neutral-skeptical\"],\n    \"1f642\":[[\"\\uD83D\\uDE42\"],\"Smileys & Emotion\",9,[\"slightly_smiling_face\"],33,56,\"1.0\",\"face-smiling\"],\n    \"1f643\":[[\"\\uD83D\\uDE43\"],\"Smileys & Emotion\",10,[\"upside_down_face\"],33,57,\"1.0\",\"face-smiling\"],\n    \"1f644\":[[\"\\uD83D\\uDE44\"],\"Smileys & Emotion\",46,[\"face_with_rolling_eyes\"],33,58,\"1.0\",\"face-neutral-skeptical\"],\n    \"1f645-200d-2640-fe0f\":[[\"\\uD83D\\uDE45\\u200D\\u2640\\uFE0F\",\"\\uD83D\\uDE45\"],\"People & Body\",267,[\"woman-gesturing-no\",\"no_good\"],33,59,\"4.0\",\"person-gesture\"],\n    \"1f645-200d-2642-fe0f\":[[\"\\uD83D\\uDE45\\u200D\\u2642\\uFE0F\"],\"People & Body\",266,[\"man-gesturing-no\"],34,3,\"4.0\",\"person-gesture\"],\n    \"1f646-200d-2640-fe0f\":[[\"\\uD83D\\uDE46\\u200D\\u2640\\uFE0F\",\"\\uD83D\\uDE46\"],\"People & Body\",270,[\"woman-gesturing-ok\",\"ok_woman\"],34,15,\"4.0\",\"person-gesture\"],\n    \"1f646-200d-2642-fe0f\":[[\"\\uD83D\\uDE46\\u200D\\u2642\\uFE0F\"],\"People & Body\",269,[\"man-gesturing-ok\"],34,21,\"4.0\",\"person-gesture\"],\n    \"1f647-200d-2640-fe0f\":[[\"\\uD83D\\uDE47\\u200D\\u2640\\uFE0F\"],\"People & Body\",282,[\"woman-bowing\"],34,33,\"4.0\",\"person-gesture\"],\n    \"1f647-200d-2642-fe0f\":[[\"\\uD83D\\uDE47\\u200D\\u2642\\uFE0F\"],\"People & Body\",281,[\"man-bowing\"],34,39,\"4.0\",\"person-gesture\"],\n    \"1f647\":[[\"\\uD83D\\uDE47\"],\"People & Body\",280,[\"bow\"],34,45,\"0.6\",\"person-gesture\"],\n    \"1f648\":[[\"\\uD83D\\uDE48\"],\"Smileys & Emotion\",128,[\"see_no_evil\"],34,51,\"0.6\",\"monkey-face\"],\n    \"1f649\":[[\"\\uD83D\\uDE49\"],\"Smileys & Emotion\",129,[\"hear_no_evil\"],34,52,\"0.6\",\"monkey-face\"],\n    \"1f64a\":[[\"\\uD83D\\uDE4A\"],\"Smileys & Emotion\",130,[\"speak_no_evil\"],34,53,\"0.6\",\"monkey-face\"],\n    \"1f64b-200d-2640-fe0f\":[[\"\\uD83D\\uDE4B\\u200D\\u2640\\uFE0F\",\"\\uD83D\\uDE4B\"],\"People & Body\",276,[\"woman-raising-hand\",\"raising_hand\"],34,54,\"4.0\",\"person-gesture\"],\n    \"1f64b-200d-2642-fe0f\":[[\"\\uD83D\\uDE4B\\u200D\\u2642\\uFE0F\"],\"People & Body\",275,[\"man-raising-hand\"],34,60,\"4.0\",\"person-gesture\"],\n    \"1f64c\":[[\"\\uD83D\\uDE4C\"],\"People & Body\",204,[\"raised_hands\"],35,10,\"0.6\",\"hands\"],\n    \"1f64d-200d-2640-fe0f\":[[\"\\uD83D\\uDE4D\\u200D\\u2640\\uFE0F\",\"\\uD83D\\uDE4D\"],\"People & Body\",261,[\"woman-frowning\",\"person_frowning\"],35,16,\"4.0\",\"person-gesture\"],\n    \"1f64d-200d-2642-fe0f\":[[\"\\uD83D\\uDE4D\\u200D\\u2642\\uFE0F\"],\"People & Body\",260,[\"man-frowning\"],35,22,\"4.0\",\"person-gesture\"],\n    \"1f64e-200d-2640-fe0f\":[[\"\\uD83D\\uDE4E\\u200D\\u2640\\uFE0F\",\"\\uD83D\\uDE4E\"],\"People & Body\",264,[\"woman-pouting\",\"person_with_pouting_face\"],35,34,\"4.0\",\"person-gesture\"],\n    \"1f64e-200d-2642-fe0f\":[[\"\\uD83D\\uDE4E\\u200D\\u2642\\uFE0F\"],\"People & Body\",263,[\"man-pouting\"],35,40,\"4.0\",\"person-gesture\"],\n    \"1f64f\":[[\"\\uD83D\\uDE4F\"],\"People & Body\",209,[\"pray\"],35,52,\"0.6\",\"hands\"],\n    \"1f680\":[[\"\\uD83D\\uDE80\"],\"Travel & Places\",987,[\"rocket\"],35,58,\"0.6\",\"transport-air\"],\n    \"1f681\":[[\"\\uD83D\\uDE81\"],\"Travel & Places\",982,[\"helicopter\"],35,59,\"1.0\",\"transport-air\"],\n    \"1f682\":[[\"\\uD83D\\uDE82\"],\"Travel & Places\",917,[\"steam_locomotive\"],35,60,\"1.0\",\"transport-ground\"],\n    \"1f683\":[[\"\\uD83D\\uDE83\"],\"Travel & Places\",918,[\"railway_car\"],35,61,\"0.6\",\"transport-ground\"],\n    \"1f684\":[[\"\\uD83D\\uDE84\"],\"Travel & Places\",919,[\"bullettrain_side\"],36,0,\"0.6\",\"transport-ground\"],\n    \"1f685\":[[\"\\uD83D\\uDE85\"],\"Travel & Places\",920,[\"bullettrain_front\"],36,1,\"0.6\",\"transport-ground\"],\n    \"1f686\":[[\"\\uD83D\\uDE86\"],\"Travel & Places\",921,[\"train2\"],36,2,\"1.0\",\"transport-ground\"],\n    \"1f687\":[[\"\\uD83D\\uDE87\"],\"Travel & Places\",922,[\"metro\"],36,3,\"0.6\",\"transport-ground\"],\n    \"1f688\":[[\"\\uD83D\\uDE88\"],\"Travel & Places\",923,[\"light_rail\"],36,4,\"1.0\",\"transport-ground\"],\n    \"1f689\":[[\"\\uD83D\\uDE89\"],\"Travel & Places\",924,[\"station\"],36,5,\"0.6\",\"transport-ground\"],\n    \"1f68a\":[[\"\\uD83D\\uDE8A\"],\"Travel & Places\",925,[\"tram\"],36,6,\"1.0\",\"transport-ground\"],\n    \"1f68b\":[[\"\\uD83D\\uDE8B\"],\"Travel & Places\",928,[\"train\"],36,7,\"1.0\",\"transport-ground\"],\n    \"1f68c\":[[\"\\uD83D\\uDE8C\"],\"Travel & Places\",929,[\"bus\"],36,8,\"0.6\",\"transport-ground\"],\n    \"1f68d\":[[\"\\uD83D\\uDE8D\"],\"Travel & Places\",930,[\"oncoming_bus\"],36,9,\"0.7\",\"transport-ground\"],\n    \"1f68e\":[[\"\\uD83D\\uDE8E\"],\"Travel & Places\",931,[\"trolleybus\"],36,10,\"1.0\",\"transport-ground\"],\n    \"1f68f\":[[\"\\uD83D\\uDE8F\"],\"Travel & Places\",956,[\"busstop\"],36,11,\"0.6\",\"transport-ground\"],\n    \"1f690\":[[\"\\uD83D\\uDE90\"],\"Travel & Places\",932,[\"minibus\"],36,12,\"1.0\",\"transport-ground\"],\n    \"1f691\":[[\"\\uD83D\\uDE91\"],\"Travel & Places\",933,[\"ambulance\"],36,13,\"0.6\",\"transport-ground\"],\n    \"1f692\":[[\"\\uD83D\\uDE92\"],\"Travel & Places\",934,[\"fire_engine\"],36,14,\"0.6\",\"transport-ground\"],\n    \"1f693\":[[\"\\uD83D\\uDE93\"],\"Travel & Places\",935,[\"police_car\"],36,15,\"0.6\",\"transport-ground\"],\n    \"1f694\":[[\"\\uD83D\\uDE94\"],\"Travel & Places\",936,[\"oncoming_police_car\"],36,16,\"0.7\",\"transport-ground\"],\n    \"1f695\":[[\"\\uD83D\\uDE95\"],\"Travel & Places\",937,[\"taxi\"],36,17,\"0.6\",\"transport-ground\"],\n    \"1f696\":[[\"\\uD83D\\uDE96\"],\"Travel & Places\",938,[\"oncoming_taxi\"],36,18,\"1.0\",\"transport-ground\"],\n    \"1f697\":[[\"\\uD83D\\uDE97\"],\"Travel & Places\",939,[\"car\",\"red_car\"],36,19,\"0.6\",\"transport-ground\"],\n    \"1f698\":[[\"\\uD83D\\uDE98\"],\"Travel & Places\",940,[\"oncoming_automobile\"],36,20,\"0.7\",\"transport-ground\"],\n    \"1f699\":[[\"\\uD83D\\uDE99\"],\"Travel & Places\",941,[\"blue_car\"],36,21,\"0.6\",\"transport-ground\"],\n    \"1f69a\":[[\"\\uD83D\\uDE9A\"],\"Travel & Places\",943,[\"truck\"],36,22,\"0.6\",\"transport-ground\"],\n    \"1f69b\":[[\"\\uD83D\\uDE9B\"],\"Travel & Places\",944,[\"articulated_lorry\"],36,23,\"1.0\",\"transport-ground\"],\n    \"1f69c\":[[\"\\uD83D\\uDE9C\"],\"Travel & Places\",945,[\"tractor\"],36,24,\"1.0\",\"transport-ground\"],\n    \"1f69d\":[[\"\\uD83D\\uDE9D\"],\"Travel & Places\",926,[\"monorail\"],36,25,\"1.0\",\"transport-ground\"],\n    \"1f69e\":[[\"\\uD83D\\uDE9E\"],\"Travel & Places\",927,[\"mountain_railway\"],36,26,\"1.0\",\"transport-ground\"],\n    \"1f69f\":[[\"\\uD83D\\uDE9F\"],\"Travel & Places\",983,[\"suspension_railway\"],36,27,\"1.0\",\"transport-air\"],\n    \"1f6a0\":[[\"\\uD83D\\uDEA0\"],\"Travel & Places\",984,[\"mountain_cableway\"],36,28,\"1.0\",\"transport-air\"],\n    \"1f6a1\":[[\"\\uD83D\\uDEA1\"],\"Travel & Places\",985,[\"aerial_tramway\"],36,29,\"1.0\",\"transport-air\"],\n    \"1f6a2\":[[\"\\uD83D\\uDEA2\"],\"Travel & Places\",975,[\"ship\"],36,30,\"0.6\",\"transport-water\"],\n    \"1f6a3-200d-2640-fe0f\":[[\"\\uD83D\\uDEA3\\u200D\\u2640\\uFE0F\"],\"People & Body\",472,[\"woman-rowing-boat\"],36,31,\"4.0\",\"person-sport\"],\n    \"1f6a3-200d-2642-fe0f\":[[\"\\uD83D\\uDEA3\\u200D\\u2642\\uFE0F\",\"\\uD83D\\uDEA3\"],\"People & Body\",471,[\"man-rowing-boat\",\"rowboat\"],36,37,\"4.0\",\"person-sport\"],\n    \"1f6a4\":[[\"\\uD83D\\uDEA4\"],\"Travel & Places\",971,[\"speedboat\"],36,49,\"0.6\",\"transport-water\"],\n    \"1f6a5\":[[\"\\uD83D\\uDEA5\"],\"Travel & Places\",963,[\"traffic_light\"],36,50,\"0.6\",\"transport-ground\"],\n    \"1f6a6\":[[\"\\uD83D\\uDEA6\"],\"Travel & Places\",964,[\"vertical_traffic_light\"],36,51,\"1.0\",\"transport-ground\"],\n    \"1f6a7\":[[\"\\uD83D\\uDEA7\"],\"Travel & Places\",966,[\"construction\"],36,52,\"0.6\",\"transport-ground\"],\n    \"1f6a8\":[[\"\\uD83D\\uDEA8\"],\"Travel & Places\",962,[\"rotating_light\"],36,53,\"0.6\",\"transport-ground\"],\n    \"1f6a9\":[[\"\\uD83D\\uDEA9\"],\"Flags\",1643,[\"triangular_flag_on_post\"],36,54,\"0.6\",\"flag\"],\n    \"1f6aa\":[[\"\\uD83D\\uDEAA\"],\"Objects\",1384,[\"door\"],36,55,\"0.6\",\"household\"],\n    \"1f6ab\":[[\"\\uD83D\\uDEAB\"],\"Symbols\",1434,[\"no_entry_sign\"],36,56,\"0.6\",\"warning\"],\n    \"1f6ac\":[[\"\\uD83D\\uDEAC\"],\"Objects\",1409,[\"smoking\"],36,57,\"0.6\",\"other-object\"],\n    \"1f6ad\":[[\"\\uD83D\\uDEAD\"],\"Symbols\",1436,[\"no_smoking\"],36,58,\"0.6\",\"warning\"],\n    \"1f6ae\":[[\"\\uD83D\\uDEAE\"],\"Symbols\",1419,[\"put_litter_in_its_place\"],36,59,\"1.0\",\"transport-sign\"],\n    \"1f6af\":[[\"\\uD83D\\uDEAF\"],\"Symbols\",1437,[\"do_not_litter\"],36,60,\"1.0\",\"warning\"],\n    \"1f6b0\":[[\"\\uD83D\\uDEB0\"],\"Symbols\",1420,[\"potable_water\"],36,61,\"1.0\",\"transport-sign\"],\n    \"1f6b1\":[[\"\\uD83D\\uDEB1\"],\"Symbols\",1438,[\"non-potable_water\"],37,0,\"1.0\",\"warning\"],\n    \"1f6b2\":[[\"\\uD83D\\uDEB2\"],\"Travel & Places\",952,[\"bike\"],37,1,\"0.6\",\"transport-ground\"],\n    \"1f6b3\":[[\"\\uD83D\\uDEB3\"],\"Symbols\",1435,[\"no_bicycles\"],37,2,\"1.0\",\"warning\"],\n    \"1f6b4-200d-2640-fe0f\":[[\"\\uD83D\\uDEB4\\u200D\\u2640\\uFE0F\"],\"People & Body\",484,[\"woman-biking\"],37,3,\"4.0\",\"person-sport\"],\n    \"1f6b4-200d-2642-fe0f\":[[\"\\uD83D\\uDEB4\\u200D\\u2642\\uFE0F\",\"\\uD83D\\uDEB4\"],\"People & Body\",483,[\"man-biking\",\"bicyclist\"],37,9,\"4.0\",\"person-sport\"],\n    \"1f6b5-200d-2640-fe0f\":[[\"\\uD83D\\uDEB5\\u200D\\u2640\\uFE0F\"],\"People & Body\",487,[\"woman-mountain-biking\"],37,21,\"4.0\",\"person-sport\"],\n    \"1f6b5-200d-2642-fe0f\":[[\"\\uD83D\\uDEB5\\u200D\\u2642\\uFE0F\",\"\\uD83D\\uDEB5\"],\"People & Body\",486,[\"man-mountain-biking\",\"mountain_bicyclist\"],37,27,\"4.0\",\"person-sport\"],\n    \"1f6b6-200d-2640-fe0f\":[[\"\\uD83D\\uDEB6\\u200D\\u2640\\uFE0F\"],\"People & Body\",411,[\"woman-walking\"],37,39,\"4.0\",\"person-activity\"],\n    \"1f6b6-200d-2640-fe0f-200d-27a1-fe0f\":[[\"\\uD83D\\uDEB6\\u200D\\u2640\\uFE0F\\u200D\\u27A1\\uFE0F\"],\"People & Body\",413,[\"woman_walking_facing_right\"],37,45,\"15.1\",\"person-activity\"],\n    \"1f6b6-200d-2642-fe0f\":[[\"\\uD83D\\uDEB6\\u200D\\u2642\\uFE0F\",\"\\uD83D\\uDEB6\"],\"People & Body\",410,[\"man-walking\",\"walking\"],37,51,\"4.0\",\"person-activity\"],\n    \"1f6b6-200d-2642-fe0f-200d-27a1-fe0f\":[[\"\\uD83D\\uDEB6\\u200D\\u2642\\uFE0F\\u200D\\u27A1\\uFE0F\"],\"People & Body\",414,[\"man_walking_facing_right\"],37,57,\"15.1\",\"person-activity\"],\n    \"1f6b6-200d-27a1-fe0f\":[[\"\\uD83D\\uDEB6\\u200D\\u27A1\\uFE0F\"],\"People & Body\",412,[\"person_walking_facing_right\"],38,1,\"15.1\",\"person-activity\"],\n    \"1f6b7\":[[\"\\uD83D\\uDEB7\"],\"Symbols\",1439,[\"no_pedestrians\"],38,13,\"1.0\",\"warning\"],\n    \"1f6b8\":[[\"\\uD83D\\uDEB8\"],\"Symbols\",1432,[\"children_crossing\"],38,14,\"1.0\",\"warning\"],\n    \"1f6b9\":[[\"\\uD83D\\uDEB9\"],\"Symbols\",1422,[\"mens\"],38,15,\"0.6\",\"transport-sign\"],\n    \"1f6ba\":[[\"\\uD83D\\uDEBA\"],\"Symbols\",1423,[\"womens\"],38,16,\"0.6\",\"transport-sign\"],\n    \"1f6bb\":[[\"\\uD83D\\uDEBB\"],\"Symbols\",1424,[\"restroom\"],38,17,\"0.6\",\"transport-sign\"],\n    \"1f6bc\":[[\"\\uD83D\\uDEBC\"],\"Symbols\",1425,[\"baby_symbol\"],38,18,\"0.6\",\"transport-sign\"],\n    \"1f6bd\":[[\"\\uD83D\\uDEBD\"],\"Objects\",1391,[\"toilet\"],38,19,\"0.6\",\"household\"],\n    \"1f6be\":[[\"\\uD83D\\uDEBE\"],\"Symbols\",1426,[\"wc\"],38,20,\"0.6\",\"transport-sign\"],\n    \"1f6bf\":[[\"\\uD83D\\uDEBF\"],\"Objects\",1393,[\"shower\"],38,21,\"1.0\",\"household\"],\n    \"1f6c0\":[[\"\\uD83D\\uDEC0\"],\"People & Body\",506,[\"bath\"],38,22,\"0.6\",\"person-resting\"],\n    \"1f6c1\":[[\"\\uD83D\\uDEC1\"],\"Objects\",1394,[\"bathtub\"],38,28,\"1.0\",\"household\"],\n    \"1f6c2\":[[\"\\uD83D\\uDEC2\"],\"Symbols\",1427,[\"passport_control\"],38,29,\"1.0\",\"transport-sign\"],\n    \"1f6c3\":[[\"\\uD83D\\uDEC3\"],\"Symbols\",1428,[\"customs\"],38,30,\"1.0\",\"transport-sign\"],\n    \"1f6c4\":[[\"\\uD83D\\uDEC4\"],\"Symbols\",1429,[\"baggage_claim\"],38,31,\"1.0\",\"transport-sign\"],\n    \"1f6c5\":[[\"\\uD83D\\uDEC5\"],\"Symbols\",1430,[\"left_luggage\"],38,32,\"1.0\",\"transport-sign\"],\n    \"1f6cb-fe0f\":[[\"\\uD83D\\uDECB\\uFE0F\"],\"Objects\",1389,[\"couch_and_lamp\"],38,33,\"0.7\",\"household\"],\n    \"1f6cc\":[[\"\\uD83D\\uDECC\"],\"People & Body\",507,[\"sleeping_accommodation\"],38,34,\"1.0\",\"person-resting\"],\n    \"1f6cd-fe0f\":[[\"\\uD83D\\uDECD\\uFE0F\"],\"Objects\",1178,[\"shopping_bags\"],38,40,\"0.7\",\"clothing\"],\n    \"1f6ce-fe0f\":[[\"\\uD83D\\uDECE\\uFE0F\"],\"Travel & Places\",989,[\"bellhop_bell\"],38,41,\"0.7\",\"hotel\"],\n    \"1f6cf-fe0f\":[[\"\\uD83D\\uDECF\\uFE0F\"],\"Objects\",1388,[\"bed\"],38,42,\"0.7\",\"household\"],\n    \"1f6d0\":[[\"\\uD83D\\uDED0\"],\"Symbols\",1465,[\"place_of_worship\"],38,43,\"1.0\",\"religion\"],\n    \"1f6d1\":[[\"\\uD83D\\uDED1\"],\"Travel & Places\",965,[\"octagonal_sign\"],38,44,\"3.0\",\"transport-ground\"],\n    \"1f6d2\":[[\"\\uD83D\\uDED2\"],\"Objects\",1408,[\"shopping_trolley\"],38,45,\"3.0\",\"household\"],\n    \"1f6d5\":[[\"\\uD83D\\uDED5\"],\"Travel & Places\",896,[\"hindu_temple\"],38,46,\"12.0\",\"place-religious\"],\n    \"1f6d6\":[[\"\\uD83D\\uDED6\"],\"Travel & Places\",873,[\"hut\"],38,47,\"13.0\",\"place-building\"],\n    \"1f6d7\":[[\"\\uD83D\\uDED7\"],\"Objects\",1385,[\"elevator\"],38,48,\"13.0\",\"household\"],\n    \"1f6dc\":[[\"\\uD83D\\uDEDC\"],\"Symbols\",1513,[\"wireless\"],38,49,\"15.0\",\"av-symbol\"],\n    \"1f6dd\":[[\"\\uD83D\\uDEDD\"],\"Travel & Places\",912,[\"playground_slide\"],38,50,\"14.0\",\"place-other\"],\n    \"1f6de\":[[\"\\uD83D\\uDEDE\"],\"Travel & Places\",961,[\"wheel\"],38,51,\"14.0\",\"transport-ground\"],\n    \"1f6df\":[[\"\\uD83D\\uDEDF\"],\"Travel & Places\",968,[\"ring_buoy\"],38,52,\"14.0\",\"transport-water\"],\n    \"1f6e0-fe0f\":[[\"\\uD83D\\uDEE0\\uFE0F\"],\"Objects\",1347,[\"hammer_and_wrench\"],38,53,\"0.7\",\"tool\"],\n    \"1f6e1-fe0f\":[[\"\\uD83D\\uDEE1\\uFE0F\"],\"Objects\",1353,[\"shield\"],38,54,\"0.7\",\"tool\"],\n    \"1f6e2-fe0f\":[[\"\\uD83D\\uDEE2\\uFE0F\"],\"Travel & Places\",959,[\"oil_drum\"],38,55,\"0.7\",\"transport-ground\"],\n    \"1f6e3-fe0f\":[[\"\\uD83D\\uDEE3\\uFE0F\"],\"Travel & Places\",957,[\"motorway\"],38,56,\"0.7\",\"transport-ground\"],\n    \"1f6e4-fe0f\":[[\"\\uD83D\\uDEE4\\uFE0F\"],\"Travel & Places\",958,[\"railway_track\"],38,57,\"0.7\",\"transport-ground\"],\n    \"1f6e5-fe0f\":[[\"\\uD83D\\uDEE5\\uFE0F\"],\"Travel & Places\",974,[\"motor_boat\"],38,58,\"0.7\",\"transport-water\"],\n    \"1f6e9-fe0f\":[[\"\\uD83D\\uDEE9\\uFE0F\"],\"Travel & Places\",977,[\"small_airplane\"],38,59,\"0.7\",\"transport-air\"],\n    \"1f6eb\":[[\"\\uD83D\\uDEEB\"],\"Travel & Places\",978,[\"airplane_departure\"],38,60,\"1.0\",\"transport-air\"],\n    \"1f6ec\":[[\"\\uD83D\\uDEEC\"],\"Travel & Places\",979,[\"airplane_arriving\"],38,61,\"1.0\",\"transport-air\"],\n    \"1f6f0-fe0f\":[[\"\\uD83D\\uDEF0\\uFE0F\"],\"Travel & Places\",986,[\"satellite\"],39,0,\"0.7\",\"transport-air\"],\n    \"1f6f3-fe0f\":[[\"\\uD83D\\uDEF3\\uFE0F\"],\"Travel & Places\",972,[\"passenger_ship\"],39,1,\"0.7\",\"transport-water\"],\n    \"1f6f4\":[[\"\\uD83D\\uDEF4\"],\"Travel & Places\",953,[\"scooter\"],39,2,\"3.0\",\"transport-ground\"],\n    \"1f6f5\":[[\"\\uD83D\\uDEF5\"],\"Travel & Places\",948,[\"motor_scooter\"],39,3,\"3.0\",\"transport-ground\"],\n    \"1f6f6\":[[\"\\uD83D\\uDEF6\"],\"Travel & Places\",970,[\"canoe\"],39,4,\"3.0\",\"transport-water\"],\n    \"1f6f7\":[[\"\\uD83D\\uDEF7\"],\"Activities\",1121,[\"sled\"],39,5,\"5.0\",\"sport\"],\n    \"1f6f8\":[[\"\\uD83D\\uDEF8\"],\"Travel & Places\",988,[\"flying_saucer\"],39,6,\"5.0\",\"transport-air\"],\n    \"1f6f9\":[[\"\\uD83D\\uDEF9\"],\"Travel & Places\",954,[\"skateboard\"],39,7,\"11.0\",\"transport-ground\"],\n    \"1f6fa\":[[\"\\uD83D\\uDEFA\"],\"Travel & Places\",951,[\"auto_rickshaw\"],39,8,\"12.0\",\"transport-ground\"],\n    \"1f6fb\":[[\"\\uD83D\\uDEFB\"],\"Travel & Places\",942,[\"pickup_truck\"],39,9,\"13.0\",\"transport-ground\"],\n    \"1f6fc\":[[\"\\uD83D\\uDEFC\"],\"Travel & Places\",955,[\"roller_skate\"],39,10,\"13.0\",\"transport-ground\"],\n    \"1f7e0\":[[\"\\uD83D\\uDFE0\"],\"Symbols\",1609,[\"large_orange_circle\"],39,11,\"12.0\",\"geometric\"],\n    \"1f7e1\":[[\"\\uD83D\\uDFE1\"],\"Symbols\",1610,[\"large_yellow_circle\"],39,12,\"12.0\",\"geometric\"],\n    \"1f7e2\":[[\"\\uD83D\\uDFE2\"],\"Symbols\",1611,[\"large_green_circle\"],39,13,\"12.0\",\"geometric\"],\n    \"1f7e3\":[[\"\\uD83D\\uDFE3\"],\"Symbols\",1613,[\"large_purple_circle\"],39,14,\"12.0\",\"geometric\"],\n    \"1f7e4\":[[\"\\uD83D\\uDFE4\"],\"Symbols\",1614,[\"large_brown_circle\"],39,15,\"12.0\",\"geometric\"],\n    \"1f7e5\":[[\"\\uD83D\\uDFE5\"],\"Symbols\",1617,[\"large_red_square\"],39,16,\"12.0\",\"geometric\"],\n    \"1f7e6\":[[\"\\uD83D\\uDFE6\"],\"Symbols\",1621,[\"large_blue_square\"],39,17,\"12.0\",\"geometric\"],\n    \"1f7e7\":[[\"\\uD83D\\uDFE7\"],\"Symbols\",1618,[\"large_orange_square\"],39,18,\"12.0\",\"geometric\"],\n    \"1f7e8\":[[\"\\uD83D\\uDFE8\"],\"Symbols\",1619,[\"large_yellow_square\"],39,19,\"12.0\",\"geometric\"],\n    \"1f7e9\":[[\"\\uD83D\\uDFE9\"],\"Symbols\",1620,[\"large_green_square\"],39,20,\"12.0\",\"geometric\"],\n    \"1f7ea\":[[\"\\uD83D\\uDFEA\"],\"Symbols\",1622,[\"large_purple_square\"],39,21,\"12.0\",\"geometric\"],\n    \"1f7eb\":[[\"\\uD83D\\uDFEB\"],\"Symbols\",1623,[\"large_brown_square\"],39,22,\"12.0\",\"geometric\"],\n    \"1f7f0\":[[\"\\uD83D\\uDFF0\"],\"Symbols\",1523,[\"heavy_equals_sign\"],39,23,\"14.0\",\"math\"],\n    \"1f90c\":[[\"\\uD83E\\uDD0C\"],\"People & Body\",182,[\"pinched_fingers\"],39,24,\"13.0\",\"hand-fingers-partial\"],\n    \"1f90d\":[[\"\\uD83E\\uDD0D\"],\"Smileys & Emotion\",155,[\"white_heart\"],39,30,\"12.0\",\"heart\"],\n    \"1f90e\":[[\"\\uD83E\\uDD0E\"],\"Smileys & Emotion\",152,[\"brown_heart\"],39,31,\"12.0\",\"heart\"],\n    \"1f90f\":[[\"\\uD83E\\uDD0F\"],\"People & Body\",183,[\"pinching_hand\"],39,32,\"12.0\",\"hand-fingers-partial\"],\n    \"1f910\":[[\"\\uD83E\\uDD10\"],\"Smileys & Emotion\",37,[\"zipper_mouth_face\"],39,38,\"1.0\",\"face-neutral-skeptical\"],\n    \"1f911\":[[\"\\uD83E\\uDD11\"],\"Smileys & Emotion\",29,[\"money_mouth_face\"],39,39,\"1.0\",\"face-tongue\"],\n    \"1f912\":[[\"\\uD83E\\uDD12\"],\"Smileys & Emotion\",60,[\"face_with_thermometer\"],39,40,\"1.0\",\"face-unwell\"],\n    \"1f913\":[[\"\\uD83E\\uDD13\"],\"Smileys & Emotion\",75,[\"nerd_face\"],39,41,\"1.0\",\"face-glasses\"],\n    \"1f914\":[[\"\\uD83E\\uDD14\"],\"Smileys & Emotion\",35,[\"thinking_face\"],39,42,\"1.0\",\"face-hand\"],\n    \"1f915\":[[\"\\uD83E\\uDD15\"],\"Smileys & Emotion\",61,[\"face_with_head_bandage\"],39,43,\"1.0\",\"face-unwell\"],\n    \"1f916\":[[\"\\uD83E\\uDD16\"],\"Smileys & Emotion\",118,[\"robot_face\"],39,44,\"1.0\",\"face-costume\"],\n    \"1f917\":[[\"\\uD83E\\uDD17\"],\"Smileys & Emotion\",30,[\"hugging_face\"],39,45,\"1.0\",\"face-hand\"],\n    \"1f918\":[[\"\\uD83E\\uDD18\"],\"People & Body\",188,[\"the_horns\",\"sign_of_the_horns\"],39,46,\"1.0\",\"hand-fingers-partial\"],\n    \"1f919\":[[\"\\uD83E\\uDD19\"],\"People & Body\",189,[\"call_me_hand\"],39,52,\"3.0\",\"hand-fingers-partial\"],\n    \"1f91a\":[[\"\\uD83E\\uDD1A\"],\"People & Body\",171,[\"raised_back_of_hand\"],39,58,\"3.0\",\"hand-fingers-open\"],\n    \"1f91b\":[[\"\\uD83E\\uDD1B\"],\"People & Body\",201,[\"left-facing_fist\"],40,2,\"3.0\",\"hand-fingers-closed\"],\n    \"1f91c\":[[\"\\uD83E\\uDD1C\"],\"People & Body\",202,[\"right-facing_fist\"],40,8,\"3.0\",\"hand-fingers-closed\"],\n    \"1f91d\":[[\"\\uD83E\\uDD1D\"],\"People & Body\",208,[\"handshake\"],40,14,\"3.0\",\"hands\"],\n    \"1f91e\":[[\"\\uD83E\\uDD1E\"],\"People & Body\",185,[\"crossed_fingers\",\"hand_with_index_and_middle_fingers_crossed\"],40,40,\"3.0\",\"hand-fingers-partial\"],\n    \"1f91f\":[[\"\\uD83E\\uDD1F\"],\"People & Body\",187,[\"i_love_you_hand_sign\"],40,46,\"5.0\",\"hand-fingers-partial\"],\n    \"1f920\":[[\"\\uD83E\\uDD20\"],\"Smileys & Emotion\",71,[\"face_with_cowboy_hat\"],40,52,\"3.0\",\"face-hat\"],\n    \"1f921\":[[\"\\uD83E\\uDD21\"],\"Smileys & Emotion\",112,[\"clown_face\"],40,53,\"3.0\",\"face-costume\"],\n    \"1f922\":[[\"\\uD83E\\uDD22\"],\"Smileys & Emotion\",62,[\"nauseated_face\"],40,54,\"3.0\",\"face-unwell\"],\n    \"1f923\":[[\"\\uD83E\\uDD23\"],\"Smileys & Emotion\",7,[\"rolling_on_the_floor_laughing\"],40,55,\"3.0\",\"face-smiling\"],\n    \"1f924\":[[\"\\uD83E\\uDD24\"],\"Smileys & Emotion\",56,[\"drooling_face\"],40,56,\"3.0\",\"face-sleepy\"],\n    \"1f925\":[[\"\\uD83E\\uDD25\"],\"Smileys & Emotion\",49,[\"lying_face\"],40,57,\"3.0\",\"face-neutral-skeptical\"],\n    \"1f926-200d-2640-fe0f\":[[\"\\uD83E\\uDD26\\u200D\\u2640\\uFE0F\"],\"People & Body\",285,[\"woman-facepalming\"],40,58,\"4.0\",\"person-gesture\"],\n    \"1f926-200d-2642-fe0f\":[[\"\\uD83E\\uDD26\\u200D\\u2642\\uFE0F\"],\"People & Body\",284,[\"man-facepalming\"],41,2,\"4.0\",\"person-gesture\"],\n    \"1f926\":[[\"\\uD83E\\uDD26\"],\"People & Body\",283,[\"face_palm\"],41,8,\"3.0\",\"person-gesture\"],\n    \"1f927\":[[\"\\uD83E\\uDD27\"],\"Smileys & Emotion\",64,[\"sneezing_face\"],41,14,\"3.0\",\"face-unwell\"],\n    \"1f928\":[[\"\\uD83E\\uDD28\"],\"Smileys & Emotion\",38,[\"face_with_raised_eyebrow\",\"face_with_one_eyebrow_raised\"],41,15,\"5.0\",\"face-neutral-skeptical\"],\n    \"1f929\":[[\"\\uD83E\\uDD29\"],\"Smileys & Emotion\",17,[\"star-struck\",\"grinning_face_with_star_eyes\"],41,16,\"5.0\",\"face-affection\"],\n    \"1f92a\":[[\"\\uD83E\\uDD2A\"],\"Smileys & Emotion\",27,[\"zany_face\",\"grinning_face_with_one_large_and_one_small_eye\"],41,17,\"5.0\",\"face-tongue\"],\n    \"1f92b\":[[\"\\uD83E\\uDD2B\"],\"Smileys & Emotion\",34,[\"shushing_face\",\"face_with_finger_covering_closed_lips\"],41,18,\"5.0\",\"face-hand\"],\n    \"1f92c\":[[\"\\uD83E\\uDD2C\"],\"Smileys & Emotion\",106,[\"face_with_symbols_on_mouth\",\"serious_face_with_symbols_covering_mouth\"],41,19,\"5.0\",\"face-negative\"],\n    \"1f92d\":[[\"\\uD83E\\uDD2D\"],\"Smileys & Emotion\",31,[\"face_with_hand_over_mouth\",\"smiling_face_with_smiling_eyes_and_hand_covering_mouth\"],41,20,\"5.0\",\"face-hand\"],\n    \"1f92e\":[[\"\\uD83E\\uDD2E\"],\"Smileys & Emotion\",63,[\"face_vomiting\",\"face_with_open_mouth_vomiting\"],41,21,\"5.0\",\"face-unwell\"],\n    \"1f92f\":[[\"\\uD83E\\uDD2F\"],\"Smileys & Emotion\",70,[\"exploding_head\",\"shocked_face_with_exploding_head\"],41,22,\"5.0\",\"face-unwell\"],\n    \"1f930\":[[\"\\uD83E\\uDD30\"],\"People & Body\",364,[\"pregnant_woman\"],41,23,\"3.0\",\"person-role\"],\n    \"1f931\":[[\"\\uD83E\\uDD31\"],\"People & Body\",367,[\"breast-feeding\"],41,29,\"5.0\",\"person-role\"],\n    \"1f932\":[[\"\\uD83E\\uDD32\"],\"People & Body\",207,[\"palms_up_together\"],41,35,\"5.0\",\"hands\"],\n    \"1f933\":[[\"\\uD83E\\uDD33\"],\"People & Body\",212,[\"selfie\"],41,41,\"3.0\",\"hand-prop\"],\n    \"1f934\":[[\"\\uD83E\\uDD34\"],\"People & Body\",351,[\"prince\"],41,47,\"3.0\",\"person-role\"],\n    \"1f935-200d-2640-fe0f\":[[\"\\uD83E\\uDD35\\u200D\\u2640\\uFE0F\"],\"People & Body\",360,[\"woman_in_tuxedo\"],41,53,\"13.0\",\"person-role\"],\n    \"1f935-200d-2642-fe0f\":[[\"\\uD83E\\uDD35\\u200D\\u2642\\uFE0F\"],\"People & Body\",359,[\"man_in_tuxedo\"],41,59,\"13.0\",\"person-role\"],\n    \"1f935\":[[\"\\uD83E\\uDD35\"],\"People & Body\",358,[\"person_in_tuxedo\"],42,3,\"3.0\",\"person-role\"],\n    \"1f936\":[[\"\\uD83E\\uDD36\"],\"People & Body\",373,[\"mrs_claus\",\"mother_christmas\"],42,9,\"3.0\",\"person-fantasy\"],\n    \"1f937-200d-2640-fe0f\":[[\"\\uD83E\\uDD37\\u200D\\u2640\\uFE0F\"],\"People & Body\",288,[\"woman-shrugging\"],42,15,\"4.0\",\"person-gesture\"],\n    \"1f937-200d-2642-fe0f\":[[\"\\uD83E\\uDD37\\u200D\\u2642\\uFE0F\"],\"People & Body\",287,[\"man-shrugging\"],42,21,\"4.0\",\"person-gesture\"],\n    \"1f937\":[[\"\\uD83E\\uDD37\"],\"People & Body\",286,[\"shrug\"],42,27,\"3.0\",\"person-gesture\"],\n    \"1f938-200d-2640-fe0f\":[[\"\\uD83E\\uDD38\\u200D\\u2640\\uFE0F\"],\"People & Body\",490,[\"woman-cartwheeling\"],42,33,\"4.0\",\"person-sport\"],\n    \"1f938-200d-2642-fe0f\":[[\"\\uD83E\\uDD38\\u200D\\u2642\\uFE0F\"],\"People & Body\",489,[\"man-cartwheeling\"],42,39,\"4.0\",\"person-sport\"],\n    \"1f938\":[[\"\\uD83E\\uDD38\"],\"People & Body\",488,[\"person_doing_cartwheel\"],42,45,\"3.0\",\"person-sport\"],\n    \"1f939-200d-2640-fe0f\":[[\"\\uD83E\\uDD39\\u200D\\u2640\\uFE0F\"],\"People & Body\",502,[\"woman-juggling\"],42,51,\"4.0\",\"person-sport\"],\n    \"1f939-200d-2642-fe0f\":[[\"\\uD83E\\uDD39\\u200D\\u2642\\uFE0F\"],\"People & Body\",501,[\"man-juggling\"],42,57,\"4.0\",\"person-sport\"],\n    \"1f939\":[[\"\\uD83E\\uDD39\"],\"People & Body\",500,[\"juggling\"],43,1,\"3.0\",\"person-sport\"],\n    \"1f93a\":[[\"\\uD83E\\uDD3A\"],\"People & Body\",460,[\"fencer\"],43,7,\"3.0\",\"person-sport\"],\n    \"1f93c-200d-2640-fe0f\":[[\"\\uD83E\\uDD3C\\u200D\\u2640\\uFE0F\"],\"People & Body\",493,[\"woman-wrestling\"],43,8,\"4.0\",\"person-sport\"],\n    \"1f93c-200d-2642-fe0f\":[[\"\\uD83E\\uDD3C\\u200D\\u2642\\uFE0F\"],\"People & Body\",492,[\"man-wrestling\"],43,9,\"4.0\",\"person-sport\"],\n    \"1f93c\":[[\"\\uD83E\\uDD3C\"],\"People & Body\",491,[\"wrestlers\"],43,10,\"3.0\",\"person-sport\"],\n    \"1f93d-200d-2640-fe0f\":[[\"\\uD83E\\uDD3D\\u200D\\u2640\\uFE0F\"],\"People & Body\",496,[\"woman-playing-water-polo\"],43,11,\"4.0\",\"person-sport\"],\n    \"1f93d-200d-2642-fe0f\":[[\"\\uD83E\\uDD3D\\u200D\\u2642\\uFE0F\"],\"People & Body\",495,[\"man-playing-water-polo\"],43,17,\"4.0\",\"person-sport\"],\n    \"1f93d\":[[\"\\uD83E\\uDD3D\"],\"People & Body\",494,[\"water_polo\"],43,23,\"3.0\",\"person-sport\"],\n    \"1f93e-200d-2640-fe0f\":[[\"\\uD83E\\uDD3E\\u200D\\u2640\\uFE0F\"],\"People & Body\",499,[\"woman-playing-handball\"],43,29,\"4.0\",\"person-sport\"],\n    \"1f93e-200d-2642-fe0f\":[[\"\\uD83E\\uDD3E\\u200D\\u2642\\uFE0F\"],\"People & Body\",498,[\"man-playing-handball\"],43,35,\"4.0\",\"person-sport\"],\n    \"1f93e\":[[\"\\uD83E\\uDD3E\"],\"People & Body\",497,[\"handball\"],43,41,\"3.0\",\"person-sport\"],\n    \"1f93f\":[[\"\\uD83E\\uDD3F\"],\"Activities\",1118,[\"diving_mask\"],43,47,\"12.0\",\"sport\"],\n    \"1f940\":[[\"\\uD83E\\uDD40\"],\"Animals & Nature\",697,[\"wilted_flower\"],43,48,\"3.0\",\"plant-flower\"],\n    \"1f941\":[[\"\\uD83E\\uDD41\"],\"Objects\",1226,[\"drum_with_drumsticks\"],43,49,\"3.0\",\"musical-instrument\"],\n    \"1f942\":[[\"\\uD83E\\uDD42\"],\"Food & Drink\",836,[\"clinking_glasses\"],43,50,\"3.0\",\"drink\"],\n    \"1f943\":[[\"\\uD83E\\uDD43\"],\"Food & Drink\",837,[\"tumbler_glass\"],43,51,\"3.0\",\"drink\"],\n    \"1f944\":[[\"\\uD83E\\uDD44\"],\"Food & Drink\",847,[\"spoon\"],43,52,\"3.0\",\"dishware\"],\n    \"1f945\":[[\"\\uD83E\\uDD45\"],\"Activities\",1114,[\"goal_net\"],43,53,\"3.0\",\"sport\"],\n    \"1f947\":[[\"\\uD83E\\uDD47\"],\"Activities\",1093,[\"first_place_medal\"],43,54,\"3.0\",\"award-medal\"],\n    \"1f948\":[[\"\\uD83E\\uDD48\"],\"Activities\",1094,[\"second_place_medal\"],43,55,\"3.0\",\"award-medal\"],\n    \"1f949\":[[\"\\uD83E\\uDD49\"],\"Activities\",1095,[\"third_place_medal\"],43,56,\"3.0\",\"award-medal\"],\n    \"1f94a\":[[\"\\uD83E\\uDD4A\"],\"Activities\",1112,[\"boxing_glove\"],43,57,\"3.0\",\"sport\"],\n    \"1f94b\":[[\"\\uD83E\\uDD4B\"],\"Activities\",1113,[\"martial_arts_uniform\"],43,58,\"3.0\",\"sport\"],\n    \"1f94c\":[[\"\\uD83E\\uDD4C\"],\"Activities\",1122,[\"curling_stone\"],43,59,\"5.0\",\"sport\"],\n    \"1f94d\":[[\"\\uD83E\\uDD4D\"],\"Activities\",1109,[\"lacrosse\"],43,60,\"11.0\",\"sport\"],\n    \"1f94e\":[[\"\\uD83E\\uDD4E\"],\"Activities\",1098,[\"softball\"],43,61,\"11.0\",\"sport\"],\n    \"1f94f\":[[\"\\uD83E\\uDD4F\"],\"Activities\",1104,[\"flying_disc\"],44,0,\"11.0\",\"sport\"],\n    \"1f950\":[[\"\\uD83E\\uDD50\"],\"Food & Drink\",760,[\"croissant\"],44,1,\"3.0\",\"food-prepared\"],\n    \"1f951\":[[\"\\uD83E\\uDD51\"],\"Food & Drink\",740,[\"avocado\"],44,2,\"3.0\",\"food-vegetable\"],\n    \"1f952\":[[\"\\uD83E\\uDD52\"],\"Food & Drink\",747,[\"cucumber\"],44,3,\"3.0\",\"food-vegetable\"],\n    \"1f953\":[[\"\\uD83E\\uDD53\"],\"Food & Drink\",771,[\"bacon\"],44,4,\"3.0\",\"food-prepared\"],\n    \"1f954\":[[\"\\uD83E\\uDD54\"],\"Food & Drink\",742,[\"potato\"],44,5,\"3.0\",\"food-vegetable\"],\n    \"1f955\":[[\"\\uD83E\\uDD55\"],\"Food & Drink\",743,[\"carrot\"],44,6,\"3.0\",\"food-vegetable\"],\n    \"1f956\":[[\"\\uD83E\\uDD56\"],\"Food & Drink\",761,[\"baguette_bread\"],44,7,\"3.0\",\"food-prepared\"],\n    \"1f957\":[[\"\\uD83E\\uDD57\"],\"Food & Drink\",788,[\"green_salad\"],44,8,\"3.0\",\"food-prepared\"],\n    \"1f958\":[[\"\\uD83E\\uDD58\"],\"Food & Drink\",784,[\"shallow_pan_of_food\"],44,9,\"3.0\",\"food-prepared\"],\n    \"1f959\":[[\"\\uD83E\\uDD59\"],\"Food & Drink\",780,[\"stuffed_flatbread\"],44,10,\"3.0\",\"food-prepared\"],\n    \"1f95a\":[[\"\\uD83E\\uDD5A\"],\"Food & Drink\",782,[\"egg\"],44,11,\"3.0\",\"food-prepared\"],\n    \"1f95b\":[[\"\\uD83E\\uDD5B\"],\"Food & Drink\",825,[\"glass_of_milk\"],44,12,\"3.0\",\"drink\"],\n    \"1f95c\":[[\"\\uD83E\\uDD5C\"],\"Food & Drink\",752,[\"peanuts\"],44,13,\"3.0\",\"food-vegetable\"],\n    \"1f95d\":[[\"\\uD83E\\uDD5D\"],\"Food & Drink\",736,[\"kiwifruit\"],44,14,\"3.0\",\"food-fruit\"],\n    \"1f95e\":[[\"\\uD83E\\uDD5E\"],\"Food & Drink\",765,[\"pancakes\"],44,15,\"3.0\",\"food-prepared\"],\n    \"1f95f\":[[\"\\uD83E\\uDD5F\"],\"Food & Drink\",807,[\"dumpling\"],44,16,\"5.0\",\"food-asian\"],\n    \"1f960\":[[\"\\uD83E\\uDD60\"],\"Food & Drink\",808,[\"fortune_cookie\"],44,17,\"5.0\",\"food-asian\"],\n    \"1f961\":[[\"\\uD83E\\uDD61\"],\"Food & Drink\",809,[\"takeout_box\"],44,18,\"5.0\",\"food-asian\"],\n    \"1f962\":[[\"\\uD83E\\uDD62\"],\"Food & Drink\",844,[\"chopsticks\"],44,19,\"5.0\",\"dishware\"],\n    \"1f963\":[[\"\\uD83E\\uDD63\"],\"Food & Drink\",787,[\"bowl_with_spoon\"],44,20,\"5.0\",\"food-prepared\"],\n    \"1f964\":[[\"\\uD83E\\uDD64\"],\"Food & Drink\",839,[\"cup_with_straw\"],44,21,\"5.0\",\"drink\"],\n    \"1f965\":[[\"\\uD83E\\uDD65\"],\"Food & Drink\",739,[\"coconut\"],44,22,\"5.0\",\"food-fruit\"],\n    \"1f966\":[[\"\\uD83E\\uDD66\"],\"Food & Drink\",749,[\"broccoli\"],44,23,\"5.0\",\"food-vegetable\"],\n    \"1f967\":[[\"\\uD83E\\uDD67\"],\"Food & Drink\",818,[\"pie\"],44,24,\"5.0\",\"food-sweet\"],\n    \"1f968\":[[\"\\uD83E\\uDD68\"],\"Food & Drink\",763,[\"pretzel\"],44,25,\"5.0\",\"food-prepared\"],\n    \"1f969\":[[\"\\uD83E\\uDD69\"],\"Food & Drink\",770,[\"cut_of_meat\"],44,26,\"5.0\",\"food-prepared\"],\n    \"1f96a\":[[\"\\uD83E\\uDD6A\"],\"Food & Drink\",776,[\"sandwich\"],44,27,\"5.0\",\"food-prepared\"],\n    \"1f96b\":[[\"\\uD83E\\uDD6B\"],\"Food & Drink\",792,[\"canned_food\"],44,28,\"5.0\",\"food-prepared\"],\n    \"1f96c\":[[\"\\uD83E\\uDD6C\"],\"Food & Drink\",748,[\"leafy_green\"],44,29,\"11.0\",\"food-vegetable\"],\n    \"1f96d\":[[\"\\uD83E\\uDD6D\"],\"Food & Drink\",728,[\"mango\"],44,30,\"11.0\",\"food-fruit\"],\n    \"1f96e\":[[\"\\uD83E\\uDD6E\"],\"Food & Drink\",805,[\"moon_cake\"],44,31,\"11.0\",\"food-asian\"],\n    \"1f96f\":[[\"\\uD83E\\uDD6F\"],\"Food & Drink\",764,[\"bagel\"],44,32,\"11.0\",\"food-prepared\"],\n    \"1f970\":[[\"\\uD83E\\uDD70\"],\"Smileys & Emotion\",15,[\"smiling_face_with_3_hearts\"],44,33,\"11.0\",\"face-affection\"],\n    \"1f971\":[[\"\\uD83E\\uDD71\"],\"Smileys & Emotion\",102,[\"yawning_face\"],44,34,\"12.0\",\"face-concerned\"],\n    \"1f972\":[[\"\\uD83E\\uDD72\"],\"Smileys & Emotion\",23,[\"smiling_face_with_tear\"],44,35,\"13.0\",\"face-affection\"],\n    \"1f973\":[[\"\\uD83E\\uDD73\"],\"Smileys & Emotion\",72,[\"partying_face\"],44,36,\"11.0\",\"face-hat\"],\n    \"1f974\":[[\"\\uD83E\\uDD74\"],\"Smileys & Emotion\",67,[\"woozy_face\"],44,37,\"11.0\",\"face-unwell\"],\n    \"1f975\":[[\"\\uD83E\\uDD75\"],\"Smileys & Emotion\",65,[\"hot_face\"],44,38,\"11.0\",\"face-unwell\"],\n    \"1f976\":[[\"\\uD83E\\uDD76\"],\"Smileys & Emotion\",66,[\"cold_face\"],44,39,\"11.0\",\"face-unwell\"],\n    \"1f977\":[[\"\\uD83E\\uDD77\"],\"People & Body\",346,[\"ninja\"],44,40,\"13.0\",\"person-role\"],\n    \"1f978\":[[\"\\uD83E\\uDD78\"],\"Smileys & Emotion\",73,[\"disguised_face\"],44,46,\"13.0\",\"face-hat\"],\n    \"1f979\":[[\"\\uD83E\\uDD79\"],\"Smileys & Emotion\",87,[\"face_holding_back_tears\"],44,47,\"14.0\",\"face-concerned\"],\n    \"1f97a\":[[\"\\uD83E\\uDD7A\"],\"Smileys & Emotion\",86,[\"pleading_face\"],44,48,\"11.0\",\"face-concerned\"],\n    \"1f97b\":[[\"\\uD83E\\uDD7B\"],\"Objects\",1168,[\"sari\"],44,49,\"12.0\",\"clothing\"],\n    \"1f97c\":[[\"\\uD83E\\uDD7C\"],\"Objects\",1157,[\"lab_coat\"],44,50,\"11.0\",\"clothing\"],\n    \"1f97d\":[[\"\\uD83E\\uDD7D\"],\"Objects\",1156,[\"goggles\"],44,51,\"11.0\",\"clothing\"],\n    \"1f97e\":[[\"\\uD83E\\uDD7E\"],\"Objects\",1183,[\"hiking_boot\"],44,52,\"11.0\",\"clothing\"],\n    \"1f97f\":[[\"\\uD83E\\uDD7F\"],\"Objects\",1184,[\"womans_flat_shoe\"],44,53,\"11.0\",\"clothing\"],\n    \"1f980\":[[\"\\uD83E\\uDD80\"],\"Animals & Nature\",670,[\"crab\"],44,54,\"1.0\",\"animal-marine\"],\n    \"1f981\":[[\"\\uD83E\\uDD81\"],\"Animals & Nature\",576,[\"lion_face\"],44,55,\"1.0\",\"animal-mammal\"],\n    \"1f982\":[[\"\\uD83E\\uDD82\"],\"Animals & Nature\",686,[\"scorpion\"],44,56,\"1.0\",\"animal-bug\"],\n    \"1f983\":[[\"\\uD83E\\uDD83\"],\"Animals & Nature\",627,[\"turkey\"],44,57,\"1.0\",\"animal-bird\"],\n    \"1f984\":[[\"\\uD83E\\uDD84\"],\"Animals & Nature\",584,[\"unicorn_face\"],44,58,\"1.0\",\"animal-mammal\"],\n    \"1f985\":[[\"\\uD83E\\uDD85\"],\"Animals & Nature\",636,[\"eagle\"],44,59,\"3.0\",\"animal-bird\"],\n    \"1f986\":[[\"\\uD83E\\uDD86\"],\"Animals & Nature\",637,[\"duck\"],44,60,\"3.0\",\"animal-bird\"],\n    \"1f987\":[[\"\\uD83E\\uDD87\"],\"Animals & Nature\",616,[\"bat\"],44,61,\"3.0\",\"animal-mammal\"],\n    \"1f988\":[[\"\\uD83E\\uDD88\"],\"Animals & Nature\",665,[\"shark\"],45,0,\"3.0\",\"animal-marine\"],\n    \"1f989\":[[\"\\uD83E\\uDD89\"],\"Animals & Nature\",639,[\"owl\"],45,1,\"3.0\",\"animal-bird\"],\n    \"1f98a\":[[\"\\uD83E\\uDD8A\"],\"Animals & Nature\",571,[\"fox_face\"],45,2,\"3.0\",\"animal-mammal\"],\n    \"1f98b\":[[\"\\uD83E\\uDD8B\"],\"Animals & Nature\",676,[\"butterfly\"],45,3,\"3.0\",\"animal-bug\"],\n    \"1f98c\":[[\"\\uD83E\\uDD8C\"],\"Animals & Nature\",586,[\"deer\"],45,4,\"3.0\",\"animal-mammal\"],\n    \"1f98d\":[[\"\\uD83E\\uDD8D\"],\"Animals & Nature\",563,[\"gorilla\"],45,5,\"3.0\",\"animal-mammal\"],\n    \"1f98e\":[[\"\\uD83E\\uDD8E\"],\"Animals & Nature\",652,[\"lizard\"],45,6,\"3.0\",\"animal-reptile\"],\n    \"1f98f\":[[\"\\uD83E\\uDD8F\"],\"Animals & Nature\",605,[\"rhinoceros\"],45,7,\"3.0\",\"animal-mammal\"],\n    \"1f990\":[[\"\\uD83E\\uDD90\"],\"Animals & Nature\",672,[\"shrimp\"],45,8,\"3.0\",\"animal-marine\"],\n    \"1f991\":[[\"\\uD83E\\uDD91\"],\"Animals & Nature\",673,[\"squid\"],45,9,\"3.0\",\"animal-marine\"],\n    \"1f992\":[[\"\\uD83E\\uDD92\"],\"Animals & Nature\",602,[\"giraffe_face\"],45,10,\"5.0\",\"animal-mammal\"],\n    \"1f993\":[[\"\\uD83E\\uDD93\"],\"Animals & Nature\",585,[\"zebra_face\"],45,11,\"5.0\",\"animal-mammal\"],\n    \"1f994\":[[\"\\uD83E\\uDD94\"],\"Animals & Nature\",615,[\"hedgehog\"],45,12,\"5.0\",\"animal-mammal\"],\n    \"1f995\":[[\"\\uD83E\\uDD95\"],\"Animals & Nature\",656,[\"sauropod\"],45,13,\"5.0\",\"animal-reptile\"],\n    \"1f996\":[[\"\\uD83E\\uDD96\"],\"Animals & Nature\",657,[\"t-rex\"],45,14,\"5.0\",\"animal-reptile\"],\n    \"1f997\":[[\"\\uD83E\\uDD97\"],\"Animals & Nature\",682,[\"cricket\"],45,15,\"5.0\",\"animal-bug\"],\n    \"1f998\":[[\"\\uD83E\\uDD98\"],\"Animals & Nature\",624,[\"kangaroo\"],45,16,\"11.0\",\"animal-mammal\"],\n    \"1f999\":[[\"\\uD83E\\uDD99\"],\"Animals & Nature\",601,[\"llama\"],45,17,\"11.0\",\"animal-mammal\"],\n    \"1f99a\":[[\"\\uD83E\\uDD9A\"],\"Animals & Nature\",643,[\"peacock\"],45,18,\"11.0\",\"animal-bird\"],\n    \"1f99b\":[[\"\\uD83E\\uDD9B\"],\"Animals & Nature\",606,[\"hippopotamus\"],45,19,\"11.0\",\"animal-mammal\"],\n    \"1f99c\":[[\"\\uD83E\\uDD9C\"],\"Animals & Nature\",644,[\"parrot\"],45,20,\"11.0\",\"animal-bird\"],\n    \"1f99d\":[[\"\\uD83E\\uDD9D\"],\"Animals & Nature\",572,[\"raccoon\"],45,21,\"11.0\",\"animal-mammal\"],\n    \"1f99e\":[[\"\\uD83E\\uDD9E\"],\"Animals & Nature\",671,[\"lobster\"],45,22,\"11.0\",\"animal-marine\"],\n    \"1f99f\":[[\"\\uD83E\\uDD9F\"],\"Animals & Nature\",687,[\"mosquito\"],45,23,\"11.0\",\"animal-bug\"],\n    \"1f9a0\":[[\"\\uD83E\\uDDA0\"],\"Animals & Nature\",690,[\"microbe\"],45,24,\"11.0\",\"animal-bug\"],\n    \"1f9a1\":[[\"\\uD83E\\uDDA1\"],\"Animals & Nature\",625,[\"badger\"],45,25,\"11.0\",\"animal-mammal\"],\n    \"1f9a2\":[[\"\\uD83E\\uDDA2\"],\"Animals & Nature\",638,[\"swan\"],45,26,\"11.0\",\"animal-bird\"],\n    \"1f9a3\":[[\"\\uD83E\\uDDA3\"],\"Animals & Nature\",604,[\"mammoth\"],45,27,\"13.0\",\"animal-mammal\"],\n    \"1f9a4\":[[\"\\uD83E\\uDDA4\"],\"Animals & Nature\",640,[\"dodo\"],45,28,\"13.0\",\"animal-bird\"],\n    \"1f9a5\":[[\"\\uD83E\\uDDA5\"],\"Animals & Nature\",621,[\"sloth\"],45,29,\"12.0\",\"animal-mammal\"],\n    \"1f9a6\":[[\"\\uD83E\\uDDA6\"],\"Animals & Nature\",622,[\"otter\"],45,30,\"12.0\",\"animal-mammal\"],\n    \"1f9a7\":[[\"\\uD83E\\uDDA7\"],\"Animals & Nature\",564,[\"orangutan\"],45,31,\"12.0\",\"animal-mammal\"],\n    \"1f9a8\":[[\"\\uD83E\\uDDA8\"],\"Animals & Nature\",623,[\"skunk\"],45,32,\"12.0\",\"animal-mammal\"],\n    \"1f9a9\":[[\"\\uD83E\\uDDA9\"],\"Animals & Nature\",642,[\"flamingo\"],45,33,\"12.0\",\"animal-bird\"],\n    \"1f9aa\":[[\"\\uD83E\\uDDAA\"],\"Animals & Nature\",674,[\"oyster\"],45,34,\"12.0\",\"animal-marine\"],\n    \"1f9ab\":[[\"\\uD83E\\uDDAB\"],\"Animals & Nature\",614,[\"beaver\"],45,35,\"13.0\",\"animal-mammal\"],\n    \"1f9ac\":[[\"\\uD83E\\uDDAC\"],\"Animals & Nature\",587,[\"bison\"],45,36,\"13.0\",\"animal-mammal\"],\n    \"1f9ad\":[[\"\\uD83E\\uDDAD\"],\"Animals & Nature\",661,[\"seal\"],45,37,\"13.0\",\"animal-marine\"],\n    \"1f9ae\":[[\"\\uD83E\\uDDAE\"],\"Animals & Nature\",567,[\"guide_dog\"],45,38,\"12.0\",\"animal-mammal\"],\n    \"1f9af\":[[\"\\uD83E\\uDDAF\"],\"Objects\",1361,[\"probing_cane\"],45,39,\"12.0\",\"tool\"],\n    \"1f9b4\":[[\"\\uD83E\\uDDB4\"],\"People & Body\",225,[\"bone\"],45,40,\"11.0\",\"body-parts\"],\n    \"1f9b5\":[[\"\\uD83E\\uDDB5\"],\"People & Body\",216,[\"leg\"],45,41,\"11.0\",\"body-parts\"],\n    \"1f9b6\":[[\"\\uD83E\\uDDB6\"],\"People & Body\",217,[\"foot\"],45,47,\"11.0\",\"body-parts\"],\n    \"1f9b7\":[[\"\\uD83E\\uDDB7\"],\"People & Body\",224,[\"tooth\"],45,53,\"11.0\",\"body-parts\"],\n    \"1f9b8-200d-2640-fe0f\":[[\"\\uD83E\\uDDB8\\u200D\\u2640\\uFE0F\"],\"People & Body\",377,[\"female_superhero\"],45,54,\"11.0\",\"person-fantasy\"],\n    \"1f9b8-200d-2642-fe0f\":[[\"\\uD83E\\uDDB8\\u200D\\u2642\\uFE0F\"],\"People & Body\",376,[\"male_superhero\"],45,60,\"11.0\",\"person-fantasy\"],\n    \"1f9b8\":[[\"\\uD83E\\uDDB8\"],\"People & Body\",375,[\"superhero\"],46,4,\"11.0\",\"person-fantasy\"],\n    \"1f9b9-200d-2640-fe0f\":[[\"\\uD83E\\uDDB9\\u200D\\u2640\\uFE0F\"],\"People & Body\",380,[\"female_supervillain\"],46,10,\"11.0\",\"person-fantasy\"],\n    \"1f9b9-200d-2642-fe0f\":[[\"\\uD83E\\uDDB9\\u200D\\u2642\\uFE0F\"],\"People & Body\",379,[\"male_supervillain\"],46,16,\"11.0\",\"person-fantasy\"],\n    \"1f9b9\":[[\"\\uD83E\\uDDB9\"],\"People & Body\",378,[\"supervillain\"],46,22,\"11.0\",\"person-fantasy\"],\n    \"1f9ba\":[[\"\\uD83E\\uDDBA\"],\"Objects\",1158,[\"safety_vest\"],46,28,\"12.0\",\"clothing\"],\n    \"1f9bb\":[[\"\\uD83E\\uDDBB\"],\"People & Body\",219,[\"ear_with_hearing_aid\"],46,29,\"12.0\",\"body-parts\"],\n    \"1f9bc\":[[\"\\uD83E\\uDDBC\"],\"Travel & Places\",950,[\"motorized_wheelchair\"],46,35,\"12.0\",\"transport-ground\"],\n    \"1f9bd\":[[\"\\uD83E\\uDDBD\"],\"Travel & Places\",949,[\"manual_wheelchair\"],46,36,\"12.0\",\"transport-ground\"],\n    \"1f9be\":[[\"\\uD83E\\uDDBE\"],\"People & Body\",214,[\"mechanical_arm\"],46,37,\"12.0\",\"body-parts\"],\n    \"1f9bf\":[[\"\\uD83E\\uDDBF\"],\"People & Body\",215,[\"mechanical_leg\"],46,38,\"12.0\",\"body-parts\"],\n    \"1f9c0\":[[\"\\uD83E\\uDDC0\"],\"Food & Drink\",767,[\"cheese_wedge\"],46,39,\"1.0\",\"food-prepared\"],\n    \"1f9c1\":[[\"\\uD83E\\uDDC1\"],\"Food & Drink\",817,[\"cupcake\"],46,40,\"11.0\",\"food-sweet\"],\n    \"1f9c2\":[[\"\\uD83E\\uDDC2\"],\"Food & Drink\",791,[\"salt\"],46,41,\"11.0\",\"food-prepared\"],\n    \"1f9c3\":[[\"\\uD83E\\uDDC3\"],\"Food & Drink\",841,[\"beverage_box\"],46,42,\"12.0\",\"drink\"],\n    \"1f9c4\":[[\"\\uD83E\\uDDC4\"],\"Food & Drink\",750,[\"garlic\"],46,43,\"12.0\",\"food-vegetable\"],\n    \"1f9c5\":[[\"\\uD83E\\uDDC5\"],\"Food & Drink\",751,[\"onion\"],46,44,\"12.0\",\"food-vegetable\"],\n    \"1f9c6\":[[\"\\uD83E\\uDDC6\"],\"Food & Drink\",781,[\"falafel\"],46,45,\"12.0\",\"food-prepared\"],\n    \"1f9c7\":[[\"\\uD83E\\uDDC7\"],\"Food & Drink\",766,[\"waffle\"],46,46,\"12.0\",\"food-prepared\"],\n    \"1f9c8\":[[\"\\uD83E\\uDDC8\"],\"Food & Drink\",790,[\"butter\"],46,47,\"12.0\",\"food-prepared\"],\n    \"1f9c9\":[[\"\\uD83E\\uDDC9\"],\"Food & Drink\",842,[\"mate_drink\"],46,48,\"12.0\",\"drink\"],\n    \"1f9ca\":[[\"\\uD83E\\uDDCA\"],\"Food & Drink\",843,[\"ice_cube\"],46,49,\"12.0\",\"drink\"],\n    \"1f9cb\":[[\"\\uD83E\\uDDCB\"],\"Food & Drink\",840,[\"bubble_tea\"],46,50,\"13.0\",\"drink\"],\n    \"1f9cc\":[[\"\\uD83E\\uDDCC\"],\"People & Body\",402,[\"troll\"],46,51,\"14.0\",\"person-fantasy\"],\n    \"1f9cd-200d-2640-fe0f\":[[\"\\uD83E\\uDDCD\\u200D\\u2640\\uFE0F\"],\"People & Body\",417,[\"woman_standing\"],46,52,\"12.0\",\"person-activity\"],\n    \"1f9cd-200d-2642-fe0f\":[[\"\\uD83E\\uDDCD\\u200D\\u2642\\uFE0F\"],\"People & Body\",416,[\"man_standing\"],46,58,\"12.0\",\"person-activity\"],\n    \"1f9cd\":[[\"\\uD83E\\uDDCD\"],\"People & Body\",415,[\"standing_person\"],47,2,\"12.0\",\"person-activity\"],\n    \"1f9ce-200d-2640-fe0f\":[[\"\\uD83E\\uDDCE\\u200D\\u2640\\uFE0F\"],\"People & Body\",420,[\"woman_kneeling\"],47,8,\"12.0\",\"person-activity\"],\n    \"1f9ce-200d-2640-fe0f-200d-27a1-fe0f\":[[\"\\uD83E\\uDDCE\\u200D\\u2640\\uFE0F\\u200D\\u27A1\\uFE0F\"],\"People & Body\",422,[\"woman_kneeling_facing_right\"],47,14,\"15.1\",\"person-activity\"],\n    \"1f9ce-200d-2642-fe0f\":[[\"\\uD83E\\uDDCE\\u200D\\u2642\\uFE0F\"],\"People & Body\",419,[\"man_kneeling\"],47,20,\"12.0\",\"person-activity\"],\n    \"1f9ce-200d-2642-fe0f-200d-27a1-fe0f\":[[\"\\uD83E\\uDDCE\\u200D\\u2642\\uFE0F\\u200D\\u27A1\\uFE0F\"],\"People & Body\",423,[\"man_kneeling_facing_right\"],47,26,\"15.1\",\"person-activity\"],\n    \"1f9ce-200d-27a1-fe0f\":[[\"\\uD83E\\uDDCE\\u200D\\u27A1\\uFE0F\"],\"People & Body\",421,[\"person_kneeling_facing_right\"],47,32,\"15.1\",\"person-activity\"],\n    \"1f9ce\":[[\"\\uD83E\\uDDCE\"],\"People & Body\",418,[\"kneeling_person\"],47,38,\"12.0\",\"person-activity\"],\n    \"1f9cf-200d-2640-fe0f\":[[\"\\uD83E\\uDDCF\\u200D\\u2640\\uFE0F\"],\"People & Body\",279,[\"deaf_woman\"],47,44,\"12.0\",\"person-gesture\"],\n    \"1f9cf-200d-2642-fe0f\":[[\"\\uD83E\\uDDCF\\u200D\\u2642\\uFE0F\"],\"People & Body\",278,[\"deaf_man\"],47,50,\"12.0\",\"person-gesture\"],\n    \"1f9cf\":[[\"\\uD83E\\uDDCF\"],\"People & Body\",277,[\"deaf_person\"],47,56,\"12.0\",\"person-gesture\"],\n    \"1f9d0\":[[\"\\uD83E\\uDDD0\"],\"Smileys & Emotion\",76,[\"face_with_monocle\"],48,0,\"5.0\",\"face-glasses\"],\n    \"1f9d1-200d-1f33e\":[[\"\\uD83E\\uDDD1\\u200D\\uD83C\\uDF3E\"],\"People & Body\",301,[\"farmer\"],48,1,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f373\":[[\"\\uD83E\\uDDD1\\u200D\\uD83C\\uDF73\"],\"People & Body\",304,[\"cook\"],48,7,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f37c\":[[\"\\uD83E\\uDDD1\\u200D\\uD83C\\uDF7C\"],\"People & Body\",370,[\"person_feeding_baby\"],48,13,\"13.0\",\"person-role\"],\n    \"1f9d1-200d-1f384\":[[\"\\uD83E\\uDDD1\\u200D\\uD83C\\uDF84\"],\"People & Body\",374,[\"mx_claus\"],48,19,\"13.0\",\"person-fantasy\"],\n    \"1f9d1-200d-1f393\":[[\"\\uD83E\\uDDD1\\u200D\\uD83C\\uDF93\"],\"People & Body\",292,[\"student\"],48,25,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f3a4\":[[\"\\uD83E\\uDDD1\\u200D\\uD83C\\uDFA4\"],\"People & Body\",322,[\"singer\"],48,31,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f3a8\":[[\"\\uD83E\\uDDD1\\u200D\\uD83C\\uDFA8\"],\"People & Body\",325,[\"artist\"],48,37,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f3eb\":[[\"\\uD83E\\uDDD1\\u200D\\uD83C\\uDFEB\"],\"People & Body\",295,[\"teacher\"],48,43,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f3ed\":[[\"\\uD83E\\uDDD1\\u200D\\uD83C\\uDFED\"],\"People & Body\",310,[\"factory_worker\"],48,49,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f4bb\":[[\"\\uD83E\\uDDD1\\u200D\\uD83D\\uDCBB\"],\"People & Body\",319,[\"technologist\"],48,55,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f4bc\":[[\"\\uD83E\\uDDD1\\u200D\\uD83D\\uDCBC\"],\"People & Body\",313,[\"office_worker\"],48,61,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f527\":[[\"\\uD83E\\uDDD1\\u200D\\uD83D\\uDD27\"],\"People & Body\",307,[\"mechanic\"],49,5,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f52c\":[[\"\\uD83E\\uDDD1\\u200D\\uD83D\\uDD2C\"],\"People & Body\",316,[\"scientist\"],49,11,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f680\":[[\"\\uD83E\\uDDD1\\u200D\\uD83D\\uDE80\"],\"People & Body\",331,[\"astronaut\"],49,17,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f692\":[[\"\\uD83E\\uDDD1\\u200D\\uD83D\\uDE92\"],\"People & Body\",334,[\"firefighter\"],49,23,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-1f91d-200d-1f9d1\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1\"],\"People & Body\",508,[\"people_holding_hands\"],49,29,\"12.0\",\"family\"],\n    \"1f9d1-200d-1f9af-200d-27a1-fe0f\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDAF\\u200D\\u27A1\\uFE0F\"],\"People & Body\",425,[\"person_with_white_cane_facing_right\"],49,55,\"15.1\",\"person-activity\"],\n    \"1f9d1-200d-1f9af\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDAF\"],\"People & Body\",424,[\"person_with_probing_cane\"],49,61,\"12.1\",\"person-activity\"],\n    \"1f9d1-200d-1f9b0\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDB0\"],\"People & Body\",247,[\"red_haired_person\"],50,5,\"12.1\",\"person\"],\n    \"1f9d1-200d-1f9b1\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDB1\"],\"People & Body\",249,[\"curly_haired_person\"],50,11,\"12.1\",\"person\"],\n    \"1f9d1-200d-1f9b2\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDB2\"],\"People & Body\",253,[\"bald_person\"],50,17,\"12.1\",\"person\"],\n    \"1f9d1-200d-1f9b3\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDB3\"],\"People & Body\",251,[\"white_haired_person\"],50,23,\"12.1\",\"person\"],\n    \"1f9d1-200d-1f9bc-200d-27a1-fe0f\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDBC\\u200D\\u27A1\\uFE0F\"],\"People & Body\",431,[\"person_in_motorized_wheelchair_facing_right\"],50,29,\"15.1\",\"person-activity\"],\n    \"1f9d1-200d-1f9bc\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDBC\"],\"People & Body\",430,[\"person_in_motorized_wheelchair\"],50,35,\"12.1\",\"person-activity\"],\n    \"1f9d1-200d-1f9bd-200d-27a1-fe0f\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDBD\\u200D\\u27A1\\uFE0F\"],\"People & Body\",437,[\"person_in_manual_wheelchair_facing_right\"],50,41,\"15.1\",\"person-activity\"],\n    \"1f9d1-200d-1f9bd\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDBD\"],\"People & Body\",436,[\"person_in_manual_wheelchair\"],50,47,\"12.1\",\"person-activity\"],\n    \"1f9d1-200d-1f9d1-200d-1f9d2\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDD1\\u200D\\uD83E\\uDDD2\"],\"People & Body\",550,[\"family_adult_adult_child\"],50,53,\"15.1\",\"person-symbol\"],\n    \"1f9d1-200d-1f9d1-200d-1f9d2-200d-1f9d2\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDD1\\u200D\\uD83E\\uDDD2\\u200D\\uD83E\\uDDD2\"],\"People & Body\",551,[\"family_adult_adult_child_child\"],50,54,\"15.1\",\"person-symbol\"],\n    \"1f9d1-200d-1f9d2-200d-1f9d2\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDD2\\u200D\\uD83E\\uDDD2\"],\"People & Body\",553,[\"family_adult_child_child\"],50,55,\"15.1\",\"person-symbol\"],\n    \"1f9d1-200d-1f9d2\":[[\"\\uD83E\\uDDD1\\u200D\\uD83E\\uDDD2\"],\"People & Body\",552,[\"family_adult_child\"],50,56,\"15.1\",\"person-symbol\"],\n    \"1f9d1-200d-2695-fe0f\":[[\"\\uD83E\\uDDD1\\u200D\\u2695\\uFE0F\"],\"People & Body\",289,[\"health_worker\"],50,57,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-2696-fe0f\":[[\"\\uD83E\\uDDD1\\u200D\\u2696\\uFE0F\"],\"People & Body\",298,[\"judge\"],51,1,\"12.1\",\"person-role\"],\n    \"1f9d1-200d-2708-fe0f\":[[\"\\uD83E\\uDDD1\\u200D\\u2708\\uFE0F\"],\"People & Body\",328,[\"pilot\"],51,7,\"12.1\",\"person-role\"],\n    \"1f9d1\":[[\"\\uD83E\\uDDD1\"],\"People & Body\",235,[\"adult\"],51,13,\"5.0\",\"person\"],\n    \"1f9d2\":[[\"\\uD83E\\uDDD2\"],\"People & Body\",232,[\"child\"],51,19,\"5.0\",\"person\"],\n    \"1f9d3\":[[\"\\uD83E\\uDDD3\"],\"People & Body\",256,[\"older_adult\"],51,25,\"5.0\",\"person\"],\n    \"1f9d4-200d-2640-fe0f\":[[\"\\uD83E\\uDDD4\\u200D\\u2640\\uFE0F\"],\"People & Body\",240,[\"woman_with_beard\"],51,31,\"13.1\",\"person\"],\n    \"1f9d4-200d-2642-fe0f\":[[\"\\uD83E\\uDDD4\\u200D\\u2642\\uFE0F\"],\"People & Body\",239,[\"man_with_beard\"],51,37,\"13.1\",\"person\"],\n    \"1f9d4\":[[\"\\uD83E\\uDDD4\"],\"People & Body\",238,[\"bearded_person\"],51,43,\"5.0\",\"person\"],\n    \"1f9d5\":[[\"\\uD83E\\uDDD5\"],\"People & Body\",357,[\"person_with_headscarf\"],51,49,\"5.0\",\"person-role\"],\n    \"1f9d6-200d-2640-fe0f\":[[\"\\uD83E\\uDDD6\\u200D\\u2640\\uFE0F\"],\"People & Body\",456,[\"woman_in_steamy_room\"],51,55,\"5.0\",\"person-activity\"],\n    \"1f9d6-200d-2642-fe0f\":[[\"\\uD83E\\uDDD6\\u200D\\u2642\\uFE0F\",\"\\uD83E\\uDDD6\"],\"People & Body\",455,[\"man_in_steamy_room\",\"person_in_steamy_room\"],51,61,\"5.0\",\"person-activity\"],\n    \"1f9d7-200d-2640-fe0f\":[[\"\\uD83E\\uDDD7\\u200D\\u2640\\uFE0F\",\"\\uD83E\\uDDD7\"],\"People & Body\",459,[\"woman_climbing\",\"person_climbing\"],52,11,\"5.0\",\"person-activity\"],\n    \"1f9d7-200d-2642-fe0f\":[[\"\\uD83E\\uDDD7\\u200D\\u2642\\uFE0F\"],\"People & Body\",458,[\"man_climbing\"],52,17,\"5.0\",\"person-activity\"],\n    \"1f9d8-200d-2640-fe0f\":[[\"\\uD83E\\uDDD8\\u200D\\u2640\\uFE0F\",\"\\uD83E\\uDDD8\"],\"People & Body\",505,[\"woman_in_lotus_position\",\"person_in_lotus_position\"],52,29,\"5.0\",\"person-resting\"],\n    \"1f9d8-200d-2642-fe0f\":[[\"\\uD83E\\uDDD8\\u200D\\u2642\\uFE0F\"],\"People & Body\",504,[\"man_in_lotus_position\"],52,35,\"5.0\",\"person-resting\"],\n    \"1f9d9-200d-2640-fe0f\":[[\"\\uD83E\\uDDD9\\u200D\\u2640\\uFE0F\",\"\\uD83E\\uDDD9\"],\"People & Body\",383,[\"female_mage\",\"mage\"],52,47,\"5.0\",\"person-fantasy\"],\n    \"1f9d9-200d-2642-fe0f\":[[\"\\uD83E\\uDDD9\\u200D\\u2642\\uFE0F\"],\"People & Body\",382,[\"male_mage\"],52,53,\"5.0\",\"person-fantasy\"],\n    \"1f9da-200d-2640-fe0f\":[[\"\\uD83E\\uDDDA\\u200D\\u2640\\uFE0F\",\"\\uD83E\\uDDDA\"],\"People & Body\",386,[\"female_fairy\",\"fairy\"],53,3,\"5.0\",\"person-fantasy\"],\n    \"1f9da-200d-2642-fe0f\":[[\"\\uD83E\\uDDDA\\u200D\\u2642\\uFE0F\"],\"People & Body\",385,[\"male_fairy\"],53,9,\"5.0\",\"person-fantasy\"],\n    \"1f9db-200d-2640-fe0f\":[[\"\\uD83E\\uDDDB\\u200D\\u2640\\uFE0F\",\"\\uD83E\\uDDDB\"],\"People & Body\",389,[\"female_vampire\",\"vampire\"],53,21,\"5.0\",\"person-fantasy\"],\n    \"1f9db-200d-2642-fe0f\":[[\"\\uD83E\\uDDDB\\u200D\\u2642\\uFE0F\"],\"People & Body\",388,[\"male_vampire\"],53,27,\"5.0\",\"person-fantasy\"],\n    \"1f9dc-200d-2640-fe0f\":[[\"\\uD83E\\uDDDC\\u200D\\u2640\\uFE0F\"],\"People & Body\",392,[\"mermaid\"],53,39,\"5.0\",\"person-fantasy\"],\n    \"1f9dc-200d-2642-fe0f\":[[\"\\uD83E\\uDDDC\\u200D\\u2642\\uFE0F\",\"\\uD83E\\uDDDC\"],\"People & Body\",391,[\"merman\",\"merperson\"],53,45,\"5.0\",\"person-fantasy\"],\n    \"1f9dd-200d-2640-fe0f\":[[\"\\uD83E\\uDDDD\\u200D\\u2640\\uFE0F\"],\"People & Body\",395,[\"female_elf\"],53,57,\"5.0\",\"person-fantasy\"],\n    \"1f9dd-200d-2642-fe0f\":[[\"\\uD83E\\uDDDD\\u200D\\u2642\\uFE0F\",\"\\uD83E\\uDDDD\"],\"People & Body\",394,[\"male_elf\",\"elf\"],54,1,\"5.0\",\"person-fantasy\"],\n    \"1f9de-200d-2640-fe0f\":[[\"\\uD83E\\uDDDE\\u200D\\u2640\\uFE0F\"],\"People & Body\",398,[\"female_genie\"],54,13,\"5.0\",\"person-fantasy\"],\n    \"1f9de-200d-2642-fe0f\":[[\"\\uD83E\\uDDDE\\u200D\\u2642\\uFE0F\",\"\\uD83E\\uDDDE\"],\"People & Body\",397,[\"male_genie\",\"genie\"],54,14,\"5.0\",\"person-fantasy\"],\n    \"1f9df-200d-2640-fe0f\":[[\"\\uD83E\\uDDDF\\u200D\\u2640\\uFE0F\"],\"People & Body\",401,[\"female_zombie\"],54,16,\"5.0\",\"person-fantasy\"],\n    \"1f9df-200d-2642-fe0f\":[[\"\\uD83E\\uDDDF\\u200D\\u2642\\uFE0F\",\"\\uD83E\\uDDDF\"],\"People & Body\",400,[\"male_zombie\",\"zombie\"],54,17,\"5.0\",\"person-fantasy\"],\n    \"1f9e0\":[[\"\\uD83E\\uDDE0\"],\"People & Body\",221,[\"brain\"],54,19,\"5.0\",\"body-parts\"],\n    \"1f9e1\":[[\"\\uD83E\\uDDE1\"],\"Smileys & Emotion\",146,[\"orange_heart\"],54,20,\"5.0\",\"heart\"],\n    \"1f9e2\":[[\"\\uD83E\\uDDE2\"],\"Objects\",1194,[\"billed_cap\"],54,21,\"5.0\",\"clothing\"],\n    \"1f9e3\":[[\"\\uD83E\\uDDE3\"],\"Objects\",1162,[\"scarf\"],54,22,\"5.0\",\"clothing\"],\n    \"1f9e4\":[[\"\\uD83E\\uDDE4\"],\"Objects\",1163,[\"gloves\"],54,23,\"5.0\",\"clothing\"],\n    \"1f9e5\":[[\"\\uD83E\\uDDE5\"],\"Objects\",1164,[\"coat\"],54,24,\"5.0\",\"clothing\"],\n    \"1f9e6\":[[\"\\uD83E\\uDDE6\"],\"Objects\",1165,[\"socks\"],54,25,\"5.0\",\"clothing\"],\n    \"1f9e7\":[[\"\\uD83E\\uDDE7\"],\"Activities\",1084,[\"red_envelope\"],54,26,\"11.0\",\"event\"],\n    \"1f9e8\":[[\"\\uD83E\\uDDE8\"],\"Activities\",1073,[\"firecracker\"],54,27,\"11.0\",\"event\"],\n    \"1f9e9\":[[\"\\uD83E\\uDDE9\"],\"Activities\",1134,[\"jigsaw\"],54,28,\"11.0\",\"game\"],\n    \"1f9ea\":[[\"\\uD83E\\uDDEA\"],\"Objects\",1371,[\"test_tube\"],54,29,\"11.0\",\"science\"],\n    \"1f9eb\":[[\"\\uD83E\\uDDEB\"],\"Objects\",1372,[\"petri_dish\"],54,30,\"11.0\",\"science\"],\n    \"1f9ec\":[[\"\\uD83E\\uDDEC\"],\"Objects\",1373,[\"dna\"],54,31,\"11.0\",\"science\"],\n    \"1f9ed\":[[\"\\uD83E\\uDDED\"],\"Travel & Places\",857,[\"compass\"],54,32,\"11.0\",\"place-map\"],\n    \"1f9ee\":[[\"\\uD83E\\uDDEE\"],\"Objects\",1250,[\"abacus\"],54,33,\"11.0\",\"computer\"],\n    \"1f9ef\":[[\"\\uD83E\\uDDEF\"],\"Objects\",1407,[\"fire_extinguisher\"],54,34,\"11.0\",\"household\"],\n    \"1f9f0\":[[\"\\uD83E\\uDDF0\"],\"Objects\",1366,[\"toolbox\"],54,35,\"11.0\",\"tool\"],\n    \"1f9f1\":[[\"\\uD83E\\uDDF1\"],\"Travel & Places\",870,[\"bricks\"],54,36,\"11.0\",\"place-building\"],\n    \"1f9f2\":[[\"\\uD83E\\uDDF2\"],\"Objects\",1367,[\"magnet\"],54,37,\"11.0\",\"tool\"],\n    \"1f9f3\":[[\"\\uD83E\\uDDF3\"],\"Travel & Places\",990,[\"luggage\"],54,38,\"11.0\",\"hotel\"],\n    \"1f9f4\":[[\"\\uD83E\\uDDF4\"],\"Objects\",1397,[\"lotion_bottle\"],54,39,\"11.0\",\"household\"],\n    \"1f9f5\":[[\"\\uD83E\\uDDF5\"],\"Activities\",1150,[\"thread\"],54,40,\"11.0\",\"arts & crafts\"],\n    \"1f9f6\":[[\"\\uD83E\\uDDF6\"],\"Activities\",1152,[\"yarn\"],54,41,\"11.0\",\"arts & crafts\"],\n    \"1f9f7\":[[\"\\uD83E\\uDDF7\"],\"Objects\",1398,[\"safety_pin\"],54,42,\"11.0\",\"household\"],\n    \"1f9f8\":[[\"\\uD83E\\uDDF8\"],\"Activities\",1135,[\"teddy_bear\"],54,43,\"11.0\",\"game\"],\n    \"1f9f9\":[[\"\\uD83E\\uDDF9\"],\"Objects\",1399,[\"broom\"],54,44,\"11.0\",\"household\"],\n    \"1f9fa\":[[\"\\uD83E\\uDDFA\"],\"Objects\",1400,[\"basket\"],54,45,\"11.0\",\"household\"],\n    \"1f9fb\":[[\"\\uD83E\\uDDFB\"],\"Objects\",1401,[\"roll_of_paper\"],54,46,\"11.0\",\"household\"],\n    \"1f9fc\":[[\"\\uD83E\\uDDFC\"],\"Objects\",1403,[\"soap\"],54,47,\"11.0\",\"household\"],\n    \"1f9fd\":[[\"\\uD83E\\uDDFD\"],\"Objects\",1406,[\"sponge\"],54,48,\"11.0\",\"household\"],\n    \"1f9fe\":[[\"\\uD83E\\uDDFE\"],\"Objects\",1292,[\"receipt\"],54,49,\"11.0\",\"money\"],\n    \"1f9ff\":[[\"\\uD83E\\uDDFF\"],\"Objects\",1413,[\"nazar_amulet\"],54,50,\"11.0\",\"other-object\"],\n    \"1fa70\":[[\"\\uD83E\\uDE70\"],\"Objects\",1187,[\"ballet_shoes\"],54,51,\"12.0\",\"clothing\"],\n    \"1fa71\":[[\"\\uD83E\\uDE71\"],\"Objects\",1169,[\"one-piece_swimsuit\"],54,52,\"12.0\",\"clothing\"],\n    \"1fa72\":[[\"\\uD83E\\uDE72\"],\"Objects\",1170,[\"briefs\"],54,53,\"12.0\",\"clothing\"],\n    \"1fa73\":[[\"\\uD83E\\uDE73\"],\"Objects\",1171,[\"shorts\"],54,54,\"12.0\",\"clothing\"],\n    \"1fa74\":[[\"\\uD83E\\uDE74\"],\"Objects\",1180,[\"thong_sandal\"],54,55,\"13.0\",\"clothing\"],\n    \"1fa75\":[[\"\\uD83E\\uDE75\"],\"Smileys & Emotion\",150,[\"light_blue_heart\"],54,56,\"15.0\",\"heart\"],\n    \"1fa76\":[[\"\\uD83E\\uDE76\"],\"Smileys & Emotion\",154,[\"grey_heart\"],54,57,\"15.0\",\"heart\"],\n    \"1fa77\":[[\"\\uD83E\\uDE77\"],\"Smileys & Emotion\",145,[\"pink_heart\"],54,58,\"15.0\",\"heart\"],\n    \"1fa78\":[[\"\\uD83E\\uDE78\"],\"Objects\",1378,[\"drop_of_blood\"],54,59,\"12.0\",\"medical\"],\n    \"1fa79\":[[\"\\uD83E\\uDE79\"],\"Objects\",1380,[\"adhesive_bandage\"],54,60,\"12.0\",\"medical\"],\n    \"1fa7a\":[[\"\\uD83E\\uDE7A\"],\"Objects\",1382,[\"stethoscope\"],54,61,\"12.0\",\"medical\"],\n    \"1fa7b\":[[\"\\uD83E\\uDE7B\"],\"Objects\",1383,[\"x-ray\"],55,0,\"14.0\",\"medical\"],\n    \"1fa7c\":[[\"\\uD83E\\uDE7C\"],\"Objects\",1381,[\"crutch\"],55,1,\"14.0\",\"medical\"],\n    \"1fa80\":[[\"\\uD83E\\uDE80\"],\"Activities\",1124,[\"yo-yo\"],55,2,\"12.0\",\"game\"],\n    \"1fa81\":[[\"\\uD83E\\uDE81\"],\"Activities\",1125,[\"kite\"],55,3,\"12.0\",\"game\"],\n    \"1fa82\":[[\"\\uD83E\\uDE82\"],\"Travel & Places\",980,[\"parachute\"],55,4,\"12.0\",\"transport-air\"],\n    \"1fa83\":[[\"\\uD83E\\uDE83\"],\"Objects\",1351,[\"boomerang\"],55,5,\"13.0\",\"tool\"],\n    \"1fa84\":[[\"\\uD83E\\uDE84\"],\"Activities\",1129,[\"magic_wand\"],55,6,\"13.0\",\"game\"],\n    \"1fa85\":[[\"\\uD83E\\uDE85\"],\"Activities\",1136,[\"pinata\"],55,7,\"13.0\",\"game\"],\n    \"1fa86\":[[\"\\uD83E\\uDE86\"],\"Activities\",1138,[\"nesting_dolls\"],55,8,\"13.0\",\"game\"],\n    \"1fa87\":[[\"\\uD83E\\uDE87\"],\"Objects\",1228,[\"maracas\"],55,9,\"15.0\",\"musical-instrument\"],\n    \"1fa88\":[[\"\\uD83E\\uDE88\"],\"Objects\",1229,[\"flute\"],55,10,\"15.0\",\"musical-instrument\"],\n    \"1fa89\":[[\"\\uD83E\\uDE89\"],\"Objects\",1230,[\"harp\"],55,11,\"16.0\",\"musical-instrument\"],\n    \"1fa8f\":[[\"\\uD83E\\uDE8F\"],\"Objects\",1369,[\"shovel\"],55,12,\"16.0\",\"tool\"],\n    \"1fa90\":[[\"\\uD83E\\uDE90\"],\"Travel & Places\",1038,[\"ringed_planet\"],55,13,\"12.0\",\"sky & weather\"],\n    \"1fa91\":[[\"\\uD83E\\uDE91\"],\"Objects\",1390,[\"chair\"],55,14,\"12.0\",\"household\"],\n    \"1fa92\":[[\"\\uD83E\\uDE92\"],\"Objects\",1396,[\"razor\"],55,15,\"12.0\",\"household\"],\n    \"1fa93\":[[\"\\uD83E\\uDE93\"],\"Objects\",1344,[\"axe\"],55,16,\"12.0\",\"tool\"],\n    \"1fa94\":[[\"\\uD83E\\uDE94\"],\"Objects\",1266,[\"diya_lamp\"],55,17,\"12.0\",\"light & video\"],\n    \"1fa95\":[[\"\\uD83E\\uDE95\"],\"Objects\",1225,[\"banjo\"],55,18,\"12.0\",\"musical-instrument\"],\n    \"1fa96\":[[\"\\uD83E\\uDE96\"],\"Objects\",1195,[\"military_helmet\"],55,19,\"13.0\",\"clothing\"],\n    \"1fa97\":[[\"\\uD83E\\uDE97\"],\"Objects\",1220,[\"accordion\"],55,20,\"13.0\",\"musical-instrument\"],\n    \"1fa98\":[[\"\\uD83E\\uDE98\"],\"Objects\",1227,[\"long_drum\"],55,21,\"13.0\",\"musical-instrument\"],\n    \"1fa99\":[[\"\\uD83E\\uDE99\"],\"Objects\",1285,[\"coin\"],55,22,\"13.0\",\"money\"],\n    \"1fa9a\":[[\"\\uD83E\\uDE9A\"],\"Objects\",1354,[\"carpentry_saw\"],55,23,\"13.0\",\"tool\"],\n    \"1fa9b\":[[\"\\uD83E\\uDE9B\"],\"Objects\",1356,[\"screwdriver\"],55,24,\"13.0\",\"tool\"],\n    \"1fa9c\":[[\"\\uD83E\\uDE9C\"],\"Objects\",1368,[\"ladder\"],55,25,\"13.0\",\"tool\"],\n    \"1fa9d\":[[\"\\uD83E\\uDE9D\"],\"Objects\",1365,[\"hook\"],55,26,\"13.0\",\"tool\"],\n    \"1fa9e\":[[\"\\uD83E\\uDE9E\"],\"Objects\",1386,[\"mirror\"],55,27,\"13.0\",\"household\"],\n    \"1fa9f\":[[\"\\uD83E\\uDE9F\"],\"Objects\",1387,[\"window\"],55,28,\"13.0\",\"household\"],\n    \"1faa0\":[[\"\\uD83E\\uDEA0\"],\"Objects\",1392,[\"plunger\"],55,29,\"13.0\",\"household\"],\n    \"1faa1\":[[\"\\uD83E\\uDEA1\"],\"Activities\",1151,[\"sewing_needle\"],55,30,\"13.0\",\"arts & crafts\"],\n    \"1faa2\":[[\"\\uD83E\\uDEA2\"],\"Activities\",1153,[\"knot\"],55,31,\"13.0\",\"arts & crafts\"],\n    \"1faa3\":[[\"\\uD83E\\uDEA3\"],\"Objects\",1402,[\"bucket\"],55,32,\"13.0\",\"household\"],\n    \"1faa4\":[[\"\\uD83E\\uDEA4\"],\"Objects\",1395,[\"mouse_trap\"],55,33,\"13.0\",\"household\"],\n    \"1faa5\":[[\"\\uD83E\\uDEA5\"],\"Objects\",1405,[\"toothbrush\"],55,34,\"13.0\",\"household\"],\n    \"1faa6\":[[\"\\uD83E\\uDEA6\"],\"Objects\",1411,[\"headstone\"],55,35,\"13.0\",\"other-object\"],\n    \"1faa7\":[[\"\\uD83E\\uDEA7\"],\"Objects\",1416,[\"placard\"],55,36,\"13.0\",\"other-object\"],\n    \"1faa8\":[[\"\\uD83E\\uDEA8\"],\"Travel & Places\",871,[\"rock\"],55,37,\"13.0\",\"place-building\"],\n    \"1faa9\":[[\"\\uD83E\\uDEA9\"],\"Activities\",1137,[\"mirror_ball\"],55,38,\"14.0\",\"game\"],\n    \"1faaa\":[[\"\\uD83E\\uDEAA\"],\"Objects\",1417,[\"identification_card\"],55,39,\"14.0\",\"other-object\"],\n    \"1faab\":[[\"\\uD83E\\uDEAB\"],\"Objects\",1238,[\"low_battery\"],55,40,\"14.0\",\"computer\"],\n    \"1faac\":[[\"\\uD83E\\uDEAC\"],\"Objects\",1414,[\"hamsa\"],55,41,\"14.0\",\"other-object\"],\n    \"1faad\":[[\"\\uD83E\\uDEAD\"],\"Objects\",1174,[\"folding_hand_fan\"],55,42,\"15.0\",\"clothing\"],\n    \"1faae\":[[\"\\uD83E\\uDEAE\"],\"Objects\",1189,[\"hair_pick\"],55,43,\"15.0\",\"clothing\"],\n    \"1faaf\":[[\"\\uD83E\\uDEAF\"],\"Symbols\",1477,[\"khanda\"],55,44,\"15.0\",\"religion\"],\n    \"1fab0\":[[\"\\uD83E\\uDEB0\"],\"Animals & Nature\",688,[\"fly\"],55,45,\"13.0\",\"animal-bug\"],\n    \"1fab1\":[[\"\\uD83E\\uDEB1\"],\"Animals & Nature\",689,[\"worm\"],55,46,\"13.0\",\"animal-bug\"],\n    \"1fab2\":[[\"\\uD83E\\uDEB2\"],\"Animals & Nature\",680,[\"beetle\"],55,47,\"13.0\",\"animal-bug\"],\n    \"1fab3\":[[\"\\uD83E\\uDEB3\"],\"Animals & Nature\",683,[\"cockroach\"],55,48,\"13.0\",\"animal-bug\"],\n    \"1fab4\":[[\"\\uD83E\\uDEB4\"],\"Animals & Nature\",704,[\"potted_plant\"],55,49,\"13.0\",\"plant-other\"],\n    \"1fab5\":[[\"\\uD83E\\uDEB5\"],\"Travel & Places\",872,[\"wood\"],55,50,\"13.0\",\"place-building\"],\n    \"1fab6\":[[\"\\uD83E\\uDEB6\"],\"Animals & Nature\",641,[\"feather\"],55,51,\"13.0\",\"animal-bird\"],\n    \"1fab7\":[[\"\\uD83E\\uDEB7\"],\"Animals & Nature\",694,[\"lotus\"],55,52,\"14.0\",\"plant-flower\"],\n    \"1fab8\":[[\"\\uD83E\\uDEB8\"],\"Animals & Nature\",668,[\"coral\"],55,53,\"14.0\",\"animal-marine\"],\n    \"1fab9\":[[\"\\uD83E\\uDEB9\"],\"Animals & Nature\",716,[\"empty_nest\"],55,54,\"14.0\",\"plant-other\"],\n    \"1faba\":[[\"\\uD83E\\uDEBA\"],\"Animals & Nature\",717,[\"nest_with_eggs\"],55,55,\"14.0\",\"plant-other\"],\n    \"1fabb\":[[\"\\uD83E\\uDEBB\"],\"Animals & Nature\",702,[\"hyacinth\"],55,56,\"15.0\",\"plant-flower\"],\n    \"1fabc\":[[\"\\uD83E\\uDEBC\"],\"Animals & Nature\",669,[\"jellyfish\"],55,57,\"15.0\",\"animal-marine\"],\n    \"1fabd\":[[\"\\uD83E\\uDEBD\"],\"Animals & Nature\",645,[\"wing\"],55,58,\"15.0\",\"animal-bird\"],\n    \"1fabe\":[[\"\\uD83E\\uDEBE\"],\"Animals & Nature\",719,[\"leafless_tree\"],55,59,\"16.0\",\"plant-other\"],\n    \"1fabf\":[[\"\\uD83E\\uDEBF\"],\"Animals & Nature\",647,[\"goose\"],55,60,\"15.0\",\"animal-bird\"],\n    \"1fac0\":[[\"\\uD83E\\uDEC0\"],\"People & Body\",222,[\"anatomical_heart\"],55,61,\"13.0\",\"body-parts\"],\n    \"1fac1\":[[\"\\uD83E\\uDEC1\"],\"People & Body\",223,[\"lungs\"],56,0,\"13.0\",\"body-parts\"],\n    \"1fac2\":[[\"\\uD83E\\uDEC2\"],\"People & Body\",548,[\"people_hugging\"],56,1,\"13.0\",\"person-symbol\"],\n    \"1fac3\":[[\"\\uD83E\\uDEC3\"],\"People & Body\",365,[\"pregnant_man\"],56,2,\"14.0\",\"person-role\"],\n    \"1fac4\":[[\"\\uD83E\\uDEC4\"],\"People & Body\",366,[\"pregnant_person\"],56,8,\"14.0\",\"person-role\"],\n    \"1fac5\":[[\"\\uD83E\\uDEC5\"],\"People & Body\",350,[\"person_with_crown\"],56,14,\"14.0\",\"person-role\"],\n    \"1fac6\":[[\"\\uD83E\\uDEC6\"],\"People & Body\",555,[\"fingerprint\"],56,20,\"16.0\",\"person-symbol\"],\n    \"1face\":[[\"\\uD83E\\uDECE\"],\"Animals & Nature\",581,[\"moose\"],56,21,\"15.0\",\"animal-mammal\"],\n    \"1facf\":[[\"\\uD83E\\uDECF\"],\"Animals & Nature\",582,[\"donkey\"],56,22,\"15.0\",\"animal-mammal\"],\n    \"1fad0\":[[\"\\uD83E\\uDED0\"],\"Food & Drink\",735,[\"blueberries\"],56,23,\"13.0\",\"food-fruit\"],\n    \"1fad1\":[[\"\\uD83E\\uDED1\"],\"Food & Drink\",746,[\"bell_pepper\"],56,24,\"13.0\",\"food-vegetable\"],\n    \"1fad2\":[[\"\\uD83E\\uDED2\"],\"Food & Drink\",738,[\"olive\"],56,25,\"13.0\",\"food-fruit\"],\n    \"1fad3\":[[\"\\uD83E\\uDED3\"],\"Food & Drink\",762,[\"flatbread\"],56,26,\"13.0\",\"food-prepared\"],\n    \"1fad4\":[[\"\\uD83E\\uDED4\"],\"Food & Drink\",779,[\"tamale\"],56,27,\"13.0\",\"food-prepared\"],\n    \"1fad5\":[[\"\\uD83E\\uDED5\"],\"Food & Drink\",786,[\"fondue\"],56,28,\"13.0\",\"food-prepared\"],\n    \"1fad6\":[[\"\\uD83E\\uDED6\"],\"Food & Drink\",827,[\"teapot\"],56,29,\"13.0\",\"drink\"],\n    \"1fad7\":[[\"\\uD83E\\uDED7\"],\"Food & Drink\",838,[\"pouring_liquid\"],56,30,\"14.0\",\"drink\"],\n    \"1fad8\":[[\"\\uD83E\\uDED8\"],\"Food & Drink\",753,[\"beans\"],56,31,\"14.0\",\"food-vegetable\"],\n    \"1fad9\":[[\"\\uD83E\\uDED9\"],\"Food & Drink\",849,[\"jar\"],56,32,\"14.0\",\"dishware\"],\n    \"1fada\":[[\"\\uD83E\\uDEDA\"],\"Food & Drink\",755,[\"ginger_root\"],56,33,\"15.0\",\"food-vegetable\"],\n    \"1fadb\":[[\"\\uD83E\\uDEDB\"],\"Food & Drink\",756,[\"pea_pod\"],56,34,\"15.0\",\"food-vegetable\"],\n    \"1fadc\":[[\"\\uD83E\\uDEDC\"],\"Food & Drink\",758,[\"root_vegetable\"],56,35,\"16.0\",\"food-vegetable\"],\n    \"1fadf\":[[\"\\uD83E\\uDEDF\"],\"Symbols\",1555,[\"splatter\"],56,36,\"16.0\",\"other-symbol\"],\n    \"1fae0\":[[\"\\uD83E\\uDEE0\"],\"Smileys & Emotion\",11,[\"melting_face\"],56,37,\"14.0\",\"face-smiling\"],\n    \"1fae1\":[[\"\\uD83E\\uDEE1\"],\"Smileys & Emotion\",36,[\"saluting_face\"],56,38,\"14.0\",\"face-hand\"],\n    \"1fae2\":[[\"\\uD83E\\uDEE2\"],\"Smileys & Emotion\",32,[\"face_with_open_eyes_and_hand_over_mouth\"],56,39,\"14.0\",\"face-hand\"],\n    \"1fae3\":[[\"\\uD83E\\uDEE3\"],\"Smileys & Emotion\",33,[\"face_with_peeking_eye\"],56,40,\"14.0\",\"face-hand\"],\n    \"1fae4\":[[\"\\uD83E\\uDEE4\"],\"Smileys & Emotion\",78,[\"face_with_diagonal_mouth\"],56,41,\"14.0\",\"face-concerned\"],\n    \"1fae5\":[[\"\\uD83E\\uDEE5\"],\"Smileys & Emotion\",42,[\"dotted_line_face\"],56,42,\"14.0\",\"face-neutral-skeptical\"],\n    \"1fae6\":[[\"\\uD83E\\uDEE6\"],\"People & Body\",230,[\"biting_lip\"],56,43,\"14.0\",\"body-parts\"],\n    \"1fae7\":[[\"\\uD83E\\uDEE7\"],\"Objects\",1404,[\"bubbles\"],56,44,\"14.0\",\"household\"],\n    \"1fae8\":[[\"\\uD83E\\uDEE8\"],\"Smileys & Emotion\",50,[\"shaking_face\"],56,45,\"15.0\",\"face-neutral-skeptical\"],\n    \"1fae9\":[[\"\\uD83E\\uDEE9\"],\"Smileys & Emotion\",58,[\"face_with_bags_under_eyes\"],56,46,\"16.0\",\"face-sleepy\"],\n    \"1faf0\":[[\"\\uD83E\\uDEF0\"],\"People & Body\",186,[\"hand_with_index_finger_and_thumb_crossed\"],56,47,\"14.0\",\"hand-fingers-partial\"],\n    \"1faf1\":[[\"\\uD83E\\uDEF1\"],\"People & Body\",175,[\"rightwards_hand\"],56,53,\"14.0\",\"hand-fingers-open\"],\n    \"1faf2\":[[\"\\uD83E\\uDEF2\"],\"People & Body\",176,[\"leftwards_hand\"],56,59,\"14.0\",\"hand-fingers-open\"],\n    \"1faf3\":[[\"\\uD83E\\uDEF3\"],\"People & Body\",177,[\"palm_down_hand\"],57,3,\"14.0\",\"hand-fingers-open\"],\n    \"1faf4\":[[\"\\uD83E\\uDEF4\"],\"People & Body\",178,[\"palm_up_hand\"],57,9,\"14.0\",\"hand-fingers-open\"],\n    \"1faf5\":[[\"\\uD83E\\uDEF5\"],\"People & Body\",196,[\"index_pointing_at_the_viewer\"],57,15,\"14.0\",\"hand-single-finger\"],\n    \"1faf6\":[[\"\\uD83E\\uDEF6\"],\"People & Body\",205,[\"heart_hands\"],57,21,\"14.0\",\"hands\"],\n    \"1faf7\":[[\"\\uD83E\\uDEF7\"],\"People & Body\",179,[\"leftwards_pushing_hand\"],57,27,\"15.0\",\"hand-fingers-open\"],\n    \"1faf8\":[[\"\\uD83E\\uDEF8\"],\"People & Body\",180,[\"rightwards_pushing_hand\"],57,33,\"15.0\",\"hand-fingers-open\"],\n    \"203c-fe0f\":[[\"\\u203C\\uFE0F\"],\"Symbols\",1525,[\"bangbang\"],57,39,\"0.6\",\"punctuation\"],\n    \"2049-fe0f\":[[\"\\u2049\\uFE0F\"],\"Symbols\",1526,[\"interrobang\"],57,40,\"0.6\",\"punctuation\"],\n    \"2122-fe0f\":[[\"\\u2122\\uFE0F\"],\"Symbols\",1554,[\"tm\"],57,41,\"0.6\",\"other-symbol\"],\n    \"2139-fe0f\":[[\"\\u2139\\uFE0F\"],\"Symbols\",1580,[\"information_source\"],57,42,\"0.6\",\"alphanum\"],\n    \"2194-fe0f\":[[\"\\u2194\\uFE0F\"],\"Symbols\",1453,[\"left_right_arrow\"],57,43,\"0.6\",\"arrow\"],\n    \"2195-fe0f\":[[\"\\u2195\\uFE0F\"],\"Symbols\",1452,[\"arrow_up_down\"],57,44,\"0.6\",\"arrow\"],\n    \"2196-fe0f\":[[\"\\u2196\\uFE0F\"],\"Symbols\",1451,[\"arrow_upper_left\"],57,45,\"0.6\",\"arrow\"],\n    \"2197-fe0f\":[[\"\\u2197\\uFE0F\"],\"Symbols\",1445,[\"arrow_upper_right\"],57,46,\"0.6\",\"arrow\"],\n    \"2198-fe0f\":[[\"\\u2198\\uFE0F\"],\"Symbols\",1447,[\"arrow_lower_right\"],57,47,\"0.6\",\"arrow\"],\n    \"2199-fe0f\":[[\"\\u2199\\uFE0F\"],\"Symbols\",1449,[\"arrow_lower_left\"],57,48,\"0.6\",\"arrow\"],\n    \"21a9-fe0f\":[[\"\\u21A9\\uFE0F\"],\"Symbols\",1454,[\"leftwards_arrow_with_hook\"],57,49,\"0.6\",\"arrow\"],\n    \"21aa-fe0f\":[[\"\\u21AA\\uFE0F\"],\"Symbols\",1455,[\"arrow_right_hook\"],57,50,\"0.6\",\"arrow\"],\n    \"231a\":[[\"\\u231A\"],\"Travel & Places\",993,[\"watch\"],57,51,\"0.6\",\"time\"],\n    \"231b\":[[\"\\u231B\"],\"Travel & Places\",991,[\"hourglass\"],57,52,\"0.6\",\"time\"],\n    \"2328-fe0f\":[[\"\\u2328\\uFE0F\"],\"Objects\",1243,[\"keyboard\"],57,53,\"1.0\",\"computer\"],\n    \"23cf-fe0f\":[[\"\\u23CF\\uFE0F\"],\"Symbols\",1508,[\"eject\"],57,54,\"1.0\",\"av-symbol\"],\n    \"23e9\":[[\"\\u23E9\"],\"Symbols\",1495,[\"fast_forward\"],57,55,\"0.6\",\"av-symbol\"],\n    \"23ea\":[[\"\\u23EA\"],\"Symbols\",1499,[\"rewind\"],57,56,\"0.6\",\"av-symbol\"],\n    \"23eb\":[[\"\\u23EB\"],\"Symbols\",1502,[\"arrow_double_up\"],57,57,\"0.6\",\"av-symbol\"],\n    \"23ec\":[[\"\\u23EC\"],\"Symbols\",1504,[\"arrow_double_down\"],57,58,\"0.6\",\"av-symbol\"],\n    \"23ed-fe0f\":[[\"\\u23ED\\uFE0F\"],\"Symbols\",1496,[\"black_right_pointing_double_triangle_with_vertical_bar\"],57,59,\"0.7\",\"av-symbol\"],\n    \"23ee-fe0f\":[[\"\\u23EE\\uFE0F\"],\"Symbols\",1500,[\"black_left_pointing_double_triangle_with_vertical_bar\"],57,60,\"0.7\",\"av-symbol\"],\n    \"23ef-fe0f\":[[\"\\u23EF\\uFE0F\"],\"Symbols\",1497,[\"black_right_pointing_triangle_with_double_vertical_bar\"],57,61,\"1.0\",\"av-symbol\"],\n    \"23f0\":[[\"\\u23F0\"],\"Travel & Places\",994,[\"alarm_clock\"],58,0,\"0.6\",\"time\"],\n    \"23f1-fe0f\":[[\"\\u23F1\\uFE0F\"],\"Travel & Places\",995,[\"stopwatch\"],58,1,\"1.0\",\"time\"],\n    \"23f2-fe0f\":[[\"\\u23F2\\uFE0F\"],\"Travel & Places\",996,[\"timer_clock\"],58,2,\"1.0\",\"time\"],\n    \"23f3\":[[\"\\u23F3\"],\"Travel & Places\",992,[\"hourglass_flowing_sand\"],58,3,\"0.6\",\"time\"],\n    \"23f8-fe0f\":[[\"\\u23F8\\uFE0F\"],\"Symbols\",1505,[\"double_vertical_bar\"],58,4,\"0.7\",\"av-symbol\"],\n    \"23f9-fe0f\":[[\"\\u23F9\\uFE0F\"],\"Symbols\",1506,[\"black_square_for_stop\"],58,5,\"0.7\",\"av-symbol\"],\n    \"23fa-fe0f\":[[\"\\u23FA\\uFE0F\"],\"Symbols\",1507,[\"black_circle_for_record\"],58,6,\"0.7\",\"av-symbol\"],\n    \"24c2-fe0f\":[[\"\\u24C2\\uFE0F\"],\"Symbols\",1582,[\"m\"],58,7,\"0.6\",\"alphanum\"],\n    \"25aa-fe0f\":[[\"\\u25AA\\uFE0F\"],\"Symbols\",1630,[\"black_small_square\"],58,8,\"0.6\",\"geometric\"],\n    \"25ab-fe0f\":[[\"\\u25AB\\uFE0F\"],\"Symbols\",1631,[\"white_small_square\"],58,9,\"0.6\",\"geometric\"],\n    \"25b6-fe0f\":[[\"\\u25B6\\uFE0F\"],\"Symbols\",1494,[\"arrow_forward\"],58,10,\"0.6\",\"av-symbol\"],\n    \"25c0-fe0f\":[[\"\\u25C0\\uFE0F\"],\"Symbols\",1498,[\"arrow_backward\"],58,11,\"0.6\",\"av-symbol\"],\n    \"25fb-fe0f\":[[\"\\u25FB\\uFE0F\"],\"Symbols\",1627,[\"white_medium_square\"],58,12,\"0.6\",\"geometric\"],\n    \"25fc-fe0f\":[[\"\\u25FC\\uFE0F\"],\"Symbols\",1626,[\"black_medium_square\"],58,13,\"0.6\",\"geometric\"],\n    \"25fd\":[[\"\\u25FD\"],\"Symbols\",1629,[\"white_medium_small_square\"],58,14,\"0.6\",\"geometric\"],\n    \"25fe\":[[\"\\u25FE\"],\"Symbols\",1628,[\"black_medium_small_square\"],58,15,\"0.6\",\"geometric\"],\n    \"2600-fe0f\":[[\"\\u2600\\uFE0F\"],\"Travel & Places\",1035,[\"sunny\"],58,16,\"0.6\",\"sky & weather\"],\n    \"2601-fe0f\":[[\"\\u2601\\uFE0F\"],\"Travel & Places\",1043,[\"cloud\"],58,17,\"0.6\",\"sky & weather\"],\n    \"2602-fe0f\":[[\"\\u2602\\uFE0F\"],\"Travel & Places\",1058,[\"umbrella\"],58,18,\"0.7\",\"sky & weather\"],\n    \"2603-fe0f\":[[\"\\u2603\\uFE0F\"],\"Travel & Places\",1063,[\"snowman\"],58,19,\"0.7\",\"sky & weather\"],\n    \"2604-fe0f\":[[\"\\u2604\\uFE0F\"],\"Travel & Places\",1065,[\"comet\"],58,20,\"1.0\",\"sky & weather\"],\n    \"260e-fe0f\":[[\"\\u260E\\uFE0F\"],\"Objects\",1233,[\"phone\",\"telephone\"],58,21,\"0.6\",\"phone\"],\n    \"2611-fe0f\":[[\"\\u2611\\uFE0F\"],\"Symbols\",1542,[\"ballot_box_with_check\"],58,22,\"0.6\",\"other-symbol\"],\n    \"2614\":[[\"\\u2614\"],\"Travel & Places\",1059,[\"umbrella_with_rain_drops\"],58,23,\"0.6\",\"sky & weather\"],\n    \"2615\":[[\"\\u2615\"],\"Food & Drink\",826,[\"coffee\"],58,24,\"0.6\",\"drink\"],\n    \"2618-fe0f\":[[\"\\u2618\\uFE0F\"],\"Animals & Nature\",711,[\"shamrock\"],58,25,\"1.0\",\"plant-other\"],\n    \"261d-fe0f\":[[\"\\u261D\\uFE0F\"],\"People & Body\",195,[\"point_up\"],58,26,\"0.6\",\"hand-single-finger\"],\n    \"2620-fe0f\":[[\"\\u2620\\uFE0F\"],\"Smileys & Emotion\",110,[\"skull_and_crossbones\"],58,32,\"1.0\",\"face-negative\"],\n    \"2622-fe0f\":[[\"\\u2622\\uFE0F\"],\"Symbols\",1442,[\"radioactive_sign\"],58,33,\"1.0\",\"warning\"],\n    \"2623-fe0f\":[[\"\\u2623\\uFE0F\"],\"Symbols\",1443,[\"biohazard_sign\"],58,34,\"1.0\",\"warning\"],\n    \"2626-fe0f\":[[\"\\u2626\\uFE0F\"],\"Symbols\",1472,[\"orthodox_cross\"],58,35,\"1.0\",\"religion\"],\n    \"262a-fe0f\":[[\"\\u262A\\uFE0F\"],\"Symbols\",1473,[\"star_and_crescent\"],58,36,\"0.7\",\"religion\"],\n    \"262e-fe0f\":[[\"\\u262E\\uFE0F\"],\"Symbols\",1474,[\"peace_symbol\"],58,37,\"1.0\",\"religion\"],\n    \"262f-fe0f\":[[\"\\u262F\\uFE0F\"],\"Symbols\",1470,[\"yin_yang\"],58,38,\"0.7\",\"religion\"],\n    \"2638-fe0f\":[[\"\\u2638\\uFE0F\"],\"Symbols\",1469,[\"wheel_of_dharma\"],58,39,\"0.7\",\"religion\"],\n    \"2639-fe0f\":[[\"\\u2639\\uFE0F\"],\"Smileys & Emotion\",81,[\"white_frowning_face\"],58,40,\"0.7\",\"face-concerned\"],\n    \"263a-fe0f\":[[\"\\u263A\\uFE0F\"],\"Smileys & Emotion\",20,[\"relaxed\"],58,41,\"0.6\",\"face-affection\"],\n    \"2640-fe0f\":[[\"\\u2640\\uFE0F\"],\"Symbols\",1516,[\"female_sign\"],58,42,\"4.0\",\"gender\"],\n    \"2642-fe0f\":[[\"\\u2642\\uFE0F\"],\"Symbols\",1517,[\"male_sign\"],58,43,\"4.0\",\"gender\"],\n    \"2648\":[[\"\\u2648\"],\"Symbols\",1478,[\"aries\"],58,44,\"0.6\",\"zodiac\"],\n    \"2649\":[[\"\\u2649\"],\"Symbols\",1479,[\"taurus\"],58,45,\"0.6\",\"zodiac\"],\n    \"264a\":[[\"\\u264A\"],\"Symbols\",1480,[\"gemini\"],58,46,\"0.6\",\"zodiac\"],\n    \"264b\":[[\"\\u264B\"],\"Symbols\",1481,[\"cancer\"],58,47,\"0.6\",\"zodiac\"],\n    \"264c\":[[\"\\u264C\"],\"Symbols\",1482,[\"leo\"],58,48,\"0.6\",\"zodiac\"],\n    \"264d\":[[\"\\u264D\"],\"Symbols\",1483,[\"virgo\"],58,49,\"0.6\",\"zodiac\"],\n    \"264e\":[[\"\\u264E\"],\"Symbols\",1484,[\"libra\"],58,50,\"0.6\",\"zodiac\"],\n    \"264f\":[[\"\\u264F\"],\"Symbols\",1485,[\"scorpius\"],58,51,\"0.6\",\"zodiac\"],\n    \"2650\":[[\"\\u2650\"],\"Symbols\",1486,[\"sagittarius\"],58,52,\"0.6\",\"zodiac\"],\n    \"2651\":[[\"\\u2651\"],\"Symbols\",1487,[\"capricorn\"],58,53,\"0.6\",\"zodiac\"],\n    \"2652\":[[\"\\u2652\"],\"Symbols\",1488,[\"aquarius\"],58,54,\"0.6\",\"zodiac\"],\n    \"2653\":[[\"\\u2653\"],\"Symbols\",1489,[\"pisces\"],58,55,\"0.6\",\"zodiac\"],\n    \"265f-fe0f\":[[\"\\u265F\\uFE0F\"],\"Activities\",1143,[\"chess_pawn\"],58,56,\"11.0\",\"game\"],\n    \"2660-fe0f\":[[\"\\u2660\\uFE0F\"],\"Activities\",1139,[\"spades\"],58,57,\"0.6\",\"game\"],\n    \"2663-fe0f\":[[\"\\u2663\\uFE0F\"],\"Activities\",1142,[\"clubs\"],58,58,\"0.6\",\"game\"],\n    \"2665-fe0f\":[[\"\\u2665\\uFE0F\"],\"Activities\",1140,[\"hearts\"],58,59,\"0.6\",\"game\"],\n    \"2666-fe0f\":[[\"\\u2666\\uFE0F\"],\"Activities\",1141,[\"diamonds\"],58,60,\"0.6\",\"game\"],\n    \"2668-fe0f\":[[\"\\u2668\\uFE0F\"],\"Travel & Places\",910,[\"hotsprings\"],58,61,\"0.6\",\"place-other\"],\n    \"267b-fe0f\":[[\"\\u267B\\uFE0F\"],\"Symbols\",1535,[\"recycle\"],59,0,\"0.6\",\"other-symbol\"],\n    \"267e-fe0f\":[[\"\\u267E\\uFE0F\"],\"Symbols\",1524,[\"infinity\"],59,1,\"11.0\",\"math\"],\n    \"267f\":[[\"\\u267F\"],\"Symbols\",1421,[\"wheelchair\"],59,2,\"0.6\",\"transport-sign\"],\n    \"2692-fe0f\":[[\"\\u2692\\uFE0F\"],\"Objects\",1346,[\"hammer_and_pick\"],59,3,\"1.0\",\"tool\"],\n    \"2693\":[[\"\\u2693\"],\"Travel & Places\",967,[\"anchor\"],59,4,\"0.6\",\"transport-water\"],\n    \"2694-fe0f\":[[\"\\u2694\\uFE0F\"],\"Objects\",1349,[\"crossed_swords\"],59,5,\"1.0\",\"tool\"],\n    \"2695-fe0f\":[[\"\\u2695\\uFE0F\"],\"Symbols\",1534,[\"medical_symbol\",\"staff_of_aesculapius\"],59,6,\"4.0\",\"other-symbol\"],\n    \"2696-fe0f\":[[\"\\u2696\\uFE0F\"],\"Objects\",1360,[\"scales\"],59,7,\"1.0\",\"tool\"],\n    \"2697-fe0f\":[[\"\\u2697\\uFE0F\"],\"Objects\",1370,[\"alembic\"],59,8,\"1.0\",\"science\"],\n    \"2699-fe0f\":[[\"\\u2699\\uFE0F\"],\"Objects\",1358,[\"gear\"],59,9,\"1.0\",\"tool\"],\n    \"269b-fe0f\":[[\"\\u269B\\uFE0F\"],\"Symbols\",1466,[\"atom_symbol\"],59,10,\"1.0\",\"religion\"],\n    \"269c-fe0f\":[[\"\\u269C\\uFE0F\"],\"Symbols\",1536,[\"fleur_de_lis\"],59,11,\"1.0\",\"other-symbol\"],\n    \"26a0-fe0f\":[[\"\\u26A0\\uFE0F\"],\"Symbols\",1431,[\"warning\"],59,12,\"0.6\",\"warning\"],\n    \"26a1\":[[\"\\u26A1\"],\"Travel & Places\",1061,[\"zap\"],59,13,\"0.6\",\"sky & weather\"],\n    \"26a7-fe0f\":[[\"\\u26A7\\uFE0F\"],\"Symbols\",1518,[\"transgender_symbol\"],59,14,\"13.0\",\"gender\"],\n    \"26aa\":[[\"\\u26AA\"],\"Symbols\",1616,[\"white_circle\"],59,15,\"0.6\",\"geometric\"],\n    \"26ab\":[[\"\\u26AB\"],\"Symbols\",1615,[\"black_circle\"],59,16,\"0.6\",\"geometric\"],\n    \"26b0-fe0f\":[[\"\\u26B0\\uFE0F\"],\"Objects\",1410,[\"coffin\"],59,17,\"1.0\",\"other-object\"],\n    \"26b1-fe0f\":[[\"\\u26B1\\uFE0F\"],\"Objects\",1412,[\"funeral_urn\"],59,18,\"1.0\",\"other-object\"],\n    \"26bd\":[[\"\\u26BD\"],\"Activities\",1096,[\"soccer\"],59,19,\"0.6\",\"sport\"],\n    \"26be\":[[\"\\u26BE\"],\"Activities\",1097,[\"baseball\"],59,20,\"0.6\",\"sport\"],\n    \"26c4\":[[\"\\u26C4\"],\"Travel & Places\",1064,[\"snowman_without_snow\"],59,21,\"0.6\",\"sky & weather\"],\n    \"26c5\":[[\"\\u26C5\"],\"Travel & Places\",1044,[\"partly_sunny\"],59,22,\"0.6\",\"sky & weather\"],\n    \"26c8-fe0f\":[[\"\\u26C8\\uFE0F\"],\"Travel & Places\",1045,[\"thunder_cloud_and_rain\"],59,23,\"0.7\",\"sky & weather\"],\n    \"26ce\":[[\"\\u26CE\"],\"Symbols\",1490,[\"ophiuchus\"],59,24,\"0.6\",\"zodiac\"],\n    \"26cf-fe0f\":[[\"\\u26CF\\uFE0F\"],\"Objects\",1345,[\"pick\"],59,25,\"0.7\",\"tool\"],\n    \"26d1-fe0f\":[[\"\\u26D1\\uFE0F\"],\"Objects\",1196,[\"helmet_with_white_cross\"],59,26,\"0.7\",\"clothing\"],\n    \"26d3-fe0f-200d-1f4a5\":[[\"\\u26D3\\uFE0F\\u200D\\uD83D\\uDCA5\"],\"Objects\",1363,[\"broken_chain\"],59,27,\"15.1\",\"tool\"],\n    \"26d3-fe0f\":[[\"\\u26D3\\uFE0F\"],\"Objects\",1364,[\"chains\"],59,28,\"0.7\",\"tool\"],\n    \"26d4\":[[\"\\u26D4\"],\"Symbols\",1433,[\"no_entry\"],59,29,\"0.6\",\"warning\"],\n    \"26e9-fe0f\":[[\"\\u26E9\\uFE0F\"],\"Travel & Places\",898,[\"shinto_shrine\"],59,30,\"0.7\",\"place-religious\"],\n    \"26ea\":[[\"\\u26EA\"],\"Travel & Places\",894,[\"church\"],59,31,\"0.6\",\"place-religious\"],\n    \"26f0-fe0f\":[[\"\\u26F0\\uFE0F\"],\"Travel & Places\",859,[\"mountain\"],59,32,\"0.7\",\"place-geographic\"],\n    \"26f1-fe0f\":[[\"\\u26F1\\uFE0F\"],\"Travel & Places\",1060,[\"umbrella_on_ground\"],59,33,\"0.7\",\"sky & weather\"],\n    \"26f2\":[[\"\\u26F2\"],\"Travel & Places\",900,[\"fountain\"],59,34,\"0.6\",\"place-other\"],\n    \"26f3\":[[\"\\u26F3\"],\"Activities\",1115,[\"golf\"],59,35,\"0.6\",\"sport\"],\n    \"26f4-fe0f\":[[\"\\u26F4\\uFE0F\"],\"Travel & Places\",973,[\"ferry\"],59,36,\"0.7\",\"transport-water\"],\n    \"26f5\":[[\"\\u26F5\"],\"Travel & Places\",969,[\"boat\",\"sailboat\"],59,37,\"0.6\",\"transport-water\"],\n    \"26f7-fe0f\":[[\"\\u26F7\\uFE0F\"],\"People & Body\",462,[\"skier\"],59,38,\"0.7\",\"person-sport\"],\n    \"26f8-fe0f\":[[\"\\u26F8\\uFE0F\"],\"Activities\",1116,[\"ice_skate\"],59,39,\"0.7\",\"sport\"],\n    \"26f9-fe0f-200d-2640-fe0f\":[[\"\\u26F9\\uFE0F\\u200D\\u2640\\uFE0F\"],\"People & Body\",478,[\"woman-bouncing-ball\"],59,40,\"4.0\",\"person-sport\"],\n    \"26f9-fe0f-200d-2642-fe0f\":[[\"\\u26F9\\uFE0F\\u200D\\u2642\\uFE0F\",\"\\u26F9\\uFE0F\"],\"People & Body\",477,[\"man-bouncing-ball\",\"person_with_ball\"],59,46,\"4.0\",\"person-sport\"],\n    \"26fa\":[[\"\\u26FA\"],\"Travel & Places\",901,[\"tent\"],59,58,\"0.6\",\"place-other\"],\n    \"26fd\":[[\"\\u26FD\"],\"Travel & Places\",960,[\"fuelpump\"],59,59,\"0.6\",\"transport-ground\"],\n    \"2702-fe0f\":[[\"\\u2702\\uFE0F\"],\"Objects\",1333,[\"scissors\"],59,60,\"0.6\",\"office\"],\n    \"2705\":[[\"\\u2705\"],\"Symbols\",1541,[\"white_check_mark\"],59,61,\"0.6\",\"other-symbol\"],\n    \"2708-fe0f\":[[\"\\u2708\\uFE0F\"],\"Travel & Places\",976,[\"airplane\"],60,0,\"0.6\",\"transport-air\"],\n    \"2709-fe0f\":[[\"\\u2709\\uFE0F\"],\"Objects\",1294,[\"email\",\"envelope\"],60,1,\"0.6\",\"mail\"],\n    \"270a\":[[\"\\u270A\"],\"People & Body\",199,[\"fist\"],60,2,\"0.6\",\"hand-fingers-closed\"],\n    \"270b\":[[\"\\u270B\"],\"People & Body\",173,[\"hand\",\"raised_hand\"],60,8,\"0.6\",\"hand-fingers-open\"],\n    \"270c-fe0f\":[[\"\\u270C\\uFE0F\"],\"People & Body\",184,[\"v\"],60,14,\"0.6\",\"hand-fingers-partial\"],\n    \"270d-fe0f\":[[\"\\u270D\\uFE0F\"],\"People & Body\",210,[\"writing_hand\"],60,20,\"0.7\",\"hand-prop\"],\n    \"270f-fe0f\":[[\"\\u270F\\uFE0F\"],\"Objects\",1307,[\"pencil2\"],60,26,\"0.6\",\"writing\"],\n    \"2712-fe0f\":[[\"\\u2712\\uFE0F\"],\"Objects\",1308,[\"black_nib\"],60,27,\"0.6\",\"writing\"],\n    \"2714-fe0f\":[[\"\\u2714\\uFE0F\"],\"Symbols\",1543,[\"heavy_check_mark\"],60,28,\"0.6\",\"other-symbol\"],\n    \"2716-fe0f\":[[\"\\u2716\\uFE0F\"],\"Symbols\",1519,[\"heavy_multiplication_x\"],60,29,\"0.6\",\"math\"],\n    \"271d-fe0f\":[[\"\\u271D\\uFE0F\"],\"Symbols\",1471,[\"latin_cross\"],60,30,\"0.7\",\"religion\"],\n    \"2721-fe0f\":[[\"\\u2721\\uFE0F\"],\"Symbols\",1468,[\"star_of_david\"],60,31,\"0.7\",\"religion\"],\n    \"2728\":[[\"\\u2728\"],\"Activities\",1074,[\"sparkles\"],60,32,\"0.6\",\"event\"],\n    \"2733-fe0f\":[[\"\\u2733\\uFE0F\"],\"Symbols\",1549,[\"eight_spoked_asterisk\"],60,33,\"0.6\",\"other-symbol\"],\n    \"2734-fe0f\":[[\"\\u2734\\uFE0F\"],\"Symbols\",1550,[\"eight_pointed_black_star\"],60,34,\"0.6\",\"other-symbol\"],\n    \"2744-fe0f\":[[\"\\u2744\\uFE0F\"],\"Travel & Places\",1062,[\"snowflake\"],60,35,\"0.6\",\"sky & weather\"],\n    \"2747-fe0f\":[[\"\\u2747\\uFE0F\"],\"Symbols\",1551,[\"sparkle\"],60,36,\"0.6\",\"other-symbol\"],\n    \"274c\":[[\"\\u274C\"],\"Symbols\",1544,[\"x\"],60,37,\"0.6\",\"other-symbol\"],\n    \"274e\":[[\"\\u274E\"],\"Symbols\",1545,[\"negative_squared_cross_mark\"],60,38,\"0.6\",\"other-symbol\"],\n    \"2753\":[[\"\\u2753\"],\"Symbols\",1527,[\"question\"],60,39,\"0.6\",\"punctuation\"],\n    \"2754\":[[\"\\u2754\"],\"Symbols\",1528,[\"grey_question\"],60,40,\"0.6\",\"punctuation\"],\n    \"2755\":[[\"\\u2755\"],\"Symbols\",1529,[\"grey_exclamation\"],60,41,\"0.6\",\"punctuation\"],\n    \"2757\":[[\"\\u2757\"],\"Symbols\",1530,[\"exclamation\",\"heavy_exclamation_mark\"],60,42,\"0.6\",\"punctuation\"],\n    \"2763-fe0f\":[[\"\\u2763\\uFE0F\"],\"Smileys & Emotion\",140,[\"heavy_heart_exclamation_mark_ornament\"],60,43,\"1.0\",\"heart\"],\n    \"2764-fe0f-200d-1f525\":[[\"\\u2764\\uFE0F\\u200D\\uD83D\\uDD25\"],\"Smileys & Emotion\",142,[\"heart_on_fire\"],60,44,\"13.1\",\"heart\"],\n    \"2764-fe0f-200d-1fa79\":[[\"\\u2764\\uFE0F\\u200D\\uD83E\\uDE79\"],\"Smileys & Emotion\",143,[\"mending_heart\"],60,45,\"13.1\",\"heart\"],\n    \"2764-fe0f\":[[\"\\u2764\\uFE0F\"],\"Smileys & Emotion\",144,[\"heart\"],60,46,\"0.6\",\"heart\",\"<3\"],\n    \"2795\":[[\"\\u2795\"],\"Symbols\",1520,[\"heavy_plus_sign\"],60,47,\"0.6\",\"math\"],\n    \"2796\":[[\"\\u2796\"],\"Symbols\",1521,[\"heavy_minus_sign\"],60,48,\"0.6\",\"math\"],\n    \"2797\":[[\"\\u2797\"],\"Symbols\",1522,[\"heavy_division_sign\"],60,49,\"0.6\",\"math\"],\n    \"27a1-fe0f\":[[\"\\u27A1\\uFE0F\"],\"Symbols\",1446,[\"arrow_right\"],60,50,\"0.6\",\"arrow\"],\n    \"27b0\":[[\"\\u27B0\"],\"Symbols\",1546,[\"curly_loop\"],60,51,\"0.6\",\"other-symbol\"],\n    \"27bf\":[[\"\\u27BF\"],\"Symbols\",1547,[\"loop\"],60,52,\"1.0\",\"other-symbol\"],\n    \"2934-fe0f\":[[\"\\u2934\\uFE0F\"],\"Symbols\",1456,[\"arrow_heading_up\"],60,53,\"0.6\",\"arrow\"],\n    \"2935-fe0f\":[[\"\\u2935\\uFE0F\"],\"Symbols\",1457,[\"arrow_heading_down\"],60,54,\"0.6\",\"arrow\"],\n    \"2b05-fe0f\":[[\"\\u2B05\\uFE0F\"],\"Symbols\",1450,[\"arrow_left\"],60,55,\"0.6\",\"arrow\"],\n    \"2b06-fe0f\":[[\"\\u2B06\\uFE0F\"],\"Symbols\",1444,[\"arrow_up\"],60,56,\"0.6\",\"arrow\"],\n    \"2b07-fe0f\":[[\"\\u2B07\\uFE0F\"],\"Symbols\",1448,[\"arrow_down\"],60,57,\"0.6\",\"arrow\"],\n    \"2b1b\":[[\"\\u2B1B\"],\"Symbols\",1624,[\"black_large_square\"],60,58,\"0.6\",\"geometric\"],\n    \"2b1c\":[[\"\\u2B1C\"],\"Symbols\",1625,[\"white_large_square\"],60,59,\"0.6\",\"geometric\"],\n    \"2b50\":[[\"\\u2B50\"],\"Travel & Places\",1039,[\"star\"],60,60,\"0.6\",\"sky & weather\"],\n    \"2b55\":[[\"\\u2B55\"],\"Symbols\",1540,[\"o\"],60,61,\"0.6\",\"other-symbol\"],\n    \"3030-fe0f\":[[\"\\u3030\\uFE0F\"],\"Symbols\",1531,[\"wavy_dash\"],61,0,\"0.6\",\"punctuation\"],\n    \"303d-fe0f\":[[\"\\u303D\\uFE0F\"],\"Symbols\",1548,[\"part_alternation_mark\"],61,1,\"0.6\",\"other-symbol\"],\n    \"3297-fe0f\":[[\"\\u3297\\uFE0F\"],\"Symbols\",1604,[\"congratulations\"],61,2,\"0.6\",\"alphanum\"],\n    \"3299-fe0f\":[[\"\\u3299\\uFE0F\"],\"Symbols\",1605,[\"secret\"],61,3,\"0.6\",\"alphanum\"]\n};\n\nfor(var key in data) {\n\tfor(var i = 0; i < data[key][3].length; i++)\n\t\tconsole.log('@\"' + data[key][3][i] + '\":@\"' + data[key][0][0] +'\",')\n}\n\nconsole.log('')\n\nvar aliases = {\n    '1f44d': ['like', 'thumbs_up'],\n    '1f44e': ['dislike', 'thumbs_down'],\n    '1f415': ['doge'],\n    '1f346': ['aubergine'],\n    '1f4a8': ['gust_of_wind'],\n    '1f389': ['party_popper'],\n    '1f631': ['shock'],\n    '269b-fe0f': ['atom'],\n    '2764-fe0f': ['<3'],\n    '1f494': ['</3'],\n    '1f642': ['simple_smile', ':)', ':-)', ')', '-)'],\n    '1f603': ['=D'],\n    '1f600': [':D', 'D'],\n    '1f61e': [':(', '('],\n    '1f622': [\":'(\", \"'(\"],\n    '1f62d': [':_(', '_(','loudly_crying_face','sad_tears','bawl'],\n    '1f609': [';)'],\n    '1f61c': [';p'],\n    '1f606': ['XD'],\n    '1f604': ['^_^'],\n    '1f605': ['^_^;'],\n    '1f923': ['rofl'],\n    '1f610': [':|', '|'],\n    '1f623': ['>.<'],\n    '1f6f8': ['ufo'],\n    '1f9d9-200d-2640-fe0f': ['female_wizard'],\n    '1f9d9-200d-2642-fe0f': ['male_wizard'],\n    '1f995': ['brontosaurus', 'diplodocus'],\n    '1f996': ['tyrannosaurus'],\n    '1f969': ['steak'],\n    '1f96b': ['soup_tin'],\n    '1f9e2': ['baseball_cap'],\n    '1f9d8-200d-2640-fe0f': ['female_yoga'],\n    '1f9d8-200d-2642-fe0f': ['male_yoga'],\n    '1f9d6-200d-2640-fe0f': ['female_sauna'],\n    '1f9d6-200d-2642-fe0f': ['male_sauna'],\n    '1f9d5': ['hijab'],\n    '1f41e': ['ladybird','ladybug','ladybeetle','coccinellid'],\n    '1f48e': ['diamond'],\n    '1f607': ['angel_face'],\n    '1f608': ['smiling_devil'],\n    '1f47f': ['frowning_devil'],\n    '1f621': ['mad_rage', 'angry_rage'],\n    '1f620': ['mad'],\n    '1f682': ['steam_train'],\n    '1f393': ['graduation_cap'],\n    '1f4a1': ['lightbulb'],\n    '1f60e': ['cool_dude', 'deal_with_it'],\n    '1f925': ['liar'],\n    '1f430': ['bunny'],\n    '1f407': ['bunny2'],\n    '1f6ac': ['cigarette', 'fag'],\n    '1f30a': ['water_wave'],\n    '1f92a': ['crazy_face'],\n    '1f92b': ['sh'],\n    '1f92c': ['angry_swearing','mad_swearing','cursing','swearing','pissed_off','fuck'],\n    '1f92d': ['oops'],\n    '1f92e': ['throwing_up', 'being_sick'],\n    '1f92f': ['mind_blown'],\n    '26a1': ['lightning_bolt'],\n    '1f38a': ['confetti'],\n    '1f5d1-fe0f': ['rubbish', 'trash', 'garbage', 'bin', 'wastepaper_basket']\n};\n\nfor(var key in aliases) {\n\tfor(var i = 0; i < aliases[key].length; i++)\n\t\tconsole.log('@\"' + aliases[key][i] + '\":@\"' + data[key][0][0] +'\",')\n}\n"
  },
  {
    "path": "build-scripts/git-revision.sh",
    "content": "#!/bin/bash\nVERSION=`cat $PROJECT_DIR/build-scripts/VERSION`\necho -n \"#define VERSION_STRING \" > $PROJECT_DIR/IRCCloud/InfoPlist.h\necho $VERSION >> $PROJECT_DIR/IRCCloud/InfoPlist.h\n\ngit rev-parse 2> /dev/null > /dev/null\nIS_GIT=$?\n\nif [ $CONFIGURATION == \"AppStore\" ] || [ $IS_GIT -ne 0 ]; then\n    bN=$((`cat $PROJECT_DIR/build-scripts/BUILD`+1))\n    echo -n $bN > $PROJECT_DIR/build-scripts/BUILD\nelse\n    bN=$(/usr/bin/git rev-parse --short HEAD)\nfi\necho -n \"#define GIT_VERSION \" >> $PROJECT_DIR/IRCCloud/InfoPlist.h\nif [ $PLATFORM_NAME == \"iphonesimulator\" ]; then\n    echo `cat $PROJECT_DIR/build-scripts/BUILD` >> $PROJECT_DIR/IRCCloud/InfoPlist.h\nelse\n    echo $bN >> $PROJECT_DIR/IRCCloud/InfoPlist.h\nfi\n\nCRASHLYTICS_TOKEN=`grep CRASHLYTICS_TOKEN $PROJECT_DIR/IRCCloud/config.h | awk '{print $3}' | sed 's/\"//g'`\nif [ -n \"$CRASHLYTICS_TOKEN\" ]; then\n    echo -n \"#define FABRIC_API_KEY \" >> $PROJECT_DIR/IRCCloud/InfoPlist.h\n    echo $CRASHLYTICS_TOKEN >> $PROJECT_DIR/IRCCloud/InfoPlist.h\nfi\n\ntouch $PROJECT_DIR/IRCCloud/IRCCloud-Info.plist\ntouch $PROJECT_DIR/IRCCloud/IRCCloud-Enterprise-Info.plist\ntouch $PROJECT_DIR/ShareExtension/Info.plist\ntouch $PROJECT_DIR/ShareExtension/Info-Enterprise.plist\ntouch $PROJECT_DIR/NotificationService/Info.plist\n"
  },
  {
    "path": "fastlane/Fastfile",
    "content": "# Customise this file, documentation can be found here:\n# https://github.com/fastlane/fastlane/tree/master/fastlane/docs\n# All available actions: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Actions.md\n# can also be listed using the `fastlane actions` command\n\n# Change the syntax highlighting to Ruby\n# All lines starting with a # are ignored when running `fastlane`\n\n# If you want to automatically update fastlane if a new version is available:\n#update_fastlane\n\n# This is the minimum version number required.\n# Update this, if you use features of a newer version\nfastlane_version \"2.102.0\"\n\ndefault_platform :ios\n# xcode_select(\"/Applications/Xcode-beta.app\")\ndef app_vers\n  File.read('../build-scripts/VERSION').split('\\n')[0].strip\nend\n\nplatform :ios do\n  desc \"Check all certs and provisioning profiles from github\"\n  lane :certs do\n    app_root = \"com.irccloud.\"\n    for type in [\"development\"] do\n      match(type: type, app_identifier: [\n        \"#{app_root}IRCCloud\",\n        \"#{app_root}IRCCloud.ShareExtension\",\n        \"#{app_root}IRCCloud.NotificationService\",\n        \"#{app_root}enterprise\",\n        \"#{app_root}enterprise.ShareExtension\",\n        \"#{app_root}enterprise.NotificationService\"\n       ])\n    end\n  end\n\n  desc \"Generate new push certs\"\n  lane :apn do |options|\n    if options[:enterprise]\n        bundle_id = \"com.irccloud.enterprise\"\n    else\n        bundle_id = \"com.irccloud.IRCCloud\"\n    end\n\n    get_push_certificate(\n      generate_p12: false,\n      app_identifier: bundle_id\n    )\n  end\n\n  desc \"Upload symbols to FirebaseCrashlytics\"\n  lane :upload_symbols do |options|\n    sh \"cd .. && pods/FirebaseCrashlytics/upload-symbols -gsp IRCCloud/GoogleService-Info.plist -p ios IRCCloud.app.dSYM.zip\"\n  end\n\n  desc \"Build and push to iTunes Connect\"\n  lane :push do |options|\n    if options[:enterprise]\n        ipa = \"IRCEnterprise.ipa\"\n        scheme = \"IRCCloud Enterprise\"\n        bundle_id = \"com.irccloud.enterprise\"\n        profile_root = \"App Store Enterprise\"\n    else\n        ipa = \"IRCCloud.ipa\"\n        scheme = \"IRCCloud\"\n        bundle_id = \"com.irccloud.IRCCloud\"\n        profile_root = \"App Store\"\n    end\n    \n    # Set a build number manually if provided\n    # TODO pull this from the Info.plist\n    default_build_number = \"GIT_VERSION\"\n    if options[:build]\n        sh \"cd .. && agvtool new-version -all #{options[:build]}\"\n    end\n    \n    # Install CocoaPods\n    cocoapods(podfile: \"./Podfile\")\n\n    # Build an ipa\n    gym(\n      scheme: scheme,\n      configuration: \"AppStore\",\n      export_method: \"app-store\",\n      export_options: {\n        method: \"app-store\",\n        provisioningProfiles: {\n          \"#{bundle_id}\" => \"#{profile_root}\",\n          \"#{bundle_id}.ShareExtension\" => \"#{profile_root} ShareExtension\",\n          \"#{bundle_id}.NotificationService\" => \"#{profile_root} NotificationService\",\n        }\n      }\n    )\n\n    # Reset the build number\n    if options[:build]\n        sh \"cd .. && agvtool new-version -all #{default_build_number}\"\n    end\n    \n    # Upload to iTunes Connect\n    deliver(\n        ipa: ipa,\n        skip_metadata: true,\n        skip_screenshots: true\n    )\n    \n    sh \"cd .. && pods/FirebaseCrashlytics/upload-symbols -gsp IRCCloud/GoogleService-Info.plist -p ios IRCCloud.app.dSYM.zip\"\n  end\n\n  desc \"Print version\"\n  lane :vers do\n    UI.success \"Version: #{app_vers()}\"\n  end\n  \n  desc \"Take screenshots\"\n  lane :screenshots do\n    snapshot(\n      clear_previous_screenshots: true,\n      skip_open_summary: true,\n      clean: true,\n      derived_data_path: \"./build\",\n      devices: [\"iPhone X\", \"iPhone 6s Plus\", \"iPhone 13 Pro Max\"],\n      ios_version: \"12.2\",\n      launch_arguments: [\"-bigphone YES\"]\n    )\n    snapshot(\n      clear_previous_screenshots: false,\n      skip_open_summary: true,\n      derived_data_path: \"./build\",\n      test_without_building: true,\n      devices: [\n      \"iPhone 5s\",\n      \"iPhone 6s\",\n      \"iPad Pro (9.7-inch)\",\n      \"iPad Pro (10.5-inch)\",\n      \"iPad Pro (11-inch)\",\n      \"iPad Pro (12.9-inch) (2nd generation)\"\n      ],\n      ios_version: \"12.2\"\n    )\n    frameit()\n    notification(\n      subtitle: \"screenshots\",\n      message: \"iOS screenshots complete\",\n      activate: \"com.googlecode.iterm2\"\n    )\n  end\n\n  desc \"Upload metadata\"\n  lane :metadata do |options|\n    fastlane_require 'json'\n\n    if options[:enterprise]\n        metadata_path = \"./fastlane/metadata-enterprise\"\n        app_identifier = \"com.irccloud.enterprise\"\n    else\n        metadata_path = \"./fastlane/metadata\"\n        app_identifier = \"com.irccloud.IRCCloud\"\n    end\n    \n    skip_screenshots = !options[:screenshots]\n    \n    app_version = options[:app_version] || app_vers()\n    deliver(\n        app_version: app_version,\n        app_identifier: app_identifier,\n        skip_binary_upload: true,\n        skip_screenshots: skip_screenshots,\n        metadata_path: metadata_path,\n        automatic_release: true\n    )\n  end\n\n  desc \"Make sure all devices are added to the ad-hoc profile\"\n  lane :updateadhoc do\n    match(type: \"adhoc\", force_for_new_devices: true, app_identifier: \"com.irccloud.IRCCloud\")\n    match(type: \"adhoc\", force_for_new_devices: true, app_identifier: \"com.irccloud.IRCCloud.ShareExtension\")\n    match(type: \"adhoc\", force_for_new_devices: true, app_identifier: \"com.irccloud.IRCCloud.NotificationService\")\n  end\nend\n\n\nplatform :mac do\n  desc \"Build and push to iTunes Connect\"\n  lane :push do |options|\n    pkg = \"IRCCloud.pkg\"\n    scheme = \"IRCCloud\"\n    \n    # Set a build number manually if provided\n    # TODO pull this from the Info.plist\n    default_build_number = \"GIT_VERSION\"\n    if options[:build]\n        sh \"cd .. && agvtool new-version -all #{options[:build]}\"\n    end\n    \n    # Build a pkg\n    gym(\n      scheme: scheme,\n      configuration: \"AppStore\",\n      export_method: \"app-store\",\n      catalyst_platform: \"macos\",\n      skip_profile_detection: true,\n      export_options: {\n        method: \"app-store\",\n        provisioningProfiles: {\n          \"com.irccloud.IRCCloud\" => \"Catalyst IRCCloud\",\n          \"com.irccloud.IRCCloud.ShareExtension\" => \"Catalyst ShareExtension\",\n          \"com.irccloud.IRCCloud.NotificationService\" => \"Catalyst NotificationService\",\n        }\n      }\n    )\n\n    # Reset the build number\n    if options[:build]\n        sh \"cd .. && agvtool new-version -all #{default_build_number}\"\n    end\n    \n    # Upload to iTunes Connect\n    deliver(\n        pkg: pkg,\n        platform: \"osx\",\n        run_precheck_before_submit: false,\n        skip_metadata: true,\n        skip_screenshots: true\n    )\n  end\nend\n\n\n# More information about multiple platforms in fastlane: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Platforms.md\n# All available actions: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Actions.md\n\n# fastlane reports which actions are used\n# No personal data is recorded. Learn more at https://github.com/fastlane/enhancer\n#\n"
  },
  {
    "path": "fastlane/README.md",
    "content": "fastlane documentation\n----\n\n# Installation\n\nMake sure you have the latest version of the Xcode command line tools installed:\n\n```sh\nxcode-select --install\n```\n\nFor _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane)\n\n# Available Actions\n\n## iOS\n\n### ios certs\n\n```sh\n[bundle exec] fastlane ios certs\n```\n\nCheck all certs and provisioning profiles from github\n\n### ios apn\n\n```sh\n[bundle exec] fastlane ios apn\n```\n\nGenerate new push certs\n\n### ios upload_symbols\n\n```sh\n[bundle exec] fastlane ios upload_symbols\n```\n\nUpload symbols to FirebaseCrashlytics\n\n### ios push\n\n```sh\n[bundle exec] fastlane ios push\n```\n\nBuild and push to iTunes Connect\n\n### ios vers\n\n```sh\n[bundle exec] fastlane ios vers\n```\n\nPrint version\n\n### ios screenshots\n\n```sh\n[bundle exec] fastlane ios screenshots\n```\n\nTake screenshots\n\n### ios metadata\n\n```sh\n[bundle exec] fastlane ios metadata\n```\n\nUpload metadata\n\n### ios updateadhoc\n\n```sh\n[bundle exec] fastlane ios updateadhoc\n```\n\nMake sure all devices are added to the ad-hoc profile\n\n----\n\n\n## Mac\n\n### mac push\n\n```sh\n[bundle exec] fastlane mac push\n```\n\nBuild and push to iTunes Connect\n\n----\n\nThis README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.\n\nMore information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).\n\nThe documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).\n"
  },
  {
    "path": "fastlane/Snapfile",
    "content": "languages([\n  \"en-US\"\n])\n\n# Arguments to pass to the app on launch. See https://github.com/fastlane/snapshot#launch-arguments\n# launch_arguments([\"-favColor red\"])\n\n# The name of the scheme which contains the UI Tests\nscheme \"IRCCloud Mock Data\"\n\n# Where should the resulting screenshots be stored?\noutput_directory \"./screenshots\"\n\nclear_previous_screenshots true # remove the '#' to clear all previously generated screenshots before creating new ones\n\n# Choose which project/workspace to use\nproject \"./IRCCloud.xcodeproj\"\n\n# For more information about all available options run\n# snapshot --help\n"
  },
  {
    "path": "fastlane/metadata/copyright.txt",
    "content": "2021 IRCCloud Ltd."
  },
  {
    "path": "fastlane/metadata/en-US/description.txt",
    "content": "Chat on IRC from anywhere, and never miss a message.\n\n• Stay connected when you're on the move. No need to rely on constant data access, we keep your IRC connection running on our servers.\n• Your entire chat history is fully synced to the cloud so you can catch up at your leisure.\n• Get push notifications for mentions and private messages.\n• Upload and share photos, videos and files straight from your device.\n• Full support for iPhone and iPad.\n• Choose from 9 colourful themes.\n• Monospace font option.\n\nJoin our #feedback channel on irc.irccloud.com for feedback and suggestions to help us improve this app. You can also email us at team@irccloud.com or find us on Twitter: @irccloud"
  },
  {
    "path": "fastlane/metadata/en-US/keywords.txt",
    "content": "irc,cloud,irccloud,group,messaging,team,collaboration,chat"
  },
  {
    "path": "fastlane/metadata/en-US/marketing_url.txt",
    "content": ""
  },
  {
    "path": "fastlane/metadata/en-US/name.txt",
    "content": "IRCCloud"
  },
  {
    "path": "fastlane/metadata/en-US/privacy_url.txt",
    "content": "https://www.irccloud.com/privacy"
  },
  {
    "path": "fastlane/metadata/en-US/release_notes.txt",
    "content": "• Fixed an issue where the share extension couldn't send to channels containing an ampersand symbol\n• Stability improvements and minor fixes"
  },
  {
    "path": "fastlane/metadata/en-US/support_url.txt",
    "content": "https://www.irccloud.com/?/feedback"
  },
  {
    "path": "fastlane/metadata/primary_category.txt",
    "content": "BUSINESS"
  },
  {
    "path": "fastlane/metadata/primary_first_sub_category.txt",
    "content": ""
  },
  {
    "path": "fastlane/metadata/primary_second_sub_category.txt",
    "content": ""
  },
  {
    "path": "fastlane/metadata/review_notes.txt",
    "content": "notes"
  },
  {
    "path": "fastlane/metadata/secondary_category.txt",
    "content": "SOCIAL_NETWORKING"
  },
  {
    "path": "fastlane/metadata/secondary_first_sub_category.txt",
    "content": ""
  },
  {
    "path": "fastlane/metadata/secondary_second_sub_category.txt",
    "content": ""
  },
  {
    "path": "fastlane/metadata-enterprise/copyright.txt",
    "content": "2019 IRCCloud Ltd."
  },
  {
    "path": "fastlane/metadata-enterprise/en-US/description.txt",
    "content": "This app lets you connect to an organisation's self-hosted IRCCloud install for Enterprise. If you access your account on irccloud.com this app is not for you.\n\nChat on IRC from anywhere, and never miss a message.\n\n• Stay connected when you're on the move. No need to rely on constant data access, your IRC connection is kept running on your enterprise servers.\n• Your entire chat history is fully synced with your enterprise install so you can catch up at your leisure.\n• Get push notifications for mentions and private messages.\n• Upload and share photos, videos and files straight from your device.\n• Full support for iPhone and iPad.\n• Choose from 9 colourful themes.\n• Monospace font option.\n\nJoin our #feedback channel on irc.irccloud.com for feedback and suggestions to help us improve this app. You can also email us at enterprise@irccloud.com or find us on Twitter: @irccloud"
  },
  {
    "path": "fastlane/metadata-enterprise/en-US/keywords.txt",
    "content": "irc,irccloud,chat,communication,enterprise,comms,channels,group,messaging,team,collaboration"
  },
  {
    "path": "fastlane/metadata-enterprise/en-US/marketing_url.txt",
    "content": ""
  },
  {
    "path": "fastlane/metadata-enterprise/en-US/name.txt",
    "content": "IRCCloud Enterprise"
  },
  {
    "path": "fastlane/metadata-enterprise/en-US/privacy_url.txt",
    "content": "https://www.irccloud.com/privacy"
  },
  {
    "path": "fastlane/metadata-enterprise/en-US/release_notes.txt",
    "content": "• Add an option to automatically switch between Dawn and Midnight themes based on the current iOS dark mode setting\n• Fix status bar overlapping the navigation bar when rotating from landscape to portrait on some devices\n• Fix an issue that could messages to show the wrong avatar while being sent\n• Image thumbnails can no longer unexpectedly appear in the wrong channel\n• Fix scroll position when showing/hiding the keyboard\n• Improved detection of hyperlinks\n• Stability improvements and minor fixes\n"
  },
  {
    "path": "fastlane/metadata-enterprise/en-US/support_url.txt",
    "content": "https://www.irccloud.com/?/feedback"
  },
  {
    "path": "fastlane/metadata-enterprise/primary_category.txt",
    "content": "MZGenre.Business"
  },
  {
    "path": "fastlane/metadata-enterprise/primary_first_sub_category.txt",
    "content": ""
  },
  {
    "path": "fastlane/metadata-enterprise/primary_second_sub_category.txt",
    "content": ""
  },
  {
    "path": "fastlane/metadata-enterprise/review_notes.txt",
    "content": "notes"
  },
  {
    "path": "fastlane/metadata-enterprise/secondary_category.txt",
    "content": "MZGenre.SocialNetworking"
  },
  {
    "path": "fastlane/metadata-enterprise/secondary_first_sub_category.txt",
    "content": ""
  },
  {
    "path": "fastlane/metadata-enterprise/secondary_second_sub_category.txt",
    "content": ""
  },
  {
    "path": "fastlane/review_info.json",
    "content": "{\n  \"first_name\": \"first_name\",\n  \"last_name\": \"last_name\",\n  \"phone_number\": \"phone_number\",\n  \"email_address\": \"email_address\",\n  \"demo_user\": \"demo_user\",\n  \"demo_password\": \"demo_password\"\n}\n"
  }
]