text:
//
//  MyWKWebView.m
//  Webkit-Demo
//
//  Created by luowei on 15/6/25.
//  Copyright (c) 2015 rootls. All rights reserved.
//

#import "MyWKWebView.h"
#import "MyWKWebViewController.h"
#import "MyHelper.h"
#import "Reachability.h"
#import "Defines.h"
#import "UserSetting.h"
#import "RegExCategories.h"
#import <objc/message.h>

@implementation MyWKUserContentController

//获得MyWKUserContentController单例
+ (instancetype)shareInstance {
    static MyWKUserContentController *myContentController = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        myContentController = [[self alloc] init];
    });

    return myContentController;
}

- (instancetype)init {
    self = [super init];
    if (self) {

        //-----修改百度logo图片------

        //文档开始加载时
        NSString *docStartInjectionJS = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DocStartInjection" ofType:@"js"]
                                                                  encoding:NSUTF8StringEncoding error:NULL];

        //在document加载前执行注入js脚本
        WKUserScript *docStartScript = [[WKUserScript alloc] initWithSource:docStartInjectionJS injectionTime:WKUserScriptInjectionTimeAtDocumentStart
                                                           forMainFrameOnly:NO];
        [self addUserScript:docStartScript];

        //文档完成加载时
        NSString *docEndInjectionJS = [NSString stringWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"DocEndInjection" withExtension:@"js"]
                                                               encoding:NSUTF8StringEncoding error:NULL];

        //在document加载完成后执行注入js脚本
        WKUserScript *docEndScript = [[WKUserScript alloc] initWithSource:docEndInjectionJS injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
                                                         forMainFrameOnly:YES];
        [self addUserScript:docEndScript];

        //-------无图模式--------

        //无图模式注入js
        NSString *jsPath = [[NSBundle mainBundle] pathForResource:@"imageBlocker" ofType:@"js"];
        NSString *source = [NSString stringWithContentsOfFile:jsPath encoding:NSUTF8StringEncoding error:nil];
        WKUserScript *blockImageUserScript = [[WKUserScript alloc] initWithSource:source injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [self addUserScript:blockImageUserScript];

        WKUserScript *blockBackgroundImageUserScript = [[WKUserScript alloc] initWithSource:@"ImageBlocker.removeBackgroundImages();" injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
        [self addUserScript:blockBackgroundImageUserScript];

        //-------广告拦截-------
        NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"abp" ofType:@ "bundle"];
        NSBundle *abpBundle = [NSBundle bundleWithPath:bundlePath];

        NSString *publicSuffixListSource = [[NSString stringWithContentsOfFile:[abpBundle pathForResource:@"publicSuffixList" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil] stringByReplacingOccurrencesOfString:@"\n" withString:@""];
        WKUserScript *publicSuffixListUserScript = [[WKUserScript alloc] initWithSource:publicSuffixListSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [self addUserScript:publicSuffixListUserScript];

        NSString *basedomainSource = [NSString stringWithContentsOfFile:[abpBundle pathForResource:@"basedomain" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil];
        WKUserScript *basedomainUserScript = [[WKUserScript alloc] initWithSource:basedomainSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [self addUserScript:basedomainUserScript];

        NSString *filterClassesSource = [NSString stringWithContentsOfFile:[abpBundle pathForResource:@"filterClasses" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil];
        WKUserScript *filterClassesUserScript = [[WKUserScript alloc] initWithSource:filterClassesSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [self addUserScript:filterClassesUserScript];

        NSString *matcherSource = [NSString stringWithContentsOfFile:[abpBundle pathForResource:@"matcher" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil];
        WKUserScript *matcherUserScript = [[WKUserScript alloc] initWithSource:matcherSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [self addUserScript:matcherUserScript];

        NSString *elemHidePath = [abpBundle pathForResource:@"elemHide" ofType:@"js"];
        WKUserScript *elemHideUserScript = [[WKUserScript alloc] initWithSource:[NSString stringWithContentsOfFile:elemHidePath encoding:NSUTF8StringEncoding error:nil] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [self addUserScript:elemHideUserScript];

        NSString *adBlockerPath = [[NSBundle mainBundle] pathForResource:@"adBlocker" ofType:@"js"];
        WKUserScript *adBlockerUserScript = [[WKUserScript alloc] initWithSource:[NSString stringWithContentsOfFile:adBlockerPath encoding:NSUTF8StringEncoding error:nil] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [self addUserScript:adBlockerUserScript];

        NSString *adElemHidePath = [[NSBundle mainBundle] pathForResource:@"adElemHide" ofType:@"js"];
        WKUserScript *adElemHideUserScript = [[WKUserScript alloc] initWithSource:[NSString stringWithContentsOfFile:adElemHidePath encoding:NSUTF8StringEncoding error:nil] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [self addUserScript:adElemHideUserScript];

        NSString *adRequestBlockerPath = [[NSBundle mainBundle] pathForResource:@"adRequestBlocker" ofType:@"js"];
        WKUserScript *adRequestBlockerUserScript = [[WKUserScript alloc] initWithSource:[NSString stringWithContentsOfFile:adRequestBlockerPath encoding:NSUTF8StringEncoding error:nil] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [self addUserScript:adRequestBlockerUserScript];

        NSString *blockRules = [UserSetting getEasyListText];
        blockRules = [blockRules stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"];
        blockRules = [blockRules stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
        blockRules = [blockRules stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"];
        blockRules = [blockRules stringByReplacingOccurrencesOfString:@"\r" withString:@""];

        BOOL adblockStatus = [UserSetting adblockerStatus];
        NSString *compileFiltersSource = [NSString stringWithFormat:@"AdBlocker.compileABPRules('%@');AdBlocker.enable=%@;", blockRules, adblockStatus?@"true":@"false"];

        WKUserScript *compileFiltersUserScript = [[WKUserScript alloc] initWithSource:compileFiltersSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [self addUserScript:compileFiltersUserScript];

    }

    return self;
}

- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name {
    [super addScriptMessageHandler:scriptMessageHandler name:name];
    _handlerNames = _handlerNames ?: @{}.mutableCopy;
    [_handlerNames setValue:[NSNull null] forKey:name];
}

@end

@interface MyWKWebView () {

}

@property(nonatomic, strong) NSError *error;
@end

@implementation MyWKWebView

static WKProcessPool *_pool;

+ (WKProcessPool *)pool {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _pool = [[WKProcessPool alloc] init];
    });
    return _pool;
}

- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration {

    //设置多窗口cookie共享
    configuration.processPool = [MyWKWebView pool];
//    self.backForwardList

    self = [super initWithFrame:frame configuration:configuration];
    if (self) {
        self.navigationDelegate = self;
        self.UIDelegate = self;
        self.allowsBackForwardNavigationGestures = YES;
//        self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

        //加载用户js文件,修改加载网页内容
        [self addUserScriptsToWeb:configuration.userContentController];

        //网络连接状态标示
        _netStatusLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        //隐藏
        _netStatusLabel.alpha = 0;
        _netStatusLabel.text = NSLocalizedString(@"Unable Open Web Page With NetWork Disconnected", nil);
        _netStatusLabel.font = [UIFont systemFontOfSize:20.0];
        _netStatusLabel.textColor = [UIColor grayColor];
        [_netStatusLabel sizeToFit];
        _netStatusLabel.center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
        [self addSubview:_netStatusLabel];
        _netStatusLabel.hidden = YES;
    }

    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];

    _netStatusLabel.text = NSLocalizedString(@"Unable Open Web Page With NetWork Disconnected", nil);
    [_netStatusLabel sizeToFit];
    _netStatusLabel.center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
}

- (void)dealloc {
    self.removeProgressObserverBlock();
}

//加载用户js文件
- (void)addUserScriptsToWeb:(MyWKUserContentController *)userContentController {

    //添加脚本消息处理器根据消息名称

    if (![userContentController.handlerNames valueForKey:@"docStartInjection"])
        [userContentController addScriptMessageHandler:self name:@"docStartInjection"];
    if (![userContentController.handlerNames valueForKey:@"docEndInjection"])
        [userContentController addScriptMessageHandler:self name:@"docEndInjection"];

    if (![userContentController.handlerNames valueForKey:@"decideImageBlockStatus"])
        [userContentController addScriptMessageHandler:self name:@"decideImageBlockStatus"];
    if (![userContentController.handlerNames valueForKey:@"decideAdBlockStatus"])
        [userContentController addScriptMessageHandler:self name:@"decideAdBlockStatus"];
    if (![userContentController.handlerNames valueForKey:@"increaseAdBlockCount"])
        [userContentController addScriptMessageHandler:self name:@"increaseAdBlockCount"];

//        //js注入,用于改变网页字体的大小
//        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"webFontjs" ofType:@"js"];
//        NSString *jsString = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
//        [self evaluateJavaScript:jsString completionHandler:nil];

    //添加ScriptMessageHandler
    if (![userContentController.handlerNames valueForKey:@"webViewBack"])
        [userContentController addScriptMessageHandler:self name:@"webViewBack"];
    if (![userContentController.handlerNames valueForKey:@"webViewReload"])
        [userContentController addScriptMessageHandler:self name:@"webViewReload"];

}

//Sync JavaScript in WKWebView(同步版的javascript执行器)
//evaluateJavaScript is callback type. result should be handled by callback so, it is async.
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)javascript {
    __block NSString *res = nil;
    __block BOOL finish = NO;
    [self evaluateJavaScript:javascript completionHandler:^(NSString *result, NSError *error) {
        res = result;
        finish = YES;
    }];

    while (!finish) {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
    }
    return res;
}

//加载请求
- (WKNavigation *)loadRequest:(NSURLRequest *)request {

    NSMutableURLRequest *mutableURLRequest = [NSMutableURLRequest requestWithURL:request.URL];

    //Add cookies to a request
//    [mutableURLRequest addValue:@"TeskCookieKey1=TeskCookieValue1;TeskCookieKey2=TeskCookieValue2;" forHTTPHeaderField:@"Cookie"];
//    // use stringWithFormat: in the above line to inject your values programmatically

    //set user-agent
//    [mutableURLRequest setValue:@"YourUserAgent/1.0" forHTTPHeaderField:@"User-Agent"];
    NSString *urlText = nil;
    if (request && request.URL) {
        urlText = request.URL.absoluteString;
    }
    self.updateSearchBarTextBlock(urlText);

    _netStatusLabel.hidden = [self connected];

    return [super loadRequest:request];
}

#pragma mark WKNavigationDelegate Implementation

//决定是否请允许打开
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

/*
    NSURL *url = navigationAction.request.URL;
    //处理App一类的特殊网址
    if (![url.absoluteString isHttpURL] && ![url.absoluteString isDomain]) {
        [[UIApplication sharedApplication] openURL:url];
        decisionHandler(WKNavigationActionPolicyCancel);
    } else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
*/

    NSURL *url = navigationAction.request.URL;
    NSString *urlString = (url) ? url.absoluteString : @"";
    // iTunes: App Store link跳转不了问题
    if ([urlString isMatch:RX(@"\\/\\/itunes\\.apple\\.com\\/")]) {
        [[UIApplication sharedApplication] openURL:url];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    //蒲公英安装不了问题
    if ([urlString hasPrefix:@"itms-services://?action=download-manifest"]) {
        [[UIApplication sharedApplication] openURL:url];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    if ([url.scheme isEqualToString:@"tel"]) {
        NSString *phoneNumber = url.resourceSpecifier.stringByRemovingPercentEncoding;
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:phoneNumber message:nil preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Call", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
            [[UIApplication sharedApplication] openURL:url];
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }]];
        [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {

        }]];
        self.presentViewControllerBlock(alertController);
    }
    //决定是否新窗口打开
    if (!navigationAction.targetFrame) {
        if ([urlString hasSuffix:@".apk"]) {
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
        [webView loadRequest:navigationAction.request];
    }

    decisionHandler(WKNavigationActionPolicyAllow);
}

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
/*
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
    NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];

    for (NSHTTPCookie *cookie in cookies) {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
    }
*/

//    if(navigationResponse.canShowMIMEType){
//        NSString *mimeType = navigationResponse.response.MIMEType.lowercaseString;
//        if([mimeType isEqualToString:@"image/jpeg"] || [mimeType isEqualToString:@"image/png"] || [mimeType isEqualToString:@"image/gif"]){
//            decisionHandler(WKNavigationResponsePolicyCancel);
//            return;
//        }
//    }
    decisionHandler(WKNavigationResponsePolicyAllow);
}

- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
}

//处理当接收到验证窗口时
- (void)  webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
    NSString *hostName = webView.URL.host;

    NSString *authenticationMethod = [[challenge protectionSpace] authenticationMethod];
    if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodDefault]
            || [authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]
            || [authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest]) {

        NSString *title = @"Authentication Challenge";
        NSString *message = [NSString stringWithFormat:@"%@ requires user name and password", hostName];
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
        [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
            textField.placeholder = @"User";
            //textField.secureTextEntry = YES;
        }];
        [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
            textField.placeholder = @"Password";
            textField.secureTextEntry = YES;
        }];
        [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {

            NSString *userName = ((UITextField *) alertController.textFields[0]).text;
            NSString *password = ((UITextField *) alertController.textFields[1]).text;

            NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:userName password:password persistence:NSURLCredentialPersistenceNone];

            completionHandler(NSURLSessionAuthChallengeUseCredential, credential);

        }]];
        [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
        }]];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.presentViewControllerBlock(alertController);
        });

    } else {
        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
    }

}

- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

    if ([UserSetting UASignIsChanged]) {
        [self switchUAMode:@([UserSetting UASign])];
        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"UASignIsChanged"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    //修改浏览器UA设置
    if ([UserSetting UserAgent] == nil) {
        __weak typeof(self) weadSelf = self;
        [self evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
            NSString *userAgent = result;
            if (userAgent && userAgent.length > 0) {
                [UserSetting SetUserAgent:userAgent];
                [weadSelf switchUAMode:@([UserSetting UASign])];
            }
        }];
    }

    //todo:清除当前广告拦截数据记录
    //[AdblockManager cleanCurrentBlockCount];

    //todo:更新返回按钮及进度条(didStartLoadingWebView)
}

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"error = %@", error);
    self.error = error;
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];

    //todo:更新进度条(didFailLoadWebView)

    switch ([error code]) {
        case kCFURLErrorServerCertificateUntrusted: {
            //解决12306不能买票问题
            NSRange range = [[webView.URL host] rangeOfString:@"12306.cn"];

            if (range.location != NSNotFound && range.location) {
                NSArray *chain = error.userInfo[@"NSErrorPeerCertificateChainKey"];
                NSURL *failingURL = error.userInfo[@"NSErrorFailingURLKey"];
                [self setAllowsHTTPSCertifcateWithCertChain:chain ForHost:[failingURL host]];
                [webView loadRequest:[NSURLRequest requestWithURL:failingURL]];
            } else {
                // 网站证书不被信任,给出提示
                UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:
                                [NSString stringWithFormat:NSLocalizedString(@"HTTPS Certifcate Not Trust", nil), webView.URL.host]
                                                                   delegate:self
                                                          cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
                                                     destructiveButtonTitle:NSLocalizedString(@"OK", nil)
                                                          otherButtonTitles:nil, nil];
                [sheet showInView:self];
            }
            break;
        }
        case kCFURLErrorBadServerResponse:
        case kCFURLErrorNotConnectedToInternet:
        case kCFSOCKS5ErrorNoAcceptableMethod:
        case kCFErrorHTTPBadCredentials:
        case kCFErrorHTTPConnectionLost:
        case kCFErrorHTTPBadURL:
        case kCFErrorHTTPBadProxyCredentials:
        case kCFURLErrorBadURL:
        case kCFURLErrorTimedOut:
        case kCFURLErrorCannotFindHost:
        case kCFURLErrorCannotConnectToHost:
        case kCFURLErrorNetworkConnectionLost:
        case kCFNetServiceErrorTimeout:
        case kCFNetServiceErrorNotFound:
//            NSLog(@"errorCode:%ld",(long)[error code]);
            //error webView
            if (self.estimatedProgress < 0.3) {
                NSString *path = [[NSBundle mainBundle] pathForResource:@"failedPage" ofType:@"htm"];
                NSError *error2;
                NSString *htmlString = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error2];
                NSURL *failingURL = error.userInfo[@"NSErrorFailingURLKey"];
                [webView loadHTMLString:htmlString baseURL:failingURL];
            }
            break;
        default: {
            break;
        }
    }
}

//当加载页面发生错误
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {

//    UIAlertController *alertViewController = [UIAlertController alertControllerWithTitle:@"Error"
//                                                                                message:error.localizedDescription
//                                                                          preferredStyle:UIAlertControllerStyleAlert];
//    [alertViewController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:nil]];
//    self.presentViewControllerBlock(alertViewController);

    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    ((MyWKWebView *)webView).updateSearchBarTextBlock(webView.URL.absoluteString);
    //todo:更新进度条(didFailLoadWebView)

    switch ([error code]) {
        case kCFURLErrorServerCertificateUntrusted: {
            //解决12306不能买票问题
            NSRange range = [[webView.URL host] rangeOfString:@"12306.cn"];
            if (range.location != NSNotFound) {
                NSArray *chain = error.userInfo[@"NSErrorPeerCertificateChainKey"];
                NSURL *failingURL = error.userInfo[@"NSErrorFailingURLKey"];
                [self setAllowsHTTPSCertifcateWithCertChain:chain ForHost:[failingURL host]];
                [webView loadRequest:[NSURLRequest requestWithURL:failingURL]];
            }
            break;
        }
        case kCFURLErrorBadServerResponse:
        case kCFURLErrorNotConnectedToInternet:
        case kCFSOCKS5ErrorNoAcceptableMethod:
        case kCFErrorHTTPBadCredentials:
        case kCFErrorHTTPConnectionLost:
        case kCFErrorHTTPBadURL:
        case kCFErrorHTTPBadProxyCredentials:
        case kCFURLErrorBadURL:
        case kCFURLErrorTimedOut:
        case kCFURLErrorCannotFindHost:
        case kCFURLErrorCannotConnectToHost:
        case kCFURLErrorNetworkConnectionLost:
        case kCFNetServiceErrorTimeout:
        case kCFNetServiceErrorNotFound:
            NSLog(@"errorCode:%ld", (long) [error code]);
            //error webView
            if (self.estimatedProgress < 0.3) {
                NSString *path = [[NSBundle mainBundle] pathForResource:@"failedPage" ofType:@"htm"];
                NSError *error2;
                NSString *htmlString = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error2];
                NSURL *failingURL = error.userInfo[@"NSErrorFailingURLKey"];
                [webView loadHTMLString:htmlString baseURL:failingURL];
            }
            break;
        default: {
            break;
        }
    }

}

//当页面加载完成
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    self.finishNavigationProgressBlock();

    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    ((MyWKWebView *)webView).updateSearchBarTextBlock(webView.URL.absoluteString);

//    //获得网站的icon
//    [self evaluateJavaScript:[self JSToolCode] completionHandler:nil];
//    __weak typeof(self) weadSelf = self;
//    [self evaluateJavaScript:@"getAppIcon();" completionHandler:^(NSString *result, NSError *error) {
//        [self.delegate mainView:weadSelf updateFavIcon:result];
//    }];

}

//允许HTTPS验证钥匙中证书
- (void)setAllowsHTTPSCertifcateWithCertChain:(NSArray *)certChain ForHost:(NSString *)host {
    ((void (*)(id, SEL, id, id)) objc_msgSend)(self.configuration.processPool,
            //- (void)_setAllowsSpecificHTTPSCertificate:(id)arg1 forHost:(id)arg2;
            NSSelectorFromString([NSString base64Decoding:@"X3NldEFsbG93c1NwZWNpZmljSFRUUFNDZXJ0aWZpY2F0ZTpmb3JIb3N0Og=="]),
            certChain, host);
}

//切换用户代理模式
- (void)switchUAMode:(NSNumber *)modeNumber {
    if ([UserSetting UserAgent] != nil) {
        NSString *appVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"];
        NSString *UAString = nil;
        switch ([modeNumber intValue]) {
            case 0:
                if ([UserSetting UserAgent] != nil) {
                    UAString = [NSString stringWithFormat:@"%@ MyBrowser/%@", [UserSetting UserAgent], appVersion];
                }
                break;
            case 1:
                if ([UserSetting UserAgent] != nil) {
                    UAString = [NSString stringWithFormat:@"%@ MyBrowser Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.3.18 (KHTML, like Gecko) Version/8.0.3 Safari/600.3.18", [UserSetting UserAgent]];
                }
                break;

            default:
                break;
        }

        //- (void)_setCustomUserAgent:(id)arg1;
        ((void (*)(id, SEL, id)) objc_msgSend)(self, NSSelectorFromString([NSString base64Decoding:@"X3NldEN1c3RvbVVzZXJBZ2VudDo="]), UAString);
    }
}

#pragma mark WKMessageHandle Implementation

//处理当接收到html页面脚本发来的消息
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    //返回
    if ([message.name isEqualToString:@"webViewBack"]) {
        [self goBack];

        //重新加载
    } else if ([message.name isEqualToString:@"webViewReload"]) {
        [self reload];

        //开启广告拦截
    } else if ([message.name isEqualToString:@"decideAdBlockStatus"]) {
        [self enableAdBlocker:[UserSetting adblockerStatus]];

        //记录拦截数
    } else if ([message.name isEqualToString:@"increaseAdBlockCount"]) {
        //记录拦截了多少条广告

        //开启无图模式
    } else if ([message.name isEqualToString:@"decideImageBlockStatus"]) {
        [self enableImageBlock:[UserSetting imageBlockerStatus]];
    }
}

//开启广告拦截
- (void)enableAdBlocker:(BOOL)enable {
    if (enable) {
        [self evaluateJavaScript:@"AdBlocker.enable=true;" completionHandler:nil];
    } else {
        [self evaluateJavaScript:@"AdBlocker.enable=false;" completionHandler:nil];
    }

}

//开启无图模式
- (void)enableImageBlock:(BOOL)enable {
    if (enable) {
        [self evaluateJavaScript:@"ImageBlocker.enable=true;" completionHandler:nil];
    } else {
        [self evaluateJavaScript:@"ImageBlocker.enable=false;" completionHandler:nil];
    }

}

#pragma mark WKUIDelegate Implementation

//let link has arget="_blank" work
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
   forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {

    //
//    if (!navigationAction.targetFrame.isMainFrame) {
////        NSURL *url = navigationAction.request.URL;
////        UIApplication *app = [UIApplication sharedApplication];
////        if ([app canOpenURL:url]) {
////            [app openURL:url];
////        }
//        MyWKWebView *wb = nil;
//        self.addWKWebViewBlock(&wb,navigationAction.request.mainDocumentURL);
//        [webView loadRequest:navigationAction.request];
//        return wb;
//    }
    if (!navigationAction.targetFrame.isMainFrame) {
        [webView loadRequest:navigationAction.request];
    }

    return nil;
}

//处理页面的alert弹窗
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)())completionHandler {
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:webView.URL.host message:message preferredStyle:UIAlertControllerStyleAlert];

    [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Close", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        completionHandler();
    }]];
    self.presentViewControllerBlock(alertController);
}

//处理页面的confirm弹窗
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {

    // TODO We have to think message to confirm "YES"
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:webView.URL.host message:message preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        completionHandler(YES);
    }]];
    [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        completionHandler(NO);
    }]];
    self.presentViewControllerBlock(alertController);
}

//处理页面的promt弹窗
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *))completionHandler {

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:webView.URL.host preferredStyle:UIAlertControllerStyleAlert];
    [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
        textField.text = defaultText;
    }];

    [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        NSString *input = ((UITextField *) alertController.textFields.firstObject).text;
        completionHandler(input);
    }]];

    [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        completionHandler(nil);
    }]];
    self.presentViewControllerBlock(alertController);
}

#pragma mark - UIActionSheetDelegate

// 网站证书不被信任的情况
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    switch (buttonIndex) {
        case 0: {
            NSArray *chain = _error.userInfo[@"NSErrorPeerCertificateChainKey"];
            NSURL *failingURL = _error.userInfo[@"NSErrorFailingURLKey"];
            [self setAllowsHTTPSCertifcateWithCertChain:chain ForHost:[failingURL host]];
            [self loadRequest:[NSURLRequest requestWithURL:failingURL]];
            break;
        }
        default:
            break;
    }
}

//判断网络连接状态
- (BOOL)connected {
    Reachability *reachability = [Reachability reachabilityForInternetConnection];
    NetworkStatus networkStatus = [reachability currentReachabilityStatus];
    return networkStatus != NotReachable;
}

#pragma mark - snapshot(快照截图)

//截图快照
- (void)snapshot {
    __weak typeof(self) weakSelf = self;
    [self snapshotWithHandler:^(CGImageRef imgRef) {
        UIImage *image = [UIImage imageWithCGImage:imgRef];
        UIImageWriteToSavedPhotosAlbum(image, weakSelf, NULL, NULL);
    }];
}

//快照截图Handler
- (void)snapshotWithHandler:(void (^)(CGImageRef imgRef))completionHandler {

    CGRect bounds = self.bounds;
    CGFloat imageWidth = self.frame.size.width * [UIScreen mainScreen].scale;

    //- (void)_snapshotRect:(CGRect)rectInViewCoordinates intoImageOfWidth:(CGFloat)imageWidth completionHandler:(void(^)(CGImageRef))completionHandler;
    SEL snapShotSel = NSSelectorFromString([NSString base64Decoding:@"X3NuYXBzaG90UmVjdDppbnRvSW1hZ2VPZldpZHRoOmNvbXBsZXRpb25IYW5kbGVyOg=="]);

    if ([self respondsToSelector:snapShotSel]) {
        ((void (*)(id, SEL, CGRect, CGFloat, id)) objc_msgSend)(self, snapShotSel, bounds, imageWidth, completionHandler);

    }

}

@end

redpajama_set_name: RedPajamaGithub


Clara Louise Maass portrait. Credit: National Museum of Health and Medicine. CC BY 2.0.
Clara Maass was born on June 28, 1876, in the quiet New Jersey township of East Orange. The oldest daughter of Hedwig and Robert E. Maass, she grew up helping to raise and provide for her eight younger siblings. She learned quickly to put others' needs before her own, finding her first paying job at the age of fifteen, after having started work five years earlier as an unpaid "mother's helper."1 Her early experiences in caregiving aided her when, at seventeen, she entered nursing school at the Newark German Hospital. As the child of German immigrants, she was able to tend especially well to the area's German-speaking population, an attribute the hospital had been searching for. She graduated in 1895, and rose quickly through the ranks, becoming the hospital's head nurse three years later.
In 1898, following her appointment as head nurse, the Spanish-American War broke out. While this would not have an immediate effect on Maass, news of the war inevitably traveled. Perhaps more importantly, after initial reluctance, the US Army recognized the need for female nurses in the war effort. Consequently, they began a search and hired 1,563 contract nurses to care for the sick and wounded.2 Clara Maass was one of them.
Her service as a contract nurse would not be the last time Maass would cross paths with yellow fever, but before the two would meet again, the method of transmission would be confirmed. The work of this discovery had begun with Dr. Carlos Finlay,5 but was completed by Major Walter Reed and the U.S. Army Fourth Yellow Fever Commission Board.
The Yellow Fever Commission Board was formed May 23, 1900.6 Prior to their work, a bacteriologist named Giuseppe Sanarelli claimed to have isolated the organism causing yellow fever, and in order to prove it he had injected it into five patients. These patients were uninformed they were part of an experiment and three of them died. The scientific community reacted with appropriate outcry, putting pressure on Reed and his team to get things right in their own experiments.7 Their first steps toward ethical experimentation began with self-experimentation.
Volunteers for the second round of study were carefully selected, and each was paid $100 for participating and an additional $100 if they contracted yellow fever. Monetary payment for medical trials remains controversial today, but at the time was an improvement over the unpaid and undisclosed trials of the past. Throughout the process, "Reed and his colleagues took pains to ensure that volunteers understood the risks associated with their participation in the experiments,"11 up to and including explaining that in the event of their death their payment would go to their appointed next of kin. Participants willing to move forward signed a contract declaring they knew the risks, and the experiment could begin. After this second round of trials, the mosquito vector theory was confirmed.
US stamp honoring Maass. C. 1976. Photograph by John Flannery. CC BY-SA 2.0.
There is no evidence that Maass, or any other participant under Gorgas, signed a consent form. Reed's experiments did increase documentation of consent for a few US researchers, but did not become standard procedure until years later. However, as a nurse Maass had an intimate view of what yellow fever could do, and what it might do to her if she contracted it, including death. With this awareness, she still chose to volunteer for the experiment, making her consent informed, even if she did not give official informed consent. In a way, her volunteering could be considered an extension of Reed's team's self-experimentation. She had already been a part of the medical community's fight to treat and eradicate yellow fever through her nursing work. By participating in the experiment, she escalated that involvement. The Cuban citizens who participated and likely had seen members of their communities or families succumb to the disease volunteered with a similar awareness.
The same cannot be said for the immigrant participants in the study, who volunteered hoping to become immune. They had heard of the disease, and had been warned they would likely contract it, but there was no way for them to know exactly what it entailed without having seen it first hand, as Maass had.
Maass' death put an end to the yellow fever experiments. With her death publicized, the Cuban public finally accepted mosquitoes as the vector for the disease. Havana was able to begin controlling the mosquito and eventually the disease. Even still, there was a reaction in the US to the yellow fever experiments, specifically those that paid volunteers. An editorial published in The Hospital in October 1901 stated that "we should still question the morality of healthy people selling themselves for experimental purposes," regardless of whether participants lived or died.16 This is a debate that continues today, and answers are not easy to reach.
It also cannot be ignored that figures like Reed and Maass are the most well remembered from this incident (at least to US audiences) whereas the Spanish immigrants to Cuba, Cuban citizen participants, and the Cuban and Spanish physicians who laid the groundwork for the research have not earned the same fame. They also risked careers, and some lost their lives.
Still, looking through the scope of history if it had not been for the work of Reed and the sacrifice of Maass, the confirmation of the mosquito vector theory and control of Havana's yellow fever epidemic may have remained out of reach. Their legacy remains important, as Reed's contract was an essential part of the progression toward ethical medical experimentation and informed consent. Clara Maass' death transformed her into a martyr and hero, honored for her dedication to the service of others. In that spirit, we must not forget the others who died for the same cause she did — helping the many.
Enrique Chaves-Carballo. " Clara Maass, Yellow Fever and Human Experimentation" Military Medicine 178, no. 5 (2013): Accessed January 25, 2019. https://doi.org/10.7205/MILMED-D-12-00430.
Russell Roberts. Discover the Hidden New Jersey. (New Brunswick, New Jersey: Rutgers University Press, 1995), 51.
Susan E Lederer. "Walter Reed and the Yellow Fever Experiments." in The Oxford Textbook of Clinical Research Ethics, ed. Ezekiel J. Emanuel, Christine C. Grady, Robert A. Crouch, Reidar K. Lie, Franklin G. Miller, and David D. Wendler. (New York, Oxford University Press, 2008), 10.
Lederer. "Walter Reed and the Yellow Fever Experiments." 4.
Achil Mehra. "Politics of Participation: Walter Reed's Yellow-Fever Experiments." Virtual Mentor 11, no. 4 (2009): Accessed January 25, 2019. doi: 10.1001/virtualmentor.2009.11.4.mhst1-0904. 327.
Lederer. "Walter Reed and the Yellow Fever Experiments." 10.
Roberts. Discover the Hidden New Jersey. 52.
"CLARA LOUISE MAASS." American Association for the History of Nursing (AAHN). Accessed January 25, 2019. https://www.aahn.org/maass.
Mehra. "Politics of Participation: Walter Reed's Yellow-Fever Experiments." 328.
"The Yellow Fever Experiments in Havanna (1901)" The Hospital 31, no. 784 (1901): 2 Accessed January 25, 2019.
Chaves-Carballo, Enrique. " Clara Maass, Yellow Fever and Human Experimentation" Military Medicine 178, no. 5 (2013): 557-562. Accessed January 25, 2019. https://doi.org/10.7205/MILMED-D-12-00430.
Lederer, Susan E. "Walter Reed and the Yellow Fever Experiments." in The Oxford Textbook of Clinical Research Ethics, edited by Ezekiel J. Emanuel, Christine C. Grady, Robert A. Crouch, Reidar K. Lie, Franklin G. Miller, and David D. Wendler, 9-17. New York, Oxford University Press, 2008.
Mehra, Achil. "Politics of Participation: Walter Reed's Yellow-Fever Experiments." Virtual Mentor 11, no. 4 (2009): 326-330. Accessed January 25, 2019. doi: 10.1001/virtualmentor.2009.11.4.mhst1-0904.
Roberts, Russell. Discover the Hidden New Jersey. New Brunswick, New Jersey: Rutgers University Press, 1995.
"The Yellow Fever Experiments in Havanna (1901)" The Hospital, 31, no. 784 (1901): 2 Accessed January 25, 2019.
MARIEL TISHMA currently serves as an Executive Editorial Assistant with Hektoen International. She's been published in Hektoen International, Argot Magazine, Syntax and Salt, The Artifice, and Fickle Muses. She graduated from Columbia College Chicago with a BA in creative writing and a minor in biology. Learn more at marieltishma.com.


text:
How do you define the word "host"? What does it mean to be a host?
Re: Host
by Battle_Weary on Thu Oct 23, 2008 6:03 pm
We don't like the term "host"...to us it implies the presence of parasites!
That said, we understand that many systems define host to mean the one that presents most and is usually somehow tied to the original or is in fact the original. Our original is asleep and we chose one to take her place at age 3. For decades that one was the "host". As we became more aware, we changed to a host-less system where everyone comes and goes as they please (when safe). Everyone within the castle that is.
I kind of agree with BattleWeary on not liking the term "host." But for us, it's because it implies one person whose "house" it is, and a bunch of people who are there at the host's pleasure.
Maybe we could change the word to "Hostess" and then it would make me think of preservative-laden sweets.
But seriously, and in terms of DID/MPD:
I think that "host" isn't necessarily the "birth" one, but is the one who is mostly in charge; part of what I don't like with the term is that it often seems to go along with the notion that the host is the "real" one, and other parts are just fragments who should get absorbed into the host.
I've heard someone define "host" as "the one who first seeks therapy." That's an interesting definition to ponder.
by panzymoon on Wed May 06, 2009 1:35 pm
We think of it as driving....we jokingly say "We are driving the Panzy short bus" but in truth it is a lot like driving. , Currently Gia of my (our)crew is driving and she will (I will) be a lot of our frontswomen. To be out is to be responsible for the body and soul....not all of us follow this rule and some are abusive, but we are trying Want to say hello to every one here and hope that we can all help each other down the road.
Gia/Panzymoon
panzymoon
why_joining1: I am a multiple having trouble coping. I have other mental problems and this is making the journey to healing difficult. I would like to join to see what help you offer and what help I can offer in return. Thanks
by doodles77 on Sat May 09, 2009 4:26 pm
we don't like the term because it tendas to set one apart from the rest . and this is difficult to the one who has been given this kind of designated spot . made her feel like she wasn't just one of the gang and that she had higher expectations . now we have diffrent levels of authority but are earned and can be lost by acting out .
we have found by giveing folks the oppertunity to earn rank not just be said you are the host ... gives motivation to try to earn a reward for doing things others may not like to do ... that a host isn't supposed to be diffrent or set apart . then they would feel may feel like they can't simply join into fun stuff ect ... because they are "diffrent"
healing might seem so slow --- yet worth all the effort
doodles77
even more posts!

redpajama_set_name: RedPajamaCommonCrawl


Thursday, September 1, 2016 — September 1, 2016 (San Francisco, CA) – Cathay Pacific Airways today announced the expansion of its non-stop Boston to Hong Kong service from four flights per week to a daily non-stop service. The additional flights will begin Monday, March 27, 2017. This comes less than two years after Cathay Pacific's inaugural Boston to Hong Kong flight, which linked New England and Hong Kong directly for the first time.
Flight CX811 – currently a Tuesday/Wednesday/Friday/Sunday schedule – departs Boston at 1:45am, arriving in Hong Kong the following day at 5:35am. This early morning arrival allows passengers to connect with every Cathay Pacific flight across Asia – including Singapore, Bangkok, Kuala Lumpur, Jakarta, and over 23 gateways in mainland China – without a layover in Hong Kong. The return flight, CX812, departs Hong Kong at 6:20pm (local time), arriving in Boston at 10:10pm (same day). This service has cut over four hours from the previous one-stop flight time to Hong Kong via JFK or Chicago and introduced a truly premium international travel experience to Asia.
The additional flights demonstrate both the growing market for leisure and business travellers as well as Cathay Pacific's ongoing commitment to expanding connectivity between North America and Asia.
The Boston service is operated by Boeing 777-300ER aircraft featuring Cathay Pacific's renowned cabin products, including First Class; awarding-winning Business Class; the newest cabin class, Premium Economy; and the new long-haul Economy Class. Together with the exceptional service provided by Cathay Pacific's award-winning cabin crew and a state-of-the-art in-flight entertainment system in all classes, passengers are provided with the best possible travel experience when they fly between Boston and Hong Kong.
The international flag carrier of Hong Kong, Cathay Pacific Airways operates over 115 flights per week to Hong Kong and beyond, including over 23 destinations in Mainland China, from six cities in the USA and two in Canada: Boston, Chicago, Los Angeles, New York (JFK), Newark Liberty, San Francisco, Vancouver and Toronto; and offers cargo services to 18 cities across the Americas using the latest 747-8 freighter fleet. Cathay Pacific is a member of the oneworld alliance.
More information, including current fares and availability, may be found at cathaypacific.com/us, www.facebook.com/cathaypacificus, or Twitter handle @CathayPacificUS. For North American reservations, dial toll-free: 1-800-233-2742.


text:
Starościn bezeichnet Ortschaften in Polen:
 Starościn (Kamionka), Dorf der Gmina Kamionka in der Woiwodschaft Lublin
 Starościn (Rzepin) (dt. Friedrichswille), Siedlung in der Gmina Rzepin in der Woiwodschaft Lebus
 Starościn (Świerczów) (dt. Sterzendorf), Dorf der Gmina Świerczów in der Woiwodschaft Opole

redpajama_set_name: RedPajamaWikipedia


At the time of publication, the U.S. State Department continues to warn citizens to avoid travel to Iraq unless it is absolutely necessary. Although travel will be unsafe indefinitely, once Iraq's political climate becomes stable, visitors will once again be able to appreciate the country's long and rich history dating back to when it was ancient Mesopotamia, which has left thousands of historical sites. Many of the sites hold an elevated status as major historical sites because of there size and distinctiveness, or they have been referenced in the teachings of Judaism, Christianity and Islam.
The historical site of Babylon is located on the western bank of the Euphrates River, approximately 50 miles south of Baghdad. Its famous Tower of Babel rose above the city, and its hanging gardens are one of the Seven Wonders of the Ancient World. Significant damage was done to Babylon during the Iraq War, but the U.S. State Department granted funds for the repair and continued excavation of the great city, once the capital of Babylonia.
The Ur of the Chaldees is near the city of Babylon and remains important as the debated birthplace of Abraham, according to Genesis, the first chapter of the Bible, causing the site to be revered by Jews, Christians and Muslims alike. Its earliest buildings date from 4000 B.C. It remained the capital of Sumeria for three dynasties. The tombs of the Sumerian kings still remain well-preserved after their discovery in 1929.
The city of Ctesiphon was constructed circa second century B.C. by the Parthians. The historical site consists of the world's largest single-span arch made from mud and bricks, which is part of the Parthian palace that was built in the sixth century. At the time of publication, the museum that was in Ctesiphon was closed because of looting during the war and the arch is fenced off because of the fear of collapse. American diplomats and provisional reconstruction teams have been working on repairing Ctesiphon to its former glory.
Hatra, an archaeological site located about 180 miles north of Baghdad, was once the center of trade and religion for the Parthian Empire during the first and second centuries B.C. Hatra remains a major historical place in Iraq because it the the best preserved of all the Parthian sites in Iraq, and it was the first Arab capital. Hatra was designated an UNESCO World Heritage Site and remains an informative example of a circular fortified city. When you visit the remains of ancient Hatra, you will see the mixture of Eastern architecture with Greek and Roman influence.
Morelock, Jessica. "Major Historical or Interesting Places to Visit in Iraq." Travel Tips - USA Today, https://traveltips.usatoday.com/major-historical-interesting-places-visit-iraq-62586.html. Accessed 22 April 2019.


Castlebar Arthritis & Fibromyalgia Support Group starts back on Wednesday 30th of January at 8pm in the Mayo Education Centre beside GMIT .
Guest speaker will be a Podiatrist and will give a talk on Arthritis and talking care of your feet.
Cup of tea and a chat after. New members welcome.
Today there are 26,000 people living with Arthritis in Mayo we are part of the 1 in 5 people suffering with 1 or more of the100 different types of Arthritis living in Ireland today.


Catherine Pulcine Wins Senators Jersey at Mayor's Breakfast!
Catherine Pulcine attended the Mayor's Breakfast in September of 2018 that was hosted by the Ottawa Board of Trade. CPI Interiors has been an active member of the Ottawa Board of Trade for many years. At this particular breakfast event, Catherine won an Ottawa Senators Jersey!
CPI Interior's Catherine and Jerome Pulcine along with their Executive Assistant, Emily Hill, sponsored and played in Rideau View Golf Club's first annual Inspirational Golf Classic. The funds raised at this event were to support The Royal's Institute of Mental Health Suicide prevention research.
CPI Interiors Celebrates 20 Years in Business!
On June 13th, 2018 CPI Interiors celebrated our 20th Anniversary surrounded by friends, family, collegues and our wonderful clients. We are so fortunate to have a growing team with a few of our "original" members still with us. We are so thankful for everyone who has contributed to our succesful journey over these past 20 years, and connot wait to see what the future holds for CPI Interiors.
Natalie Cox featured in the Ottawa Citizen!
Decorating Den Interior's Ontario Region is owned and managed by CPI Interiors' very own, Jerome Pulcine. At the 2018 annual Decorating Den Interior's Conference, Jerome's region was named the 4th largest region out of 40 other regions across North America.
CPI Interiors named #1 franchise in sales worldwide for 2017!
CPI Interior's was named the top franchise in sales for Decorting Den Interiors, worldwide! This is the 2nd consecutive year that CPI Interiors has been named top franchise worldwide and the 6th time that CPI Interiors has been named Canadian Franchise of the Year.
CPI Interior's Natalie Cox received two awards at the annual Decorating Den Interiors Awards Gala that was held in Orlando, Floriday in May of 2018. Natalie was given the Prism award for excellence in sales and she was also name Canadian Decorator of the Year for the 3rd consecutive year.
CPI Interior's very own Catherine Pulcine received the Crystal Award for volume of sales at the Decorating Den Interiors Conference that was held in Orlando, Florida in May of 2018. She is pictured on the left along with Decorating Den Interior's President & CEO, Jim Bugg Jr.
CPI Interior's Margaret Shisko received the Director's Award at the Decorating Den Interiors Conference that was held in Orlando, Florida in May of 2018. She is pictured on the left along with the Decorating Den's VP of Merchandising David Haseley and the VP of Retail Operations, Jennifer Manley.
CPI Interior's Natalie Cox entered one of her client's projects in the Dream Room Competition at the Decorating Den Interiors Conference that was held in Orlando, Florida in May of 2018. Her bathroom project placed 2nd in the bathroom category. Congrats Natalie!
CPI Interior's was named the Small Business of the Year at the West Ottawa Board of Trade Business Excellence Awards on April 5th, 2018 at the Brookstreet Hotel.
Decorating Den Interiors' franchise in Ottawa, Ontario was honored as Small Business of the Year by the West Ottawa Board of Trade on April 5th, 2018. Furniture today shared their story.
CPI's very own, Megan Lewis was featured in Ottawa's Family Living Magazine to give some ideas for Home updates. Megan Specializes in residential design and takes pride in her ability to make a space functional while maintaining a personal touch.
CPI INTERIORS is proud to have made it to the finals of the West Ottawa Business Excellence Awards for Small Business. We're celebrating another great year with a great group!
Catherine Pulcine and CPI INTERIORS was named the #1 Franchise in North America, in sales for 2016. Catherine and her team are thrilled and ready to take on 2017, hoping to have some more record breaking news this coming year.
CPI INTERIORS is featured in Casual Living Magazine showing off the amazing outdoor space Catherine Pulcine created for Jeff Hunt overlooking TD Stadium. Check out Casual Living Magazine January Issue.
We've hit 500 photo saves on Houzz! The Houzz community has saved CPI INTEIRORS' photos to their ideabooks 500 or more times! To get some ideas for your own projects or idea books check out CPI INTERIORS on Houzz!
CPI INTERIORS is featured in Ottawa Citizen, showcasing the beautiful space Catherine Pulcine created for Jeff Hunt overlooking TD Place.
CPI INTERIORS was, once again, awarded Top Canadian Franchise at this year's Decorating Den Interiors conference. Our wonderful group of decorators and staff are all to thank for receiving this great honour for the fourth year running.
This year, the CPI's own decorator Natalie Cox was the recipient of the Top Canadian Decorator award, as well as the Positive Thinker award for her amazing personality and can-do attitude.
Decorating Den Interiors holds an annual Dream Room contest to which interior designs are submitted and categorized by space (kitchen, living room, bathroom, etc.) The winners are judged as the best by an esteemed panel of international home furnishings journalists, and this year, Catherine Pulcine won for her stunning living room design.
CPI INTERIORS is proud to have made it to the finals of the West Ottawa Business Excellence Awards for Medium Business. We're celebrating a great year with a great group!
CPI INTERIORS has been awarded the Best of Houzz for the 3rd year running. We take pride in our work!
For the third year in a row, Catherine Pulcine's franchise has been named the Decorating Den Interiors Canadian Franchise of the year. She is honoured and thanks her wonderful decorators and administrators at CPI INTERIORS.
Catherine and Jerome Pulcine were recognized as the Franchise Owners of the Year for 2014. The award is presented to the franchise owner who demonstrates exceptional dedication and service to his or her profession through cooperation with other franchise owners, suppliers, and management.
Catherine Pulcine and her team at CPI INTERIORS has been awarded "Best Of Houzz" for Customer Satisfaction by Houzz, which is the leading web site and online community about architecture, interior design and decorating, landscape design and home improvement. The Best of Houzz 2015 is determined by a variety of factors, including the number and quality of client reviews a professional received in 2014.
Catherine Pulcine is often called by columnists to get her input about a design or decorating subject. She was quoted in an Ottawa Citizen newspaper article on redecorating a kids room.
Catherine Pulcine is thrilled to announce, for the second year in a row, her franchise was named Decorating Den Interiors Canadian Franchise of the year for 2013. She is extremely proud of her decorators and admin staff at CPI INTERIORS.
Catherine Pulcine and her team at CPI INTERIORS has been awarded "Best Of Houzz" for Customer Satisfaction by Houzz interior design and decorating, landscape design and home improvement. CPI INTERIORS was chosen by the more than 25 million monthly unique users that comprise the Houzz community from among more than 500,000 active home building, remodeling and design industry professionals.
Catherine Pulcine is thrilled to announce her franchise was named Decorating Den Interiors Canadian Franchise of the year for 2012 in their first year with Decorating Den Interiors after 14 years as CPI INTERIORS.


My sister, Olga, and I are doing an Instagram giveaway. Must follow both @OlgaSpitsa and @OksanaSpitsa, tag 3 friends, and name your favorite oil to participate.
Detox for healthy skin, especially in the winter when skin is dry, dull, and lacks radiance.


Students can learn so much from each other! That's why this week's FREE tool is a table, "Cooperative Learning Strategies," which lists a variety of cooperative learning activities through which students can develop their social skills. Activities such as "turn-to-your-neighbor" and "think-pair-share" allow students to directly interact with one another so they can practice social skills, teamwork, and group- and self-evaluation. The table comes from the CEC book, Social Skills for Students With Autism Spectrum Disorder Vol. I. The books is the first in a two volume set that includes 100 detailed lesson plans for elementary and secondary social skill instruction.


1975- Hank Williams Jr. has a near-fatal fall while mountain climbing in Montana.
Phil Balsley, 1939. A member of the Statler Brothers.
Webb Pierce, 1921. Honky Tonk legend from the 50's whose hits include 'There Stands The Glass' 'I Ain't Never' and 'Wondering.' Webb dies in 1991 at age 69 and is elected into the Country Music Hall of Fame in 2001.


text:
Home » Celebrities » This question changed Barack Obama's life forever
This question changed Barack Obama's life forever
Barack Obama wears many hats — he's a father, husband, former senator, and former president of the United States. Over the course of more than two decades, he's even played author by documenting much of his experiences in a handful of books. His earliest — Dreams From My Father, which was published in 1995 — remains a strikingly honest and political coming-of-age novel that recounts the first Black president's time navigating a dual identity as a multiracial child, teenager, and then adult. Later novels, like The Audacity of Hope, offer a similar rawness about himself.
Over the course of Obama's books, America has been given a glimpse into the life, mind, and what feels like the consciousness of the 44th president of the United States of America. Now, four years after leaving the White House, Obama completed the first volume of his two-part series, called A Promise Land. The book is not only a revelatory account of his time on the presidential campaign and in the West Wing, but it also paints for the reader an intimate picture of the president during his highs and lows in office — his hopes, disappointments, fears, aspirations, and even precious moments with his family of four.
In the text, Obama also reveals a question that had a lasting impact on the former president.
Barack Obama's mother asked the question that still impacts him today
In the new memoir and his past books, former president Barack Obama reveals, in detail, the lasting impact his mother, grandparents, and father's omnipresence has on his values and decisions. He describes how his grandmother would wake every morning to work at a local bank in Hawaii, eventually climbing the ladder to managerial status, and how his grandfather and father had a larger-than-life presence to him as a boy. While some of the notions Obama had about the adults in his life wore off with age and experience, he also divulges how some of the life lessons his mother imparted on him from a young boy stick with him to this day.
One particular incident happened when Obama was still in grade school, he recounted to PopSugar. "In the book, I write about a time my mother found out I was part of a group that was teasing a kid at school," he said. "She sat me down and said, 'There are people in the world who think only about themselves. Then there are people who do the opposite, who are able to imagine how others must feel, and make sure that they don't do things that hurt people."
He continued, "'So,' she asked me, 'which kind of person do you want to be?'"
The question hit former President Obama 'hard'
Barack Obama said that his mom's question "hit him hard" to the point that the philosophy has even informed how he and his wife, Michelle Obama, have raised their children, Sasha and Malia. "Michelle and I have tried to impart similar lessons to Sasha and Malia," he said to PopSugar. Be he did add that the two parents have "tried not to take too prescriptive an approach to parenting." That might especially be true, considering the unique, and sometimes grueling, upbringing Sasha and Malia have had in the spotlight.
"We'd much rather Sasha and Malia figure out who they are on their own than try to shape who they become," Obama said. Indeed, we've seen as the sisters have grown from rolling around in the snow with their father to attending concerts and college, as teens tend to do. "Though we do always make sure to tell them when we're proud of them, just as my mother did with me," the famous father said.
Giada De Laurentiis' Creamy Baked Pasta is the Ultimate Comfort Food
Detailed Look at the Trophy Room x Air Jordan 1


Location, Location, Location!! This Ranch home has the convenience of private living yet close to amenities.Off Ranchero road which is the FIRST exit coming from down the hill ! This home is on a private lot with a long driveway. Oaks Hills school district.This single story features a large lot fenced in the backyard, a large covered patio, 3 spacious bedrooms and 2 full baths with glass enclosure showers and tile flooring. Central air conditioning/Heating, ceiling fans throughout.Recessed lighting in kitchen, living room & hallway.Window have 2 1/2 blinds. Kitchen has stainless steel dishwasher, dining area with breakfast bar. Over-sized family room has natural stone fireplace. On a quiet street with views of mountains and is picturesque in the evenings when you pull in to the direct access two car garage. Home comes with fridge and is ready for a new home owner to make it their own.
Freeway 15 off at Ranchero exit, head east.
I am interested in 7175 Dalscote Street, Hesperia, CA 92345.


Question: What's the difference between a well-dressed bicyclist and a poorly dressed unicyclist?
Haha. As a bicyclist myself I admit I have not brought my fashionable best to the handlebars. I usually cycle for exercise around my neighborhood in the mornings and well, my hoodie, cropped sweat pants, and a pair of Pumas go on so easy.
But I often think of the San Francisco Tweed Ride (or London Tweed Run), which gathers a dapper biking crowd to cycle together on vintage bikes and in vintage attire – such as tweed jackets, jodhpurs, caps, and argyle socks. En masse all around the city they go creating quite a picture. I ran into them once in Civic Center and it's super fun to see all the different outfits, early 1900s to the 1930s and lots of mixing it up.
But the Tower Bridge steals the show in this photo.
I may be casual at home but last October in London I stepped it up for a bicycle tour of the city with Tally Ho! Cycle Tours. I sported wide-leg wool slacks paired with a Pendleton jacket, and a cloche hat. It was a challenging ride thanks to all the city traffic, but I was lookin' spiffy and after three hours tooling around, I made it back to tell the tale.


Gokyo Lakes Trek, the trekking around Gokyo valley is one of the best treks in Everest region of Nepal that unveils exclusive beauty of Mother Nature. The famous author Jules Renard said, "On earth there is no heaven, but there are pieces of it." Gokyo valley is definitely one of those pieces. Gokyo valley is a picturesque valley famous for its crystal clear turquoise lakes called Gokyo Lakes. Trek through highs and lows, enjoy the outstanding view of Himalayan peaks including mighty Everest and explore naturally gifted Gokyo valley along its beautiful lakes with Gokyo valley Trek. With Gokyo trek, adventure lovers get the chance to pass through stunning Himalayan landscapes through forests and to be at the top of Gokyo peak exploring the pristine turquoise lakes in the valley.
Gokyo trek starts after our arrival at the Lukla airport from Kathmandu. The trekking initiates from Phakding and continues to Namche, Phortse Tenga, Machhermo and finally at Gokyo where the world's highest fresh water lake system (comprising six main lakes) is situated. Also considered the famous pilgrimage site in Everest region, Gokyo lakes carry religious significance to both Hindus and Buddhists. Further exploring the Gokyo valley, Gokyo Ri peak nearby Himalaya's longest Ngozumpa glacier exhibits outstanding views of Everest and Lhotse. Gokyo Ri trek further lets us visit ancient monasteries on Tengboche which gives an insight to local arts, culture and tradition. Tracing our steps back towards Namche and Lukla, we board a flight back to Kathmandu which concludes our Gokyo trek of 13 days in Everest region.
Sir Edmund Hillary and Tenzing Norgay Sherpa set off on their epic journey in 1953.
Astonishing mountains view including top of the world "Mt. Everest".
Historical trading town of Namche Bazaar and Tengboche monastery.
Everest (8,484m) view from closest distance from Kalapathar (5,550m).
Mount Everest Base Camp (5,360m) and Khumbu icefall.
Accessible either 30 munities fly in Lukla (2800m).
Unique Sherpa cultural, polyandry marriage system.
We will be accommodated in Yatri Suites, Yello pagoda Hotel or Hotel Moonlight or Similar in Kathmanduand teahouses during the trek. All accommodations are on twin-shared basis. Single supplement will be served on request and will cost an additional.Summit Reisen will arrange rooms; however, teahouses in some places only have shared washing and toilet facilities. Also note that single rooms are readily available in Kathmandu and the trekking regions at lower elevation but it might be difficult to find them at higher elevations.
Bed and breakfast will be provided during the trek whereas breakfast will be served in Kathmandu. During our trek, we can enjoy authentic Nepalese food as well as Tibetan, Indian and the more common continental cuisines. We have breakfast and dinner on guest houses where we spend the night and have lunch on the way. There will also be welcome and farewell dinners.
Gokiyo Trek is suitable for passionate walkers who have the ability to walk at least 5-6 hours a day with a light rucksack. In some days we might even need to walk 8 to 9 hours. Walking in higher altitude is more physically demanding than walking in the lower altitudes; however, if we are in excellent health with average physical fitness, positive attitude, self confidence and strong determination, we can accomplish the trek successfully. Exercising and jogging regularly for a few months prior to the trip is a good idea as it will enhance our strength and stability. Past hiking experience is preferred but no technical skill is required. It is important that we consult with our doctor before booking this trek. Participants with pre-existing medical conditions such as heart, lung, and blood disease should inform Summit Reisen Nepal before booking the trek.
Autumn (Sept to December) and Spring (March to May) are the best seasons for the Trek. The weather is sunny and warm with outstanding views.
TIMS Card and park entrance fees.
Insurance coverage for guide and porters.
Any Beverage expense during trek.
Arrival in kathmandu then transfer to hotel. Briefing about program in Evening time with dinner.
Day two of the trip begins shortly after breakfast, with some catching up with the trekking crew. Trailing down towards the Bhotekoshi River and crossing a long suspension bridge over the Bhotekoshi River, Jorsele is the next destination after crossing the bridge and a walk of about two hours along the straight trail, passing a forest and few villages. Everest National Park check post, located at Jorsele welcomes you to the Khumbu Region and the national park permits are checked. Beyond this point, no firewood is allowed. Following the trail, the path drops steeply, and reaches a long suspension bridge to cross the Dudh Koshi River. Continuing on the straight trail for an hour more, the terrain becomes a bit steep. Going through various difficult terrains, a forest and several other Sherpa villages for almost two hours, the team reaches Namche Bazaar. Namche is a great spot for the first close glimpse of the mesmerizing beauty of Mount Everest.
Looking at the effort put in by all in the team, this day marks the day of rest, the acclimatization day. Due to change in weather, altitude and the rigorous exercise of walking terrains, a day is taken off the schedule for the guests to rest and enjoy, or then to have a picturesque excursion to Khumjung village. The major aim of this day is to prevent any possible AMS signs, which may hamper the rest of the trip.
Day five begins with a gentle climb towards the Dole National Park Check Post, where documentation is checked for the entry into the National Park. A forest trail is on offer after passing the army post at the entrance. Also on offer is the view of some colourful pheasants and shy deer, which leads to you reaching the village of Dole after about an hour of an uphill trek. The trail continues to climb after Dole, to reach out a planar, pleasant traverse with beautiful views. The trip finally reaches Lhapharma, offering snow-capped mountainous views from almost all directions, up, down and across the valley.


text:
Dave Richardson and Tom Pirozzoli Co-Headline in Bellows Falls
BELLOWS FALLS — Dave Richardson has been writing, recording, and performing as a solo artist for over 10 years, weaving threads of folk, country, and traditional music. He took third place in the Woody Guthrie Folk Festival songwriting contest; was awarded a featured showcase spot at the Northeast Regional Folk Alliance Conference; and was an invited performer at the New England Folk Festival. "True folk rooted in the tradition is increasingly rarely encountered. All the more reason to celebrate the music of Dave Richardson." — Fervor Coulee
Tom Pirozzoli is celebrating "Reckon by the Light", the newest CD in his 40-years-and-counting career. He got his start busking on street corners and performing at anti-war rallies, eventually finding his way into the coffeehouse scene. His Fast Folk Music recordings are now part of the Smithsonian's collection. He was named a winner in MUSICIAN magazine's Best Unsigned Band Contest in the early '80s, and has shared stages with artists like Greg Brown, Jesse Winchester, and Doc Watson. "Pirozzoli's observations and travels bring seemingly dissimilar elements to harmony." — Boston Globe
This co-headline show at Stage 33 Live will be Sunday, February 16 at 7:00. Suggested donation $10 at the door, all proceeds support the musicians. Seating is limited. The performances will be recorded and filmed.
Stage 33 Live is an intimate, industrial-rustic listening room in a former factory located at 33 Bridge Street in Bellows Falls, VT, documenting live performances and presentations of original material on a simple stage. Coffee, soda, water, and snacks by donation. Find more info about the nonprofit all-volunteer project, and this and other other upcoming events online at stage33live.com
Previous: Previous post: 2/8/20, Saturday: Synthfest Series (currently accepting performers)
Next: Next post: 3/8/20, Sunday: Jenna Rice and Emily Lyons


We had a lovely chat to florist extraordinaire Ruby Barber, the create soul behind Berlin-based Mary Lennox. This Australian-raised creative has art in her blood and a head for bespoke blooms. You can fall for her Instagram here and learn more on her website. For now, prepare to ponder her floral words (and perhaps pencil in your next trip to the German capital).
Why Mary Lennox - just a die hard Secret Garden fan or did the story mean something more to you?
I've always really loved The Secret Garden by Frances Hodges Burnett. In my first year of primary school I dressed as Mary Lennox for book week. Coincidentally my family also owned a building on the corner of Mary and Lennox street in Sydney. It was a pretty special address - it housed my father's first photography studio, my mother's first art gallery and then my first flower studio, so the name has personal significance that goes beyond liking the story.
I love the flowers the most, obviously! But I also love the significance of flowers as an exchange; people send flowers to express the most beautiful sentiments and every special occasion in life is celebrated with flowers. I love being involved in these passionate moments of human emotion.
Is there a florist community - in Berlin and beyond?
I'm still discovering the florist community here in Berlin but I am connected with florists all over the world. Every time a florist is passing through Berlin we make a point of meeting up, and the first thing I do when visiting a new city is get in touch with local florists and farmers. It is a really welcoming and supportive community and a love of flowers is a powerful bond.
What has been the most exciting project to work on to date?
I've had lots of exciting 'firsts' since moving to Berlin. Last June I worked in collaboration with Kentholz, a carpenter, to build a greenhouse for the Mercedes Benz Lobby. This was a really exciting project because it was plant based and the exhibition ran for two months. It was fun to create something that had a life span longer than cut flowers and to see it grow and evolve over the duration of the exhibition.
At the moment I am dreaming of having a cutting garden. I love Julie Newmar's garden. Perhaps it's a little far fetched to get the original Catwoman to design a garden for me, but one can dream.
I've also always loved the idea being involved with set design. I always pay careful attention to the flowers in TV shows. Shows like The Nanny and Gossip Girl always had the most extravagant florals and I would love to design flowers in this context one day.
Do you have any winning tips you have for aspiring florists?
Approach and work with as many florists as you can. In my experience the most inspiring have always been willing to teach and share their love of flowers. When I started out — against all advice — I started a floristry course. I don't think this was very beneficial in the end. The only class I would really recommend would be something at The Little Flower School run by Sarah of Saipua and Nicolette of Nicollette Camille.
What were the biggest differences you've noticed between working in Australia and Germany?
The biggest difference is the seasonal changes. The natural landscape of Berlin changes so drastically from winter, spring, summer to autumn and it's really fun to mirror the beautiful flowers and foliage each season has to offer in my arrangements.
The flower market in Australia is really special. The produce is particularly interesting and most of it comes from local farms. I really miss it. Here in Berlin local produce is very hard to come by. For me, imported flowers don't have as much charm. I'm not interested in 'perfection,' I like flowers with irregularities and delicate blooms that grow wild. These things are not available here in Berlin as a matter of course, everything is shipped in from the flower auction. I hope this is something that will change in the future. I'm doing my best to work with Berlin-based farms and grow things myself.
If someone only had 24 hours in Berlin what should they do?
I recently had a friend visiting from Australia who asked me the same question. I sent him to Teufelsberg, an abandoned listening tower in the forest. I think it was actually a really crazy thing to recommend to someone who had never been here before, there is no signage, no real entrance and no direct trains. I neglected to warn him about any of this but luckily he enjoyed the adventure. For something less ambitious, I'd recommend visiting a handful of parks (Tiergarten, Templehof, Treptow Park).
Mary Lennox currently has a new showroom at The Store x Soho House Berlin, and boy does it look beautiful.


He's having his nap now and my husband is at the gym, that's why I have some time to blog. Once he wakes, we'll be bringing him to some malls for a walk again! He's the most well-behaved in his pram outside. Can't contain him at home. So active he cannot stop moving and he hates being constrained to something like a walker/highchair/playpen, he's an escape artist when it comes to that. Even when we're carrying him, he will resist and keep fidgeting until we let him down. Once you let him down, he will crawl away at high speed haha!
I managed to film him "sprinting" towards the cupboard when he realized it's not locked!


NVIDIA GeForce GT 740M is a Display Adapters hardware device. The developer of this driver was NVIDIA. The hardware id of this driver is PCI/VEN_10DE&DEV_1292&SUBSYS_FA471179.
You can download from the link below the driver installer file for the NVIDIA NVIDIA GeForce GT 740M driver. The archive contains version 9.18.13.4144 released on 2015-02-03 of the driver.
This driver received an average rating of 3.2 stars out of 16003 votes.