diff --git a/core/composer.json b/core/composer.json
index e54ea55..019b29e 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -27,7 +27,9 @@
     "zendframework/zend-feed": "2.3.*",
     "mikey179/vfsStream": "1.*",
     "stack/builder": "1.0.*",
-    "egulias/email-validator": "1.2.*"
+    "egulias/email-validator": "1.2.*",
+    "behat/mink": "~1.6",
+    "behat/mink-goutte-driver": "~1.1"
   },
   "autoload": {
     "psr-4": {
diff --git a/core/composer.lock b/core/composer.lock
index 9c24eb3..aca1009 100644
--- a/core/composer.lock
+++ b/core/composer.lock
@@ -4,9 +4,171 @@
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "c977649e8e1a8b93301fa83283672a06",
+    "hash": "00ac3034749aec468b8abbf5811ac9a3",
     "packages": [
         {
+            "name": "behat/mink",
+            "version": "v1.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/minkphp/Mink.git",
+                "reference": "090900a0049c441f1e072bbd837db4079b2250c5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/minkphp/Mink/zipball/090900a0049c441f1e072bbd837db4079b2250c5",
+                "reference": "090900a0049c441f1e072bbd837db4079b2250c5",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.1",
+                "symfony/css-selector": "~2.0"
+            },
+            "suggest": {
+                "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)",
+                "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation",
+                "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)",
+                "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.6.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Behat\\Mink": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Konstantin Kudryashov",
+                    "email": "ever.zet@gmail.com",
+                    "homepage": "http://everzet.com"
+                }
+            ],
+            "description": "Web acceptance testing framework for PHP 5.3",
+            "homepage": "http://mink.behat.org/",
+            "keywords": [
+                "browser",
+                "testing",
+                "web"
+            ],
+            "time": "2014-09-26 09:25:05"
+        },
+        {
+            "name": "behat/mink-browserkit-driver",
+            "version": "v1.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/minkphp/MinkBrowserKitDriver.git",
+                "reference": "aed8f4a596b79014a75254c3e337511c33e38cbd"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/aed8f4a596b79014a75254c3e337511c33e38cbd",
+                "reference": "aed8f4a596b79014a75254c3e337511c33e38cbd",
+                "shasum": ""
+            },
+            "require": {
+                "behat/mink": "~1.6@dev",
+                "php": ">=5.3.1",
+                "symfony/browser-kit": "~2.0",
+                "symfony/dom-crawler": "~2.0"
+            },
+            "require-dev": {
+                "silex/silex": "~1.2"
+            },
+            "type": "mink-driver",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.2.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Behat\\Mink\\Driver": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Konstantin Kudryashov",
+                    "email": "ever.zet@gmail.com",
+                    "homepage": "http://everzet.com"
+                }
+            ],
+            "description": "Symfony2 BrowserKit driver for Mink framework",
+            "homepage": "http://mink.behat.org/",
+            "keywords": [
+                "Mink",
+                "Symfony2",
+                "browser",
+                "testing"
+            ],
+            "time": "2014-09-26 11:35:19"
+        },
+        {
+            "name": "behat/mink-goutte-driver",
+            "version": "v1.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/minkphp/MinkGoutteDriver.git",
+                "reference": "2bf327b4166694ecaa8ae7f956cb6ae252ecf03e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/2bf327b4166694ecaa8ae7f956cb6ae252ecf03e",
+                "reference": "2bf327b4166694ecaa8ae7f956cb6ae252ecf03e",
+                "shasum": ""
+            },
+            "require": {
+                "behat/mink": "~1.6@dev",
+                "behat/mink-browserkit-driver": "~1.2@dev",
+                "fabpot/goutte": "~1.0.4|~2.0",
+                "php": ">=5.3.1"
+            },
+            "type": "mink-driver",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Behat\\Mink\\Driver": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Konstantin Kudryashov",
+                    "email": "ever.zet@gmail.com",
+                    "homepage": "http://everzet.com"
+                }
+            ],
+            "description": "Goutte driver for Mink framework",
+            "homepage": "http://mink.behat.org/",
+            "keywords": [
+                "browser",
+                "goutte",
+                "headless",
+                "testing"
+            ],
+            "time": "2014-10-09 09:21:12"
+        },
+        {
             "name": "doctrine/annotations",
             "version": "v1.2.1",
             "source": {
@@ -571,6 +733,260 @@
             "time": "2014-11-06 08:59:44"
         },
         {
+            "name": "fabpot/goutte",
+            "version": "v1.0.7",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/FriendsOfPHP/Goutte.git",
+                "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/794b196e76bdd37b5155cdecbad311f0a3b07625",
+                "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625",
+                "shasum": ""
+            },
+            "require": {
+                "ext-curl": "*",
+                "guzzle/http": "~3.1",
+                "php": ">=5.3.0",
+                "symfony/browser-kit": "~2.1",
+                "symfony/css-selector": "~2.1",
+                "symfony/dom-crawler": "~2.1",
+                "symfony/finder": "~2.1",
+                "symfony/process": "~2.1"
+            },
+            "require-dev": {
+                "guzzle/plugin-history": "~3.1",
+                "guzzle/plugin-mock": "~3.1"
+            },
+            "type": "application",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Goutte": "."
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "A simple PHP Web Scraper",
+            "homepage": "https://github.com/fabpot/Goutte",
+            "keywords": [
+                "scraper"
+            ],
+            "time": "2014-10-09 15:52:51"
+        },
+        {
+            "name": "guzzle/common",
+            "version": "v3.9.2",
+            "target-dir": "Guzzle/Common",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/common.git",
+                "reference": "2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/common/zipball/2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc",
+                "reference": "2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2",
+                "symfony/event-dispatcher": ">=2.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Guzzle\\Common": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Common libraries used by Guzzle",
+            "homepage": "http://guzzlephp.org/",
+            "keywords": [
+                "collection",
+                "common",
+                "event",
+                "exception"
+            ],
+            "time": "2014-08-11 04:32:36"
+        },
+        {
+            "name": "guzzle/http",
+            "version": "v3.9.2",
+            "target-dir": "Guzzle/Http",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/http.git",
+                "reference": "1e8dd1e2ba9dc42332396f39fbfab950b2301dc5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/http/zipball/1e8dd1e2ba9dc42332396f39fbfab950b2301dc5",
+                "reference": "1e8dd1e2ba9dc42332396f39fbfab950b2301dc5",
+                "shasum": ""
+            },
+            "require": {
+                "guzzle/common": "self.version",
+                "guzzle/parser": "self.version",
+                "guzzle/stream": "self.version",
+                "php": ">=5.3.2"
+            },
+            "suggest": {
+                "ext-curl": "*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Guzzle\\Http": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                }
+            ],
+            "description": "HTTP libraries used by Guzzle",
+            "homepage": "http://guzzlephp.org/",
+            "keywords": [
+                "Guzzle",
+                "client",
+                "curl",
+                "http",
+                "http client"
+            ],
+            "time": "2014-08-11 04:32:36"
+        },
+        {
+            "name": "guzzle/parser",
+            "version": "v3.9.2",
+            "target-dir": "Guzzle/Parser",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/parser.git",
+                "reference": "6874d171318a8e93eb6d224cf85e4678490b625c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/parser/zipball/6874d171318a8e93eb6d224cf85e4678490b625c",
+                "reference": "6874d171318a8e93eb6d224cf85e4678490b625c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Guzzle\\Parser": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Interchangeable parsers used by Guzzle",
+            "homepage": "http://guzzlephp.org/",
+            "keywords": [
+                "URI Template",
+                "cookie",
+                "http",
+                "message",
+                "url"
+            ],
+            "time": "2014-02-05 18:29:46"
+        },
+        {
+            "name": "guzzle/stream",
+            "version": "v3.9.2",
+            "target-dir": "Guzzle/Stream",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/stream.git",
+                "reference": "60c7fed02e98d2c518dae8f97874c8f4622100f0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/stream/zipball/60c7fed02e98d2c518dae8f97874c8f4622100f0",
+                "reference": "60c7fed02e98d2c518dae8f97874c8f4622100f0",
+                "shasum": ""
+            },
+            "require": {
+                "guzzle/common": "self.version",
+                "php": ">=5.3.2"
+            },
+            "suggest": {
+                "guzzle/http": "To convert Guzzle request objects to PHP streams"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Guzzle\\Stream": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                }
+            ],
+            "description": "Guzzle stream wrapper component",
+            "homepage": "http://guzzlephp.org/",
+            "keywords": [
+                "Guzzle",
+                "component",
+                "stream"
+            ],
+            "time": "2014-05-01 21:36:02"
+        },
+        {
             "name": "guzzlehttp/guzzle",
             "version": "5.0.3",
             "source": {
@@ -1694,6 +2110,61 @@
             "time": "2014-10-20 20:55:17"
         },
         {
+            "name": "symfony/browser-kit",
+            "version": "v2.6.4",
+            "target-dir": "Symfony/Component/BrowserKit",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/BrowserKit.git",
+                "reference": "2ecec44ed5047020c65dd6e4a4b2f3cf13ae3c04"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/2ecec44ed5047020c65dd6e4a4b2f3cf13ae3c04",
+                "reference": "2ecec44ed5047020c65dd6e4a4b2f3cf13ae3c04",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "symfony/dom-crawler": "~2.0,>=2.0.5"
+            },
+            "require-dev": {
+                "symfony/css-selector": "~2.0,>=2.0.5",
+                "symfony/process": "~2.0,>=2.0.5"
+            },
+            "suggest": {
+                "symfony/process": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Symfony\\Component\\BrowserKit\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "http://symfony.com/contributors"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "Symfony BrowserKit Component",
+            "homepage": "http://symfony.com",
+            "time": "2015-01-03 08:01:59"
+        },
+        {
             "name": "symfony/class-loader",
             "version": "v2.6.4",
             "target-dir": "Symfony/Component/ClassLoader",
@@ -1915,6 +2386,59 @@
             "time": "2015-01-25 04:39:26"
         },
         {
+            "name": "symfony/dom-crawler",
+            "version": "v2.6.4",
+            "target-dir": "Symfony/Component/DomCrawler",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/DomCrawler.git",
+                "reference": "26a9eb302decd828990e1015afaa11b78b016073"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/26a9eb302decd828990e1015afaa11b78b016073",
+                "reference": "26a9eb302decd828990e1015afaa11b78b016073",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "symfony/css-selector": "~2.3"
+            },
+            "suggest": {
+                "symfony/css-selector": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Symfony\\Component\\DomCrawler\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "http://symfony.com/contributors"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "Symfony DomCrawler Component",
+            "homepage": "http://symfony.com",
+            "time": "2015-01-03 08:01:59"
+        },
+        {
             "name": "symfony/event-dispatcher",
             "version": "v2.6.4",
             "target-dir": "Symfony/Component/EventDispatcher",
@@ -1973,6 +2497,53 @@
             "time": "2015-02-01 16:10:57"
         },
         {
+            "name": "symfony/finder",
+            "version": "v2.6.4",
+            "target-dir": "Symfony/Component/Finder",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/Finder.git",
+                "reference": "16513333bca64186c01609961a2bb1b95b5e1355"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/Finder/zipball/16513333bca64186c01609961a2bb1b95b5e1355",
+                "reference": "16513333bca64186c01609961a2bb1b95b5e1355",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Symfony\\Component\\Finder\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "http://symfony.com/contributors"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "Symfony Finder Component",
+            "homepage": "http://symfony.com",
+            "time": "2015-01-03 08:01:59"
+        },
+        {
             "name": "symfony/http-foundation",
             "version": "v2.6.4",
             "target-dir": "Symfony/Component/HttpFoundation",
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index fcf4d44..9870754 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -106,7 +106,9 @@
  * @see http://php.net/manual/reserved.variables.server.php
  * @see http://php.net/manual/function.time.php
  */
-define('REQUEST_TIME', (int) $_SERVER['REQUEST_TIME']);
+if (!defined('REQUEST_TIME')) {
+  define('REQUEST_TIME', (int) $_SERVER['REQUEST_TIME']);
+}
 
 /**
  * Regular expression to match PHP function names.
@@ -134,7 +136,9 @@
  *
  * This strips two levels of directories off the current directory.
  */
-define('DRUPAL_ROOT', dirname(dirname(__DIR__)));
+if (!defined('DRUPAL_ROOT')) {
+  define('DRUPAL_ROOT', dirname(dirname(__DIR__)));
+}
 
 /**
  * Returns the appropriate configuration directory.
@@ -841,7 +845,9 @@ function drupal_valid_test_ua($new_prefix = NULL) {
 
   // Perform a basic check on the User-Agent HTTP request header first. Any
   // inbound request that uses the simpletest UA header needs to be validated.
-  if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/^(simpletest\d+);(.+);(.+);(.+)$/", $_SERVER['HTTP_USER_AGENT'], $matches)) {
+  $http_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : NULL;
+  $user_agent = isset($_COOKIE['SIMPLETEST_USER_AGENT']) ? $_COOKIE['SIMPLETEST_USER_AGENT'] : $http_user_agent;
+  if (isset($user_agent) && preg_match("/^(simpletest\d+);(.+);(.+);(.+)$/", $user_agent, $matches)) {
     list(, $prefix, $time, $salt, $hmac) = $matches;
     $check_string =  $prefix . ';' . $time . ';' . $salt;
     // Read the hash salt prepared by drupal_generate_test_ua().
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 2161aed..a29b24b 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -303,7 +303,8 @@ function install_begin_request($class_loader, &$install_state) {
   // The user agent header is used to pass a database prefix in the request when
   // running tests. However, for security reasons, it is imperative that no
   // installation be permitted using such a prefix.
-  if ($install_state['interactive'] && strpos($request->server->get('HTTP_USER_AGENT'), 'simpletest') !== FALSE && !drupal_valid_test_ua()) {
+  $user_agent = $request->cookies->get('SIMPLETEST_USER_AGENT') ?: $request->server->get('HTTP_USER_AGENT');
+  if ($install_state['interactive'] && strpos($user_agent, 'simpletest') !== FALSE && !drupal_valid_test_ua()) {
     header($request->server->get('SERVER_PROTOCOL') . ' 403 Forbidden');
     exit;
   }
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index 513d46d..45c8c54 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -238,6 +238,32 @@ function simpletest_phpunit_configuration_filepath() {
  *  The results as returned by exec().
  */
 function simpletest_phpunit_run_command(array $unescaped_test_classnames, $phpunit_file) {
+  // Set the up an environment variable containing the database connection so
+  // that functional tests can connect to the database.
+  $db_info = Database::getConnectionInfo();
+  if ($db_info['default']['driver'] == 'sqlite') {
+    $db_url = $db_info['default']['driver'] . '://localhost/' . $db_info['default']['database'];
+  }
+  else {
+    $user = '';
+    if ($db_info['default']['username']) {
+      $user = $db_info['default']['username'];
+      if ($db_info['default']['password']) {
+        $user .= ':' . $db_info['default']['password'];
+      }
+      $user .= '@';
+    }
+
+    $db_url = $db_info['default']['driver'] . '://' . $user . $db_info['default']['host'];
+    if (isset($db_info['default']['port'])) {
+      $db_url .= ':' . $db_info['default']['port'];
+    }
+    $db_url .= '/' . $db_info['default']['database'];
+  }
+  if ($db_info['default']['prefix']['default']) {
+    $db_url .= '#' . $db_info['default']['prefix']['default'];
+  }
+  putenv('SIMPLETEST_DB=' . $db_url);
   $phpunit_bin = simpletest_phpunit_command();
 
   $command = array(
@@ -273,6 +299,7 @@ function simpletest_phpunit_run_command(array $unescaped_test_classnames, $phpun
   // via the simpletest UI.
   $ret = exec(join($command, " "));
   chdir($old_cwd);
+  putenv('SIMPLETEST_DB=');
   return $ret;
 }
 
diff --git a/core/modules/simpletest/src/BrowserTestBase.php b/core/modules/simpletest/src/BrowserTestBase.php
new file mode 100644
index 0000000..e457fe4
--- /dev/null
+++ b/core/modules/simpletest/src/BrowserTestBase.php
@@ -0,0 +1,1379 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\simpletest\BrowserTestBase.
+ */
+
+namespace Drupal\simpletest;
+
+use Behat\Mink\Driver\GoutteDriver;
+use Behat\Mink\Element\Element;
+use Behat\Mink\Element\NodeElement;
+use Behat\Mink\Exception\Exception;
+use Behat\Mink\Mink;
+use Behat\Mink\Session;
+use Drupal\Component\Utility\Crypt;
+use Drupal\Component\Utility\Random;
+use Drupal\Component\Utility\String;
+use Drupal\Core\Cache\Cache;
+use Drupal\Core\Database\ConnectionNotDefinedException;
+use Drupal\Core\Database\Database;
+use Drupal\Core\DrupalKernel;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Session\AnonymousUserSession;
+use Drupal\Core\Session\UserSession;
+use Drupal\Core\Site\Settings;
+use Drupal\Core\StreamWrapper\StreamWrapperInterface;
+use Drupal\Core\Test\TestRunnerKernel;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Test case for typical Drupal tests.
+ *
+ * @ingroup testing
+ *
+ * All BrowserTestBase tests must have the @runTestsInSeparateProcesses
+ * annotation to ensure process isolation.
+ */
+abstract class BrowserTestBase extends \PHPUnit_Framework_TestCase {
+
+  /**
+   * Class loader.
+   *
+   * @var object
+   */
+  protected $classLoader;
+
+  /**
+   * The site directory of this test run.
+   *
+   * @var string
+   */
+  protected $siteDirectory;
+
+  /**
+   * The database prefix of this test run.
+   *
+   * @var string
+   */
+  protected $databasePrefix;
+
+  /**
+   * The site directory of the original parent site.
+   *
+   * @var string
+   */
+  protected $originalSiteDirectory;
+
+  /**
+   * Time limit in seconds for the test.
+   */
+  protected $timeLimit = 500;
+
+  /**
+   * The public file directory for the test environment.
+   *
+   * This is set in BrowserTestBase::prepareEnvironment().
+   *
+   * @var string
+   */
+  protected $publicFilesDirectory;
+
+  /**
+   * The private file directory for the test environment.
+   *
+   * This is set in BrowserTestBase::prepareEnvironment().
+   *
+   * @var string
+   */
+  protected $privateFilesDirectory;
+
+  /**
+   * The temp file directory for the test environment.
+   *
+   * This is set in BrowserTestBase::prepareEnvironment().
+   *
+   * @var string
+   */
+  protected $tempFilesDirectory;
+
+  /**
+   * The translation file directory for the test environment.
+   *
+   * This is set in BrowserTestBase::prepareEnvironment().
+   *
+   * @var string
+   */
+  protected $translationFilesDirectory;
+
+  /**
+   * The DrupalKernel instance used in the test.
+   *
+   * @var \Drupal\Core\DrupalKernel
+   */
+  protected $kernel;
+
+  /**
+   * The dependency injection container used in the test.
+   *
+   * @var \Symfony\Component\DependencyInjection\ContainerInterface
+   */
+  protected $container;
+
+  /**
+   * The config importer that can used in a test.
+   *
+   * @var \Drupal\Core\Config\ConfigImporter
+   */
+  protected $configImporter;
+
+  /**
+   * The random generator.
+   *
+   * @var \Drupal\Component\Utility\Random
+   */
+  protected $randomGenerator;
+
+  /**
+   * The profile to install as a basis for testing.
+   *
+   * @var string
+   */
+  protected $profile = 'testing';
+
+  /**
+   * The current session name, if available.
+   *
+   * @var string
+   */
+  protected $sessionName;
+
+  /**
+   * The current user logged in using the internal browser.
+   *
+   * @var bool
+   */
+  protected $loggedInUser = FALSE;
+
+  /**
+   * The root user.
+   *
+   * @var UserSession
+   */
+  protected $rootUser;
+
+  /**
+   * The config directories used in this test.
+   */
+  protected $configDirectories = array();
+
+  /**
+   * An array of custom translations suitable for drupal_rewrite_settings().
+   *
+   * @var array
+   */
+  protected $customTranslations;
+
+  /**
+   * Mink session manager.
+   *
+   * @var Mink
+   */
+  protected $mink;
+
+  /**
+   * Initializes mink sessions.
+   */
+  protected function initMink() {
+    $driver = new GoutteDriver();
+    $session = new Session($driver);
+    $this->mink = new Mink();
+    $this->mink->registerSession('goutte', $session);
+    $this->mink->setDefaultSessionName('goutte');
+    $this->registerSessions();
+    return $session;
+  }
+
+  /**
+   * Registers additional mink sessions.
+   *
+   * Tests wishing to use a different driver or change the default driver should
+   * override this method.
+   *
+   * @code
+   *   // Register a new session that uses the MinkPonyDriver.
+   *   $pony = new MinkPonyDriver();
+   *   $session = new Session($pony);
+   *   $this->mink->registerSession('pony', $session);
+   * @endcode
+   */
+  protected function registerSessions() {}
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    global $base_url;
+    parent::setUp();
+
+    // Get and set the domain of the environment we are running our test
+    // coverage against.
+    $base_url = getenv('SIMPLETEST_BASE_URL');
+    if (!$base_url) {
+      throw new \InvalidArgumentException('You must provide a SIMPLETEST_BASE_URL environment variable to run PHPUnit based functional tests.');
+    }
+
+    // Setup $_SERVER variable.
+    $parsed_url = parse_url($base_url);
+    $host = $parsed_url['host'] . (isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '');
+    $path = isset($parsed_url['path']) ? rtrim(rtrim($parsed_url['path']), '/') : '';
+    $port = (isset($parsed_url['port']) ? $parsed_url['port'] : 80);
+    if ($path == '/') {
+      $path = '';
+    }
+    // If the passed URL schema is 'https' then setup the $_SERVER variables
+    // properly so that testing will run under HTTPS.
+    if ($parsed_url['scheme'] === 'https') {
+      $_SERVER['HTTPS'] = 'on';
+    }
+    $_SERVER['HTTP_HOST'] = $host;
+    $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
+    $_SERVER['SERVER_ADDR'] = '127.0.0.1';
+    $_SERVER['SERVER_PORT'] = $port;
+    $_SERVER['SERVER_SOFTWARE'] = NULL;
+    $_SERVER['SERVER_NAME'] = 'localhost';
+    $_SERVER['REQUEST_URI'] = $path .'/';
+    $_SERVER['REQUEST_METHOD'] = 'GET';
+    $_SERVER['SCRIPT_NAME'] = $path .'/index.php';
+    $_SERVER['SCRIPT_FILENAME'] = $path .'/index.php';
+    $_SERVER['PHP_SELF'] = $path .'/index.php';
+    $_SERVER['HTTP_USER_AGENT'] = 'Drupal command line';
+
+    // Install drupal test site.
+    $this->prepareEnvironment();
+    $this->installDrupal();
+
+    // Setup Mink.
+    $session = $this->initMink();
+
+    // In order to debug web tests you need to either set a cookie, have the
+    // Xdebug session in the URL or set an environment variable in case of CLI
+    // requests. If the developer listens to connection when running tests, by
+    // default the cookie is not forwarded to the client side, so you cannot
+    // debug the code running on the test site. In order to make debuggers work
+    // this bit of information is forwarded. Make sure that the debugger listens
+    // to at least three external connections.
+    $request = \Drupal::request();
+    $cookie_params = $request->cookies;
+    if ($cookie_params->has('XDEBUG_SESSION')) {
+      $session->setCookie('XDEBUG_SESSION', $cookie_params->get('XDEBUG_SESSION'));
+    }
+    // For CLI requests, the information is stored in $_SERVER.
+    $server = $request->server;
+    if ($server->has('XDEBUG_CONFIG')) {
+      // $_SERVER['XDEBUG_CONFIG'] has the form "key1=value1 key2=value2 ...".
+      $pairs = explode(' ', $server->get('XDEBUG_CONFIG'));
+      foreach ($pairs as $pair) {
+        list($key, $value) = explode('=', $pair);
+        // Account for key-value pairs being separated by multiple spaces.
+        if (trim($key, ' ') == 'idekey') {
+          $session->setCookie('XDEBUG_SESSION', trim($value, ' '));
+        }
+      }
+    }
+  }
+
+  /**
+   * Ensures test files are deletable within file_unmanaged_delete_recursive().
+   *
+   * Some tests chmod generated files to be read only. During
+   * BrowserTestBase::cleanupEnvironment() and other cleanup operations,
+   * these files need to get deleted too.
+   *
+   * @param string $path
+   *   The file path.
+   */
+  public static function filePreDeleteCallback($path) {
+    chmod($path, 0700);
+  }
+
+  /**
+   * Clean up the simpletest environment.
+   */
+  protected function cleanupEnvironment() {
+    // Remove all prefixed tables.
+    $original_connection_info = Database::getConnectionInfo('simpletest_original_default');
+    $original_prefix = $original_connection_info['default']['prefix']['default'];
+    $test_connection_info = Database::getConnectionInfo('default');
+    $test_prefix = $test_connection_info['default']['prefix']['default'];
+    if ($original_prefix != $test_prefix) {
+      $tables = Database::getConnection()->schema()->findTables($test_prefix . '%');
+      $prefix_length = strlen($test_prefix);
+      foreach ($tables as $table) {
+        if (Database::getConnection()->schema()->dropTable(substr($table, $prefix_length))) {
+          unset($tables[$table]);
+        }
+      }
+    }
+
+    // Delete test site directory.
+    file_unmanaged_delete_recursive($this->siteDirectory, array($this, 'filePreDeleteCallback'));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function tearDown() {
+    parent::tearDown();
+
+    // Destroy the testing kernel.
+    if (isset($this->kernel)) {
+      $this->cleanupEnvironment();
+      $this->kernel->shutdown();
+    }
+
+    // Ensure that internal logged in variable is reset.
+    $this->loggedInUser = FALSE;
+
+    if ($this->mink) {
+      $this->mink->stopSessions();
+    }
+  }
+
+  /**
+   * Returns Mink session.
+   *
+   * @param string|null $name
+   *   (optional) Name of the session OR active session will be used.
+   *
+   * @return \Behat\Mink\Session
+   *   The active mink session object.
+   */
+  public function getSession($name = NULL) {
+    return $this->mink->getSession($name);
+  }
+
+  /**
+   * Returns Mink assert session.
+   *
+   * @param string|null $name
+   *   (optional) Name of the session. Defaults to the active session.
+   *
+   * @return \Drupal\simpletest\WebAssert
+   *   A new web-assert option for asserting the presence of elements with.
+   */
+  public function assertSession($name = NULL) {
+    return new WebAssert($this->getSession($name));
+  }
+
+  /**
+   * Prepare for a request to testing site.
+   *
+   * The testing site is protected via a SIMPLETEST_USER_AGENT cookie that
+   * is checked by drupal_valid_test_ua().
+   *
+   * @see drupal_valid_test_ua()
+   */
+  protected function prepareRequest() {
+    $session = $this->getSession();
+    $session->setCookie('SIMPLETEST_USER_AGENT', drupal_generate_test_ua($this->databasePrefix));
+  }
+
+  /**
+   * Retrieves a Drupal path or an absolute path.
+   *
+   * @param string $path
+   *   Drupal path or URL to load into internal browser
+   * @param array $options
+   *   (optional) Options to be forwarded to the url generator.
+   *
+   * @return string
+   *   The retrieved HTML string, also available as $this->getRawContent()
+   */
+  protected function drupalGet($path, array $options = array()) {
+    $options['absolute'] = TRUE;
+
+    // The URL generator service is not necessarily available yet; e.g., in
+    // interactive installer tests.
+    if ($this->container->has('url_generator')) {
+      $url = $this->container->get('url_generator')->generateFromPath($path, $options);
+    }
+    else {
+      $url = $this->getAbsoluteUrl($path);
+    }
+    $session = $this->getSession();
+
+    $this->prepareRequest();
+    $session->visit($url);
+    $out = $session->getPage()->getContent();
+
+    // Ensure that any changes to variables in the other thread are picked up.
+    $this->refreshVariables();
+
+    return $out;
+  }
+
+  /**
+   * Takes a path and returns an absolute path.
+   *
+   * @param string $path
+   *   A path from the internal browser content.
+   *
+   * @return string
+   *   The $path with $base_url prepended, if necessary.
+   */
+  protected function getAbsoluteUrl($path) {
+    global $base_url, $base_path;
+
+    $parts = parse_url($path);
+    if (empty($parts['host'])) {
+      // Ensure that we have a string (and no xpath object).
+      $path = (string) $path;
+      // Strip $base_path, if existent.
+      $length = strlen($base_path);
+      if (substr($path, 0, $length) === $base_path) {
+        $path = substr($path, $length);
+      }
+      // Ensure that we have an absolute path.
+      if ($path[0] !== '/') {
+        $path = '/' . $path;
+      }
+      // Finally, prepend the $base_url.
+      $path = $base_url . $path;
+    }
+    return $path;
+  }
+
+  /**
+   * Creates a user with a given set of permissions.
+   *
+   * @param array $permissions
+   *   (optional) Array of permission names to assign to user. Note that the
+   *   user always has the default permissions derived from the
+   *   "authenticated users" role.
+   * @param string $name
+   *   (optional) The user name.
+   *
+   * @return \Drupal\user\Entity\User|false
+   *   A fully loaded user object with passRaw property, or FALSE if account
+   *   creation fails.
+   */
+  protected function drupalCreateUser(array $permissions = array(), $name = NULL) {
+    // Create a role with the given permission set, if any.
+    $rid = FALSE;
+    if ($permissions) {
+      $rid = $this->drupalCreateRole($permissions);
+      if (!$rid) {
+        return FALSE;
+      }
+    }
+
+    // Create a user assigned to that role.
+    $edit = array();
+    $edit['name'] = !empty($name) ? $name : $this->randomMachineName();
+    $edit['mail'] = $edit['name'] . '@example.com';
+    $edit['pass'] = user_password();
+    $edit['status'] = 1;
+    if ($rid) {
+      $edit['roles'] = array($rid);
+    }
+
+    $account = entity_create('user', $edit);
+    $account->save();
+
+    $this->assertNotNull($account->id(), String::format('User created with name %name and pass %pass', array('%name' => $edit['name'], '%pass' => $edit['pass'])));
+    if (!$account->id()) {
+      return FALSE;
+    }
+
+    // Add the raw password so that we can log in as this user.
+    $account->passRaw = $edit['pass'];
+    return $account;
+  }
+
+  /**
+   * Creates a role with specified permissions.
+   *
+   * @param array $permissions
+   *   Array of permission names to assign to role.
+   * @param string $rid
+   *   (optional) The role ID (machine name). Defaults to a random name.
+   * @param string $name
+   *   (optional) The label for the role. Defaults to a random string.
+   * @param int $weight
+   *   (optional) The weight for the role. Defaults NULL so that entity_create()
+   *   sets the weight to maximum + 1.
+   *
+   * @return string
+   *   Role ID of newly created role, or FALSE if role creation failed.
+   */
+  protected function drupalCreateRole(array $permissions, $rid = NULL, $name = NULL, $weight = NULL) {
+    // Generate a random, lowercase machine name if none was passed.
+    if (!isset($rid)) {
+      $rid = strtolower($this->randomMachineName(8));
+    }
+    // Generate a random label.
+    if (!isset($name)) {
+      // In the role UI role names are trimmed and random string can start or
+      // end with a space.
+      $name = trim($this->randomString(8));
+    }
+
+    // Check the all the permissions strings are valid.
+    if (!$this->checkPermissions($permissions)) {
+      return FALSE;
+    }
+
+    // Create new role.
+    /* @var \Drupal\user\RoleInterface $role */
+    $role = entity_create('user_role', array(
+      'id' => $rid,
+      'label' => $name,
+    ));
+    if (!is_null($weight)) {
+      $role->set('weight', $weight);
+    }
+    $result = $role->save();
+
+    $this->assertSame($result, SAVED_NEW, String::format('Created role ID @rid with name @name.', array(
+      '@name' => var_export($role->label(), TRUE),
+      '@rid' => var_export($role->id(), TRUE),
+    )));
+
+    if ($result === SAVED_NEW) {
+      // Grant the specified permissions to the role, if any.
+      if (!empty($permissions)) {
+        user_role_grant_permissions($role->id(), $permissions);
+        $assigned_permissions = entity_load('user_role', $role->id())->getPermissions();
+        $missing_permissions = array_diff($permissions, $assigned_permissions);
+        if ($missing_permissions) {
+          $this->fail(String::format('Failed to create permissions: @perms', array('@perms' => implode(', ', $missing_permissions))));
+        }
+      }
+      return $role->id();
+    }
+    else {
+      return FALSE;
+    }
+  }
+
+  /**
+   * Generates a unique random string containing letters and numbers.
+   *
+   * Do not use this method when testing unvalidated user input. Instead, use
+   * \Drupal\simpletest\TestBase::randomString().
+   *
+   * @param int $length
+   *   (optional) Length of random string to generate.
+   *
+   * @return string
+   *   Randomly generated unique string.
+   *
+   * @see \Drupal\Component\Utility\Random::name()
+   */
+  public function randomMachineName($length = 8) {
+    return $this->getRandomGenerator()->name($length, TRUE);
+  }
+
+  /**
+   * Generates a pseudo-random string of ASCII characters of codes 32 to 126.
+   *
+   * Do not use this method when special characters are not possible (e.g., in
+   * machine or file names that have already been validated); instead, use
+   * \Drupal\simpletest\TestBase::randomMachineName(). If $length is greater
+   * than 2 the random string will include at least one ampersand ('&')
+   * character to ensure coverage for special characters and avoid the
+   * introduction of random test failures.
+   *
+   * @param int $length
+   *   (optional) Length of random string to generate.
+   *
+   * @return string
+   *   Pseudo-randomly generated unique string including special characters.
+   *
+   * @see \Drupal\Component\Utility\Random::string()
+   */
+  public function randomString($length = 8) {
+    if ($length < 3) {
+      return $this->getRandomGenerator()->string($length, TRUE, array($this, 'randomStringValidate'));
+    }
+
+    // To prevent the introduction of random test failures, ensure that the
+    // returned string contains a character that needs to be escaped in HTML by
+    // injecting an ampersand into it.
+    $replacement_pos = floor($length / 2);
+    // Remove 1 from the length to account for the ampersand character.
+    $string = $this->getRandomGenerator()->string($length - 1, TRUE, array($this, 'randomStringValidate'));
+    return substr_replace($string, '&', $replacement_pos, 0);
+  }
+
+  /**
+   * Checks whether a given list of permission names is valid.
+   *
+   * @param array $permissions
+   *   The permission names to check.
+   *
+   * @return bool
+   *   TRUE if the permissions are valid, FALSE otherwise.
+   */
+  protected function checkPermissions(array $permissions) {
+    $available = array_keys(\Drupal::service('user.permissions')->getPermissions());
+    $valid = TRUE;
+    foreach ($permissions as $permission) {
+      if (!in_array($permission, $available)) {
+        $this->fail(String::format('Invalid permission %permission.', array('%permission' => $permission)));
+        $valid = FALSE;
+      }
+    }
+    return $valid;
+  }
+
+  /**
+   * Logs in a user using the mink browser.
+   *
+   * If a user is already logged in, then the current user is logged out before
+   * logging in the specified user.
+   *
+   * Please note that neither the current user nor the passed-in user object is
+   * populated with data of the logged in user. If you need full access to the
+   * user object after logging in, it must be updated manually. If you also need
+   * access to the plain-text password of the user (set by drupalCreateUser()),
+   * e.g. to log in the same user again, then it must be re-assigned manually.
+   * For example:
+   * @code
+   *   // Create a user.
+   *   $account = $this->drupalCreateUser(array());
+   *   $this->drupalLogin($account);
+   *   // Load real user object.
+   *   $pass_raw = $account->passRaw;
+   *   $account = user_load($account->id());
+   *   $account->passRaw = $pass_raw;
+   * @endcode
+   *
+   * @param \Drupal\Core\Session\AccountInterface $account
+   *   User object representing the user to log in.
+   *
+   * @see drupalCreateUser()
+   */
+  protected function drupalLogin(AccountInterface $account) {
+    if ($this->loggedInUser) {
+      $this->drupalLogout();
+    }
+
+    $this->drupalGet('user');
+    $this->assertSession()->statusCodeEquals(200);
+    $this->submitForm(array(
+      'name' => $account->getUsername(),
+      'pass' => $account->passRaw,
+    ), t('Log in'));
+
+    // @see BrowserTestBase::drupalUserIsLoggedIn()
+    $account->sessionId = $this->getSession()->getCookie(session_name());
+    $this->assertTrue($this->drupalUserIsLoggedIn($account), String::format('User %name successfully logged in.', array('name' => $account->getUsername())));
+
+    $this->loggedInUser = $account;
+    $this->container->get('current_user')->setAccount($account);
+  }
+
+  /**
+   * Logs a user out of the internal browser and confirms.
+   *
+   * Confirms logout by checking the login page.
+   */
+  protected function drupalLogout() {
+    // Make a request to the logout page, and redirect to the user page, the
+    // idea being if you were properly logged out you should be seeing a login
+    // screen.
+    $assert_session = $this->assertSession();
+    $this->drupalGet('user/logout', array('query' => array('destination' => 'user')));
+    $assert_session->statusCodeEquals(200);
+    $assert_session->fieldExists('name');
+    $assert_session->fieldExists('pass');
+
+    // @see BrowserTestBase::drupalUserIsLoggedIn()
+    unset($this->loggedInUser->sessionId);
+    $this->loggedInUser = FALSE;
+    $this->container->get('current_user')->setAccount(new AnonymousUserSession());
+  }
+
+  /**
+   * Fills and submit a form.
+   *
+   * @param array $edit
+   *   Field data in an associative array. Changes the current input fields
+   *   (where possible) to the values indicated.
+   *
+   *   A checkbox can be set to TRUE to be checked and should be set to FALSE to
+   *   be unchecked.
+   * @param string $submit
+   *   Value of the submit button whose click is to be emulated. For example,
+   *   t('Save'). The processing of the request depends on this value. For
+   *   example, a form may have one button with the value t('Save') and another
+   *   button with the value t('Delete'), and execute different code depending
+   *   on which one is clicked.
+   * @param string $form_html_id
+   *   (optional) HTML ID of the form to be submitted. On some pages
+   *   there are many identical forms, so just using the value of the submit
+   *   button is not enough. For example: 'trigger-node-presave-assign-form'.
+   *   Note that this is not the Drupal $form_id, but rather the HTML ID of the
+   *   form, which is typically the same thing but with hyphens replacing the
+   *   underscores.
+   */
+  protected function submitForm($edit, $submit, $form_html_id = NULL) {
+    $assert_session = $this->assertSession();
+
+    // Get the form.
+    if (isset($form_html_id)) {
+      $form = $assert_session->elementExists('xpath', "//form[@id='" . $form_html_id . "']");
+      $submit_button = $assert_session->buttonExists($submit, $form);
+    }
+    else {
+      $submit_button = $assert_session->buttonExists($submit);
+      $form = $assert_session->elementExists('xpath', './ancestor::form', $submit_button);
+    }
+
+    // Edit the form values.
+    foreach ($edit as $name => $value) {
+      $field = $assert_session->fieldExists($name, $form);
+      $field->setValue($value);
+    }
+
+    // Submit form.
+    $this->prepareRequest();
+    $submit_button->press();
+
+    // Ensure that any changes to variables in the other thread are picked up.
+    $this->refreshVariables();
+  }
+
+  /**
+   * Helper function to get the options of select field.
+   *
+   * @param NodeElement|string $select
+   *   Name, ID, or Label of select field to assert.
+   * @param Element $container
+   *   (optional) Container element to check against. Defaults to current page.
+   *
+   * @return array
+   *   Associative array of option keys and values.
+   */
+  protected function getOptions($select, Element $container = NULL) {
+    if (is_string($select)) {
+      $select = $this->assertSession()->selectExists($select, $container);
+    }
+    $options = [];
+    /* @var \Behat\Mink\Element\NodeElement $option */
+    foreach ($select->findAll('xpath', '//option') as $option) {
+      $label = $option->getText();
+      $value = $option->getAttribute('value') ?: $label;
+      $options[$value] = $label;
+    }
+    return $options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function run(\PHPUnit_Framework_TestResult $result = NULL) {
+    if ($result === NULL) {
+      $result = $this->createResult();
+    }
+
+    parent::run($result);
+    return $result;
+  }
+
+  /**
+   * Override to use Mink exceptions.
+   *
+   * @return mixed
+   *   Either a test result or NULL.
+   * @throws \PHPUnit_Framework_AssertionFailedError
+   *   When exception was thrown inside the test.
+   */
+  protected function runTest() {
+    try {
+      return parent::runTest();
+    }
+    catch (Exception $e) {
+      throw new \PHPUnit_Framework_AssertionFailedError($e->getMessage());
+    }
+  }
+
+  /**
+   * Generates a unique random string containing letters and numbers.
+   *
+   * Do not use this method when testing unvalidated user input. Instead, use
+   * \Drupal\simpletest\TestBase::randomString().
+   *
+   * @param int $length
+   *   (optional) Length of random string to generate.
+   *
+   * @return string
+   *   Randomly generated unique string.
+   *
+   * @see \Drupal\Component\Utility\Random::name()
+   */
+  public function randomName($length = 8) {
+    return $this->getRandomGenerator()->name($length, TRUE);
+  }
+
+  /**
+   * Gets the random generator for the utility methods.
+   *
+   * @return \Drupal\Component\Utility\Random
+   *   The random generator
+   */
+  protected function getRandomGenerator() {
+    if (!is_object($this->randomGenerator)) {
+      $this->randomGenerator = new Random();
+    }
+    return $this->randomGenerator;
+  }
+
+  /**
+   * Installs drupal into the simpletest site.
+   */
+  public function installDrupal() {
+    // Define information about the user 1 account.
+    $this->rootUser = new UserSession(array(
+      'uid' => 1,
+      'name' => 'admin',
+      'mail' => 'admin@example.com',
+      'passRaw' => $this->randomName(),
+    ));
+
+    // Some tests (SessionTest and SessionHttpsTest) need to examine whether the
+    // proper session cookies were set on a response. Because the child site
+    // uses the same session name as the test runner, it is necessary to make
+    // that available to test-methods.
+    $this->sessionName = session_name();
+
+    // Get parameters for install_drupal() before removing global variables.
+    $parameters = $this->installParameters();
+
+    // Prepare installer settings that are not install_drupal() parameters.
+    // Copy and prepare an actual settings.php, so as to resemble a regular
+    // installation.
+    // Not using File API; a potential error must trigger a PHP warning.
+    $directory = DRUPAL_ROOT . '/' . $this->siteDirectory;
+    copy(DRUPAL_ROOT . '/sites/default/default.settings.php', $directory . '/settings.php');
+    copy(DRUPAL_ROOT . '/sites/default/default.services.yml', $directory . '/services.yml');
+
+    // All file system paths are created by System module during installation.
+    // @see system_requirements()
+    // @see TestBase::prepareEnvironment()
+    $settings['settings']['file_public_path'] = (object) array(
+      'value' => $this->publicFilesDirectory,
+      'required' => TRUE,
+    );
+    $this->writeSettings($settings);
+    // Allow for test-specific overrides.
+    $settings_testing_file = DRUPAL_ROOT . '/' . $this->originalSiteDirectory . '/settings.testing.php';
+    if (file_exists($settings_testing_file)) {
+      // Copy the testing-specific settings.php overrides in place.
+      copy($settings_testing_file, $directory . '/settings.testing.php');
+      // Add the name of the testing class to settings.php and include the
+      // testing specific overrides.
+      file_put_contents($directory . '/settings.php', "\n\$test_class = '" . get_class($this) . "';\n" . 'include DRUPAL_ROOT . \'/\' . $site_path . \'/settings.testing.php\';' . "\n", FILE_APPEND);
+    }
+    $settings_services_file = DRUPAL_ROOT . '/' . $this->originalSiteDirectory . '/testing.services.yml';
+    if (file_exists($settings_services_file)) {
+      // Copy the testing-specific service overrides in place.
+      copy($settings_services_file, $directory . '/services.yml');
+    }
+
+    // Since Drupal is bootstrapped already, install_begin_request() will not
+    // bootstrap into DRUPAL_BOOTSTRAP_CONFIGURATION (again). Hence, we have to
+    // reload the newly written custom settings.php manually.
+    Settings::initialize(DRUPAL_ROOT, $directory, $this->classLoader);
+
+    // Execute the non-interactive installer.
+    require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
+    install_drupal($parameters);
+
+    // Import new settings.php written by the installer.
+    Settings::initialize(DRUPAL_ROOT, $directory, $this->classLoader);
+    foreach ($GLOBALS['config_directories'] as $type => $path) {
+      $this->configDirectories[$type] = $path;
+    }
+
+    // After writing settings.php, the installer removes write permissions
+    // from the site directory. To allow drupal_generate_test_ua() to write
+    // a file containing the private key for drupal_valid_test_ua(), the site
+    // directory has to be writable.
+    // TestBase::restoreEnvironment() will delete the entire site directory.
+    // Not using File API; a potential error must trigger a PHP warning.
+    chmod($directory, 0777);
+
+    $request = \Drupal::request();
+    $this->kernel = DrupalKernel::createFromRequest($request, $this->classLoader, 'prod', TRUE);
+    $this->kernel->prepareLegacyRequest($request);
+    // Force the container to be built from scratch instead of loaded from the
+    // disk. This forces us to not accidently load the parent site.
+    $container = $this->kernel->rebuildContainer();
+
+    $config = $container->get('config.factory');
+
+    // Manually create and configure private and temporary files directories.
+    // While these could be preset/enforced in settings.php like the public
+    // files directory above, some tests expect them to be configurable in the
+    // UI. If declared in settings.php, they would no longer be configurable.
+    file_prepare_directory($this->privateFilesDirectory, FILE_CREATE_DIRECTORY);
+    file_prepare_directory($this->tempFilesDirectory, FILE_CREATE_DIRECTORY);
+    $config->getEditable('system.file')
+      ->set('path.private', $this->privateFilesDirectory)
+      ->set('path.temporary', $this->tempFilesDirectory)
+      ->save();
+
+    // Manually configure the test mail collector implementation to prevent
+    // tests from sending out emails and collect them in state instead.
+    // While this should be enforced via settings.php prior to installation,
+    // some tests expect to be able to test mail system implementations.
+    $config->getEditable('system.mail')
+      ->set('interface.default', 'test_mail_collector')
+      ->save();
+
+    // By default, verbosely display all errors and disable all production
+    // environment optimizations for all tests to avoid needless overhead and
+    // ensure a sane default experience for test authors.
+    // @see https://drupal.org/node/2259167
+    $config->getEditable('system.logging')
+      ->set('error_level', 'verbose')
+      ->save();
+    $config->getEditable('system.performance')
+      ->set('css.preprocess', FALSE)
+      ->set('js.preprocess', FALSE)
+      ->save();
+
+    // Collect modules to install.
+    $class = get_class($this);
+    $modules = array();
+    while ($class) {
+      if (property_exists($class, 'modules')) {
+        $modules = array_merge($modules, $class::$modules);
+      }
+      $class = get_parent_class($class);
+    }
+    if ($modules) {
+      $modules = array_unique($modules);
+      $success = $container->get('module_installer')->install($modules, TRUE);
+      $this->assertTrue($success, String::format('Enabled modules: %modules', array('%modules' => implode(', ', $modules))));
+      $this->rebuildContainer();
+    }
+
+    // Reset/rebuild all data structures after enabling the modules, primarily
+    // to synchronize all data structures and caches between the test runner and
+    // the child site.
+    // Affects e.g. file_get_stream_wrappers().
+    // @see \Drupal\Core\DrupalKernel::bootCode()
+    // @todo Test-specific setUp() methods may set up further fixtures; find a
+    //   way to execute this after setUp() is done, or to eliminate it entirely.
+    $this->resetAll();
+    $this->kernel->prepareLegacyRequest($request);
+  }
+
+  /**
+   * Returns the parameters that will be used when Simpletest installs Drupal.
+   *
+   * @see install_drupal()
+   * @see install_state_defaults()
+   */
+  protected function installParameters() {
+    $connection_info = Database::getConnectionInfo();
+    $driver = $connection_info['default']['driver'];
+    $connection_info['default']['prefix'] = $connection_info['default']['prefix']['default'];
+    unset($connection_info['default']['driver']);
+    unset($connection_info['default']['namespace']);
+    unset($connection_info['default']['pdo']);
+    unset($connection_info['default']['init_commands']);
+    $parameters = array(
+      'interactive' => FALSE,
+      'parameters' => array(
+        'profile' => $this->profile,
+        'langcode' => 'en',
+      ),
+      'forms' => array(
+        'install_settings_form' => array(
+          'driver' => $driver,
+          $driver => $connection_info['default'],
+        ),
+        'install_configure_form' => array(
+          'site_name' => 'Drupal',
+          'site_mail' => 'simpletest@example.com',
+          'account' => array(
+            'name' => $this->rootUser->name,
+            'mail' => $this->rootUser->getEmail(),
+            'pass' => array(
+              'pass1' => $this->rootUser->passRaw,
+              'pass2' => $this->rootUser->passRaw,
+            ),
+          ),
+          // form_type_checkboxes_value() requires NULL instead of FALSE values
+          // for programmatic form submissions to disable a checkbox.
+          'update_status_module' => array(
+            1 => NULL,
+            2 => NULL,
+          ),
+        ),
+      ),
+    );
+    return $parameters;
+  }
+
+  /**
+   * Generates a database prefix for running tests.
+   *
+   * The database prefix is used by prepareEnvironment() to setup a public files
+   * directory for the test to be run, which also contains the PHP error log,
+   * which is written to in case of a fatal error. Since that directory is based
+   * on the database prefix, all tests (even unit tests) need to have one, in
+   * order to access and read the error log.
+   *
+   * The generated database table prefix is used for the Drupal installation
+   * being performed for the test. It is also used by the cookie value of
+   * SIMPLETEST_USER_AGENT by the mink browser. During early Drupal bootstrap,
+   * the cookie is parsed, and if it matches, all database queries use
+   * the database table prefix that has been generated here.
+   *
+   * @see drupal_valid_test_ua()
+   * @see BrowserTestBase::prepareEnvironment()
+   */
+  private function prepareDatabasePrefix() {
+    // Ensure that the generated test site directory does not exist already,
+    // which may happen with a large amount of concurrent threads and
+    // long-running tests.
+    do {
+      $suffix = mt_rand(100000, 999999);
+      $this->siteDirectory = 'sites/simpletest/' . $suffix;
+      $this->databasePrefix = 'simpletest' . $suffix;
+    } while (is_dir(DRUPAL_ROOT . '/' . $this->siteDirectory));
+  }
+
+  /**
+   * Changes the database connection to the prefixed one.
+   *
+   * @see BrowserTestBase::prepareEnvironment()
+   */
+  private function changeDatabasePrefix() {
+    if (empty($this->databasePrefix)) {
+      $this->prepareDatabasePrefix();
+    }
+
+    // Clone the current connection and replace the current prefix.
+    $connection_info = Database::getConnectionInfo('default');
+    if (is_null($connection_info)) {
+      $db_url = getenv('SIMPLETEST_DB');
+      $info = parse_url($db_url);
+      if (!isset($info['scheme'], $info['host'], $info['path'])) {
+        throw new Wobbly();
+      }
+      $info += array(
+        'user' => '',
+        'pass' => '',
+        'fragment' => '',
+      );
+      if ($info['path'][0] === '/') {
+        $info['path'] = substr($info['path'], 1);
+      }
+      if ($info['scheme'] === 'sqlite' && $info['path'][0] !== '/') {
+        $info['path'] = DRUPAL_ROOT . '/' . $info['path'];
+      }
+      $database = array(
+        'driver' => $info['scheme'],
+        'username' => $info['user'],
+        'password' => $info['pass'],
+        'host' => $info['host'],
+        'database' => $info['path'],
+        'prefix' => array(
+          'default' => $this->databasePrefix,
+        ),
+      );
+      if (isset($info['port'])) {
+        $database['port'] = $info['port'];
+      }
+      Database::addConnectionInfo('default', 'default', $database);
+    }
+    else {
+      Database::renameConnection('default', 'simpletest_original_default');
+      foreach ($connection_info as $target => $value) {
+        // Replace the full table prefix definition to ensure that no table
+        // prefixes of the test runner leak into the test.
+        $connection_info[$target]['prefix'] = array(
+          'default' => $value['prefix']['default'] . $this->databasePrefix,
+        );
+      }
+      Database::addConnectionInfo('default', 'default', $connection_info['default']);
+    }
+  }
+
+  /**
+   * Prepares the current environment for running the test.
+   *
+   * Also sets up new resources for the testing environment, such as the public
+   * filesystem and configuration directories.
+   *
+   * This method is private as it must only be called once by
+   * BrowserTestBase::setUp() (multiple invocations for the same test would have
+   * unpredictable consequences) and it must not be callable or overridable by
+   * test classes.
+   */
+  protected function prepareEnvironment() {
+    // Bootstrap Drupal so we can use Drupal's built in functions.
+    $this->classLoader = require __DIR__ . '/../../../vendor/autoload.php';
+    $request = Request::createFromGlobals();
+    $kernel = TestRunnerKernel::createFromRequest($request, $this->classLoader);
+    // TestRunnerKernel expects the working directory to be DRUPAL_ROOT.
+    chdir(DRUPAL_ROOT);
+    $kernel->prepareLegacyRequest($request);
+    $this->prepareDatabasePrefix();
+
+    $this->originalSiteDirectory = $kernel->findSitePath($request);
+
+    // Create test directory ahead of installation so fatal errors and debug
+    // information can be logged during installation process.
+    file_prepare_directory($this->siteDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+
+    // Prepare filesystem directory paths.
+    $this->publicFilesDirectory = $this->siteDirectory . '/files';
+    $this->privateFilesDirectory = $this->siteDirectory . '/private';
+    $this->tempFilesDirectory = $this->siteDirectory . '/temp';
+    $this->translationFilesDirectory = $this->siteDirectory . '/translations';
+
+    // Ensure the configImporter is refreshed for each test.
+    $this->configImporter = NULL;
+
+    // Unregister all custom stream wrappers of the parent site.
+    $wrappers = \Drupal::service('stream_wrapper_manager')->getWrappers(StreamWrapperInterface::ALL);
+    foreach ($wrappers as $scheme => $info) {
+      stream_wrapper_unregister($scheme);
+    }
+
+    // Reset statics.
+    drupal_static_reset();
+
+    // Ensure there is no service container.
+    $this->container = NULL;
+    \Drupal::setContainer(NULL);
+
+    // Unset globals.
+    unset($GLOBALS['config_directories']);
+    unset($GLOBALS['config']);
+    unset($GLOBALS['conf']);
+
+    // Log fatal errors.
+    ini_set('log_errors', 1);
+    ini_set('error_log', DRUPAL_ROOT . '/' . $this->siteDirectory . '/error.log');
+
+    // Change the database prefix.
+    $this->changeDatabasePrefix();
+
+    // After preparing the environment and changing the database prefix, we are
+    // in a valid test environment.
+    drupal_valid_test_ua($this->databasePrefix);
+
+    // Reset settings.
+    new Settings(array(
+      // For performance, simply use the database prefix as hash salt.
+      'hash_salt' => $this->databasePrefix,
+    ));
+
+    drupal_set_time_limit($this->timeLimit);
+  }
+
+  /**
+   * Returns the database connection to the site running Simpletest.
+   *
+   * @return \Drupal\Core\Database\Connection
+   *   The database connection to use for inserting assertions.
+   */
+  public static function getDatabaseConnection() {
+    // Check whether there is a test runner connection.
+    // @see run-tests.sh
+    try {
+      $connection = Database::getConnection('default', 'test-runner');
+    }
+    catch (ConnectionNotDefinedException $e) {
+      // Check whether there is a backup of the original default connection.
+      // @see BrowserTestBase::prepareEnvironment()
+      try {
+        $connection = Database::getConnection('default', 'simpletest_original_default');
+      }
+      catch (ConnectionNotDefinedException $e) {
+        // If BrowserTestBase::prepareEnvironment() or
+        // BrowserTestBase::restoreEnvironment() failed, the test-specific
+        // database connection does not exist yet/anymore, so fall back to the
+        // default of the (UI) test runner.
+        $connection = Database::getConnection('default', 'default');
+      }
+    }
+    return $connection;
+  }
+
+  /**
+   * Rewrites the settings.php file of the test site.
+   *
+   * @param array $settings
+   *   An array of settings to write out, in the format expected by
+   *   drupal_rewrite_settings().
+   *
+   * @see drupal_rewrite_settings()
+   */
+  protected function writeSettings(array $settings) {
+    include_once DRUPAL_ROOT . '/core/includes/install.inc';
+    $filename = $this->siteDirectory . '/settings.php';
+
+    error_log($filename);
+
+    // system_requirements() removes write permissions from settings.php
+    // whenever it is invoked.
+    // Not using File API; a potential error must trigger a PHP warning.
+    chmod($filename, 0666);
+    drupal_rewrite_settings($settings, $filename);
+  }
+
+  /**
+   * Rebuilds \Drupal::getContainer().
+   *
+   * Use this to build a new kernel and service container. For example, when the
+   * list of enabled modules is changed via the internal browser, in which case
+   * the test process still contains an old kernel and service container with an
+   * old module list.
+   *
+   * @see BrowserTestBase::prepareEnvironment()
+   * @see BrowserTestBase::restoreEnvironment()
+   *
+   * @todo Fix https://www.drupal.org/node/2021959 so that module enable/disable
+   *   changes are immediately reflected in \Drupal::getContainer(). Until then,
+   *   tests can invoke this workaround when requiring services from newly
+   *   enabled modules to be immediately available in the same request.
+   */
+  protected function rebuildContainer() {
+    // Maintain the current global request object.
+    $request = \Drupal::request();
+    // Rebuild the kernel and bring it back to a fully bootstrapped state.
+    $this->container = $this->kernel->rebuildContainer();
+
+    // Make sure the url generator has a request object, otherwise calls to
+    // $this->drupalGet() will fail.
+    $this->prepareRequestForGenerator();
+  }
+
+  /**
+   * Creates a mock request and sets it on the generator.
+   *
+   * This is used to manipulate how the generator generates paths during tests.
+   * It also ensures that calls to $this->drupalGet() will work when running
+   * from run-tests.sh because the url generator no longer looks at the global
+   * variables that are set there but relies on getting this information from a
+   * request object.
+   *
+   * @param bool $clean_urls
+   *   Whether to mock the request using clean urls.
+   * @param array $override_server_vars
+   *   An array of server variables to override.
+   *
+   * @return Request
+   *   The mocked request object.
+   */
+  protected function prepareRequestForGenerator($clean_urls = TRUE, $override_server_vars = array()) {
+    $request = Request::createFromGlobals();
+    $server = $request->server->all();
+    if (basename($server['SCRIPT_FILENAME']) != basename($server['SCRIPT_NAME'])) {
+      // We need this for when the test is executed by run-tests.sh.
+      // @todo Remove this once run-tests.sh has been converted to use a Request
+      //   object.
+      $cwd = getcwd();
+      $server['SCRIPT_FILENAME'] = $cwd . '/' . basename($server['SCRIPT_NAME']);
+      $base_path = rtrim($server['REQUEST_URI'], '/');
+    }
+    else {
+      $base_path = $request->getBasePath();
+    }
+    if ($clean_urls) {
+      $request_path = $base_path ? $base_path . '/user' : 'user';
+    }
+    else {
+      $request_path = $base_path ? $base_path . '/index.php/user' : '/index.php/user';
+    }
+    $server = array_merge($server, $override_server_vars);
+
+    $request = Request::create($request_path, 'GET', array(), array(), array(), $server);
+    $this->container->get('request_stack')->push($request);
+
+    // The request context is normally set by the router_listener from within
+    // its KernelEvents::REQUEST listener. In the simpletest parent site this
+    // event is not fired, therefore it is necessary to updated the request
+    // context manually here.
+    $this->container->get('router.request_context')->fromRequest($request);
+
+    return $request;
+  }
+
+  /**
+   * Resets all data structures after having enabled new modules.
+   *
+   * This method is called by \Drupal\simpletest\WebTestBase::setUp() after
+   * enabling the requested modules. It must be called again when additional
+   * modules are enabled later.
+   */
+  protected function resetAll() {
+    // Clear all database and static caches and rebuild data structures.
+    drupal_flush_all_caches();
+    $this->container = \Drupal::getContainer();
+
+    // Reset static variables and reload permissions.
+    $this->refreshVariables();
+  }
+
+  /**
+   * Refreshes in-memory configuration and state information.
+   *
+   * Useful after a page request is made that changes configuration or state in
+   * a different thread.
+   *
+   * In other words calling a settings page with $this->drupalPostForm() with a
+   * changed value would update configuration to reflect that change, but in the
+   * thread that made the call (thread running the test) the changed values
+   * would not be picked up.
+   *
+   * This method clears the cache and loads a fresh copy.
+   */
+  protected function refreshVariables() {
+    // Clear the tag cache.
+    // @todo Replace drupal_static() usage within classes and provide a
+    //   proper interface for invoking reset() on a cache backend:
+    //   https://www.drupal.org/node/2311945.
+    drupal_static_reset('Drupal\Core\Cache\CacheBackendInterface::tagCache');
+    drupal_static_reset('Drupal\Core\Cache\DatabaseBackend::deletedTags');
+    drupal_static_reset('Drupal\Core\Cache\DatabaseBackend::invalidatedTags');
+    foreach (Cache::getBins() as $backend) {
+      if (is_callable(array($backend, 'reset'))) {
+        $backend->reset();
+      }
+    }
+
+    $this->container->get('config.factory')->reset();
+    $this->container->get('state')->resetCache();
+  }
+
+  /**
+   * Returns whether a given user account is logged in.
+   *
+   * @param \Drupal\user\UserInterface $account
+   *   The user account object to check.
+   *
+   * @return bool
+   *   Return TRUE if the user is logged in, FALSE otherwise.
+   */
+  protected function drupalUserIsLoggedIn($account) {
+    if (!isset($account->sessionId)) {
+      return FALSE;
+    }
+    // The session ID is hashed before being stored in the database.
+    // @see \Drupal\Core\Session\SessionHandler::read()
+    return (bool) db_query("SELECT sid FROM {users_field_data} u INNER JOIN {sessions} s ON u.uid = s.uid AND u.default_langcode = 1 WHERE s.sid = :sid", array(':sid' => Crypt::hashBase64($account->sessionId)))->fetchField();
+  }
+
+}
diff --git a/core/modules/simpletest/src/Form/SimpletestTestForm.php b/core/modules/simpletest/src/Form/SimpletestTestForm.php
index 03f16f5..5c8265a 100644
--- a/core/modules/simpletest/src/Form/SimpletestTestForm.php
+++ b/core/modules/simpletest/src/Form/SimpletestTestForm.php
@@ -179,6 +179,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
+    global $base_url;
     // Test discovery does not run upon form submission.
     simpletest_classloader_register();
 
@@ -209,6 +210,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       }
     }
     if (!empty($tests_list)) {
+      putenv('SIMPLETEST_BASE_URL=' . $base_url);
       $test_id = simpletest_run_tests($tests_list, 'drupal');
       $form_state->setRedirect(
         'simpletest.result_form',
diff --git a/core/modules/simpletest/src/TestDiscovery.php b/core/modules/simpletest/src/TestDiscovery.php
index a6c0e62..f3a0449 100644
--- a/core/modules/simpletest/src/TestDiscovery.php
+++ b/core/modules/simpletest/src/TestDiscovery.php
@@ -79,8 +79,9 @@ public function registerTestNamespaces() {
 
     $existing = $this->classLoader->getPrefixesPsr4();
 
-    // Add PHPUnit test namespace of Drupal core.
+    // Add PHPUnit test namespaces of Drupal core.
     $this->testNamespaces['Drupal\\Tests\\'] = [DRUPAL_ROOT . '/core/tests/Drupal/Tests'];
+    $this->testNamespaces['Drupal\\FunctionalTests\\'] = [DRUPAL_ROOT . '/core/tests/Drupal/FunctionalTests'];
 
     $this->availableExtensions = array();
     foreach ($this->getExtensions() as $name => $extension) {
@@ -95,8 +96,9 @@ public function registerTestNamespaces() {
       // Add Simpletest test namespace.
       $this->testNamespaces["Drupal\\$name\\Tests\\"][] = "$base_path/src/Tests";
 
-      // Add PHPUnit test namespace.
-      $this->testNamespaces["Drupal\\Tests\\$name\\"][] = "$base_path/tests/src";
+      // Add PHPUnit test namespaces.
+      $this->testNamespaces["Drupal\\Tests\\$name\\Unit\\"][] = "$base_path/tests/src/Unit";
+      $this->testNamespaces["Drupal\\Tests\\$name\\Functional\\"][] = "$base_path/tests/src/Functional";
     }
 
     foreach ($this->testNamespaces as $prefix => $paths) {
@@ -322,7 +324,7 @@ public static function getTestInfo($classname, $doc_comment = NULL) {
       throw new MissingGroupException(sprintf('Missing @group annotation in %s', $classname));
     }
     // Force all PHPUnit tests into the same group.
-    if (strpos($classname, 'Drupal\\Tests\\') === 0) {
+    if (static::isUnitTest($classname)) {
       $info['group'] = 'PHPUnit';
     }
     else {
@@ -408,6 +410,31 @@ public static function parseTestClassAnnotations(\ReflectionClass $class) {
   }
 
   /**
+   * Determines if the provided classname is a unit test.
+   *
+   * @param $classname
+   *   The test classname.
+   *
+   * @return bool
+   *   TRUE if the class is a unit test. FALSE if not.
+   */
+  public static function isUnitTest($classname) {
+    if (strpos($classname, 'Drupal\\Tests\\') === 0) {
+      $namespace = explode('\\', $classname);
+      $first_letter = Unicode::substr($namespace[2], 0, 1);
+      if (Unicode::strtoupper($first_letter) === $first_letter) {
+        // A core unit test.
+        return TRUE;
+      }
+      else if ($namespace[3] == 'Unit') {
+        // A module unit test
+        return TRUE;
+      }
+    }
+    return FALSE;
+  }
+
+  /**
    * Returns all available extensions.
    *
    * @return \Drupal\Core\Extension\Extension[]
diff --git a/core/modules/simpletest/src/Tests/SimpleTestBrowserTest.php b/core/modules/simpletest/src/Tests/SimpleTestBrowserTest.php
index e384a3c..c86933d 100644
--- a/core/modules/simpletest/src/Tests/SimpleTestBrowserTest.php
+++ b/core/modules/simpletest/src/Tests/SimpleTestBrowserTest.php
@@ -138,11 +138,19 @@ public function testTestingThroughUI() {
 
     $this->drupalGet('admin/config/development/testing');
     $edit = array(
-      // A PHPUnit test.
+      // A PHPUnit unit test.
       'tests[Drupal\Tests\action\Unit\Menu\ActionLocalTasksTest]' => TRUE,
     );
     $this->drupalPostForm(NULL, $edit, t('Run tests'));
     $this->assertText('0 fails, 0 exceptions');
+
+    $this->drupalGet('admin/config/development/testing');
+    $edit = array(
+      // A PHPUnit functional test.
+      'tests[Drupal\Tests\simpletest\Functional\BrowserTestBaseTest]' => TRUE,
+    );
+    $this->drupalPostForm(NULL, $edit, t('Run tests'));
+    $this->assertText('0 fails, 0 exceptions');
   }
 
 }
diff --git a/core/modules/simpletest/src/WebAssert.php b/core/modules/simpletest/src/WebAssert.php
new file mode 100644
index 0000000..daea904
--- /dev/null
+++ b/core/modules/simpletest/src/WebAssert.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\simpletest\WebAssert.
+ */
+
+namespace Drupal\simpletest;
+
+use Behat\Mink\WebAssert as MinkWebAssert;
+use Behat\Mink\Element\TraversableElement;
+use Behat\Mink\Exception\ElementNotFoundException;
+
+/**
+ * Defines a class with methods for asserting presence of elements during tests.
+ */
+class WebAssert extends MinkWebAssert {
+
+  /**
+   * Checks that specific button exists on the current page.
+   *
+   * @param string $button
+   *   One of id|name|label|value for the button.
+   * @param \Behat\Mink\Element\TraversableElement $container
+   *   The document to check against.
+   *
+   * @return \Behat\Mink\Element\NodeElement
+   *   The matching element.
+   *
+   * @throws \Behat\Mink\Exception\ElementNotFoundException
+   *   When the element doesn't exist.
+   */
+  public function buttonExists($button, TraversableElement $container = NULL) {
+    $container = $container ?: $this->session->getPage();
+    $node = $container->findButton($button);
+
+    if (NULL === $node) {
+      throw new ElementNotFoundException($this->session, 'button', 'id|name|label|value', $button);
+    }
+
+    return $node;
+  }
+
+  /**
+   * Checks that specific select field exists on the current page.
+   *
+   * @param string $select
+   *   One of id|name|label|value for the select field.
+   * @param \Behat\Mink\Element\TraversableElement $container
+   *   The document to check against.
+   *
+   * @return \Behat\Mink\Element\NodeElement
+   *   The matching element
+   *
+   * @throws \Behat\Mink\Exception\ElementNotFoundException
+   *   When the element doesn't exist.
+   */
+  public function selectExists($select, TraversableElement $container = NULL) {
+    $container = $container ?: $this->session->getPage();
+    $node = $container->find('named', array(
+      'select',
+      $this->session->getSelectorsHandler()->xpathLiteral($select),
+    ));
+
+    if (NULL === $node) {
+      throw new ElementNotFoundException($this->session, 'select', 'id|name|label|value', $select);
+    }
+
+    return $node;
+  }
+}
diff --git a/core/modules/simpletest/tests/src/Functional/BrowserTestBaseTest.php b/core/modules/simpletest/tests/src/Functional/BrowserTestBaseTest.php
new file mode 100755
index 0000000..99194c5
--- /dev/null
+++ b/core/modules/simpletest/tests/src/Functional/BrowserTestBaseTest.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @file
+ * Definition of \Drupal\Tests\simpletest\Functional\BrowserTestBaseTest.
+ */
+
+namespace Drupal\Tests\simpletest\Functional;
+
+use Drupal\simpletest\BrowserTestBase;
+
+/**
+ * Tests BrowserTestBase functionality.
+ *
+ * @group simpletest
+ * @group modern
+ *
+ * @runTestsInSeparateProcesses
+ */
+class BrowserTestBaseTest extends BrowserTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('test_page_test', 'form_test');
+
+  /**
+   * Tests basic page test.
+   */
+  public function testGoTo() {
+    $account = $this->drupalCreateUser();
+    $this->drupalLogin($account);
+
+    // Visit a Drupal page that requires login.
+    $this->drupalGet('/test-page');
+    $this->assertSession()->statusCodeEquals(200);
+
+    // Test page contains some text.
+    $this->assertSession()->pageTextContains('Test page text.');
+  }
+
+  /**
+   * Tests basic form functionality.
+   */
+  public function testForm() {
+    // Ensure the proper response code for a _form route.
+    $this->drupalGet('/form-test/object-builder');
+    $this->assertSession()->statusCodeEquals(200);
+
+    // Ensure the form and text field exist.
+    $this->assertSession()->elementExists('css', 'form#form-test-form-test-object');
+    $this->assertSession()->fieldExists('bananas');
+
+    $edit = ['bananas' => 'green'];
+    $this->submitForm($edit, 'Save', 'form-test-form-test-object');
+
+    $config_factory = $this->container->get('config.factory');
+    $value = $config_factory->get('form_test.object')->get('bananas');
+    $this->assertSame('green', $value);
+  }
+
+}
diff --git a/core/modules/simpletest/tests/src/Unit/TestInfoParsingTest.php b/core/modules/simpletest/tests/src/Unit/TestInfoParsingTest.php
index 03a87b7..4df976f 100644
--- a/core/modules/simpletest/tests/src/Unit/TestInfoParsingTest.php
+++ b/core/modules/simpletest/tests/src/Unit/TestInfoParsingTest.php
@@ -20,6 +20,7 @@ public function testTestInfoParser($expected, $classname, $doc_comment = NULL) {
   }
 
   public function infoParserProvider() {
+    // A module provided unit test.
     $tests[] = [
       // Expected result.
       [
@@ -31,6 +32,32 @@ public function infoParserProvider() {
       'Drupal\Tests\simpletest\Unit\TestInfoParsingTest',
     ];
 
+    // A core unit test.
+    $tests[] = [
+      // Expected result.
+      [
+        'name' => 'Drupal\Tests\Core\DrupalTest',
+        'group' => 'PHPUnit',
+        'description' => 'Tests \Drupal.',
+      ],
+      // Classname.
+      'Drupal\Tests\Core\DrupalTest',
+    ];
+
+    // Functional PHPUnit test.
+    $tests[] = [
+      // Expected result.
+      [
+        'name' => 'Drupal\Tests\simpletest\Functional\BrowserTestBaseTest',
+        'group' => 'simpletest',
+        'description' => 'Tests BrowserTestBase functionality.',
+      ],
+      // Classname.
+      'Drupal\Tests\simpletest\Functional\BrowserTestBaseTest',
+    ];
+
+    // Simpletest classes can not be autoloaded in a PHPUnit test, therefore
+    // provide a docblock.
     $tests[] = [
       // Expected result.
       [
diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist
index bd0edc9..44bbc33 100644
--- a/core/phpunit.xml.dist
+++ b/core/phpunit.xml.dist
@@ -6,19 +6,29 @@
     <ini name="error_reporting" value="32767"/>
     <!-- Do not limit the amount of memory tests take to run. -->
     <ini name="memory_limit" value="-1"/>
+    <env name="SIMPLETEST_BASE_URL" value="http://localhost"/>
+    <env name="SIMPLETEST_DB" value="mysql://username:password@localhost/databasename#table_prefix"/>
   </php>
   <testsuites>
-    <testsuite name="Drupal Unit Test Suite">
-      <directory>./tests</directory>
-      <directory>./modules/*/tests</directory>
-      <directory>../modules</directory>
-      <directory>../sites/*/modules</directory>
+    <testsuite name="unit">
+      <directory>./tests/Drupal/Tests</directory>
+      <directory>./modules/*/tests/src/Unit</directory>
+      <directory>../modules/*/tests/src/Unit</directory>
+      <directory>../sites/*/modules/*/tests/src/Unit</directory>
+      <!-- Exclude Composer's vendor directory so we don't run tests there. -->
+      <exclude>./vendor</exclude>
+      <!-- Exclude Drush tests. -->
+      <exclude>./drush/tests</exclude>
+    </testsuite>
+    <testsuite name="functional">
+      <directory>./tests/Drupal/FunctionalTests</directory>
+      <directory>./modules/*/tests/src/Functional</directory>
+      <directory>../modules/*/tests/src/Functional</directory>
+      <directory>../sites/*/modules/*/tests/src/Functional</directory>
       <!-- Exclude Composer's vendor directory so we don't run tests there. -->
       <exclude>./vendor</exclude>
       <!-- Exclude Drush tests. -->
       <exclude>./drush/tests</exclude>
-      <!-- Exclude special-case files from config's test modules. -->
-      <exclude>./modules/config/tests/config_test/src</exclude>
     </testsuite>
   </testsuites>
   <listeners>
@@ -36,3 +46,4 @@
      </whitelist>
   </filter>
 </phpunit>
+
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 7bf821c..6e9a950 100644
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -339,6 +339,17 @@ function simpletest_script_init() {
     }
   }
 
+  if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
+    $base_url = 'https://';
+  }
+  else {
+    $base_url = 'http://';
+  }
+  $base_url .= $host;
+  if ($path !== '') {
+    $base_url .= $path;
+  }
+  putenv('SIMPLETEST_BASE_URL=' . $base_url);
   $_SERVER['HTTP_HOST'] = $host;
   $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
   $_SERVER['SERVER_ADDR'] = '127.0.0.1';
diff --git a/core/vendor/behat/mink-browserkit-driver/.gitignore b/core/vendor/behat/mink-browserkit-driver/.gitignore
new file mode 100644
index 0000000..3ccd9ee
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/.gitignore
@@ -0,0 +1,3 @@
+vendor
+composer.lock
+/phpunit.xml
diff --git a/core/vendor/behat/mink-browserkit-driver/.travis.yml b/core/vendor/behat/mink-browserkit-driver/.travis.yml
new file mode 100644
index 0000000..838fc4e
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/.travis.yml
@@ -0,0 +1,20 @@
+language: php
+
+php: [5.3, 5.4, 5.5, 5.6, hhvm]
+
+matrix:
+  include:
+    - php: 5.5
+      env: SYMFONY_VERSION='2.3.*'
+    - php: 5.5
+      env: SYMFONY_VERSION='2.5.*@dev'
+
+before_script:
+  - sh -c 'if [ "$SYMFONY_VERSION" != "" ]; then composer require -n --no-update symfony/symfony=$SYMFONY_VERSION; fi;'
+  - composer install -n --prefer-source
+
+script: phpunit -v --coverage-clover=coverage.clover
+
+after_script:
+  - wget https://scrutinizer-ci.com/ocular.phar
+  - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
diff --git a/core/vendor/behat/mink-browserkit-driver/CHANGELOG.md b/core/vendor/behat/mink-browserkit-driver/CHANGELOG.md
new file mode 100644
index 0000000..774663f
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/CHANGELOG.md
@@ -0,0 +1,33 @@
+1.2.0 / 2014-09-26
+==================
+
+BC break:
+
+* Changed the behavior of `getValue` for checkboxes according to the BC break in Mink 1.6
+
+New features:
+
+* Implemented `getOuterHtml`
+* Added the support of manipulating forms without submit buttons
+* Added support of any request headers instead of supporting only a few hardcoded ones
+* Added support of any BrowserKit client using `filterResponse` when using BrowserKit 2.3+
+* Added the support of reset buttons
+* Implemented `submitForm`
+* Implemented `isSelected`
+
+Bug fixes:
+
+* Fixed the support of options without value attribute in `isSelected` and `getValue`
+* Added the support of radio buttons in `isChecked`
+* Fixed the submission of empty textarea fields
+* Refactored the handling of request headers to ensure they are reset when resetting the driver
+* Fixed the handling of buttons to submit only for submit buttons rather than all buttons
+* Fixed the code to throw exceptions rather than triggering a fatal error for invalid usages of the driver
+* Fixed the removal of cookies
+* Fixed the submission of form fields with same name and without id
+* Fixed `getAttribute` to return `null` for missing attributes rather than an empty string
+
+Testing:
+
+* Updated the testsuite to use the new Mink 1.6 driver testsuite
+* Added testing on HHVM
diff --git a/core/vendor/behat/mink-browserkit-driver/LICENSE b/core/vendor/behat/mink-browserkit-driver/LICENSE
new file mode 100644
index 0000000..3365ae6
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2012-2013 Konstantin Kudryashov <ever.zet@gmail.com>
+
+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:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+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.
diff --git a/core/vendor/behat/mink-browserkit-driver/README.md b/core/vendor/behat/mink-browserkit-driver/README.md
new file mode 100644
index 0000000..fc36e41
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/README.md
@@ -0,0 +1,54 @@
+Mink BrowserKit Driver
+======================
+
+[![Latest Stable Version](https://poser.pugx.org/behat/mink-browserkit-driver/v/stable.png)](https://packagist.org/packages/behat/mink-browserkit-driver)
+[![Latest Unstable Version](https://poser.pugx.org/behat/mink-browserkit-driver/v/unstable.svg)](https://packagist.org/packages/behat/mink-browserkit-driver)
+[![Total Downloads](https://poser.pugx.org/behat/mink-browserkit-driver/downloads.png)](https://packagist.org/packages/behat/mink-browserkit-driver)
+[![Build Status](https://travis-ci.org/Behat/MinkBrowserKitDriver.svg?branch=master)](https://travis-ci.org/Behat/MinkBrowserKitDriver)
+[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/Behat/MinkBrowserKitDriver/badges/quality-score.png?s=0443d284940e099ea560eb39b6b2fcdc5d4e7f29)](https://scrutinizer-ci.com/g/Behat/MinkBrowserKitDriver/)
+[![Code Coverage](https://scrutinizer-ci.com/g/Behat/MinkBrowserKitDriver/badges/coverage.png?s=48960c4495488ab0b7d310b62322f017497f5bfa)](https://scrutinizer-ci.com/g/Behat/MinkBrowserKitDriver/)
+[![License](https://poser.pugx.org/behat/mink-browserkit-driver/license.svg)](https://packagist.org/packages/behat/mink-browserkit-driver)
+
+Usage Example
+-------------
+
+``` php
+<?php
+
+use Behat\Mink\Mink,
+    Behat\Mink\Session,
+    Behat\Mink\Driver\BrowserKitDriver;
+
+use Symfony\Component\HttpKernel\Client;
+
+$app  = require_once(__DIR__.'/app.php'); // Silex app
+
+$mink = new Mink(array(
+    'silex' => new Session(new BrowserKitDriver(new Client($app))),
+));
+
+$mink->getSession('silex')->getPage()->findLink('Chat')->click();
+```
+
+Installation
+------------
+
+``` json
+{
+    "require": {
+        "behat/mink":                   "~1.5",
+        "behat/mink-browserkit-driver": "~1.1"
+    }
+}
+```
+
+``` bash
+$> curl -sS https://getcomposer.org/installer | php
+$> php composer.phar install
+```
+
+Maintainers
+-----------
+
+* Konstantin Kudryashov [everzet](http://github.com/everzet)
+* Other [awesome developers](https://github.com/Behat/MinkBrowserKitDriver/graphs/contributors)
diff --git a/core/vendor/behat/mink-browserkit-driver/composer.json b/core/vendor/behat/mink-browserkit-driver/composer.json
new file mode 100644
index 0000000..c0c5df9
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/composer.json
@@ -0,0 +1,45 @@
+{
+    "name":         "behat/mink-browserkit-driver",
+    "description":  "Symfony2 BrowserKit driver for Mink framework",
+    "keywords":     ["Symfony2", "Mink", "testing", "browser"],
+    "homepage":     "http://mink.behat.org/",
+    "type":         "mink-driver",
+    "license":      "MIT",
+
+    "authors": [
+        {
+            "name":      "Konstantin Kudryashov",
+            "email":     "ever.zet@gmail.com",
+            "homepage":  "http://everzet.com"
+        }
+    ],
+
+    "require": {
+        "php":                  ">=5.3.1",
+        "behat/mink":           "~1.6@dev",
+        "symfony/browser-kit":  "~2.0",
+        "symfony/dom-crawler":  "~2.0"
+    },
+
+    "require-dev": {
+        "silex/silex": "~1.2"
+    },
+
+    "autoload": {
+        "psr-0": {
+            "Behat\\Mink\\Driver": "src/"
+        }
+    },
+
+    "autoload-dev": {
+        "psr-4": {
+            "Behat\\Mink\\Tests\\Driver\\": "tests"
+        }
+    },
+
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.2.x-dev"
+        }
+    }
+}
diff --git a/core/vendor/behat/mink-browserkit-driver/phpunit.xml.dist b/core/vendor/behat/mink-browserkit-driver/phpunit.xml.dist
new file mode 100644
index 0000000..4f9b932
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/phpunit.xml.dist
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit colors="true" bootstrap="vendor/behat/mink/driver-testsuite/bootstrap.php">
+    <php>
+        <var name="driver_config_factory" value="Behat\Mink\Tests\Driver\BrowserKitConfig::getInstance" />
+    </php>
+
+    <testsuites>
+        <testsuite name="Driver test suite">
+            <directory>tests</directory>
+            <directory>vendor/behat/mink/driver-testsuite/tests/Basic</directory>
+            <directory>vendor/behat/mink/driver-testsuite/tests/Form</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory>./src/Behat/Mink/Driver</directory>
+        </whitelist>
+    </filter>
+</phpunit>
diff --git a/core/vendor/behat/mink-browserkit-driver/src/Behat/Mink/Driver/BrowserKitDriver.php b/core/vendor/behat/mink-browserkit-driver/src/Behat/Mink/Driver/BrowserKitDriver.php
new file mode 100644
index 0000000..28b99dc
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/src/Behat/Mink/Driver/BrowserKitDriver.php
@@ -0,0 +1,949 @@
+<?php
+
+/*
+ * This file is part of the Behat\Mink.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Driver;
+
+use Behat\Mink\Element\NodeElement;
+use Behat\Mink\Exception\DriverException;
+use Behat\Mink\Exception\UnsupportedDriverActionException;
+use Behat\Mink\Session;
+use Symfony\Component\BrowserKit\Client;
+use Symfony\Component\BrowserKit\Cookie;
+use Symfony\Component\BrowserKit\Request;
+use Symfony\Component\BrowserKit\Response;
+use Symfony\Component\DomCrawler\Crawler;
+use Symfony\Component\DomCrawler\Field\ChoiceFormField;
+use Symfony\Component\DomCrawler\Field\FileFormField;
+use Symfony\Component\DomCrawler\Field\FormField;
+use Symfony\Component\DomCrawler\Field\InputFormField;
+use Symfony\Component\DomCrawler\Field\TextareaFormField;
+use Symfony\Component\DomCrawler\Form;
+use Symfony\Component\HttpFoundation\Request as HttpFoundationRequest;
+use Symfony\Component\HttpFoundation\Response as HttpFoundationResponse;
+use Symfony\Component\HttpKernel\Client as HttpKernelClient;
+
+/**
+ * Symfony2 BrowserKit driver.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class BrowserKitDriver extends CoreDriver
+{
+    private $session;
+    private $client;
+
+    /**
+     * @var Form[]
+     */
+    private $forms = array();
+    private $serverParameters = array();
+    private $started = false;
+    private $removeScriptFromUrl = false;
+    private $removeHostFromUrl = false;
+
+    /**
+     * Initializes BrowserKit driver.
+     *
+     * @param Client      $client  BrowserKit client instance
+     * @param string|null $baseUrl Base URL for HttpKernel clients
+     */
+    public function __construct(Client $client, $baseUrl = null)
+    {
+        $this->client = $client;
+        $this->client->followRedirects(true);
+
+        if ($baseUrl !== null && $client instanceof HttpKernelClient) {
+            $client->setServerParameter('SCRIPT_FILENAME', parse_url($baseUrl, PHP_URL_PATH));
+        }
+    }
+
+    /**
+     * Returns BrowserKit HTTP client instance.
+     *
+     * @return Client
+     */
+    public function getClient()
+    {
+        return $this->client;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setSession(Session $session)
+    {
+        $this->session = $session;
+    }
+
+    /**
+     * Tells driver to remove hostname from URL.
+     *
+     * @param Boolean $remove
+     *
+     * @deprecated Deprecated as of 1.2, to be removed in 2.0. Pass the base url in the constructor instead.
+     */
+    public function setRemoveHostFromUrl($remove = true)
+    {
+        trigger_error(
+            'setRemoveHostFromUrl() is deprecated as of 1.2 and will be removed in 2.0. Pass the base url in the constructor instead.',
+            E_USER_DEPRECATED
+        );
+        $this->removeHostFromUrl = (bool) $remove;
+    }
+
+    /**
+     * Tells driver to remove script name from URL.
+     *
+     * @param Boolean $remove
+     *
+     * @deprecated Deprecated as of 1.2, to be removed in 2.0. Pass the base url in the constructor instead.
+     */
+    public function setRemoveScriptFromUrl($remove = true)
+    {
+        trigger_error(
+            'setRemoveScriptFromUrl() is deprecated as of 1.2 and will be removed in 2.0. Pass the base url in the constructor instead.',
+            E_USER_DEPRECATED
+        );
+        $this->removeScriptFromUrl = (bool) $remove;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function start()
+    {
+        $this->started = true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isStarted()
+    {
+        return $this->started;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function stop()
+    {
+        $this->reset();
+        $this->started = false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function reset()
+    {
+        // Restarting the client resets the cookies and the history
+        $this->client->restart();
+        $this->forms = array();
+        $this->serverParameters = array();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function visit($url)
+    {
+        $this->client->request('GET', $this->prepareUrl($url), array(), array(), $this->serverParameters);
+        $this->forms = array();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getCurrentUrl()
+    {
+        if (method_exists($this->client, 'getInternalRequest')) {
+            $request = $this->client->getInternalRequest();
+        } else {
+            // BC layer for BrowserKit 2.2.x and older
+            $request = $this->client->getRequest();
+
+            if (null !== $request && !$request instanceof Request && !$request instanceof HttpFoundationRequest) {
+                throw new DriverException(sprintf(
+                    'The BrowserKit client returned an unsupported request implementation: %s. Please upgrade your BrowserKit package to 2.3 or newer.',
+                    get_class($request)
+                ));
+            }
+        }
+
+        if ($request === null) {
+            throw new DriverException('Unable to access the request before visiting a page');
+        }
+
+        return $request->getUri();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function reload()
+    {
+        $this->client->reload();
+        $this->forms = array();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function forward()
+    {
+        $this->client->forward();
+        $this->forms = array();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function back()
+    {
+        $this->client->back();
+        $this->forms = array();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setBasicAuth($user, $password)
+    {
+        if (false === $user) {
+            unset($this->serverParameters['PHP_AUTH_USER'], $this->serverParameters['PHP_AUTH_PW']);
+
+            return;
+        }
+
+        $this->serverParameters['PHP_AUTH_USER'] = $user;
+        $this->serverParameters['PHP_AUTH_PW'] = $password;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setRequestHeader($name, $value)
+    {
+        $contentHeaders = array('CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true);
+        $name = str_replace('-', '_', strtoupper($name));
+
+        // CONTENT_* are not prefixed with HTTP_ in PHP when building $_SERVER
+        if (!isset($contentHeaders[$name])) {
+            $name = 'HTTP_' . $name;
+        }
+
+        $this->serverParameters[$name] = $value;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getResponseHeaders()
+    {
+        return $this->getResponse()->getHeaders();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setCookie($name, $value = null)
+    {
+        if (null === $value) {
+            $this->deleteCookie($name);
+
+            return;
+        }
+
+        $jar = $this->client->getCookieJar();
+        $jar->set(new Cookie($name, $value));
+    }
+
+    /**
+     * Deletes a cookie by name.
+     *
+     * @param string $name Cookie name.
+     */
+    private function deleteCookie($name)
+    {
+        $path = $this->getCookiePath();
+        $jar = $this->client->getCookieJar();
+
+        do {
+            if (null !== $jar->get($name, $path)) {
+                $jar->expire($name, $path);
+            }
+
+            $path = preg_replace('/.$/', '', $path);
+        } while ($path);
+    }
+
+    /**
+     * Returns current cookie path.
+     *
+     * @return string
+     */
+    private function getCookiePath()
+    {
+        $path = dirname(parse_url($this->getCurrentUrl(), PHP_URL_PATH));
+
+        if ('\\' === DIRECTORY_SEPARATOR) {
+            $path = str_replace('\\', '/', $path);
+        }
+
+        return $path;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getCookie($name)
+    {
+        // Note that the following doesn't work well because
+        // Symfony\Component\BrowserKit\CookieJar stores cookies by name,
+        // path, AND domain and if you don't fill them all in correctly then
+        // you won't get the value that you're expecting.
+        //
+        // $jar = $this->client->getCookieJar();
+        //
+        // if (null !== $cookie = $jar->get($name)) {
+        //     return $cookie->getValue();
+        // }
+
+        $allValues = $this->client->getCookieJar()->allValues($this->getCurrentUrl());
+
+        if (isset($allValues[$name])) {
+            return $allValues[$name];
+        }
+
+        return null;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getStatusCode()
+    {
+        return $this->getResponse()->getStatus();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getContent()
+    {
+        return $this->getResponse()->getContent();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function find($xpath)
+    {
+        $nodes = $this->getCrawler()->filterXPath($xpath);
+
+        $elements = array();
+        foreach ($nodes as $i => $node) {
+            $elements[] = new NodeElement(sprintf('(%s)[%d]', $xpath, $i + 1), $this->session);
+        }
+
+        return $elements;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTagName($xpath)
+    {
+        return $this->getCrawlerNode($this->getFilteredCrawler($xpath))->nodeName;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getText($xpath)
+    {
+        $text = $this->getFilteredCrawler($xpath)->text();
+        $text = str_replace("\n", ' ', $text);
+        $text = preg_replace('/ {2,}/', ' ', $text);
+
+        return trim($text);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getHtml($xpath)
+    {
+        // cut the tag itself (making innerHTML out of outerHTML)
+        return preg_replace('/^\<[^\>]+\>|\<[^\>]+\>$/', '', $this->getOuterHtml($xpath));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getOuterHtml($xpath)
+    {
+        $node = $this->getCrawlerNode($this->getFilteredCrawler($xpath));
+
+        return $node->ownerDocument->saveXML($node);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getAttribute($xpath, $name)
+    {
+        $node = $this->getFilteredCrawler($xpath);
+
+        if ($this->getCrawlerNode($node)->hasAttribute($name)) {
+            return $node->attr($name);
+        }
+
+        return null;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getValue($xpath)
+    {
+        if (in_array($this->getAttribute($xpath, 'type'), array('submit', 'image', 'button'))) {
+            return $this->getAttribute($xpath, 'value');
+        }
+
+        $node = $this->getCrawlerNode($this->getFilteredCrawler($xpath));
+
+        if ('option' === $node->tagName) {
+            return $this->getOptionValue($node);
+        }
+
+        try {
+            $field = $this->getFormField($xpath);
+        } catch (\InvalidArgumentException $e) {
+            return $this->getAttribute($xpath, 'value');
+        }
+
+        return $field->getValue();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setValue($xpath, $value)
+    {
+        $this->getFormField($xpath)->setValue($value);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function check($xpath)
+    {
+        $this->getCheckboxField($xpath)->tick();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function uncheck($xpath)
+    {
+        $this->getCheckboxField($xpath)->untick();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function selectOption($xpath, $value, $multiple = false)
+    {
+        $field = $this->getFormField($xpath);
+
+        if (!$field instanceof ChoiceFormField) {
+            throw new DriverException(sprintf('Impossible to select an option on the element with XPath "%s" as it is not a select or radio input', $xpath));
+        }
+
+        if ($multiple) {
+            $oldValue   = (array) $field->getValue();
+            $oldValue[] = $value;
+            $value      = $oldValue;
+        }
+
+        $field->select($value);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isSelected($xpath)
+    {
+        $optionValue = $this->getOptionValue($this->getCrawlerNode($this->getFilteredCrawler($xpath)));
+        $selectField = $this->getFormField('(' . $xpath . ')/ancestor-or-self::*[local-name()="select"]');
+        $selectValue = $selectField->getValue();
+
+        return is_array($selectValue) ? in_array($optionValue, $selectValue) : $optionValue == $selectValue;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function click($xpath)
+    {
+        $node = $this->getFilteredCrawler($xpath);
+        $crawlerNode = $this->getCrawlerNode($node);
+        $tagName = $crawlerNode->nodeName;
+
+        if ('a' === $tagName) {
+            $this->client->click($node->link());
+            $this->forms = array();
+        } elseif ($this->canSubmitForm($crawlerNode)) {
+            $this->submit($node->form());
+        } elseif ($this->canResetForm($crawlerNode)) {
+            $this->resetForm($crawlerNode);
+        } else {
+            $message = sprintf('%%s supports clicking on links and buttons only. But "%s" provided', $tagName);
+
+            throw new UnsupportedDriverActionException($message, $this);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isChecked($xpath)
+    {
+        $field = $this->getFormField($xpath);
+
+        if (!$field instanceof ChoiceFormField || 'select' === $field->getType()) {
+            throw new DriverException(sprintf('Impossible to get the checked state of the element with XPath "%s" as it is not a checkbox or radio input', $xpath));
+        }
+
+        if ('checkbox' === $field->getType()) {
+            return $field->hasValue();
+        }
+
+        $radio = $this->getCrawlerNode($this->getFilteredCrawler($xpath));
+
+        return $radio->getAttribute('value') === $field->getValue();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function attachFile($xpath, $path)
+    {
+        $field = $this->getFormField($xpath);
+
+        if (!$field instanceof FileFormField) {
+            throw new DriverException(sprintf('Impossible to attach a file on the element with XPath "%s" as it is not a file input', $xpath));
+        }
+
+        $field->upload($path);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function submitForm($xpath)
+    {
+        $crawler = $this->getFilteredCrawler($xpath);
+
+        $this->submit($crawler->form());
+    }
+
+    /**
+     * @return Response
+     *
+     * @throws DriverException If there is not response yet
+     */
+    protected function getResponse()
+    {
+        if (!method_exists($this->client, 'getInternalResponse')) {
+            $implementationResponse = $this->client->getResponse();
+
+            if (null === $implementationResponse) {
+                throw new DriverException('Unable to access the response before visiting a page');
+            }
+
+            return $this->convertImplementationResponse($implementationResponse);
+        }
+
+        $response = $this->client->getInternalResponse();
+
+        if (null === $response) {
+            throw new DriverException('Unable to access the response before visiting a page');
+        }
+
+        return $response;
+    }
+
+    /**
+     * Gets the BrowserKit Response for legacy BrowserKit versions.
+     *
+     * Before 2.3.0, there was no Client::getInternalResponse method, and the
+     * return value of Client::getResponse can be anything when the implementation
+     * uses Client::filterResponse because of a bad choice done in BrowserKit and
+     * kept for BC reasons (the Client::getInternalResponse method has been added
+     * to solve it).
+     *
+     * This implementation supports client which don't rely Client::filterResponse
+     * and clients which use an HttpFoundation Response (like the HttpKernel client).
+     *
+     * @param object $response the response specific to the BrowserKit implementation
+     *
+     * @return Response
+     *
+     * @throws DriverException If the response cannot be converted to a BrowserKit response
+     */
+    private function convertImplementationResponse($response)
+    {
+        if ($response instanceof Response) {
+            return $response;
+        }
+
+        // due to a bug, the HttpKernel client implementation returns the HttpFoundation response
+        // The conversion logic is copied from Symfony\Component\HttpKernel\Client::filterResponse
+        if ($response instanceof HttpFoundationResponse) {
+            $headers = $response->headers->all();
+            if ($response->headers->getCookies()) {
+                $cookies = array();
+                foreach ($response->headers->getCookies() as $cookie) {
+                    $cookies[] = new Cookie(
+                        $cookie->getName(),
+                        $cookie->getValue(),
+                        $cookie->getExpiresTime(),
+                        $cookie->getPath(),
+                        $cookie->getDomain(),
+                        $cookie->isSecure(),
+                        $cookie->isHttpOnly()
+                    );
+                }
+                $headers['Set-Cookie'] = $cookies;
+            }
+
+            // this is needed to support StreamedResponse
+            ob_start();
+            $response->sendContent();
+            $content = ob_get_clean();
+
+            return new Response($content, $response->getStatusCode(), $headers);
+        }
+
+        throw new DriverException(sprintf(
+            'The BrowserKit client returned an unsupported response implementation: %s. Please upgrade your BrowserKit package to 2.3 or newer.',
+            get_class($response)
+        ));
+    }
+
+    /**
+     * Prepares URL for visiting.
+     * Removes "*.php/" from urls and then passes it to BrowserKitDriver::visit().
+     *
+     * @param string $url
+     *
+     * @return string
+     */
+    protected function prepareUrl($url)
+    {
+        $replacement = ($this->removeHostFromUrl ? '' : '$1') . ($this->removeScriptFromUrl ? '' : '$2');
+
+        return preg_replace('#(https?\://[^/]+)(/[^/\.]+\.php)?#', $replacement, $url);
+    }
+
+    /**
+     * Returns form field from XPath query.
+     *
+     * @param string $xpath
+     *
+     * @return FormField
+     *
+     * @throws DriverException
+     */
+    protected function getFormField($xpath)
+    {
+        $fieldNode = $this->getCrawlerNode($this->getFilteredCrawler($xpath));
+        $fieldName = str_replace('[]', '', $fieldNode->getAttribute('name'));
+
+        $formNode = $this->getFormNode($fieldNode);
+        $formId = $this->getFormNodeId($formNode);
+
+        if (!isset($this->forms[$formId])) {
+            $this->forms[$formId] = new Form($formNode, $this->getCurrentUrl());
+        }
+
+        if (is_array($this->forms[$formId][$fieldName])) {
+            return $this->forms[$formId][$fieldName][$this->getFieldPosition($fieldNode)];
+        }
+
+        return $this->forms[$formId][$fieldName];
+    }
+
+    /**
+     * Returns the checkbox field from xpath query, ensuring it is valid.
+     *
+     * @param string $xpath
+     *
+     * @return ChoiceFormField
+     *
+     * @throws DriverException when the field is not a checkbox
+     */
+    private function getCheckboxField($xpath)
+    {
+        $field = $this->getFormField($xpath);
+
+        if (!$field instanceof ChoiceFormField) {
+            throw new DriverException(sprintf('Impossible to check the element with XPath "%s" as it is not a checkbox', $xpath));
+        }
+
+        return $field;
+    }
+
+    /**
+     * @param \DOMElement $element
+     *
+     * @return \DOMElement
+     *
+     * @throws DriverException if the form node cannot be found
+     */
+    private function getFormNode(\DOMElement $element)
+    {
+        if ($element->hasAttribute('form')) {
+            $formId = $element->getAttribute('form');
+            $formNode = $element->ownerDocument->getElementById($formId);
+
+            if (null === $formNode || 'form' !== $formNode->nodeName) {
+                throw new DriverException(sprintf('The selected node has an invalid form attribute (%s).', $formId));
+            }
+
+            return $formNode;
+        }
+
+        $formNode = $element;
+
+        do {
+            // use the ancestor form element
+            if (null === $formNode = $formNode->parentNode) {
+                throw new DriverException('The selected node does not have a form ancestor.');
+            }
+        } while ('form' !== $formNode->nodeName);
+
+        return $formNode;
+    }
+
+    /**
+     * Gets the position of the field node among elements with the same name
+     *
+     * BrowserKit uses the field name as index to find the field in its Form object.
+     * When multiple fields have the same name (checkboxes for instance), it will return
+     * an array of elements in the order they appear in the DOM.
+     *
+     * @param \DOMElement $fieldNode
+     *
+     * @return integer
+     */
+    private function getFieldPosition(\DOMElement $fieldNode)
+    {
+        $elements = $this->getCrawler()->filterXPath('//*[@name=\''.$fieldNode->getAttribute('name').'\']');
+
+        if (count($elements) > 1) {
+            // more than one element contains this name !
+            // so we need to find the position of $fieldNode
+            foreach ($elements as $key => $element) {
+                /** @var \DOMElement $element */
+                if ($element->getNodePath() === $fieldNode->getNodePath()) {
+                    return $key;
+                }
+            }
+        }
+
+        return 0;
+    }
+
+    private function submit(Form $form)
+    {
+        $formId = $this->getFormNodeId($form->getFormNode());
+
+        if (isset($this->forms[$formId])) {
+            $this->mergeForms($form, $this->forms[$formId]);
+        }
+
+        // remove empty file fields from request
+        foreach ($form->getFiles() as $name => $field) {
+            if (empty($field['name']) && empty($field['tmp_name'])) {
+                $form->remove($name);
+            }
+        }
+
+        foreach ($form->all() as $field) {
+            // Add a fix for https://github.com/symfony/symfony/pull/10733 to support Symfony versions which are not fixed
+            if ($field instanceof TextareaFormField && null === $field->getValue()) {
+                $field->setValue('');
+            }
+        }
+
+        $this->client->submit($form);
+
+        $this->forms = array();
+    }
+
+    private function resetForm(\DOMElement $fieldNode)
+    {
+        $formNode = $this->getFormNode($fieldNode);
+        $formId = $this->getFormNodeId($formNode);
+        unset($this->forms[$formId]);
+    }
+
+    /**
+     * Determines if a node can submit a form.
+     *
+     * @param \DOMElement $node Node.
+     *
+     * @return boolean
+     */
+    private function canSubmitForm(\DOMElement $node)
+    {
+        $type = $node->hasAttribute('type') ? $node->getAttribute('type') : null;
+
+        if ('input' == $node->nodeName && in_array($type, array('submit', 'image'))) {
+            return true;
+        }
+
+        return 'button' == $node->nodeName && (null === $type || 'submit' == $type);
+    }
+
+    /**
+     * Determines if a node can reset a form.
+     *
+     * @param \DOMElement $node Node.
+     *
+     * @return boolean
+     */
+    private function canResetForm(\DOMElement $node)
+    {
+        $type = $node->hasAttribute('type') ? $node->getAttribute('type') : null;
+
+        return in_array($node->nodeName, array('input', 'button')) && 'reset' == $type;
+    }
+
+    /**
+     * Returns form node unique identifier.
+     *
+     * @param \DOMElement $form
+     *
+     * @return string
+     */
+    private function getFormNodeId(\DOMElement $form)
+    {
+        return md5($form->getLineNo() . $form->getNodePath() . $form->nodeValue);
+    }
+
+    /**
+     * Gets the value of an option element
+     *
+     * @param \DOMElement $option
+     *
+     * @return string
+     *
+     * @see \Symfony\Component\DomCrawler\Field\ChoiceFormField::buildOptionValue
+     */
+    private function getOptionValue(\DOMElement $option)
+    {
+        if ($option->hasAttribute('value')) {
+            return $option->getAttribute('value');
+        }
+
+        if (!empty($option->nodeValue)) {
+            return $option->nodeValue;
+        }
+
+        return '1'; // DomCrawler uses 1 by default if there is no text in the option
+    }
+
+    /**
+     * Merges second form values into first one.
+     *
+     * @param Form $to   merging target
+     * @param Form $from merging source
+     */
+    private function mergeForms(Form $to, Form $from)
+    {
+        foreach ($from->all() as $name => $field) {
+            $fieldReflection = new \ReflectionObject($field);
+            $nodeReflection  = $fieldReflection->getProperty('node');
+            $valueReflection = $fieldReflection->getProperty('value');
+
+            $nodeReflection->setAccessible(true);
+            $valueReflection->setAccessible(true);
+
+            if (!($field instanceof InputFormField && in_array(
+                $nodeReflection->getValue($field)->getAttribute('type'),
+                array('submit', 'button', 'image')
+            ))) {
+                $valueReflection->setValue($to[$name], $valueReflection->getValue($field));
+            }
+        }
+    }
+
+    /**
+     * Returns DOMElement from crawler instance.
+     *
+     * @param Crawler $crawler
+     *
+     * @return \DOMElement
+     *
+     * @throws DriverException when the node does not exist
+     */
+    private function getCrawlerNode(Crawler $crawler)
+    {
+        $crawler->rewind();
+        $node = $crawler->current();
+
+        if (null !== $node) {
+            return $node;
+        }
+
+        throw new DriverException('The element does not exist');
+    }
+
+    /**
+     * Returns a crawler filtered for the given XPath, requiring at least 1 result.
+     *
+     * @param string $xpath
+     *
+     * @return Crawler
+     *
+     * @throws DriverException when no matching elements are found
+     */
+    private function getFilteredCrawler($xpath)
+    {
+        if (!count($crawler = $this->getCrawler()->filterXPath($xpath))) {
+            throw new DriverException(sprintf('There is no element matching XPath "%s"', $xpath));
+        }
+
+        return $crawler;
+    }
+
+    /**
+     * Returns crawler instance (got from client).
+     *
+     * @return Crawler
+     *
+     * @throws DriverException
+     */
+    private function getCrawler()
+    {
+        $crawler = $this->client->getCrawler();
+
+        if (null === $crawler) {
+            throw new DriverException('Unable to access the response content before visiting a page');
+        }
+
+        return $crawler;
+    }
+}
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/BrowserKitConfig.php b/core/vendor/behat/mink-browserkit-driver/tests/BrowserKitConfig.php
new file mode 100644
index 0000000..b80a2fb
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/BrowserKitConfig.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver;
+
+use Behat\Mink\Driver\BrowserKitDriver;
+use Symfony\Component\HttpKernel\Client;
+
+class BrowserKitConfig extends AbstractConfig
+{
+    public static function getInstance()
+    {
+        return new self();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function createDriver()
+    {
+        $client = new Client(require(__DIR__.'/app.php'));
+
+        return new BrowserKitDriver($client);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getWebFixturesUrl()
+    {
+        return 'http://localhost';
+    }
+
+    protected function supportsJs()
+    {
+        return false;
+    }
+}
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/Custom/BaseUrlTest.php b/core/vendor/behat/mink-browserkit-driver/tests/Custom/BaseUrlTest.php
new file mode 100644
index 0000000..779426e
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/Custom/BaseUrlTest.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Custom;
+
+use Behat\Mink\Driver\BrowserKitDriver;
+use Behat\Mink\Session;
+use Symfony\Component\HttpKernel\Client;
+
+/**
+ * @group functional
+ */
+class BaseUrlTest extends \PHPUnit_Framework_TestCase
+{
+    public function testBaseUrl()
+    {
+        $client = new Client(require(__DIR__.'/../app.php'));
+        $driver = new BrowserKitDriver($client, 'http://localhost/foo/');
+        $session = new Session($driver);
+
+        $session->visit('http://localhost/foo/index.html');
+        $this->assertEquals(200, $session->getStatusCode());
+        $this->assertEquals('http://localhost/foo/index.html', $session->getCurrentUrl());
+    }
+}
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/Custom/ErrorHandlingTest.php b/core/vendor/behat/mink-browserkit-driver/tests/Custom/ErrorHandlingTest.php
new file mode 100644
index 0000000..32335c5
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/Custom/ErrorHandlingTest.php
@@ -0,0 +1,181 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Custom;
+
+use Behat\Mink\Driver\BrowserKitDriver;
+use Symfony\Component\BrowserKit\Client;
+use Symfony\Component\BrowserKit\Response;
+
+class ErrorHandlingTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var TestClient
+     */
+    private $client;
+
+    protected function setUp()
+    {
+        $this->client = new TestClient();
+    }
+
+    public function testGetClient()
+    {
+        $this->assertSame($this->client, $this->getDriver()->getClient());
+    }
+
+    /**
+     * @expectedException \Behat\Mink\Exception\DriverException
+     * @expectedExceptionMessage Unable to access the response before visiting a page
+     */
+    public function testGetResponseHeaderWithoutVisit()
+    {
+        $this->getDriver()->getResponseHeaders();
+    }
+
+    /**
+     * @expectedException \Behat\Mink\Exception\DriverException
+     * @expectedExceptionMessage Unable to access the response content before visiting a page
+     */
+    public function testFindWithoutVisit()
+    {
+        $this->getDriver()->find('//html');
+    }
+
+    /**
+     * @expectedException \Behat\Mink\Exception\DriverException
+     * @expectedExceptionMessage Unable to access the request before visiting a page
+     */
+    public function testGetCurrentUrlWithoutVisit()
+    {
+        $this->getDriver()->getCurrentUrl();
+    }
+
+    /**
+     * @expectedException \Behat\Mink\Exception\DriverException
+     * @expectedExceptionMessage The selected node has an invalid form attribute (foo)
+     */
+    public function testNotMatchingHtml5FormId()
+    {
+        $html = <<<'HTML'
+<html>
+<body>
+    <form id="test">
+        <input name="test" value="foo" form="foo">
+        <input type="submit">
+    </form>
+</body>
+</html>
+HTML;
+
+        $this->client->setNextResponse(new Response($html));
+
+        $driver = $this->getDriver();
+        $driver->visit('/index.php');
+        $driver->setValue('//input[./@name="test"]', 'bar');
+    }
+
+    /**
+     * @expectedException \Behat\Mink\Exception\DriverException
+     * @expectedExceptionMessage The selected node has an invalid form attribute (foo)
+     */
+    public function testInvalidHtml5FormId()
+    {
+        $html = <<<'HTML'
+<html>
+<body>
+    <form id="test">
+        <input name="test" value="foo" form="foo">
+        <input type="submit">
+    </form>
+    <div id="foo"></div>
+</body>
+</html>
+HTML;
+
+        $this->client->setNextResponse(new Response($html));
+
+        $driver = $this->getDriver();
+        $driver->visit('/index.php');
+        $driver->setValue('//input[./@name="test"]', 'bar');
+    }
+
+    /**
+     * @expectedException \Behat\Mink\Exception\DriverException
+     * @expectedExceptionMessage The selected node does not have a form ancestor.
+     */
+    public function testManipulateInputWithoutForm()
+    {
+        $html = <<<'HTML'
+<html>
+<body>
+    <form id="test">
+        <input type="submit">
+    </form>
+    <div id="foo">
+        <input name="test" value="foo">
+    </div>
+</body>
+</html>
+HTML;
+
+        $this->client->setNextResponse(new Response($html));
+
+        $driver = $this->getDriver();
+        $driver->visit('/index.php');
+        $driver->setValue('//input[./@name="test"]', 'bar');
+    }
+
+    /**
+     * @expectedException \Behat\Mink\Exception\DriverException
+     * @expectedExceptionMessage Behat\Mink\Driver\BrowserKitDriver supports clicking on links and buttons only. But "div" provided
+     */
+    public function testClickOnUnsupportedElement()
+    {
+        $html = <<<'HTML'
+<html>
+<body>
+    <div></div>
+</body>
+</html>
+HTML;
+
+        $this->client->setNextResponse(new Response($html));
+
+        $driver = $this->getDriver();
+        $driver->visit('/index.php');
+        $driver->click('//div');
+    }
+
+    private function getDriver()
+    {
+        return new BrowserKitDriver($this->client);
+    }
+}
+
+class TestClient extends Client
+{
+    protected $nextResponse = null;
+    protected $nextScript = null;
+
+    public function setNextResponse(Response $response)
+    {
+        $this->nextResponse = $response;
+    }
+
+    public function setNextScript($script)
+    {
+        $this->nextScript = $script;
+    }
+
+    protected function doRequest($request)
+    {
+        if (null === $this->nextResponse) {
+            return new Response();
+        }
+
+        $response = $this->nextResponse;
+        $this->nextResponse = null;
+
+        return $response;
+    }
+}
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/app.php b/core/vendor/behat/mink-browserkit-driver/tests/app.php
new file mode 100644
index 0000000..d3f1236
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/app.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace app;
+
+$app = new \Silex\Application();
+$app->register(new \Silex\Provider\SessionServiceProvider());
+
+$def = realpath(__DIR__.'/../vendor/behat/mink/driver-testsuite/web-fixtures');
+$ovr = realpath(__DIR__.'/web-fixtures');
+$cbk = function ($file) use ($app, $def, $ovr) {
+    $file = str_replace('.file', '.php', $file);
+    $path = file_exists($ovr.'/'.$file) ? $ovr.'/'.$file : $def.'/'.$file;
+    $resp = null;
+
+    ob_start();
+    include($path);
+    $content = ob_get_clean();
+
+    if ($resp) {
+        if ('' === $resp->getContent()) {
+            $resp->setContent($content);
+        }
+
+        return $resp;
+    }
+
+    return $content;
+};
+
+$app->get('/{file}', $cbk)->assert('file', '.*');
+$app->post('/{file}', $cbk)->assert('file', '.*');
+
+$app['debug'] = true;
+$app['exception_handler']->disable();
+$app['session.test'] = true;
+
+return $app;
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/404.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/404.php
new file mode 100644
index 0000000..2ae1ff9
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/404.php
@@ -0,0 +1,3 @@
+<?php
+
+$resp = new Symfony\Component\HttpFoundation\Response('Sorry, page not found', 404);
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/500.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/500.php
new file mode 100644
index 0000000..8f1ebb3
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/500.php
@@ -0,0 +1,3 @@
+<?php
+
+$resp = new Symfony\Component\HttpFoundation\Response('Sorry, a server error happened', 500);
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/advanced_form_post.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/advanced_form_post.php
new file mode 100644
index 0000000..71d1c8d
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/advanced_form_post.php
@@ -0,0 +1,32 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>Advanced form save</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+</head>
+<body>
+<?php
+error_reporting(0);
+
+$request = $app['request'];
+$POST = $request->request->all();
+$FILES = $request->files->all();
+
+if (isset($POST['select_multiple_numbers']) && false !== strpos($POST['select_multiple_numbers'][0], ',')) {
+    $POST['select_multiple_numbers'] = explode(',', $POST['select_multiple_numbers'][0]);
+}
+
+// checkbox can have any value and will be successful in case "on"
+// http://www.w3.org/TR/html401/interact/forms.html#checkbox
+$POST['agreement'] = isset($POST['agreement']) ? 'on' : 'off';
+ksort($POST);
+echo str_replace('>', '', var_export($POST, true)) . "\n";
+if (isset($FILES['about']) && file_exists($FILES['about']->getPathname())) {
+    echo $FILES['about']->getClientOriginalName() . "\n";
+    echo file_get_contents($FILES['about']->getPathname());
+} else {
+    echo "no file";
+}
+?>
+</body>
+</html>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/basic_auth.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/basic_auth.php
new file mode 100644
index 0000000..48132b6
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/basic_auth.php
@@ -0,0 +1,15 @@
+<?php
+$SERVER = $app['request']->server->all();
+
+$username = isset($SERVER['PHP_AUTH_USER']) ? $SERVER['PHP_AUTH_USER'] : false;
+$password = isset($SERVER['PHP_AUTH_PW']) ? $SERVER['PHP_AUTH_PW'] : false;
+
+if ($username == 'mink-user' && $password == 'mink-password') {
+    echo 'is authenticated';
+} else {
+    $resp = new \Symfony\Component\HttpFoundation\Response();
+    $resp->setStatusCode(401);
+    $resp->headers->set('WWW-Authenticate', 'Basic realm="Mink Testing Area"');
+
+    echo 'is not authenticated';
+}
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/basic_form_post.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/basic_form_post.php
new file mode 100644
index 0000000..1efe45e
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/basic_form_post.php
@@ -0,0 +1,14 @@
+<?php  ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>Basic Form Saving</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <h1>Anket for <?php echo $app['request']->request->get('first_name') ?></h1>
+
+    <span id="first">Firstname: <?php echo $app['request']->request->get('first_name') ?></span>
+    <span id="last">Lastname: <?php echo $app['request']->request->get('last_name') ?></span>
+</body>
+</html>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/basic_get_form.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/basic_get_form.php
new file mode 100644
index 0000000..fd2817d
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/basic_get_form.php
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>Basic Get Form</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <h1>Basic Get Form Page</h1>
+
+    <div id="serach">
+        <?php
+        $GET = $app['request']->query->all();
+        echo isset($GET['q']) && $GET['q'] ? $GET['q'] : 'No search query'
+        ?>
+    </div>
+
+    <form>
+        <input name="q" value="" type="text" />
+
+        <input type="submit" value="Find" />
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/cookie_page1.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/cookie_page1.php
new file mode 100644
index 0000000..a928b2f
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/cookie_page1.php
@@ -0,0 +1,17 @@
+<?php
+    $resp = new Symfony\Component\HttpFoundation\Response();
+    $cook = new Symfony\Component\HttpFoundation\Cookie('srvr_cookie', 'srv_var_is_set', 0, '/');
+    $resp->headers->setCookie($cook);
+?>
+<!doctype html public "-//w3c//dtd xhtml 1.1//en" "http://www.w3.org/tr/xhtml11/dtd/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>basic form</title>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
+    <script>
+    </script>
+</head>
+<body>
+    basic page with cookie set from server side
+</body>
+</html>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/cookie_page2.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/cookie_page2.php
new file mode 100644
index 0000000..ab54243
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/cookie_page2.php
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>Basic Form</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+    <script>
+    </script>
+</head>
+<body>
+    Previous cookie: <?php
+        echo $app['request']->cookies->has('srvr_cookie') ? $app['request']->cookies->get('srvr_cookie') : 'NO';
+    ?>
+</body>
+</html>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/cookie_page3.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/cookie_page3.php
new file mode 100644
index 0000000..f24d587
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/cookie_page3.php
@@ -0,0 +1,20 @@
+<?php
+
+$hasCookie = $app['request']->cookies->has('foo');
+$resp = new Symfony\Component\HttpFoundation\Response();
+$cook = new Symfony\Component\HttpFoundation\Cookie('foo', 'bar');
+$resp->headers->setCookie($cook);
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>HttpOnly Cookie Test</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+    <script>
+    </script>
+</head>
+<body>
+    <div id="cookie-status">Has Cookie: <?php echo json_encode($hasCookie) ?></div>
+</body>
+</html>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/headers.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/headers.php
new file mode 100644
index 0000000..b829425
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/headers.php
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>Headers page</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <?php print_r($app['request']->server->all()); ?>
+</body>
+</html>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/issue130.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/issue130.php
new file mode 100644
index 0000000..2079673
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/issue130.php
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<html>
+<body>
+    <?php
+    if ('1' === $app['request']->query->get('p')) {
+        echo '<a href="/issue130.php?p=2">Go to 2</a>';
+    } else {
+        echo '<strong>'.$app['request']->headers->get('referer').'</strong>';
+    }
+    ?>
+</body>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/issue140.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/issue140.php
new file mode 100644
index 0000000..42d8437
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/issue140.php
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<html>
+<body>
+<?php if ($app['request']->isMethod('POST')) {
+    $resp = new Symfony\Component\HttpFoundation\Response();
+    $cook = new Symfony\Component\HttpFoundation\Cookie('tc', $app['request']->request->get('cookie_value'));
+    $resp->headers->setCookie($cook);
+} elseif ($app['request']->query->has('show_value')) {
+    echo $app['request']->cookies->get('tc');
+    return;
+}
+?>
+    <form method="post">
+        <input name="cookie_value">
+        <input type="submit" value="Set cookie">
+    </form>
+</body>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/print_cookies.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/print_cookies.php
new file mode 100644
index 0000000..ac6f078
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/print_cookies.php
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>Cookies page</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <?php
+    $cookies = $app['request']->cookies->all();
+    unset($cookies['MOCKSESSID']);
+
+    if (isset($cookies['srvr_cookie'])) {
+        $srvrCookie = $cookies['srvr_cookie'];
+        unset($cookies['srvr_cookie']);
+        $cookies['_SESS'] = '';
+        $cookies['srvr_cookie'] = $srvrCookie;
+    }
+
+    foreach ($cookies as $name => $val) {
+        $cookies[$name] = (string)$val;
+    }
+    echo str_replace(array('>'), '', var_export($cookies, true));
+    ?>
+</body>
+</html>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/redirector.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/redirector.php
new file mode 100644
index 0000000..39e8a53
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/redirector.php
@@ -0,0 +1,3 @@
+<?php
+
+$resp = new Symfony\Component\HttpFoundation\RedirectResponse('/redirect_destination.html');
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/response_headers.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/response_headers.php
new file mode 100644
index 0000000..a2f48f8
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/response_headers.php
@@ -0,0 +1,15 @@
+<?php
+    $resp = new Symfony\Component\HttpFoundation\Response();
+    $resp->headers->set('X-Mink-Test', 'response-headers');
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <title>Response headers</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+    <h1>Response headers</h1>
+</body>
+</html>
+
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/session_test.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/session_test.php
new file mode 100644
index 0000000..58576e3
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/session_test.php
@@ -0,0 +1,19 @@
+<?php
+$session = $app['request']->getSession();
+
+if ($app['request']->query->has('login')) {
+    $session->migrate();
+}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>Session Test</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+    <script>
+    </script>
+</head>
+<body>
+    <div id="session-id"><?php echo $session->getId() ?></div>
+</body>
+</html>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/sub-folder/cookie_page1.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/sub-folder/cookie_page1.php
new file mode 100644
index 0000000..807c23e
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/sub-folder/cookie_page1.php
@@ -0,0 +1,18 @@
+<?php
+    $requestUri = $app['request']->server->get('REQUEST_URI');
+    $resp = new Symfony\Component\HttpFoundation\Response();
+    $cook = new Symfony\Component\HttpFoundation\Cookie('srvr_cookie', 'srv_var_is_set_sub_folder', 0, dirname($requestUri));
+    $resp->headers->setCookie($cook);
+?>
+<!doctype html public "-//w3c//dtd xhtml 1.1//en" "http://www.w3.org/tr/xhtml11/dtd/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>basic form</title>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
+    <script>
+    </script>
+</head>
+<body>
+    basic page with cookie set from server side
+</body>
+</html>
diff --git a/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/sub-folder/cookie_page2.php b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/sub-folder/cookie_page2.php
new file mode 100644
index 0000000..22a7dab
--- /dev/null
+++ b/core/vendor/behat/mink-browserkit-driver/tests/web-fixtures/sub-folder/cookie_page2.php
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
+<head>
+    <title>Basic Form</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+    <script>
+    </script>
+</head>
+<body>
+    Previous cookie: <?php
+    if ($app['request']->cookies->has('srvr_cookie')) {
+        echo $app['request']->cookies->get('srvr_cookie');
+    } else {
+        echo 'NO';
+    }
+    ?>
+</body>
+</html>
diff --git a/core/vendor/behat/mink-goutte-driver/.gitignore b/core/vendor/behat/mink-goutte-driver/.gitignore
new file mode 100644
index 0000000..1d034f4
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/.gitignore
@@ -0,0 +1,4 @@
+vendor
+composer.phar
+composer.lock
+phpunit.xml
diff --git a/core/vendor/behat/mink-goutte-driver/.travis.yml b/core/vendor/behat/mink-goutte-driver/.travis.yml
new file mode 100644
index 0000000..b09e457
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/.travis.yml
@@ -0,0 +1,19 @@
+language: php
+
+php: [5.3, 5.4, 5.5, 5.6, hhvm]
+
+before_script:
+  - export WEB_FIXTURES_HOST=http://localhost
+
+  - composer install --dev --prefer-source
+
+  - sudo apt-get update
+  - sudo apt-get install -y --force-yes apache2 libapache2-mod-php5
+  - sudo sed -i -e "s,/var/www,$(pwd)/vendor/behat/mink/driver-testsuite/web-fixtures,g" /etc/apache2/sites-available/default
+  - sudo /etc/init.d/apache2 restart
+
+script: phpunit -v --coverage-clover=coverage.clover
+
+after_script:
+  - wget https://scrutinizer-ci.com/ocular.phar
+  - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
diff --git a/core/vendor/behat/mink-goutte-driver/CHANGELOG.md b/core/vendor/behat/mink-goutte-driver/CHANGELOG.md
new file mode 100644
index 0000000..fcaa7f0
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/CHANGELOG.md
@@ -0,0 +1,20 @@
+1.1.0 / 2014-10-09
+==================
+
+The driver now relies on BrowserKitDriver 1.2.x, so all changes of this driver are relevant.
+The changes below only describe the changes related to GoutteDriver specifically.
+
+New features:
+
+* Added the possibility to use a normal Goutte client instead of requiring to use an extended one
+* Added the support of Goutte 2.0 as well
+
+Bug fixes:
+
+* Fixed the support of disabling basic auth
+* Fixed the resetting of the driver to reset the basic auth
+
+Testing:
+
+* Updated the testsuite to use the new Mink 1.6 driver testsuite
+* Added testing on HHVM
diff --git a/core/vendor/behat/mink-goutte-driver/LICENSE b/core/vendor/behat/mink-goutte-driver/LICENSE
new file mode 100644
index 0000000..3365ae6
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2012-2013 Konstantin Kudryashov <ever.zet@gmail.com>
+
+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:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+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.
diff --git a/core/vendor/behat/mink-goutte-driver/README.md b/core/vendor/behat/mink-goutte-driver/README.md
new file mode 100644
index 0000000..c7877c5
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/README.md
@@ -0,0 +1,53 @@
+Mink Goutte Driver
+==================
+
+[![Latest Stable Version](https://poser.pugx.org/behat/mink-goutte-driver/v/stable.svg)](https://packagist.org/packages/behat/mink-goutte-driver)
+[![Latest Unstable Version](https://poser.pugx.org/behat/mink-goutte-driver/v/unstable.svg)](https://packagist.org/packages/behat/mink-goutte-driver)
+[![Total Downloads](https://poser.pugx.org/behat/mink-goutte-driver/downloads.svg)](https://packagist.org/packages/behat/mink-goutte-driver)
+[![Build Status](https://travis-ci.org/Behat/MinkGoutteDriver.svg?branch=master)](https://travis-ci.org/Behat/MinkGoutteDriver)
+[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/Behat/MinkGoutteDriver/badges/quality-score.png?s=ca141bb2cad18e74cf3d3b132b1a6aa0f3f004a5)](https://scrutinizer-ci.com/g/Behat/MinkGoutteDriver/)
+[![Code Coverage](https://scrutinizer-ci.com/g/Behat/MinkGoutteDriver/badges/coverage.png?s=ca2d17a948660bfaeb4a95bf1a709644305c54f3)](https://scrutinizer-ci.com/g/Behat/MinkGoutteDriver/)
+[![License](https://poser.pugx.org/behat/mink-goutte-driver/license.svg)](https://packagist.org/packages/behat/mink-goutte-driver)
+
+Usage Example
+-------------
+
+``` php
+<?php
+
+use Behat\Mink\Mink,
+    Behat\Mink\Session,
+    Behat\Mink\Driver\GoutteDriver,
+    Behat\Mink\Driver\Goutte\Client as GoutteClient;
+
+$startUrl = 'http://example.com';
+
+$mink = new Mink(array(
+    'goutte' => new Session(new GoutteDriver(new GoutteClient($startUrl))),
+));
+
+$mink->getSession('goutte')->getPage()->findLink('Chat')->click();
+```
+
+Installation
+------------
+
+``` json
+{
+    "require": {
+        "behat/mink":               "~1.5",
+        "behat/mink-goutte-driver": "~1.0"
+    }
+}
+```
+
+``` bash
+$> curl -sS https://getcomposer.org/installer | php
+$> php composer.phar install
+```
+
+Maintainers
+-----------
+
+* Konstantin Kudryashov [everzet](http://github.com/everzet)
+* Other [awesome developers](https://github.com/Behat/MinkGoutteDriver/graphs/contributors)
diff --git a/core/vendor/behat/mink-goutte-driver/composer.json b/core/vendor/behat/mink-goutte-driver/composer.json
new file mode 100644
index 0000000..7444a50
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/composer.json
@@ -0,0 +1,41 @@
+{
+    "name":         "behat/mink-goutte-driver",
+    "description":  "Goutte driver for Mink framework",
+    "keywords":     ["goutte", "headless", "testing", "browser"],
+    "homepage":     "http://mink.behat.org/",
+    "type":         "mink-driver",
+    "license":      "MIT",
+
+    "authors": [
+        {
+            "name":      "Konstantin Kudryashov",
+            "email":     "ever.zet@gmail.com",
+            "homepage":  "http://everzet.com"
+        }
+    ],
+
+    "require": {
+        "php":                           ">=5.3.1",
+        "behat/mink":                    "~1.6@dev",
+        "behat/mink-browserkit-driver":  "~1.2@dev",
+        "fabpot/goutte":                 "~1.0.4|~2.0"
+    },
+
+    "autoload": {
+        "psr-0": {
+            "Behat\\Mink\\Driver": "src/"
+        }
+    },
+
+    "autoload-dev": {
+        "psr-4": {
+            "Behat\\Mink\\Tests\\Driver\\": "tests"
+        }
+    },
+
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.1.x-dev"
+        }
+    }
+}
diff --git a/core/vendor/behat/mink-goutte-driver/phpunit.xml.dist b/core/vendor/behat/mink-goutte-driver/phpunit.xml.dist
new file mode 100644
index 0000000..f374c53
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/phpunit.xml.dist
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit colors="true" bootstrap="vendor/behat/mink/driver-testsuite/bootstrap.php">
+    <testsuites>
+        <testsuite name="Driver test suite">
+            <directory>tests</directory>
+            <directory>vendor/behat/mink/driver-testsuite/tests/Basic</directory>
+            <directory>vendor/behat/mink/driver-testsuite/tests/Form</directory>
+        </testsuite>
+    </testsuites>
+
+    <php>
+        <var name="driver_config_factory" value="Behat\Mink\Tests\Driver\GoutteConfig::getInstance" />
+
+        <!--server name="WEB_FIXTURES_HOST" value="http://test.mink.dev" /-->
+    </php>
+
+    <filter>
+        <whitelist>
+            <directory>./src/Behat/Mink/Driver</directory>
+        </whitelist>
+    </filter>
+</phpunit>
diff --git a/core/vendor/behat/mink-goutte-driver/src/Behat/Mink/Driver/Goutte/Client.php b/core/vendor/behat/mink-goutte-driver/src/Behat/Mink/Driver/Goutte/Client.php
new file mode 100644
index 0000000..9d64be7
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/src/Behat/Mink/Driver/Goutte/Client.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Behat\Mink.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Driver\Goutte;
+
+use Goutte\Client as BaseClient;
+use Symfony\Component\BrowserKit\Response;
+
+/**
+ * Client overrides to support Mink functionality.
+ */
+class Client extends BaseClient
+{
+    /**
+     * Reads response meta tags to guess content-type charset.
+     *
+     * @param Response $response
+     *
+     * @return Response
+     */
+    protected function filterResponse($response)
+    {
+        $contentType = $response->getHeader('Content-Type');
+
+        if (!$contentType || false === strpos($contentType, 'charset=')) {
+            if (preg_match('/\<meta[^\>]+charset *= *["\']?([a-zA-Z\-0-9]+)/i', $response->getContent(), $matches)) {
+                $headers = $response->getHeaders();
+                $headers['Content-Type'] = $contentType.';charset='.$matches[1];
+
+                $response = new Response($response->getContent(), $response->getStatus(), $headers);
+            }
+        }
+
+        return parent::filterResponse($response);
+    }
+}
diff --git a/core/vendor/behat/mink-goutte-driver/src/Behat/Mink/Driver/GoutteDriver.php b/core/vendor/behat/mink-goutte-driver/src/Behat/Mink/Driver/GoutteDriver.php
new file mode 100644
index 0000000..a42d5a2
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/src/Behat/Mink/Driver/GoutteDriver.php
@@ -0,0 +1,75 @@
+<?php
+
+/*
+ * This file is part of the Behat\Mink.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Driver;
+
+use Behat\Mink\Driver\Goutte\Client as ExtendedClient;
+use Goutte\Client;
+
+/**
+ * Goutte driver.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class GoutteDriver extends BrowserKitDriver
+{
+    /**
+     * Initializes Goutte driver.
+     *
+     * @param Client $client Goutte client instance
+     */
+    public function __construct(Client $client = null)
+    {
+        parent::__construct($client ?: new ExtendedClient());
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setBasicAuth($user, $password)
+    {
+        if (false === $user) {
+            $this->getClient()->resetAuth();
+
+            return;
+        }
+
+        $this->getClient()->setAuth($user, $password);
+    }
+
+    /**
+     * Gets the Goutte client.
+     *
+     * The method is overwritten only to provide the appropriate return type hint.
+     *
+     * @return Client
+     */
+    public function getClient()
+    {
+        return parent::getClient();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function reset()
+    {
+        parent::reset();
+        $this->getClient()->resetAuth();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function prepareUrl($url)
+    {
+        return $url;
+    }
+}
diff --git a/core/vendor/behat/mink-goutte-driver/tests/Custom/InstantiationTest.php b/core/vendor/behat/mink-goutte-driver/tests/Custom/InstantiationTest.php
new file mode 100644
index 0000000..db75a18
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/tests/Custom/InstantiationTest.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Custom;
+
+use Behat\Mink\Driver\GoutteDriver;
+
+class InstantiationTest extends \PHPUnit_Framework_TestCase
+{
+    public function testInstantiateWithClient()
+    {
+        $client = $this->getMockBuilder('Goutte\Client')->disableOriginalConstructor()->getMock();
+        $client->expects($this->once())
+            ->method('followRedirects')
+            ->with(true);
+
+        $driver = new GoutteDriver($client);
+
+        $this->assertSame($client, $driver->getClient());
+    }
+
+    public function testInstantiateWithoutClient()
+    {
+        $driver = new GoutteDriver();
+
+        $this->assertInstanceOf('Behat\Mink\Driver\Goutte\Client', $driver->getClient());
+    }
+}
diff --git a/core/vendor/behat/mink-goutte-driver/tests/GoutteConfig.php b/core/vendor/behat/mink-goutte-driver/tests/GoutteConfig.php
new file mode 100644
index 0000000..bbe90f7
--- /dev/null
+++ b/core/vendor/behat/mink-goutte-driver/tests/GoutteConfig.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver;
+
+use Behat\Mink\Driver\GoutteDriver;
+
+class GoutteConfig extends AbstractConfig
+{
+    public static function getInstance()
+    {
+        return new self();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function createDriver()
+    {
+        return new GoutteDriver();
+    }
+
+    protected function supportsJs()
+    {
+        return false;
+    }
+}
diff --git a/core/vendor/behat/mink/.gitignore b/core/vendor/behat/mink/.gitignore
new file mode 100644
index 0000000..66de342
--- /dev/null
+++ b/core/vendor/behat/mink/.gitignore
@@ -0,0 +1,5 @@
+*.tgz
+*.phar
+phpunit.xml
+composer.lock
+vendor
diff --git a/core/vendor/behat/mink/.travis.yml b/core/vendor/behat/mink/.travis.yml
new file mode 100644
index 0000000..74ea58c
--- /dev/null
+++ b/core/vendor/behat/mink/.travis.yml
@@ -0,0 +1,12 @@
+language: php
+
+php: [5.3, 5.4, 5.5, 5.6, hhvm]
+
+before_script:
+  - composer install --dev --prefer-source
+
+script: phpunit -v --coverage-clover=coverage.clover
+
+after_script:
+  - wget https://scrutinizer-ci.com/ocular.phar
+  - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
diff --git a/core/vendor/behat/mink/CHANGES.md b/core/vendor/behat/mink/CHANGES.md
new file mode 100644
index 0000000..3404cad
--- /dev/null
+++ b/core/vendor/behat/mink/CHANGES.md
@@ -0,0 +1,238 @@
+1.6.0 / 2014-09-26
+==================
+
+  * [BC break] Changed the named selector to prefer exact matches over partial matches
+  * [BC break] Changed `NodeElement::getValue` for checkboxes to return the value rather than the checked state (use `isChecked` for that)
+  * Fixed the XPath prefixing when searching inside an existing element
+  * Refactored the driver testsuite entirely and expand it to cover drivers entirely (covering many more cases for consistency)
+  * Changed `NodeElement::setValue` to support any fields rather than only input elements
+  * Removed the wrapping of any driver-level exception in a MinkException on invalid usage as it was making the code too complex
+  * Fixed the matching of the input type in the named selector to be case insensitive according to the HTML spec
+  * Introduced `Behat\Mink\Selector\Xpath\Escaper` to allow reusing the XPath escaping
+  * Deprecated `Element::getSession`. Code needing the session should get it from outside rather than the element
+  * Changed ElementNotFoundException to extend from ExpectationException
+  * Added `Element::getOuterHtml` to get the HTML code of the element including itself
+  * Fixed the name selectors to match on the `placeholder` only for textual inputs
+  * Enforced consistent behavior for drivers on 4xx and 5xx response to return the response rather than throwing an exception
+  * Added `Element::waitFor` to allow retrying some code until it succeeds or the timeout is reached
+  * Added `Element::isValid` to check whether an element still exists in the page
+  * Made `Session::executeScript` compatible across drivers by ensuring they all support the same syntaxes for the JS expression
+  * Made `Session::evaluateScript` compatible across drivers by ensuring they all support the same syntaxes for the JS expression
+  * Removed `hasClass` from `DocumentElement` (instead of triggering a fatal error)
+  * Added testing on HHVM to ensure consistency
+  * Fixed `NodeElement::getTagName` to ensure that the tag name is lowercase for all drivers
+  * Fixed `Element::hasAttribute` to ensure it supports attributes with an empty value
+  * Fixed the `field` selector to avoid matching inputs with the type `submit` or `reset`
+  * Changed the button XPath selection to accept `reset` buttons as well
+  * Changed `Session::wait` to return the condition value rather than nothing
+  * Added `Session::getWindowName` and `Session::getWindowNames` to get the name of the current and of all windows
+  * Added `Session::maximizeWindow` to maximize the window
+  * Added `NodeElement::isSelected` to check whether an `<option>` is selected
+  * Added `NodeElement::submitForm` to allow submitting a form without using a button
+  * Added assertions about the value of an attribute
+  * Added the anchor in the assertion on the URL in `WebAssert`
+
+1.5.0 / 2013-04-14
+==================
+
+  * Add `CoreDriver` to simplify future drivers improvements
+  * Add `Mink::isSessionStarted()` method
+  * Fix multibite string `preg_replace` bugs
+  * Fix handling of whitespaces in `WebAssert::pageText...()` methods
+
+1.4.3 / 2013-03-02
+==================
+
+  * Bump dependencies constraints
+
+1.4.2 / 2013-02-13
+==================
+
+  * Fix wrong test case to ensure that core drivers work as expected
+
+1.4.1 / 2013-02-10
+==================
+
+  * Update dependencies
+  * Add ElementException to element actions
+  * Rel attribute support for named selectors
+  * Add hasClass() helper to traversable elements
+  * Add getScreenshot() method to session
+  * Name attr support in named selector for button
+  * Fix for bunch of bugs
+
+1.4.0 / 2012-05-40
+==================
+
+  * New `Session::selectWindow()` and `Session::selectIFrame()` methods
+  * New built-in `WebAssert` class
+  * Fixed DocBlocks (autocompletion in any IDE now should just work)
+  * Moved Behat-related code into `Behat\MinkExtension`
+  * Removed PHPUnit test case class
+  * Updated composer dependencies to not require custom repository anymore
+  * All drivers moved into separate packages
+
+1.3.3 / 2012-03-23
+==================
+
+  * Prevent exceptions in `__toString()`
+  * Added couple of useful step definitions for Behat
+  * Fixed issues #168, #211, #212, #208
+  * Lot of small bug fixes and improvements
+  * Fixed dependencies and composer installation routine
+
+1.3.2 / 2011-12-21
+==================
+
+  * Fixed webdriver registration in MinkContext
+
+1.3.1 / 2011-12-21
+==================
+
+  * Fixed Composer package
+
+1.3.0 / 2011-12-21
+==================
+
+  * Brand new Selenium2Driver (webdriver session)
+  * Multiselect bugfixes
+  * ZombieDriver back in the business
+  * Composer now manages dependencies
+  * Some MinkContext steps got fixes
+  * Lots of bug fixes and cleanup
+
+1.2.0 / 2011-11-04
+==================
+
+  * Brand new SeleniumDriver (thanks @alexandresalome)
+  * Multiselect support (multiple options selection), including new Behat steps
+  * Ability to select option by it's text (in addition to value)
+  * ZombieDriver updates
+  * Use SuiteHooks to populate parameters (no need to call parent __construct anymore)
+  * Updated Goutte and all vendors
+  * Lot of bugfixes and new tests
+
+1.1.1 / 2011-08-12
+==================
+
+  * Fixed Zombie.js server termination on Linux
+  * Fixed base_url usage for external URLs
+
+1.1.0 / 2011-08-08
+==================
+
+  * Added Zombie.js driver (thanks @b00giZm)
+  * Added pt translation (thanks Daniel Gomes)
+  * Refactored MinkContext and MinkTestCase
+
+1.0.3 / 2011-08-02
+==================
+
+  * File uploads for empty fields fixed (GoutteDriver)
+  * Lazy sessions restart
+  * `show_tmp_dir` option in MinkContext
+  * Updated to stable Symfony2 components
+  * SahiClient connection limit bumped to 60 seconds
+  * Dutch language support
+
+1.0.2 / 2011-07-22
+==================
+
+  * ElementHtmlException fixed (thanks @Stof)
+
+1.0.1 / 2011-07-21
+==================
+
+  * Fixed buggy assertions in MinkContext
+
+1.0.0 / 2011-07-20
+==================
+
+  * Added missing tests for almost everything
+  * Hude speedup for SahiDriver
+  * Support for Behat 2.0 contexts
+  * Bundled PHPUnit TestCase
+  * Deep element traversing
+  * Correct behavior of getText() method
+  * New getHtml() method
+  * Basic HTTP auth support
+  * Soft and hard session resetting
+  * Cookies management
+  * Browser history interactions (reload(), back(), forward())
+  * Weaverryan'd exception messages
+  * Huge amount of bugfixes and small additions
+
+0.3.2 / 2011-06-20
+==================
+
+  * Fixed file uploads in Goutte driver
+  * Fixed setting of long texts into fields
+  * Added getPlainText() (returns text without tags and whitespaces) method to the element's API
+  * Start_url is now optional parameter
+  * Default session (if needed) name now need to be always specified by hands with setDefaultSessionName()
+  * default_driver => default_session
+  * Updated Symfony Components
+
+0.3.1 / 2011-05-17
+==================
+
+  * Small SahiClient update (it generates SID now if no provided)
+  * setActiveSessionName => setDefaultSessionName method rename
+
+0.3.0 / 2011-05-17
+==================
+
+  * Rewritten from scratch Mink drivers handler. Now it's sessions handler. And Mink now
+    sessions-centric tool. See examples in readme. Much cleaner API now.
+
+0.2.4 / 2011-05-12
+==================
+
+  * Fixed wrong url locator function
+  * Fixed wrong regex in `should see` step
+  * Fixed delimiters use in `should see` step
+  * Added url-match step for checking urls against regex
+
+0.2.3 / 2011-05-01
+==================
+
+  * Updated SahiClient with new version, which is faster and cleaner with it's exceptions
+
+0.2.2 / 2011-05-01
+==================
+
+  * Ability to use already started browser as SahiDriver aim
+  * Added japanese translation for bundled steps (thanks @hidenorigoto)
+  * 10 seconds limit for browser connection in SahiDriver
+
+0.2.1 / 2011-04-21
+==================
+
+  * Fixed some bundled step definitions
+
+0.2.0 / 2011-04-21
+==================
+
+  * Additional step definitions
+  * Support for extended drivers configuration through behat.yml environment parameters
+  * Lots of new named selectors
+  * Bug fixes
+  * Small improvements
+
+0.1.2 / 2011-04-08
+==================
+
+  * Fixed Sahi url escaping
+
+0.1.1 / 2011-04-06
+==================
+
+  * Fixed should/should_not steps
+  * Added spanish translation
+  * Fixed forms to use <base> element
+  * Fixed small UnsupportedByDriverException issue
+
+0.1.0 / 2011-04-04
+==================
+
+  * Initial release
diff --git a/core/vendor/behat/mink/CONTRIBUTING.md b/core/vendor/behat/mink/CONTRIBUTING.md
new file mode 100644
index 0000000..5db4d85
--- /dev/null
+++ b/core/vendor/behat/mink/CONTRIBUTING.md
@@ -0,0 +1,22 @@
+# Contributing
+Mink is an open source, community-driven project. If you'd like to contribute, feel free to do this, but remember to follow these few simple rules:
+
+## Submitting an issues
+- __Driver-related__ issues must be reported in the corresponding driver repository
+- A reproducible example is required for every bug report, otherwise it will most probably be __closed without warning__
+- If you are going to make a big, substantial change, let's discuss it first
+
+## Working with Pull Requests
+1. Create your feature addition or a bug fix branch based on `master` branch in your repository's fork.
+2. Make necessary changes, but __don't mix__ code reformatting with code changes on topic.
+3. Add tests for those changes (please look into `tests/` folder for some examples). This is important so we don't break it in a future version unintentionally.
+4. Commit your code, but do not mess with `CHANGES.md`.
+5. Squash your commits by topic to preserve a clean and readable log.
+6. Create Pull Request.
+
+# Running tests
+Make sure that you don't break anything with your changes by running:
+
+```bash
+$> phpunit
+```
diff --git a/core/vendor/behat/mink/LICENSE b/core/vendor/behat/mink/LICENSE
new file mode 100644
index 0000000..14f15e8
--- /dev/null
+++ b/core/vendor/behat/mink/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2011-2013 Konstantin Kudryashov <ever.zet@gmail.com>
+
+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:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+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.
diff --git a/core/vendor/behat/mink/README.md b/core/vendor/behat/mink/README.md
new file mode 100644
index 0000000..d87cf3a
--- /dev/null
+++ b/core/vendor/behat/mink/README.md
@@ -0,0 +1,72 @@
+Mink
+====
+[![Latest Stable Version](https://poser.pugx.org/behat/mink/v/stable.svg)](https://packagist.org/packages/behat/mink)
+[![Latest Unstable Version](https://poser.pugx.org/behat/mink/v/unstable.svg)](https://packagist.org/packages/behat/mink)
+[![Total Downloads](https://poser.pugx.org/behat/mink/downloads.svg)](https://packagist.org/packages/behat/mink)
+[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/Behat/Mink/badges/quality-score.png?s=d4faf469d6b399df121deed6070390800722ada0)](https://scrutinizer-ci.com/g/Behat/Mink/)
+[![Code Coverage](https://scrutinizer-ci.com/g/Behat/Mink/badges/coverage.png?s=88ab1cee4e131f4ef595f17ae4837001ef2aec3b)](https://scrutinizer-ci.com/g/Behat/Mink/)
+[![Build Status](https://travis-ci.org/Behat/Mink.svg?branch=master)](https://travis-ci.org/Behat/Mink)
+[![SensioLabsInsight](https://insight.sensiolabs.com/projects/5bb8fab0-978f-428a-ae23-44ee4e129fbc/mini.png)](https://insight.sensiolabs.com/projects/5bb8fab0-978f-428a-ae23-44ee4e129fbc)
+[![License](https://poser.pugx.org/behat/mink/license.svg)](https://packagist.org/packages/behat/mink)
+
+
+Useful Links
+------------
+
+- The main website with documentation is at [http://mink.behat.org](http://mink.behat.org)
+- Official Google Group is at [http://groups.google.com/group/behat](http://groups.google.com/group/behat)
+- IRC channel on [#freenode](http://freenode.net/) is `#behat`
+- [Note on Patches/Pull Requests](CONTRIBUTING.md)
+
+Usage Example
+-------------
+
+``` php
+<?php
+
+use Behat\Mink\Mink,
+    Behat\Mink\Session,
+    Behat\Mink\Driver\GoutteDriver,
+    Behat\Mink\Driver\Goutte\Client as GoutteClient;
+
+$startUrl = 'http://example.com';
+
+// init Mink and register sessions
+$mink = new Mink(array(
+    'goutte1' => new Session(new GoutteDriver(new GoutteClient())),
+    'goutte2' => new Session(new GoutteDriver(new GoutteClient())),
+    'custom'  => new Session(new MyCustomDriver($startUrl))
+));
+
+// set the default session name
+$mink->setDefaultSessionName('goutte2');
+
+// visit a page
+$mink->getSession()->visit($startUrl);
+
+// call to getSession() without argument will always return a default session if has one (goutte2 here)
+$mink->getSession()->getPage()->findLink('Downloads')->click();
+echo $mink->getSession()->getPage()->getContent();
+
+// call to getSession() with argument will return session by its name
+$mink->getSession('custom')->getPage()->findLink('Downloads')->click();
+echo $mink->getSession('custom')->getPage()->getContent();
+
+// this all is done to make possible mixing sessions
+$mink->getSession('goutte1')->getPage()->findLink('Chat')->click();
+$mink->getSession('goutte2')->getPage()->findLink('Chat')->click();
+```
+
+Install Dependencies
+--------------------
+
+``` bash
+$> curl -sS https://getcomposer.org/installer | php
+$> php composer.phar install
+```
+
+Contributors
+------------
+
+* Konstantin Kudryashov [everzet](http://github.com/everzet) [lead developer]
+* Other [awesome developers](https://github.com/Behat/Mink/graphs/contributors)
diff --git a/core/vendor/behat/mink/composer.json b/core/vendor/behat/mink/composer.json
new file mode 100644
index 0000000..0aeee7b
--- /dev/null
+++ b/core/vendor/behat/mink/composer.json
@@ -0,0 +1,46 @@
+{
+    "name":         "behat/mink",
+    "description":  "Web acceptance testing framework for PHP 5.3",
+    "keywords":     ["web", "testing", "browser"],
+    "homepage":     "http://mink.behat.org/",
+    "type":         "library",
+    "license":      "MIT",
+
+    "authors": [
+        {
+            "name":      "Konstantin Kudryashov",
+            "email":     "ever.zet@gmail.com",
+            "homepage":  "http://everzet.com"
+        }
+    ],
+
+    "require": {
+        "php":                   ">=5.3.1",
+        "symfony/css-selector":  "~2.0"
+    },
+
+    "suggest": {
+        "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)",
+        "behat/mink-goutte-driver":     "fast headless driver for any app without JS emulation",
+        "behat/mink-selenium2-driver":  "slow, but JS-enabled driver for any app (requires Selenium2)",
+        "behat/mink-zombie-driver":     "fast and JS-enabled headless driver for any app (requires node.js)"
+    },
+
+    "autoload": {
+        "psr-0": {
+            "Behat\\Mink": "src/"
+        }
+    },
+
+    "autoload-dev": {
+        "psr-4": {
+            "Behat\\Mink\\Tests\\": "tests"
+        }
+    },
+
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.6.x-dev"
+        }
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/README.md b/core/vendor/behat/mink/driver-testsuite/README.md
new file mode 100644
index 0000000..d21a747
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/README.md
@@ -0,0 +1,93 @@
+Mink Driver testsuite
+=====================
+
+This is the common testsuite for Mink drivers to ensure consistency among implementations.
+
+Usage
+-----
+
+The testsuite of a driver should be based as follow:
+
+```json
+{
+    "require": {
+        "behat/mink": "~1.6@dev"
+    },
+
+    "autoload-dev": {
+        "psr-4": {
+            "Acme\MyDriver\Tests\\": "tests"
+        }
+    }
+}
+```
+
+```xml
+<!-- phpunit.xml.dist -->
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit colors="true" bootstrap="vendor/behat/mink/driver-testsuite/bootstrap.php">
+    <php>
+        <var name="driver_config_factory" value="Acme\MyDriver\Tests\Config::getInstance" />
+
+        <server name="WEB_FIXTURES_HOST" value="http://test.mink.dev" />
+    </php>
+
+    <testsuites>
+        <testsuite name="Driver test suite">
+            <directory>./tests/</directory><!-- if needed to add more tests -->
+            <directory>vendor/behat/mink/driver-testsuite/tests</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory>./src/Acme/MyDriver</directory>
+        </whitelist>
+    </filter>
+</phpunit>
+```
+
+Then create the driver config for the testsuite:
+
+```php
+// tests/Config.php
+
+namespace Acme\MyDriver\Tests;
+
+use Behat\Mink\Tests\Driver\AbstractConfig;
+
+class Config extends AbstractConfig
+{
+    /**
+     * Creates an instance of the config.
+     *
+     * This is the callable registered as a php variable in the phpunit.xml config file.
+     * It could be outside the class but this is convenient.
+     */
+    public static function getInstance()
+    {
+        return new self();
+    }
+
+    /**
+     * Creates driver instance.
+     *
+     * @return \Behat\Mink\Driver\DriverInterface
+     */
+    public function createDriver()
+    {
+        return new \Acme\MyDriver\MyDriver();
+    }
+}
+```
+
+Some other methods are available in the AbstractConfig which can be overwritten to adapt the testsuite to
+the needs of the driver (skipping some tests for instance).
+
+Adding Driver-specific Tests
+----------------------------
+
+When adding extra test cases specific to the driver, either use your own namespace or put them in the
+``Behat\Mink\Tests\Driver\Custom`` subnamespace to ensure that you will not create conflicts with test cases
+added in the driver testsuite in the future.
diff --git a/core/vendor/behat/mink/driver-testsuite/bootstrap.php b/core/vendor/behat/mink/driver-testsuite/bootstrap.php
new file mode 100644
index 0000000..f69a45b
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/bootstrap.php
@@ -0,0 +1,28 @@
+<?php
+
+$file = __DIR__.'/../../../autoload.php';
+
+if (!file_exists($file)) {
+    echo PHP_EOL.'The Mink driver testsuite expects Mink to be installed as a composer dependency of your project'.PHP_EOL;
+    exit(1);
+}
+
+/** @var \Composer\Autoload\ClassLoader $loader */
+$loader = require $file;
+
+$loader->addPsr4('Behat\Mink\Tests\Driver\\', __DIR__.'/tests');
+
+// Clean the global variables
+unset($file);
+unset($loader);
+
+// Check the definition of the driverLoaderFactory
+
+if (!isset($GLOBALS['driver_config_factory'])) {
+    echo PHP_EOL.'The "driver_config_factory" global variable must be set.'.PHP_EOL;
+    exit(1);
+}
+if (!is_callable($GLOBALS['driver_config_factory'])) {
+    echo PHP_EOL.'The "driver_config_factory" global variable must be a callable.'.PHP_EOL;
+    exit(1);
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/AbstractConfig.php b/core/vendor/behat/mink/driver-testsuite/tests/AbstractConfig.php
new file mode 100644
index 0000000..5d02df2
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/AbstractConfig.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver;
+
+use Behat\Mink\Driver\DriverInterface;
+
+abstract class AbstractConfig
+{
+    /**
+     * Creates driver instance.
+     *
+     * @return DriverInterface
+     */
+    abstract public function createDriver();
+
+    /**
+     * Map remote file path.
+     *
+     * @param string $file File path.
+     *
+     * @return string
+     */
+    public function mapRemoteFilePath($file)
+    {
+        if (!isset($_SERVER['TEST_MACHINE_BASE_PATH']) || !isset($_SERVER['DRIVER_MACHINE_BASE_PATH'])) {
+            return $file;
+        }
+
+        $pattern = '/^' . preg_quote($_SERVER['TEST_MACHINE_BASE_PATH'], '/') . '/';
+        $basePath = $_SERVER['DRIVER_MACHINE_BASE_PATH'];
+
+        return preg_replace($pattern, $basePath, $file, 1);
+    }
+
+    /**
+     * Gets the base url to the fixture folder
+     *
+     * @return string
+     */
+    public function getWebFixturesUrl()
+    {
+        return $_SERVER['WEB_FIXTURES_HOST'];
+    }
+
+    /**
+     * @param string $testCase The name of the TestCase class
+     * @param string $test     The name of the test method
+     *
+     * @return string|null A message explaining why the test should be skipped, or null to run the test.
+     */
+    public function skipMessage($testCase, $test)
+    {
+        if (!$this->supportsCss() && 0 === strpos($testCase, 'Behat\Mink\Tests\Driver\Css\\')) {
+            return 'This driver does not support CSS.';
+        }
+
+        if (!$this->supportsJs() && 0 === strpos($testCase, 'Behat\Mink\Tests\Driver\Js\\')) {
+            return 'This driver does not support JavaScript.';
+        }
+
+        return null;
+    }
+
+    /**
+     * Whether the JS tests should run or no.
+     *
+     * @return bool
+     */
+    protected function supportsJs()
+    {
+        return true;
+    }
+
+    /**
+     * Whether the CSS tests should run or no.
+     *
+     * @return bool
+     */
+    protected function supportsCss()
+    {
+        return false;
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/BasicAuthTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/BasicAuthTest.php
new file mode 100644
index 0000000..40d932d
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/BasicAuthTest.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class BasicAuthTest extends TestCase
+{
+    /**
+     * @dataProvider setBasicAuthDataProvider
+     */
+    public function testSetBasicAuth($user, $pass, $pageText)
+    {
+        $session = $this->getSession();
+
+        $session->setBasicAuth($user, $pass);
+
+        $session->visit($this->pathTo('/basic_auth.php'));
+
+        $this->assertContains($pageText, $session->getPage()->getContent());
+    }
+
+    public function setBasicAuthDataProvider()
+    {
+        return array(
+            array('mink-user', 'mink-password', 'is authenticated'),
+            array('', '', 'is not authenticated'),
+        );
+    }
+
+    public function testResetBasicAuth()
+    {
+        $session = $this->getSession();
+
+        $session->setBasicAuth('mink-user', 'mink-password');
+
+        $session->visit($this->pathTo('/basic_auth.php'));
+
+        $this->assertContains('is authenticated', $session->getPage()->getContent());
+
+        $session->setBasicAuth(false);
+
+        $session->visit($this->pathTo('/headers.php'));
+
+        $this->assertNotContains('PHP_AUTH_USER', $session->getPage()->getContent());
+    }
+
+    public function testResetWithBasicAuth()
+    {
+        $session = $this->getSession();
+
+        $session->setBasicAuth('mink-user', 'mink-password');
+
+        $session->visit($this->pathTo('/basic_auth.php'));
+
+        $this->assertContains('is authenticated', $session->getPage()->getContent());
+
+        $session->reset();
+
+        $session->visit($this->pathTo('/headers.php'));
+
+        $this->assertNotContains('PHP_AUTH_USER', $session->getPage()->getContent());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/ContentTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/ContentTest.php
new file mode 100644
index 0000000..e68e8d0
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/ContentTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class ContentTest extends TestCase
+{
+    public function testOuterHtml()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $element = $this->getAssertSession()->elementExists('css', '.travers');
+
+        $this->assertEquals(
+            "<div class=\"travers\">\n            <div class=\"sub\">el1</div>\n".
+            "            <div class=\"sub\">el2</div>\n            <div class=\"sub\">\n".
+            "                <a href=\"some_url\">some <strong>deep</strong> url</a>\n".
+            "            </div>\n        </div>",
+            $element->getOuterHtml()
+        );
+    }
+
+    /**
+     * @dataProvider getAttributeDataProvider
+     */
+    public function testGetAttribute($attributeName, $attributeValue)
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $element = $this->getSession()->getPage()->findById('attr-elem[' . $attributeName . ']');
+
+        $this->assertNotNull($element);
+        $this->assertSame($attributeValue, $element->getAttribute($attributeName));
+    }
+
+    public function getAttributeDataProvider()
+    {
+        return array(
+            array('with-value', 'some-value'),
+            array('without-value', ''),
+            array('with-empty-value', ''),
+            array('with-missing', null),
+        );
+    }
+
+    public function testJson()
+    {
+        $this->getSession()->visit($this->pathTo('/json.php'));
+        $this->assertContains(
+            '{"key1":"val1","key2":234,"key3":[1,2,3]}',
+            $this->getSession()->getPage()->getContent()
+        );
+    }
+
+    public function testHtmlDecodingNotPerformed()
+    {
+        $session = $this->getSession();
+        $webAssert = $this->getAssertSession();
+        $session->visit($this->pathTo('/html_decoding.html'));
+        $page = $session->getPage();
+
+        $span = $webAssert->elementExists('css', 'span');
+        $input = $webAssert->elementExists('css', 'input');
+
+        $expectedHtml = '<span custom-attr="&amp;">some text</span>';
+        $this->assertContains($expectedHtml, $page->getHtml(), '.innerHTML is returned as-is');
+        $this->assertContains($expectedHtml, $page->getContent(), '.outerHTML is returned as-is');
+
+        $this->assertEquals('&', $span->getAttribute('custom-attr'), '.getAttribute value is decoded');
+        $this->assertEquals('&', $input->getAttribute('value'), '.getAttribute value is decoded');
+        $this->assertEquals('&', $input->getValue(), 'node value is decoded');
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/CookieTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/CookieTest.php
new file mode 100644
index 0000000..355dd71
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/CookieTest.php
@@ -0,0 +1,167 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class CookieTest extends TestCase
+{
+    /**
+     * test cookie decoding
+     * @group issue140
+     */
+    public function testIssue140()
+    {
+        $this->getSession()->visit($this->pathTo('/issue140.php'));
+
+        $this->getSession()->getPage()->fillField('cookie_value', 'some:value;');
+        $this->getSession()->getPage()->pressButton('Set cookie');
+
+        $this->getSession()->visit($this->pathTo('/issue140.php?show_value'));
+        $this->assertEquals('some:value;', $this->getSession()->getCookie('tc'));
+        $this->assertEquals('some:value;', $this->getSession()->getPage()->getText());
+    }
+
+    public function testCookie()
+    {
+        $this->getSession()->visit($this->pathTo('/cookie_page2.php'));
+        $this->assertContains('Previous cookie: NO', $this->getSession()->getPage()->getText());
+        $this->assertNull($this->getSession()->getCookie('srvr_cookie'));
+
+        $this->getSession()->setCookie('srvr_cookie', 'client cookie set');
+        $this->getSession()->reload();
+        $this->assertContains('Previous cookie: client cookie set', $this->getSession()->getPage()->getText());
+        $this->assertEquals('client cookie set', $this->getSession()->getCookie('srvr_cookie'));
+
+        $this->getSession()->setCookie('srvr_cookie', null);
+        $this->getSession()->reload();
+        $this->assertContains('Previous cookie: NO', $this->getSession()->getPage()->getText());
+
+        $this->getSession()->visit($this->pathTo('/cookie_page1.php'));
+        $this->getSession()->visit($this->pathTo('/cookie_page2.php'));
+
+        $this->assertContains('Previous cookie: srv_var_is_set', $this->getSession()->getPage()->getText());
+        $this->getSession()->setCookie('srvr_cookie', null);
+        $this->getSession()->reload();
+        $this->assertContains('Previous cookie: NO', $this->getSession()->getPage()->getText());
+    }
+
+    /**
+     * @dataProvider cookieWithPathsDataProvider
+     */
+    public function testCookieWithPaths($cookieRemovalMode)
+    {
+        // start clean
+        $session = $this->getSession();
+        $session->visit($this->pathTo('/sub-folder/cookie_page2.php'));
+        $this->assertContains('Previous cookie: NO', $session->getPage()->getText());
+
+        // cookie from root path is accessible in sub-folder
+        $session->visit($this->pathTo('/cookie_page1.php'));
+        $session->visit($this->pathTo('/sub-folder/cookie_page2.php'));
+        $this->assertContains('Previous cookie: srv_var_is_set', $session->getPage()->getText());
+
+        // cookie from sub-folder overrides cookie from root path
+        $session->visit($this->pathTo('/sub-folder/cookie_page1.php'));
+        $session->visit($this->pathTo('/sub-folder/cookie_page2.php'));
+        $this->assertContains('Previous cookie: srv_var_is_set_sub_folder', $session->getPage()->getText());
+
+        if ($cookieRemovalMode == 'session_reset') {
+            $session->reset();
+        } elseif ($cookieRemovalMode == 'cookie_delete') {
+            $session->setCookie('srvr_cookie', null);
+        }
+
+        // cookie is removed from all paths
+        $session->visit($this->pathTo('/sub-folder/cookie_page2.php'));
+        $this->assertContains('Previous cookie: NO', $session->getPage()->getText());
+    }
+
+    public function cookieWithPathsDataProvider()
+    {
+        return array(
+            array('session_reset'),
+            array('cookie_delete'),
+        );
+    }
+
+    public function testReset()
+    {
+        $this->getSession()->visit($this->pathTo('/cookie_page1.php'));
+        $this->getSession()->visit($this->pathTo('/cookie_page2.php'));
+        $this->assertContains('Previous cookie: srv_var_is_set', $this->getSession()->getPage()->getText());
+
+        $this->getSession()->reset();
+        $this->getSession()->visit($this->pathTo('/cookie_page2.php'));
+
+        $this->assertContains('Previous cookie: NO', $this->getSession()->getPage()->getText());
+
+        $this->getSession()->setCookie('srvr_cookie', 'test_cookie');
+        $this->getSession()->visit($this->pathTo('/cookie_page2.php'));
+        $this->assertContains('Previous cookie: test_cookie', $this->getSession()->getPage()->getText());
+        $this->getSession()->reset();
+        $this->getSession()->visit($this->pathTo('/cookie_page2.php'));
+        $this->assertContains('Previous cookie: NO', $this->getSession()->getPage()->getText());
+
+        $this->getSession()->setCookie('client_cookie1', 'some_val');
+        $this->getSession()->setCookie('client_cookie2', 123);
+        $this->getSession()->visit($this->pathTo('/session_test.php'));
+        $this->getSession()->visit($this->pathTo('/cookie_page1.php'));
+
+        $this->getSession()->visit($this->pathTo('/print_cookies.php'));
+        $this->assertContains(
+            "'client_cookie1' = 'some_val'",
+            $this->getSession()->getPage()->getText()
+        );
+        $this->assertContains(
+            "'client_cookie2' = '123'",
+            $this->getSession()->getPage()->getText()
+        );
+        $this->assertContains(
+            "_SESS' = ",
+            $this->getSession()->getPage()->getText()
+        );
+        $this->assertContains(
+            " 'srvr_cookie' = 'srv_var_is_set'",
+            $this->getSession()->getPage()->getText()
+        );
+
+        $this->getSession()->reset();
+        $this->getSession()->visit($this->pathTo('/print_cookies.php'));
+        $this->assertContains('array ( )', $this->getSession()->getPage()->getText());
+    }
+
+    public function testHttpOnlyCookieIsDeleted()
+    {
+        $this->getSession()->restart();
+        $this->getSession()->visit($this->pathTo('/cookie_page3.php'));
+        $this->assertEquals('Has Cookie: false', $this->findById('cookie-status')->getText());
+
+        $this->getSession()->reload();
+        $this->assertEquals('Has Cookie: true', $this->findById('cookie-status')->getText());
+
+        $this->getSession()->restart();
+        $this->getSession()->visit($this->pathTo('/cookie_page3.php'));
+        $this->assertEquals('Has Cookie: false', $this->findById('cookie-status')->getText());
+    }
+
+    public function testSessionPersistsBetweenRequests()
+    {
+        $this->getSession()->visit($this->pathTo('/session_test.php'));
+        $webAssert = $this->getAssertSession();
+        $node = $webAssert->elementExists('css', '#session-id');
+        $sessionId = $node->getText();
+
+        $this->getSession()->visit($this->pathTo('/session_test.php'));
+        $node = $webAssert->elementExists('css', '#session-id');
+        $this->assertEquals($sessionId, $node->getText());
+
+        $this->getSession()->visit($this->pathTo('/session_test.php?login'));
+        $node = $webAssert->elementExists('css', '#session-id');
+        $this->assertNotEquals($sessionId, $newSessionId = $node->getText());
+
+        $this->getSession()->visit($this->pathTo('/session_test.php'));
+        $node = $webAssert->elementExists('css', '#session-id');
+        $this->assertEquals($newSessionId, $node->getText());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/ErrorHandlingTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/ErrorHandlingTest.php
new file mode 100644
index 0000000..440585a
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/ErrorHandlingTest.php
@@ -0,0 +1,262 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class ErrorHandlingTest extends TestCase
+{
+    const NOT_FOUND_XPATH = '//html/./invalid';
+
+    const NOT_FOUND_EXCEPTION = 'Exception';
+
+    const INVALID_EXCEPTION = 'Exception';
+
+    public function testVisitErrorPage()
+    {
+        $this->getSession()->visit($this->pathTo('/500.php'));
+
+        $this->assertContains(
+            'Sorry, a server error happened',
+            $this->getSession()->getPage()->getContent(),
+            'Drivers allow loading pages with a 500 status code'
+        );
+    }
+
+    public function testCheckInvalidElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+        $element = $this->findById('user-name');
+
+        $this->setExpectedException(self::INVALID_EXCEPTION);
+        $this->getSession()->getDriver()->check($element->getXpath());
+    }
+
+    public function testCheckNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->check(self::NOT_FOUND_XPATH);
+    }
+
+    public function testUncheckInvalidElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+        $element = $this->findById('user-name');
+
+        $this->setExpectedException(self::INVALID_EXCEPTION);
+        $this->getSession()->getDriver()->uncheck($element->getXpath());
+    }
+
+    public function testUncheckNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->uncheck(self::NOT_FOUND_XPATH);
+    }
+
+    public function testSelectOptionInvalidElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+        $element = $this->findById('user-name');
+
+        $this->setExpectedException(self::INVALID_EXCEPTION);
+        $this->getSession()->getDriver()->selectOption($element->getXpath(), 'test');
+    }
+
+    public function testSelectOptionNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->selectOption(self::NOT_FOUND_XPATH, 'test');
+    }
+
+    public function testAttachFileInvalidElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+        $element = $this->findById('user-name');
+
+        $this->setExpectedException(self::INVALID_EXCEPTION);
+        $this->getSession()->getDriver()->attachFile($element->getXpath(), __FILE__);
+    }
+
+    public function testAttachFileNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->attachFile(self::NOT_FOUND_XPATH, __FILE__);
+    }
+
+    public function testSubmitFormInvalidElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+        $element = $this->findById('core');
+
+        $this->setExpectedException(self::INVALID_EXCEPTION);
+        $this->getSession()->getDriver()->submitForm($element->getXpath());
+    }
+
+    public function testSubmitFormNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->submitForm(self::NOT_FOUND_XPATH);
+    }
+
+    public function testGetTagNameNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->getTagName(self::NOT_FOUND_XPATH);
+    }
+
+    public function testGetTextNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->getText(self::NOT_FOUND_XPATH);
+    }
+
+    public function testGetHtmlNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->getHtml(self::NOT_FOUND_XPATH);
+    }
+
+    public function testGetOuterHtmlNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->getOuterHtml(self::NOT_FOUND_XPATH);
+    }
+
+    public function testGetValueNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->getValue(self::NOT_FOUND_XPATH);
+    }
+
+    public function testSetValueNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->setValue(self::NOT_FOUND_XPATH, 'test');
+    }
+
+    public function testIsSelectedNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->isSelected(self::NOT_FOUND_XPATH);
+    }
+
+    public function testIsCheckedNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->isChecked(self::NOT_FOUND_XPATH);
+    }
+
+    public function testIsVisibleNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->isVisible(self::NOT_FOUND_XPATH);
+    }
+
+    public function testClickNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->click(self::NOT_FOUND_XPATH);
+    }
+
+    public function testDoubleClickNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->doubleClick(self::NOT_FOUND_XPATH);
+    }
+
+    public function testRightClickNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->rightClick(self::NOT_FOUND_XPATH);
+    }
+
+    public function testGetAttributeNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->getAttribute(self::NOT_FOUND_XPATH, 'id');
+    }
+
+    public function testMouseOverNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->mouseOver(self::NOT_FOUND_XPATH);
+    }
+
+    public function testFocusNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->focus(self::NOT_FOUND_XPATH);
+    }
+
+    public function testBlurNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->blur(self::NOT_FOUND_XPATH);
+    }
+
+    public function testKeyPressNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->keyPress(self::NOT_FOUND_XPATH, 'a');
+    }
+
+    public function testKeyDownNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->keyDown(self::NOT_FOUND_XPATH, 'a');
+    }
+
+    public function testKeyUpNotFoundElement()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->setExpectedException(self::NOT_FOUND_EXCEPTION);
+        $this->getSession()->getDriver()->keyUp(self::NOT_FOUND_XPATH, 'a');
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/HeaderTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/HeaderTest.php
new file mode 100644
index 0000000..0288ff1
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/HeaderTest.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class HeaderTest extends TestCase
+{
+    /**
+     * test referrer
+     * @group issue130
+     */
+    public function testIssue130()
+    {
+        $this->getSession()->visit($this->pathTo('/issue130.php?p=1'));
+        $page = $this->getSession()->getPage();
+
+        $page->clickLink('Go to 2');
+        $this->assertEquals($this->pathTo('/issue130.php?p=1'), $page->getText());
+    }
+
+    public function testHeaders()
+    {
+        $this->getSession()->setRequestHeader('Accept-Language', 'fr');
+        $this->getSession()->visit($this->pathTo('/headers.php'));
+
+        $this->assertContains('[HTTP_ACCEPT_LANGUAGE] => fr', $this->getSession()->getPage()->getContent());
+    }
+
+    public function testSetUserAgent()
+    {
+        $session = $this->getSession();
+
+        $session->setRequestHeader('user-agent', 'foo bar');
+        $session->visit($this->pathTo('/headers.php'));
+        $this->assertContains('[HTTP_USER_AGENT] => foo bar', $session->getPage()->getContent());
+    }
+
+    public function testResetHeaders()
+    {
+        $session = $this->getSession();
+
+        $session->setRequestHeader('X-Mink-Test', 'test');
+        $session->visit($this->pathTo('/headers.php'));
+
+        $this->assertContains(
+            '[HTTP_X_MINK_TEST] => test',
+            $session->getPage()->getContent(),
+            'The custom header should be sent',
+            true
+        );
+
+        $session->reset();
+        $session->visit($this->pathTo('/headers.php'));
+
+        $this->assertNotContains(
+            '[HTTP_X_MINK_TEST] => test',
+            $session->getPage()->getContent(),
+            'The custom header should not be sent after resetting',
+            true
+        );
+    }
+
+    public function testResponseHeaders()
+    {
+        $this->getSession()->visit($this->pathTo('/response_headers.php'));
+
+        $headers = $this->getSession()->getResponseHeaders();
+
+        $lowercasedHeaders = array();
+        foreach ($headers as $name => $value) {
+            $lowercasedHeaders[str_replace('_', '-', strtolower($name))] = $value;
+        }
+
+        $this->assertArrayHasKey('x-mink-test', $lowercasedHeaders);
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/IFrameTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/IFrameTest.php
new file mode 100644
index 0000000..0ed0f9e
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/IFrameTest.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class IFrameTest extends TestCase
+{
+    public function testIFrame()
+    {
+        $this->getSession()->visit($this->pathTo('/iframe.html'));
+        $webAssert = $this->getAssertSession();
+
+        $el = $webAssert->elementExists('css', '#text');
+        $this->assertSame('Main window div text', $el->getText());
+
+        $this->getSession()->switchToIFrame('subframe');
+
+        $el = $webAssert->elementExists('css', '#text');
+        $this->assertSame('iFrame div text', $el->getText());
+
+        $this->getSession()->switchToIFrame();
+
+        $el = $webAssert->elementExists('css', '#text');
+        $this->assertSame('Main window div text', $el->getText());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/NavigationTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/NavigationTest.php
new file mode 100644
index 0000000..8ecb139
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/NavigationTest.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class NavigationTest extends TestCase
+{
+    public function testRedirect()
+    {
+        $this->getSession()->visit($this->pathTo('/redirector.php'));
+        $this->assertEquals($this->pathTo('/redirect_destination.html'), $this->getSession()->getCurrentUrl());
+    }
+
+    public function testPageControlls()
+    {
+        $this->getSession()->visit($this->pathTo('/randomizer.php'));
+        $number1 = $this->getSession()->getPage()->find('css', '#number')->getText();
+
+        $this->getSession()->reload();
+        $number2 = $this->getSession()->getPage()->find('css', '#number')->getText();
+
+        $this->assertNotEquals($number1, $number2);
+
+        $this->getSession()->visit($this->pathTo('/links.html'));
+        $this->getSession()->getPage()->clickLink('Random number page');
+
+        $this->assertEquals($this->pathTo('/randomizer.php'), $this->getSession()->getCurrentUrl());
+
+        $this->getSession()->back();
+        $this->assertEquals($this->pathTo('/links.html'), $this->getSession()->getCurrentUrl());
+
+        $this->getSession()->forward();
+        $this->assertEquals($this->pathTo('/randomizer.php'), $this->getSession()->getCurrentUrl());
+    }
+
+    public function testLinks()
+    {
+        $this->getSession()->visit($this->pathTo('/links.html'));
+        $page = $this->getSession()->getPage();
+        $link = $page->findLink('Redirect me to');
+
+        $this->assertNotNull($link);
+        $this->assertRegExp('/redirector\.php$/', $link->getAttribute('href'));
+        $link->click();
+
+        $this->assertEquals($this->pathTo('/redirect_destination.html'), $this->getSession()->getCurrentUrl());
+
+        $this->getSession()->visit($this->pathTo('/links.html'));
+        $page = $this->getSession()->getPage();
+        $link = $page->findLink('basic form image');
+
+        $this->assertNotNull($link);
+        $this->assertRegExp('/basic_form\.html$/', $link->getAttribute('href'));
+        $link->click();
+
+        $this->assertEquals($this->pathTo('/basic_form.html'), $this->getSession()->getCurrentUrl());
+
+        $this->getSession()->visit($this->pathTo('/links.html'));
+        $page = $this->getSession()->getPage();
+        $link = $page->findLink("Link with a ");
+
+        $this->assertNotNull($link);
+        $this->assertRegExp('/links\.html\?quoted$/', $link->getAttribute('href'));
+        $link->click();
+
+        $this->assertEquals($this->pathTo('/links.html?quoted'), $this->getSession()->getCurrentUrl());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/ScreenshotTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/ScreenshotTest.php
new file mode 100644
index 0000000..329f2d3
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/ScreenshotTest.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class ScreenshotTest extends TestCase
+{
+    public function testScreenshot()
+    {
+        if (!extension_loaded('gd')) {
+            $this->markTestSkipped('Testing screenshots requires the GD extension');
+        }
+
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $screenShot = $this->getSession()->getScreenshot();
+
+        $this->assertInternalType('string', $screenShot);
+        $this->assertFalse(base64_decode($screenShot, true), 'The returned screenshot should not be base64-encoded');
+
+        $img = imagecreatefromstring($screenShot);
+
+        if (false === $img) {
+            $this->fail('The screenshot should be a valid image');
+        }
+
+        imagedestroy($img);
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/StatusCodeTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/StatusCodeTest.php
new file mode 100644
index 0000000..34ca7f0
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/StatusCodeTest.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class StatusCodeTest extends TestCase
+{
+    public function testStatuses()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->assertEquals(200, $this->getSession()->getStatusCode());
+        $this->assertEquals($this->pathTo('/index.html'), $this->getSession()->getCurrentUrl());
+
+        $this->getSession()->visit($this->pathTo('/404.php'));
+
+        $this->assertEquals($this->pathTo('/404.php'), $this->getSession()->getCurrentUrl());
+        $this->assertEquals(404, $this->getSession()->getStatusCode());
+        $this->assertEquals('Sorry, page not found', $this->getSession()->getPage()->getContent());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/TraversingTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/TraversingTest.php
new file mode 100644
index 0000000..b31f7fc
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/TraversingTest.php
@@ -0,0 +1,129 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class TraversingTest extends TestCase
+{
+    /**
+     * find by label
+     * @group issue211
+     */
+    public function testIssue211()
+    {
+        $this->getSession()->visit($this->pathTo('/issue211.html'));
+        $field = $this->getSession()->getPage()->findField('TÃ©lÃ©phone');
+
+        $this->assertNotNull($field);
+    }
+
+    public function testElementsTraversing()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $page = $this->getSession()->getPage();
+
+        $this->assertNotNull($page->find('css', 'h1'));
+        $this->assertEquals('Extremely useless page', $page->find('css', 'h1')->getText());
+        $this->assertEquals('h1', $page->find('css', 'h1')->getTagName());
+
+        $this->assertNotNull($page->find('xpath', '//div/strong[3]'));
+        $this->assertEquals('pariatur', $page->find('xpath', '//div/strong[3]')->getText());
+        $this->assertEquals('super-duper', $page->find('xpath', '//div/strong[3]')->getAttribute('class'));
+        $this->assertTrue($page->find('xpath', '//div/strong[3]')->hasAttribute('class'));
+
+        $this->assertNotNull($page->find('xpath', '//div/strong[2]'));
+        $this->assertEquals('veniam', $page->find('xpath', '//div/strong[2]')->getText());
+        $this->assertEquals('strong', $page->find('xpath', '//div/strong[2]')->getTagName());
+        $this->assertNull($page->find('xpath', '//div/strong[2]')->getAttribute('class'));
+        $this->assertFalse($page->find('xpath', '//div/strong[2]')->hasAttribute('class'));
+
+        $strongs = $page->findAll('css', 'div#core > strong');
+        $this->assertCount(3, $strongs);
+        $this->assertEquals('Lorem', $strongs[0]->getText());
+        $this->assertEquals('pariatur', $strongs[2]->getText());
+
+        $element = $page->find('css', '#some-element');
+
+        $this->assertEquals('some very interesting text', $element->getText());
+        $this->assertEquals(
+            "\n            some <div>very\n            </div>\n".
+            "<em>interesting</em>      text\n        ",
+            $element->getHtml()
+        );
+
+        $this->assertTrue($element->hasAttribute('data-href'));
+        $this->assertFalse($element->hasAttribute('data-url'));
+        $this->assertEquals('http://mink.behat.org', $element->getAttribute('data-href'));
+        $this->assertNull($element->getAttribute('data-url'));
+        $this->assertEquals('div', $element->getTagName());
+    }
+
+    public function testVeryDeepElementsTraversing()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $page = $this->getSession()->getPage();
+
+        $footer = $page->find('css', 'footer');
+        $this->assertNotNull($footer);
+
+        $searchForm = $footer->find('css', 'form#search-form');
+        $this->assertNotNull($searchForm);
+        $this->assertEquals('search-form', $searchForm->getAttribute('id'));
+
+        $searchInput = $searchForm->findField('Search site...');
+        $this->assertNotNull($searchInput);
+        $this->assertEquals('text', $searchInput->getAttribute('type'));
+
+        $searchInput = $searchForm->findField('Search site...');
+        $this->assertNotNull($searchInput);
+        $this->assertEquals('text', $searchInput->getAttribute('type'));
+
+        $profileForm = $footer->find('css', '#profile');
+        $this->assertNotNull($profileForm);
+
+        $profileFormDiv = $profileForm->find('css', 'div');
+        $this->assertNotNull($profileFormDiv);
+
+        $profileFormDivLabel = $profileFormDiv->find('css', 'label');
+        $this->assertNotNull($profileFormDivLabel);
+
+        $profileFormDivParent = $profileFormDivLabel->getParent();
+        $this->assertNotNull($profileFormDivParent);
+
+        $profileFormDivParent = $profileFormDivLabel->getParent();
+        $this->assertEquals('something', $profileFormDivParent->getAttribute('data-custom'));
+
+        $profileFormInput = $profileFormDivLabel->findField('user-name');
+        $this->assertNotNull($profileFormInput);
+        $this->assertEquals('username', $profileFormInput->getAttribute('name'));
+    }
+
+    public function testDeepTraversing()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $traversDiv = $this->getSession()->getPage()->findAll('css', 'div.travers');
+
+        $this->assertCount(1, $traversDiv);
+        $traversDiv = $traversDiv[0];
+
+        $subDivs = $traversDiv->findAll('css', 'div.sub');
+        $this->assertCount(3, $subDivs);
+
+        $this->assertTrue($subDivs[2]->hasLink('some deep url'));
+        $this->assertFalse($subDivs[2]->hasLink('come deep url'));
+        $subUrl = $subDivs[2]->findLink('some deep url');
+        $this->assertNotNull($subUrl);
+
+        $this->assertRegExp('/some_url$/', $subUrl->getAttribute('href'));
+        $this->assertEquals('some deep url', $subUrl->getText());
+        $this->assertEquals('some <strong>deep</strong> url', $subUrl->getHtml());
+
+        $this->assertTrue($subUrl->has('css', 'strong'));
+        $this->assertFalse($subUrl->has('css', 'em'));
+        $this->assertEquals('deep', $subUrl->find('css', 'strong')->getText());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Basic/VisibilityTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Basic/VisibilityTest.php
new file mode 100644
index 0000000..b3daf31
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Basic/VisibilityTest.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Basic;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class VisibilityTest extends TestCase
+{
+    public function testVisibility()
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+        $webAssert = $this->getAssertSession();
+
+        $clicker   = $webAssert->elementExists('css', '.elements div#clicker');
+        $invisible = $webAssert->elementExists('css', '#invisible');
+
+        $this->assertFalse($invisible->isVisible());
+        $this->assertTrue($clicker->isVisible());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Css/HoverTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Css/HoverTest.php
new file mode 100644
index 0000000..87041d4
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Css/HoverTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Css;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class HoverTest extends TestCase
+{
+    /**
+     * @group mouse-events
+     */
+    public function testMouseOverHover()
+    {
+        $this->getSession()->visit($this->pathTo('/css_mouse_events.html'));
+
+        $this->findById('reset-square')->mouseOver();
+        $this->assertActionSquareHeight(100);
+
+        $this->findById('action-square')->mouseOver();
+        $this->assertActionSquareHeight(200);
+    }
+
+    /**
+     * @group mouse-events
+     * @depends testMouseOverHover
+     */
+    public function testClickHover()
+    {
+        $this->getSession()->visit($this->pathTo('/css_mouse_events.html'));
+
+        $this->findById('reset-square')->mouseOver();
+        $this->assertActionSquareHeight(100);
+
+        $this->findById('action-square')->click();
+        $this->assertActionSquareHeight(200);
+    }
+
+    /**
+     * @group mouse-events
+     * @depends testMouseOverHover
+     */
+    public function testDoubleClickHover()
+    {
+        $this->getSession()->visit($this->pathTo('/css_mouse_events.html'));
+
+        $this->findById('reset-square')->mouseOver();
+        $this->assertActionSquareHeight(100);
+
+        $this->findById('action-square')->doubleClick();
+        $this->assertActionSquareHeight(200);
+    }
+
+    /**
+     * @group mouse-events
+     * @depends testMouseOverHover
+     */
+    public function testRightClickHover()
+    {
+        $this->getSession()->visit($this->pathTo('/css_mouse_events.html'));
+
+        $this->findById('reset-square')->mouseOver();
+        $this->assertActionSquareHeight(100);
+
+        $this->findById('action-square')->rightClick();
+        $this->assertActionSquareHeight(200);
+    }
+
+    private function assertActionSquareHeight($expected)
+    {
+        $this->assertEquals(
+            $expected,
+            $this->getSession()->evaluateScript("return window.$('#action-square').height();"),
+            'Mouse is located over the object when mouse-related action is performed'
+        );
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Form/CheckboxTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Form/CheckboxTest.php
new file mode 100644
index 0000000..e1ce4ab
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Form/CheckboxTest.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Form;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class CheckboxTest extends TestCase
+{
+    public function testManipulate()
+    {
+        $this->getSession()->visit($this->pathTo('advanced_form.html'));
+
+        $checkbox = $this->getAssertSession()->fieldExists('agreement');
+
+        $this->assertNull($checkbox->getValue());
+        $this->assertFalse($checkbox->isChecked());
+
+        $checkbox->check();
+
+        $this->assertEquals('yes', $checkbox->getValue());
+        $this->assertTrue($checkbox->isChecked());
+
+        $checkbox->uncheck();
+
+        $this->assertNull($checkbox->getValue());
+        $this->assertFalse($checkbox->isChecked());
+    }
+
+    public function testSetValue()
+    {
+        $this->getSession()->visit($this->pathTo('advanced_form.html'));
+
+        $checkbox = $this->getAssertSession()->fieldExists('agreement');
+
+        $this->assertNull($checkbox->getValue());
+        $this->assertFalse($checkbox->isChecked());
+
+        $checkbox->setValue(true);
+
+        $this->assertEquals('yes', $checkbox->getValue());
+        $this->assertTrue($checkbox->isChecked());
+
+        $checkbox->setValue(false);
+
+        $this->assertNull($checkbox->getValue());
+        $this->assertFalse($checkbox->isChecked());
+    }
+
+    public function testCheckboxMultiple()
+    {
+        $this->getSession()->visit($this->pathTo('/multicheckbox_form.html'));
+        $webAssert = $this->getAssertSession();
+
+        $this->assertEquals('Multicheckbox Test', $webAssert->elementExists('css', 'h1')->getText());
+
+        $updateMail  = $webAssert->elementExists('css', '[name="mail_types[]"][value="update"]');
+        $spamMail    = $webAssert->elementExists('css', '[name="mail_types[]"][value="spam"]');
+
+        $this->assertEquals('update', $updateMail->getValue());
+        $this->assertNull($spamMail->getValue());
+
+        $this->assertTrue($updateMail->isChecked());
+        $this->assertFalse($spamMail->isChecked());
+
+        $updateMail->uncheck();
+        $this->assertFalse($updateMail->isChecked());
+        $this->assertFalse($spamMail->isChecked());
+
+        $spamMail->check();
+        $this->assertFalse($updateMail->isChecked());
+        $this->assertTrue($spamMail->isChecked());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Form/GeneralTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Form/GeneralTest.php
new file mode 100644
index 0000000..263be70
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Form/GeneralTest.php
@@ -0,0 +1,312 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Form;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class GeneralTest extends TestCase
+{
+    // test multiple submit buttons
+    public function testIssue212()
+    {
+        $session = $this->getSession();
+
+        $session->visit($this->pathTo('/issue212.html'));
+
+        $field = $this->findById('poney-button');
+        $this->assertEquals('poney', $field->getValue());
+    }
+
+    public function testBasicForm()
+    {
+        $this->getSession()->visit($this->pathTo('/basic_form.html'));
+
+        $webAssert = $this->getAssertSession();
+        $page = $this->getSession()->getPage();
+        $this->assertEquals('Basic Form Page', $webAssert->elementExists('css', 'h1')->getText());
+
+        $firstname  = $webAssert->fieldExists('first_name');
+        $lastname   = $webAssert->fieldExists('lastn');
+
+        $this->assertEquals('Firstname', $firstname->getValue());
+        $this->assertEquals('Lastname', $lastname->getValue());
+
+        $firstname->setValue('Konstantin');
+        $page->fillField('last_name', 'Kudryashov');
+
+        $this->assertEquals('Konstantin', $firstname->getValue());
+        $this->assertEquals('Kudryashov', $lastname->getValue());
+
+        $page->findButton('Reset')->click();
+
+        $this->assertEquals('Firstname', $firstname->getValue());
+        $this->assertEquals('Lastname', $lastname->getValue());
+
+        $firstname->setValue('Konstantin');
+        $page->fillField('last_name', 'Kudryashov');
+
+        $page->findButton('Save')->click();
+
+        if ($this->safePageWait(5000, 'document.getElementById("first") !== null')) {
+            $this->assertEquals('Anket for Konstantin', $webAssert->elementExists('css', 'h1')->getText());
+            $this->assertEquals('Firstname: Konstantin', $webAssert->elementExists('css', '#first')->getText());
+            $this->assertEquals('Lastname: Kudryashov', $webAssert->elementExists('css', '#last')->getText());
+        }
+    }
+
+    /**
+     * @dataProvider formSubmitWaysDataProvider
+     */
+    public function testFormSubmitWays($submitVia)
+    {
+        $session = $this->getSession();
+        $session->visit($this->pathTo('/basic_form.html'));
+        $page = $session->getPage();
+        $webAssert = $this->getAssertSession();
+
+        $firstname = $webAssert->fieldExists('first_name');
+        $firstname->setValue('Konstantin');
+
+        $page->findButton($submitVia)->click();
+
+        if ($this->safePageWait(5000, 'document.getElementById("first") !== null')) {
+            $this->assertEquals('Firstname: Konstantin', $webAssert->elementExists('css', '#first')->getText());
+        } else {
+            $this->fail('Form was never submitted');
+        }
+    }
+
+    public function formSubmitWaysDataProvider()
+    {
+        return array(
+            array('Save'),
+            array('input-type-image'),
+            array('button-without-type'),
+            array('button-type-submit'),
+        );
+    }
+
+    public function testFormSubmit()
+    {
+        $session = $this->getSession();
+        $session->visit($this->pathTo('/basic_form.html'));
+
+        $webAssert = $this->getAssertSession();
+        $webAssert->fieldExists('first_name')->setValue('Konstantin');
+
+        $webAssert->elementExists('xpath', 'descendant-or-self::form[1]')->submit();
+
+        if ($this->safePageWait(5000, 'document.getElementById("first") !== null')) {
+            $this->assertEquals('Firstname: Konstantin', $webAssert->elementExists('css', '#first')->getText());
+        };
+    }
+
+    public function testFormSubmitWithoutButton()
+    {
+        $session = $this->getSession();
+        $session->visit($this->pathTo('/form_without_button.html'));
+
+        $webAssert = $this->getAssertSession();
+        $webAssert->fieldExists('first_name')->setValue('Konstantin');
+
+        $webAssert->elementExists('xpath', 'descendant-or-self::form[1]')->submit();
+
+        if ($this->safePageWait(5000, 'document.getElementById("first") !== null')) {
+            $this->assertEquals('Firstname: Konstantin', $webAssert->elementExists('css', '#first')->getText());
+        };
+    }
+
+    public function testBasicGetForm()
+    {
+        $this->getSession()->visit($this->pathTo('/basic_get_form.php'));
+        $webAssert = $this->getAssertSession();
+
+        $page = $this->getSession()->getPage();
+        $this->assertEquals('Basic Get Form Page', $webAssert->elementExists('css', 'h1')->getText());
+
+        $search = $webAssert->fieldExists('q');
+        $search->setValue('some#query');
+        $page->pressButton('Find');
+
+        $div = $webAssert->elementExists('css', 'div');
+        $this->assertEquals('some#query', $div->getText());
+    }
+
+    public function testAdvancedForm()
+    {
+        $this->getSession()->visit($this->pathTo('/advanced_form.html'));
+        $page = $this->getSession()->getPage();
+
+        $page->fillField('first_name', 'ever');
+        $page->fillField('last_name', 'zet');
+
+        $page->pressButton('Register');
+
+        $this->assertContains('no file', $page->getContent());
+
+        $this->getSession()->visit($this->pathTo('/advanced_form.html'));
+
+        $webAssert = $this->getAssertSession();
+        $page = $this->getSession()->getPage();
+        $this->assertEquals('ADvanced Form Page', $webAssert->elementExists('css', 'h1')->getText());
+
+        $firstname   = $webAssert->fieldExists('first_name');
+        $lastname    = $webAssert->fieldExists('lastn');
+        $email       = $webAssert->fieldExists('Your email:');
+        $select      = $webAssert->fieldExists('select_number');
+        $sex         = $webAssert->fieldExists('sex');
+        $maillist    = $webAssert->fieldExists('mail_list');
+        $agreement   = $webAssert->fieldExists('agreement');
+        $notes       = $webAssert->fieldExists('notes');
+        $about       = $webAssert->fieldExists('about');
+
+        $this->assertEquals('Firstname', $firstname->getValue());
+        $this->assertEquals('Lastname', $lastname->getValue());
+        $this->assertEquals('your@email.com', $email->getValue());
+        $this->assertEquals('20', $select->getValue());
+        $this->assertEquals('w', $sex->getValue());
+        $this->assertEquals('original notes', $notes->getValue());
+
+        $this->assertEquals('on', $maillist->getValue());
+        $this->assertNull($agreement->getValue());
+
+        $this->assertTrue($maillist->isChecked());
+        $this->assertFalse($agreement->isChecked());
+
+        $agreement->check();
+        $this->assertTrue($agreement->isChecked());
+
+        $maillist->uncheck();
+        $this->assertFalse($maillist->isChecked());
+
+        $select->selectOption('thirty');
+        $this->assertEquals('30', $select->getValue());
+
+        $sex->selectOption('m');
+        $this->assertEquals('m', $sex->getValue());
+
+        $notes->setValue('new notes');
+        $this->assertEquals('new notes', $notes->getValue());
+
+        $about->attachFile($this->mapRemoteFilePath(__DIR__ . '/../../web-fixtures/some_file.txt'));
+
+        $button = $page->findButton('Register');
+        $this->assertNotNull($button);
+
+        $page->fillField('first_name', 'Foo "item"');
+        $page->fillField('last_name', 'Bar');
+        $page->fillField('Your email:', 'ever.zet@gmail.com');
+
+        $this->assertEquals('Foo "item"', $firstname->getValue());
+        $this->assertEquals('Bar', $lastname->getValue());
+
+        $button->press();
+
+        if ($this->safePageWait(5000, 'document.getElementsByTagName("title") !== null')) {
+            $out = <<<OUT
+array (
+  'agreement' = 'on',
+  'email' = 'ever.zet@gmail.com',
+  'first_name' = 'Foo "item"',
+  'last_name' = 'Bar',
+  'notes' = 'new notes',
+  'select_number' = '30',
+  'sex' = 'm',
+  'submit' = 'Register',
+)
+some_file.txt
+1 uploaded file
+OUT;
+            $this->assertContains($out, $page->getContent());
+        }
+    }
+
+    public function testMultiInput()
+    {
+        $this->getSession()->visit($this->pathTo('/multi_input_form.html'));
+        $page = $this->getSession()->getPage();
+        $webAssert = $this->getAssertSession();
+        $this->assertEquals('Multi input Test', $webAssert->elementExists('css', 'h1')->getText());
+
+        $first = $webAssert->fieldExists('First');
+        $second = $webAssert->fieldExists('Second');
+        $third = $webAssert->fieldExists('Third');
+
+        $this->assertEquals('tag1', $first->getValue());
+        $this->assertSame('tag2', $second->getValue());
+        $this->assertEquals('tag1', $third->getValue());
+
+        $first->setValue('tag2');
+        $this->assertEquals('tag2', $first->getValue());
+        $this->assertSame('tag2', $second->getValue());
+        $this->assertEquals('tag1', $third->getValue());
+
+        $second->setValue('one');
+
+        $this->assertEquals('tag2', $first->getValue());
+        $this->assertSame('one', $second->getValue());
+
+        $third->setValue('tag3');
+
+        $this->assertEquals('tag2', $first->getValue());
+        $this->assertSame('one', $second->getValue());
+        $this->assertEquals('tag3', $third->getValue());
+
+        $button = $page->findButton('Register');
+        $this->assertNotNull($button);
+        $button->press();
+
+        $space = ' ';
+        $out = <<<OUT
+  'tags' =$space
+  array (
+    0 = 'tag2',
+    1 = 'one',
+    2 = 'tag3',
+  ),
+OUT;
+        $this->assertContains($out, $page->getContent());
+    }
+
+    public function testAdvancedFormSecondSubmit()
+    {
+        $this->getSession()->visit($this->pathTo('/advanced_form.html'));
+        $page = $this->getSession()->getPage();
+
+        $button = $page->findButton('Login');
+        $this->assertNotNull($button);
+        $button->press();
+
+        $toSearch = array(
+            "'agreement' = 'off',",
+            "'submit' = 'Login',",
+            'no file',
+        );
+
+        $pageContent = $page->getContent();
+
+        foreach ($toSearch as $searchString) {
+            $this->assertContains($searchString, $pageContent);
+        }
+    }
+
+    public function testSubmitEmptyTextarea()
+    {
+        $this->getSession()->visit($this->pathTo('/empty_textarea.html'));
+        $page = $this->getSession()->getPage();
+
+        $page->pressButton('Save');
+
+        $toSearch = array(
+            "'textarea' = '',",
+            "'submit' = 'Save',",
+            'no file',
+        );
+
+        $pageContent = $page->getContent();
+
+        foreach ($toSearch as $searchString) {
+            $this->assertContains($searchString, $pageContent);
+        }
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Form/Html5Test.php b/core/vendor/behat/mink/driver-testsuite/tests/Form/Html5Test.php
new file mode 100644
index 0000000..b7f4716
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Form/Html5Test.php
@@ -0,0 +1,128 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Form;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class Html5Test extends TestCase
+{
+    public function testHtml5FormInputAttribute()
+    {
+        $this->getSession()->visit($this->pathTo('/html5_form.html'));
+        $page = $this->getSession()->getPage();
+        $webAssert = $this->getAssertSession();
+
+        $firstName = $webAssert->fieldExists('first_name');
+        $lastName = $webAssert->fieldExists('last_name');
+
+        $this->assertEquals('not set', $lastName->getValue());
+        $firstName->setValue('John');
+        $lastName->setValue('Doe');
+
+        $this->assertEquals('Doe', $lastName->getValue());
+
+        $page->pressButton('Submit in form');
+
+        if ($this->safePageWait(5000, 'document.getElementsByTagName("title") !== null')) {
+            $out = <<<OUT
+  'first_name' = 'John',
+  'last_name' = 'Doe',
+OUT;
+            $this->assertContains($out, $page->getContent());
+            $this->assertNotContains('other_field', $page->getContent());
+        }
+    }
+
+    public function testHtml5FormRadioAttribute()
+    {
+        $this->getSession()->visit($this->pathTo('html5_radio.html'));
+        $page = $this->getSession()->getPage();
+
+        $radio = $this->findById('sex_f');
+        $otherRadio = $this->findById('sex_invalid');
+
+        $this->assertEquals('f', $radio->getValue());
+        $this->assertEquals('invalid', $otherRadio->getValue());
+
+        $radio->selectOption('m');
+
+        $this->assertEquals('m', $radio->getValue());
+        $this->assertEquals('invalid', $otherRadio->getValue());
+
+        $page->pressButton('Submit in form');
+
+        $out = <<<OUT
+  'sex' = 'm',
+OUT;
+        $this->assertContains($out, $page->getContent());
+    }
+
+    public function testHtml5FormButtonAttribute()
+    {
+        $this->getSession()->visit($this->pathTo('/html5_form.html'));
+        $page = $this->getSession()->getPage();
+        $webAssert = $this->getAssertSession();
+
+        $firstName = $webAssert->fieldExists('first_name');
+        $lastName = $webAssert->fieldExists('last_name');
+
+        $firstName->setValue('John');
+        $lastName->setValue('Doe');
+
+        $page->pressButton('Submit outside form');
+
+        if ($this->safePageWait(5000, 'document.getElementsByTagName("title") !== null')) {
+            $out = <<<OUT
+  'first_name' = 'John',
+  'last_name' = 'Doe',
+  'submit_button' = 'test',
+OUT;
+            $this->assertContains($out, $page->getContent());
+        }
+    }
+
+    public function testHtml5FormOutside()
+    {
+        $this->getSession()->visit($this->pathTo('/html5_form.html'));
+        $page = $this->getSession()->getPage();
+
+        $page->fillField('other_field', 'hello');
+
+        $page->pressButton('Submit separate form');
+
+        if ($this->safePageWait(5000, 'document.getElementsByTagName("title") !== null')) {
+            $out = <<<OUT
+  'other_field' = 'hello',
+OUT;
+            $this->assertContains($out, $page->getContent());
+            $this->assertNotContains('first_name', $page->getContent());
+        }
+    }
+
+    public function testHtml5Types()
+    {
+        $this->getSession()->visit($this->pathTo('html5_types.html'));
+        $page = $this->getSession()->getPage();
+
+        $page->fillField('url', 'http://mink.behat.org/');
+        $page->fillField('email', 'mink@example.org');
+        $page->fillField('number', '6');
+        $page->fillField('search', 'mink');
+        $page->fillField('date', '2014-05-19');
+        $page->fillField('color', '#ff00aa');
+
+        $page->pressButton('Submit');
+
+        $out = <<<OUT
+  'color' = '#ff00aa',
+  'date' = '2014-05-19',
+  'email' = 'mink@example.org',
+  'number' = '6',
+  'search' = 'mink',
+  'submit_button' = 'Submit',
+  'url' = 'http://mink.behat.org/',
+OUT;
+
+        $this->assertContains($out, $page->getContent());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Form/RadioTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Form/RadioTest.php
new file mode 100644
index 0000000..39cd743
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Form/RadioTest.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Form;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class RadioTest extends TestCase
+{
+    protected function setUp()
+    {
+        $this->getSession()->visit($this->pathTo('radio.html'));
+    }
+
+    public function testIsChecked()
+    {
+        $option = $this->findById('first');
+        $option2 = $this->findById('second');
+
+        $this->assertTrue($option->isChecked());
+        $this->assertFalse($option2->isChecked());
+
+        $option2->selectOption('updated');
+
+        $this->assertFalse($option->isChecked());
+        $this->assertTrue($option2->isChecked());
+    }
+
+    public function testSelectOption()
+    {
+        $option = $this->findById('first');
+
+        $this->assertEquals('set', $option->getValue());
+
+        $option->selectOption('updated');
+
+        $this->assertEquals('updated', $option->getValue());
+
+        $option->selectOption('set');
+
+        $this->assertEquals('set', $option->getValue());
+    }
+
+    public function testSetValue()
+    {
+        $option = $this->findById('first');
+
+        $this->assertEquals('set', $option->getValue());
+
+        $option->setValue('updated');
+
+        $this->assertEquals('updated', $option->getValue());
+        $this->assertFalse($option->isChecked());
+    }
+
+    public function testSameNameInMultipleForms()
+    {
+        $option1 = $this->findById('reused_form1');
+        $option2 = $this->findById('reused_form2');
+
+        $this->assertEquals('test2', $option1->getValue());
+        $this->assertEquals('test3', $option2->getValue());
+
+        $option1->selectOption('test');
+
+        $this->assertEquals('test', $option1->getValue());
+        $this->assertEquals('test3', $option2->getValue());
+    }
+
+    /**
+     * @see https://github.com/Behat/MinkSahiDriver/issues/32
+     */
+    public function testSetValueXPathEscaping()
+    {
+        $session = $this->getSession();
+        $session->visit($this->pathTo('/advanced_form.html'));
+        $page = $session->getPage();
+
+        $sex = $page->find('xpath', '//*[@name = "sex"]' . "\n|\n" . '//*[@id = "sex"]');
+        $this->assertNotNull($sex, 'xpath with line ending works');
+
+        $sex->setValue('m');
+        $this->assertEquals('m', $sex->getValue(), 'no double xpath escaping during radio button value change');
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Form/SelectTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Form/SelectTest.php
new file mode 100644
index 0000000..492625a
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Form/SelectTest.php
@@ -0,0 +1,135 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Form;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class SelectTest extends TestCase
+{
+    public function testMultiselect()
+    {
+        $this->getSession()->visit($this->pathTo('/multiselect_form.html'));
+        $webAssert = $this->getAssertSession();
+        $page = $this->getSession()->getPage();
+        $this->assertEquals('Multiselect Test', $webAssert->elementExists('css', 'h1')->getText());
+
+        $select      = $webAssert->fieldExists('select_number');
+        $multiSelect = $webAssert->fieldExists('select_multiple_numbers[]');
+        $secondMultiSelect = $webAssert->fieldExists('select_multiple_values[]');
+
+        $this->assertEquals('20', $select->getValue());
+        $this->assertSame(array(), $multiSelect->getValue());
+        $this->assertSame(array('2', '3'), $secondMultiSelect->getValue());
+
+        $select->selectOption('thirty');
+        $this->assertEquals('30', $select->getValue());
+
+        $multiSelect->selectOption('one', true);
+
+        $this->assertSame(array('1'), $multiSelect->getValue());
+
+        $multiSelect->selectOption('three', true);
+
+        $this->assertEquals(array('1', '3'), $multiSelect->getValue());
+
+        $secondMultiSelect->selectOption('two');
+        $this->assertSame(array('2'), $secondMultiSelect->getValue());
+
+        $button = $page->findButton('Register');
+        $this->assertNotNull($button);
+        $button->press();
+
+        $space = ' ';
+        $out = <<<OUT
+  'agreement' = 'off',
+  'select_multiple_numbers' =$space
+  array (
+    0 = '1',
+    1 = '3',
+  ),
+  'select_multiple_values' =$space
+  array (
+    0 = '2',
+  ),
+  'select_number' = '30',
+OUT;
+        $this->assertContains($out, $page->getContent());
+    }
+
+    /**
+     * @dataProvider testElementSelectedStateCheckDataProvider
+     */
+    public function testElementSelectedStateCheck($selectName, $optionValue, $optionText)
+    {
+        $session = $this->getSession();
+        $webAssert = $this->getAssertSession();
+        $session->visit($this->pathTo('/multiselect_form.html'));
+        $select = $webAssert->fieldExists($selectName);
+
+        $optionValueEscaped = $session->getSelectorsHandler()->xpathLiteral($optionValue);
+        $option = $webAssert->elementExists('named', array('option', $optionValueEscaped));
+
+        $this->assertFalse($option->isSelected());
+        $select->selectOption($optionText);
+        $this->assertTrue($option->isSelected());
+    }
+
+    public function testElementSelectedStateCheckDataProvider()
+    {
+        return array(
+            array('select_number', '30', 'thirty'),
+            array('select_multiple_numbers[]', '2', 'two'),
+        );
+    }
+
+    public function testSetValueSingleSelect()
+    {
+        $session = $this->getSession();
+        $session->visit($this->pathTo('/multiselect_form.html'));
+        $select = $this->getAssertSession()->fieldExists('select_number');
+
+        $select->setValue('10');
+        $this->assertEquals('10', $select->getValue());
+    }
+
+    public function testSetValueMultiSelect()
+    {
+        $session = $this->getSession();
+        $session->visit($this->pathTo('/multiselect_form.html'));
+        $select = $this->getAssertSession()->fieldExists('select_multiple_values[]');
+
+        $select->setValue(array('1', '2'));
+        $this->assertEquals(array('1', '2'), $select->getValue());
+    }
+
+    /**
+     * @see https://github.com/Behat/Mink/issues/193
+     */
+    public function testOptionWithoutValue()
+    {
+        $session = $this->getSession();
+        $session->visit($this->pathTo('/issue193.html'));
+
+        $session->getPage()->selectFieldOption('options-without-values', 'Two');
+        $this->assertEquals('Two', $this->findById('options-without-values')->getValue());
+
+        $this->assertTrue($this->findById('two')->isSelected());
+        $this->assertFalse($this->findById('one')->isSelected());
+
+        $session->getPage()->selectFieldOption('options-with-values', 'two');
+        $this->assertEquals('two', $this->findById('options-with-values')->getValue());
+    }
+
+    /**
+     * @see https://github.com/Behat/Mink/issues/131
+     */
+    public function testAccentuatedOption()
+    {
+        $this->getSession()->visit($this->pathTo('/issue131.html'));
+        $page = $this->getSession()->getPage();
+
+        $page->selectFieldOption('foobar', 'Gimme some accentuÃ©s characters');
+
+        $this->assertEquals('1', $page->findField('foobar')->getValue());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Js/ChangeEventTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Js/ChangeEventTest.php
new file mode 100644
index 0000000..d1fd3f1
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Js/ChangeEventTest.php
@@ -0,0 +1,152 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Js;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class ChangeEventTest extends TestCase
+{
+    /**
+     * 'change' event should be fired after selecting an <option> in a <select>
+     *
+     * TODO check whether this test is redundant with other change event tests.
+     */
+    public function testIssue255()
+    {
+        $session = $this->getSession();
+        $session->visit($this->pathTo('/issue255.html'));
+
+        $session->getPage()->selectFieldOption('foo_select', 'Option 3');
+
+        $session->wait(2000, '$("#output_foo_select").text() != ""');
+        $this->assertEquals('onChangeSelect', $session->getPage()->find('css', '#output_foo_select')->getText());
+    }
+
+    public function testIssue178()
+    {
+        $session = $this->getSession();
+        $session->visit($this->pathTo('/issue178.html'));
+
+        $this->findById('source')->setValue('foo');
+        $this->assertEquals('foo', $this->findById('target')->getText());
+    }
+
+    /**
+     * @dataProvider setValueChangeEventDataProvider
+     * @group change-event-detector
+     */
+    public function testSetValueChangeEvent($elementId, $valueForEmpty, $valueForFilled = '')
+    {
+        $this->getSession()->visit($this->pathTo('/element_change_detector.html'));
+        $page = $this->getSession()->getPage();
+
+        $input = $this->findById($elementId);
+        $this->assertNull($page->findById($elementId.'-result'));
+
+        // Verify setting value, when control is initially empty.
+        $input->setValue($valueForEmpty);
+        $this->assertElementChangeCount($elementId, 'initial value setting triggers change event');
+
+        if ($valueForFilled) {
+            // Verify setting value, when control already has a value.
+            $this->findById('results')->click();
+            $input->setValue($valueForFilled);
+            $this->assertElementChangeCount($elementId, 'value change triggers change event');
+        }
+    }
+
+    public function setValueChangeEventDataProvider()
+    {
+        return array(
+            'input default' => array('the-input-default', 'from empty', 'from existing'),
+            'input text' => array('the-input-text', 'from empty', 'from existing'),
+            'input email' => array('the-email', 'from empty', 'from existing'),
+            'textarea' => array('the-textarea', 'from empty', 'from existing'),
+            'file' => array('the-file', 'from empty', 'from existing'),
+            'select' => array('the-select', '30'),
+            'radio' => array('the-radio-m', 'm'),
+        );
+    }
+
+    /**
+     * @dataProvider selectOptionChangeEventDataProvider
+     * @group change-event-detector
+     */
+    public function testSelectOptionChangeEvent($elementId, $elementValue)
+    {
+        $this->getSession()->visit($this->pathTo('/element_change_detector.html'));
+        $page = $this->getSession()->getPage();
+
+        $input = $this->findById($elementId);
+        $this->assertNull($page->findById($elementId.'-result'));
+
+        $input->selectOption($elementValue);
+        $this->assertElementChangeCount($elementId);
+    }
+
+    public function selectOptionChangeEventDataProvider()
+    {
+        return array(
+            'select' => array('the-select', '30'),
+            'radio' => array('the-radio-m', 'm'),
+        );
+    }
+
+    /**
+     * @dataProvider checkboxTestWayDataProvider
+     * @group change-event-detector
+     */
+    public function testCheckChangeEvent($useSetValue)
+    {
+        $this->getSession()->visit($this->pathTo('/element_change_detector.html'));
+        $page = $this->getSession()->getPage();
+
+        $checkbox = $this->findById('the-unchecked-checkbox');
+        $this->assertNull($page->findById('the-unchecked-checkbox-result'));
+
+        if ($useSetValue) {
+            $checkbox->setValue(true);
+        } else {
+            $checkbox->check();
+        }
+
+        $this->assertElementChangeCount('the-unchecked-checkbox');
+    }
+
+    /**
+     * @dataProvider checkboxTestWayDataProvider
+     * @group change-event-detector
+     */
+    public function testUncheckChangeEvent($useSetValue)
+    {
+        $this->getSession()->visit($this->pathTo('/element_change_detector.html'));
+        $page = $this->getSession()->getPage();
+
+        $checkbox = $this->findById('the-checked-checkbox');
+        $this->assertNull($page->findById('the-checked-checkbox-result'));
+
+        if ($useSetValue) {
+            $checkbox->setValue(false);
+        } else {
+            $checkbox->uncheck();
+        }
+
+        $this->assertElementChangeCount('the-checked-checkbox');
+    }
+
+    public function checkboxTestWayDataProvider()
+    {
+        return array(
+            array(true),
+            array(false),
+        );
+    }
+
+    private function assertElementChangeCount($elementId, $message = '')
+    {
+        $counterElement = $this->getSession()->getPage()->findById($elementId.'-result');
+        $actualCount = null === $counterElement ? 0 : $counterElement->getText();
+
+        $this->assertEquals('1', $actualCount, $message);
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Js/EventsTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Js/EventsTest.php
new file mode 100644
index 0000000..00d084b
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Js/EventsTest.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Js;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class EventsTest extends TestCase
+{
+    /**
+     * @group mouse-events
+     */
+    public function testClick()
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+        $clicker = $this->getAssertSession()->elementExists('css', '.elements div#clicker');
+        $this->assertEquals('not clicked', $clicker->getText());
+
+        $clicker->click();
+        $this->assertEquals('single clicked', $clicker->getText());
+    }
+
+    /**
+     * @group mouse-events
+     */
+    public function testDoubleClick()
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+        $clicker = $this->getAssertSession()->elementExists('css', '.elements div#clicker');
+        $this->assertEquals('not clicked', $clicker->getText());
+
+        $clicker->doubleClick();
+        $this->assertEquals('double clicked', $clicker->getText());
+    }
+
+    /**
+     * @group mouse-events
+     */
+    public function testRightClick()
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+        $clicker = $this->getAssertSession()->elementExists('css', '.elements div#clicker');
+        $this->assertEquals('not clicked', $clicker->getText());
+
+        $clicker->rightClick();
+        $this->assertEquals('right clicked', $clicker->getText());
+    }
+
+    /**
+     * @group mouse-events
+     */
+    public function testFocus()
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+        $focusBlurDetector = $this->getAssertSession()->elementExists('css', '.elements input#focus-blur-detector');
+        $this->assertEquals('no action detected', $focusBlurDetector->getValue());
+
+        $focusBlurDetector->focus();
+        $this->assertEquals('focused', $focusBlurDetector->getValue());
+    }
+
+    /**
+     * @group mouse-events
+     * @depends testFocus
+     */
+    public function testBlur()
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+        $focusBlurDetector = $this->getAssertSession()->elementExists('css', '.elements input#focus-blur-detector');
+        $this->assertEquals('no action detected', $focusBlurDetector->getValue());
+
+        $focusBlurDetector->blur();
+        $this->assertEquals('blured', $focusBlurDetector->getValue());
+    }
+
+    /**
+     * @group mouse-events
+     */
+    public function testMouseOver()
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+        $mouseOverDetector = $this->getAssertSession()->elementExists('css', '.elements div#mouseover-detector');
+        $this->assertEquals('no mouse action detected', $mouseOverDetector->getText());
+
+        $mouseOverDetector->mouseOver();
+        $this->assertEquals('mouse overed', $mouseOverDetector->getText());
+    }
+
+    /**
+     * @dataProvider provideKeyboardEventsModifiers
+     */
+    public function testKeyboardEvents($modifier, $eventProperties)
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+        $webAssert = $this->getAssertSession();
+
+        $input1 = $webAssert->elementExists('css', '.elements input.input.first');
+        $input2 = $webAssert->elementExists('css', '.elements input.input.second');
+        $input3 = $webAssert->elementExists('css', '.elements input.input.third');
+        $event  = $webAssert->elementExists('css', '.elements .text-event');
+
+        $input1->keyDown('u', $modifier);
+        $this->assertEquals('key downed:' . $eventProperties, $event->getText());
+
+        $input2->keyPress('r', $modifier);
+        $this->assertEquals('key pressed:114 / ' . $eventProperties, $event->getText());
+
+        $input3->keyUp(78, $modifier);
+        $this->assertEquals('key upped:78 / ' . $eventProperties, $event->getText());
+    }
+
+    public function provideKeyboardEventsModifiers()
+    {
+        return array(
+            'none' => array(null, '0 / 0 / 0 / 0'),
+            'alt' => array('alt', '1 / 0 / 0 / 0'),
+             // jQuery considers ctrl as being a metaKey in the normalized event
+            'ctrl' => array('ctrl', '0 / 1 / 0 / 1'),
+            'shift' => array('shift', '0 / 0 / 1 / 0'),
+            'meta' => array('meta', '0 / 0 / 0 / 1'),
+        );
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Js/JavascriptEvaluationTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Js/JavascriptEvaluationTest.php
new file mode 100644
index 0000000..00235d1
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Js/JavascriptEvaluationTest.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Js;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class JavascriptEvaluationTest extends TestCase
+{
+    /**
+     * Tests, that `wait` method returns check result after exit.
+     */
+    public function testWaitReturnValue()
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+
+        $found = $this->getSession()->wait(5000, '$("#draggable").length == 1');
+        $this->assertTrue($found);
+    }
+
+    public function testWait()
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+
+        $waitable = $this->findById('waitable');
+
+        $waitable->click();
+        $this->getSession()->wait(3000, '$("#waitable").has("div").length > 0');
+        $this->assertEquals('arrived', $this->getSession()->getPage()->find('css', '#waitable > div')->getText());
+
+        $waitable->click();
+        $this->getSession()->wait(3000, 'false');
+        $this->assertEquals('timeout', $this->getSession()->getPage()->find('css', '#waitable > div')->getText());
+    }
+
+    /**
+     * @dataProvider provideExecutedScript
+     */
+    public function testExecuteScript($script)
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->getSession()->executeScript($script);
+
+        sleep(1);
+
+        $heading = $this->getAssertSession()->elementExists('css', 'h1');
+        $this->assertEquals('Hello world', $heading->getText());
+    }
+
+    public function provideExecutedScript()
+    {
+        return array(
+            array('document.querySelector("h1").textContent = "Hello world"'),
+            array('document.querySelector("h1").textContent = "Hello world";'),
+            array('function () {document.querySelector("h1").textContent = "Hello world";}()'),
+            array('function () {document.querySelector("h1").textContent = "Hello world";}();'),
+            array('(function () {document.querySelector("h1").textContent = "Hello world";})()'),
+            array('(function () {document.querySelector("h1").textContent = "Hello world";})();'),
+        );
+    }
+
+    /**
+     * @dataProvider provideEvaluatedScript
+     */
+    public function testEvaluateJavascript($script)
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+
+        $this->assertSame(2, $this->getSession()->evaluateScript($script));
+    }
+
+    public function provideEvaluatedScript()
+    {
+        return array(
+            array('1 + 1'),
+            array('1 + 1;'),
+            array('return 1 + 1'),
+            array('return 1 + 1;'),
+            array('function () {return 1+1;}()'),
+            array('(function () {return 1+1;})()'),
+            array('return function () { return 1+1;}()'),
+            array('return (function () {return 1+1;})()'),
+        );
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Js/JavascriptTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Js/JavascriptTest.php
new file mode 100644
index 0000000..86cfa65
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Js/JavascriptTest.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Js;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class JavascriptTest extends TestCase
+{
+    public function testAriaRoles()
+    {
+        $this->getSession()->visit($this->pathTo('/aria_roles.html'));
+
+        $this->getSession()->wait(5000, '$("#hidden-element").is(":visible") === false');
+        $this->getSession()->getPage()->pressButton('Toggle');
+        $this->getSession()->wait(5000, '$("#hidden-element").is(":visible") === true');
+
+        $this->getSession()->getPage()->clickLink('Go to Index');
+        $this->assertEquals($this->pathTo('/index.html'), $this->getSession()->getCurrentUrl());
+    }
+
+    public function testDragDrop()
+    {
+        $this->getSession()->visit($this->pathTo('/js_test.html'));
+        $webAssert = $this->getAssertSession();
+
+        $draggable = $webAssert->elementExists('css', '#draggable');
+        $droppable = $webAssert->elementExists('css', '#droppable');
+
+        $draggable->dragTo($droppable);
+        $this->assertEquals('Dropped!', $droppable->find('css', 'p')->getText());
+    }
+
+    // test accentuated char in button
+    public function testIssue225()
+    {
+        $this->getSession()->visit($this->pathTo('/issue225.html'));
+        $this->getSession()->getPage()->pressButton('CrÃ©er un compte');
+        $this->getSession()->wait(5000, '$("#panel").text() != ""');
+
+        $this->assertContains('OH AIH!', $this->getSession()->getPage()->getText());
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/Js/WindowTest.php b/core/vendor/behat/mink/driver-testsuite/tests/Js/WindowTest.php
new file mode 100644
index 0000000..70b9ed9
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/Js/WindowTest.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver\Js;
+
+use Behat\Mink\Tests\Driver\TestCase;
+
+class WindowTest extends TestCase
+{
+    public function testWindow()
+    {
+        $this->getSession()->visit($this->pathTo('/window.html'));
+        $session = $this->getSession();
+        $page    = $session->getPage();
+        $webAssert = $this->getAssertSession();
+
+        $page->clickLink('Popup #1');
+        $session->switchToWindow(null);
+
+        $page->clickLink('Popup #2');
+        $session->switchToWindow(null);
+
+        $el = $webAssert->elementExists('css', '#text');
+        $this->assertSame('Main window div text', $el->getText());
+
+        $session->switchToWindow('popup_1');
+        $el = $webAssert->elementExists('css', '#text');
+        $this->assertSame('Popup#1 div text', $el->getText());
+
+        $session->switchToWindow('popup_2');
+        $el = $webAssert->elementExists('css', '#text');
+        $this->assertSame('Popup#2 div text', $el->getText());
+
+        $session->switchToWindow(null);
+        $el = $webAssert->elementExists('css', '#text');
+        $this->assertSame('Main window div text', $el->getText());
+    }
+
+    public function testGetWindowNames()
+    {
+        $this->getSession()->visit($this->pathTo('/window.html'));
+        $session = $this->getSession();
+        $page    = $session->getPage();
+
+        $windowName = $this->getSession()->getWindowName();
+
+        $this->assertNotNull($windowName);
+
+        $page->clickLink('Popup #1');
+        $page->clickLink('Popup #2');
+
+        $windowNames = $this->getSession()->getWindowNames();
+
+        $this->assertNotNull($windowNames[0]);
+        $this->assertNotNull($windowNames[1]);
+        $this->assertNotNull($windowNames[2]);
+    }
+
+    public function testResizeWindow()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+        $session = $this->getSession();
+
+        $session->resizeWindow(400, 300);
+        $session->wait(1000, 'false');
+
+        $script = "return Math.abs(window.outerHeight - 300) <= 100 && Math.abs(window.outerWidth - 400) <= 100;";
+
+        $this->assertTrue($session->evaluateScript($script));
+    }
+
+    public function testWindowMaximize()
+    {
+        $this->getSession()->visit($this->pathTo('/index.html'));
+        $session = $this->getSession();
+
+        $session->maximizeWindow();
+        $session->wait(1000, 'false');
+
+        $script = "return Math.abs(screen.availHeight - window.outerHeight) <= 100;";
+
+        $this->assertTrue($session->evaluateScript($script));
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/tests/TestCase.php b/core/vendor/behat/mink/driver-testsuite/tests/TestCase.php
new file mode 100644
index 0000000..22860f6
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/tests/TestCase.php
@@ -0,0 +1,156 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver;
+
+use Behat\Mink\Exception\UnsupportedDriverActionException;
+use Behat\Mink\Mink;
+use Behat\Mink\Session;
+use Behat\Mink\WebAssert;
+
+abstract class TestCase extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Mink session manager.
+     *
+     * @var Mink
+     */
+    private static $mink;
+
+    /**
+     * @var AbstractConfig
+     */
+    private static $config;
+
+    /**
+     * Initializes the test case
+     */
+    public static function setUpBeforeClass()
+    {
+        if (null === self::$mink) {
+            $session = new Session(self::getConfig()->createDriver());
+            self::$mink = new Mink(array('sess' => $session));
+        }
+    }
+
+    /**
+     * @return AbstractConfig
+     *
+     * @throws \UnexpectedValueException if the global driver_config_factory returns an invalid object
+     */
+    private static function getConfig()
+    {
+        if (null === self::$config) {
+            self::$config = call_user_func($GLOBALS['driver_config_factory']);
+
+            if (!self::$config instanceof AbstractConfig) {
+                throw new \UnexpectedValueException('The "driver_config_factory" global variable must return a \Behat\Mink\Tests\Driver\AbstractConfig.');
+            }
+        }
+
+        return self::$config;
+    }
+
+    protected function checkRequirements()
+    {
+        if (null !== $message = self::getConfig()->skipMessage(get_class($this), $this->getName(false))) {
+            $this->markTestSkipped($message);
+        }
+
+        parent::checkRequirements();
+    }
+
+    protected function tearDown()
+    {
+        if (null !== self::$mink) {
+            self::$mink->resetSessions();
+        }
+    }
+
+    protected function onNotSuccessfulTest(\Exception $e)
+    {
+        if ($e instanceof UnsupportedDriverActionException) {
+            $this->markTestSkipped($e->getMessage());
+        }
+
+        parent::onNotSuccessfulTest($e);
+    }
+
+    /**
+     * Returns session.
+     *
+     * @return Session
+     */
+    protected function getSession()
+    {
+        return self::$mink->getSession('sess');
+    }
+
+    /**
+     * Returns assert session.
+     *
+     * @return WebAssert
+     */
+    protected function getAssertSession()
+    {
+        return self::$mink->assertSession('sess');
+    }
+
+    /**
+     * @param string $id
+     *
+     * @return \Behat\Mink\Element\NodeElement
+     */
+    protected function findById($id)
+    {
+        $id = $this->getSession()->getSelectorsHandler()->xpathLiteral($id);
+
+        return $this->getAssertSession()->elementExists('named', array('id', $id));
+    }
+
+    /**
+     * Map remote file path.
+     *
+     * @param string $file File path.
+     *
+     * @return string
+     */
+    protected function mapRemoteFilePath($file)
+    {
+        $realPath = realpath($file);
+
+        if (false !== $realPath) {
+            $file = $realPath;
+        }
+
+        return self::getConfig()->mapRemoteFilePath($file);
+    }
+
+    /**
+     * @param string $path
+     *
+     * @return string
+     */
+    protected function pathTo($path)
+    {
+        return rtrim(self::getConfig()->getWebFixturesUrl(), '/') . '/' . ltrim($path, '/');
+    }
+
+    /**
+     * Waits for a condition to be true, considering than it is successful for drivers not supporting wait()
+     *
+     * @param int    $time
+     * @param string $condition A JS condition to evaluate
+     *
+     * @return bool
+     *
+     * @see \Behat\Mink\Session::wait()
+     */
+    protected function safePageWait($time, $condition)
+    {
+        try {
+            return $this->getSession()->wait($time, $condition);
+        } catch (UnsupportedDriverActionException $e) {
+            return true;
+        }
+    }
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/404.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/404.php
new file mode 100644
index 0000000..d16db99
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/404.php
@@ -0,0 +1,2 @@
+<?php header("HTTP/1.0 404 Not Found") ?>
+Sorry, page not found
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/500.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/500.php
new file mode 100644
index 0000000..c43efcb
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/500.php
@@ -0,0 +1,2 @@
+<?php header("HTTP/1.0 500 Server Error") ?>
+Sorry, a server error happened
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/advanced_form.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/advanced_form.html
new file mode 100644
index 0000000..a2392c0
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/advanced_form.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>ADvanced Form</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <h1>ADvanced Form Page</h1>
+
+    <form method="POST" enctype="multipart/form-data" action="advanced_form_post.php">
+        <input name="first_name" value="Firstname" type="text" />
+        <input id="lastn" name="last_name" value="Lastname" type="text" />
+        <label for="email">
+            Your email:
+            <input type="email" id="email" name="email" value="your@email.com" />
+        </label>
+
+        <select name="select_number">
+            <option value="10">ten</option>
+            <option selected="selected" value="20">twenty</option>
+            <option value="30">thirty</option>
+        </select>
+
+        <label>
+            <span><input type="radio" name="sex" value="m" /> m</span>
+            <span><input type="radio" name="sex" value="w" checked="checked" /> w</span>
+        </label>
+
+        <input type="checkbox" name="mail_list" checked="checked" value="on"/>
+        <input type="checkbox" name="agreement" value="yes"/>
+
+        <textarea name="notes">original notes</textarea>
+
+        <input type="file" name="about" />
+
+        <input type="submit" name="submit" value="Register" />
+        <input type="submit" name="submit" value="Login" />
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/advanced_form_post.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/advanced_form_post.php
new file mode 100644
index 0000000..755806d
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/advanced_form_post.php
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Advanced form save</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+</head>
+<body>
+<?php
+error_reporting(0);
+
+if (isset($_POST['select_multiple_numbers']) && false !== strpos($_POST['select_multiple_numbers'][0], ',')) {
+    $_POST['select_multiple_numbers'] = explode(',', $_POST['select_multiple_numbers'][0]);
+}
+
+$_POST['agreement'] = isset($_POST['agreement']) ? 'on' : 'off';
+ksort($_POST);
+echo str_replace('>', '', var_export($_POST, true)) . "\n";
+if (isset($_FILES['about']) && file_exists($_FILES['about']['tmp_name'])) {
+    echo $_FILES['about']['name'] . "\n";
+    echo file_get_contents($_FILES['about']['tmp_name']);
+} else {
+    echo "no file";
+}
+?>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/aria_roles.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/aria_roles.html
new file mode 100644
index 0000000..7074e85
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/aria_roles.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>ARIA roles test</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+	This page tests selected ARIA roles<br />
+	(see <a href="http://www.w3.org/TR/wai-aria/">http://www.w3.org/TR/wai-aria/</a>)
+
+	<div id="hidden-element-toggle-button" role="button">Toggle</div>
+	<div id="hidden-element" style="display:none;">This content's visibility is changed by clicking the Toggle Button.</div>
+
+	<!-- This link is created programmatically -->
+	<div id="link-element"></div>
+
+    <script language="javascript" type="text/javascript" src="js/jquery-1.6.2-min.js"></script>
+	<script language="javascript" type="text/javascript">
+		$(document).ready(function() {
+			$('#hidden-element-toggle-button').click(function() {
+				$('#hidden-element').toggle();
+			});
+
+			$('#link-element').attr('role', 'link').text('Go to Index').click(function() {
+        window.location.href = 'index.html';
+			});
+		});
+	</script>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_auth.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_auth.php
new file mode 100644
index 0000000..9620a0e
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_auth.php
@@ -0,0 +1,12 @@
+<?php
+$username = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : false;
+$password = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : false;
+
+if ($username == 'mink-user' && $password == 'mink-password') {
+    echo 'is authenticated';
+} else {
+    header('WWW-Authenticate: Basic realm="Mink Testing Area"');
+    header('HTTP/1.0 401 Unauthorized');
+
+    echo 'is not authenticated';
+}
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_form.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_form.html
new file mode 100644
index 0000000..2d330cf
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_form.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Basic Form</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <h1>Basic Form Page</h1>
+
+    <form method="POST" action="basic_form_post.php">
+        <input name="first_name" value="Firstname" type="text" />
+        <input id="lastn" name="last_name" value="Lastname" type="text" />
+
+        <input type="reset" id="Reset" />
+
+        <input type="submit" id="Save" />
+        <input type="image" id="input-type-image"/>
+        <button>button-without-type</button>
+        <button type="submit">button-type-submit</button>
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_form_post.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_form_post.php
new file mode 100644
index 0000000..8a5e340
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_form_post.php
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Basic Form Saving</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <h1>Anket for <?php echo $_POST['first_name'] ?></h1>
+
+    <span id="first">Firstname: <?php echo $_POST['first_name'] ?></span>
+    <span id="last">Lastname: <?php echo $_POST['last_name'] ?></span>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_get_form.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_get_form.php
new file mode 100644
index 0000000..a0b3516
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/basic_get_form.php
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Basic Get Form</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <h1>Basic Get Form Page</h1>
+
+    <div id="serach">
+        <?php echo isset($_GET['q']) && $_GET['q'] ? $_GET['q'] : 'No search query' ?>
+    </div>
+
+    <form>
+        <input name="q" value="" type="text" />
+
+        <input type="submit" value="Find" />
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/cookie_page1.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/cookie_page1.php
new file mode 100644
index 0000000..7f128ca
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/cookie_page1.php
@@ -0,0 +1,21 @@
+<?php
+if (!isset($cookieAtRootPath)) {
+    $cookieAtRootPath = true;
+}
+
+if (!isset($cookieValue)) {
+    $cookieValue = 'srv_var_is_set';
+}
+
+setcookie('srvr_cookie', $cookieValue, null, $cookieAtRootPath ? '/' : null);
+?>
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Basic Form</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    Basic Page With Cookie Set from Server Side
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/cookie_page2.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/cookie_page2.php
new file mode 100644
index 0000000..22bcd1b
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/cookie_page2.php
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Basic Form</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    Previous cookie: <?php echo isset($_COOKIE['srvr_cookie']) ? $_COOKIE['srvr_cookie'] : 'NO'; ?>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/cookie_page3.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/cookie_page3.php
new file mode 100644
index 0000000..caa28bc
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/cookie_page3.php
@@ -0,0 +1,16 @@
+<?php
+
+$hasCookie = isset($_COOKIE['foo']);
+setcookie('foo', 'bar', 0, '/', null, false, true);
+
+?>
+<!DOCTYPE html>
+<html>
+<head>
+    <title>HttpOnly Cookie Test</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+	<div id="cookie-status">Has Cookie: <?php echo json_encode($hasCookie) ?></div>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/css_mouse_events.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/css_mouse_events.html
new file mode 100644
index 0000000..750ca54
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/css_mouse_events.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <title>CSS Mouse Events Testing</title>
+        <style type="text/css">
+            .squares div {
+                width: 100px;
+                height: 100px;
+                border: 1px solid black;
+                margin-right: 4px;
+                float: left;
+            }
+
+            .squares div:hover {
+                height: 200px;
+                background-color: red;
+            }
+        </style>
+
+        <script language="javascript" type="text/javascript" src="js/jquery-1.6.2-min.js"></script>
+    </head>
+
+    <body>
+        <div class="squares">
+            <div id="reset-square">reset</div>
+            <div id="action-square">mouse action</div>
+        </div>
+        <script>
+            $('#action-square').bind('contextmenu', function (e) {
+                // Prevent opening the context menu on right click as the browser might consider the
+                // mouse is in the context menu rather than hovering the element
+                e.preventDefault();
+            });
+        </script>
+    </body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/element_change_detector.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/element_change_detector.html
new file mode 100644
index 0000000..af3032a
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/element_change_detector.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>ADvanced Form</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+    <script src="js/jquery-1.6.2-min.js"></script>
+</head>
+<body>
+    <h1>ADvanced Form Page</h1>
+
+    <form method="POST" enctype="multipart/form-data" action="advanced_form_post.php">
+        <input id="the-input-default" value="" />
+        <input type="text" id="the-input-text" value="" />
+        <input type="email" id="the-email" value="" />
+
+        <select id="the-select">
+            <option value="10">ten</option>
+            <option value="20" selected="selected">twenty</option>
+            <option value="30">thirty</option>
+        </select>
+
+        <label>
+            <span><input type="radio" name="sex" id="the-radio-m" value="m" /> m</span>
+            <span><input type="radio" name="sex" id="the-radio-w" value="w" checked="checked" /> w</span>
+        </label>
+
+        <input type="checkbox" id="the-checked-checkbox" value="cb-val" checked/>
+        <input type="checkbox" id="the-unchecked-checkbox" value="cb-val"/>
+
+        <textarea id="the-textarea"></textarea>
+
+        <input type="file" id="the-file" />
+    </form>
+
+    <ul id="results" style="border: 1px solid red;">
+        <li>for easy element location</li>
+    </ul>
+
+    <script type="text/javascript">
+        $(document).ready(function () {
+            var $change_registry = {},
+                $results = $('#results');
+
+            $(':input').change(function ($e) {
+                var $result_id = this.id + '-result';
+
+                if (!$change_registry[this.id]) {
+                    $change_registry[this.id] = 1;
+                    $results.append('<li id="' + $result_id + '"></li>');
+                }
+                else {
+                    $change_registry[this.id]++;
+                }
+
+                $('#' + $result_id).text($change_registry[this.id]);
+            });
+
+            $results.click(function () {
+                $results.empty();
+                $change_registry = {};
+            });
+        });
+    </script>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/empty_textarea.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/empty_textarea.html
new file mode 100644
index 0000000..f0779ee
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/empty_textarea.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <title>Empty textarea submission</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+    <h1>Empty textarea submission</h1>
+    <form method="POST" action="advanced_form_post.php">
+        <textarea name="textarea"></textarea>
+        <input type="submit" name="submit" value="Save" />
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/form_without_button.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/form_without_button.html
new file mode 100644
index 0000000..8063026
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/form_without_button.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>Form submission without button test</title>
+</head>
+<body>
+    <form action="basic_form_post.php" method="POST">
+        <input name="first_name" type="text" value="not set">
+        <input name="last_name" type="text" value="not set">
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/headers.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/headers.php
new file mode 100644
index 0000000..25d9b90
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/headers.php
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Headers page</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <?php print_r($_SERVER); ?>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/html5_form.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/html5_form.html
new file mode 100644
index 0000000..9070353
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/html5_form.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>HTML5 form attribute test</title>
+</head>
+<body>
+    <form action="advanced_form_post.php" method="POST" id="test-form">
+        <input name="first_name" type="text" value="not set">
+        <input name="other_field" type="text" value="not submitted" form="another">
+        <input type="submit" value="Submit separate form" form="another">
+        <input type="submit" value="Submit in form">
+    </form>
+    <input name="last_name" type="text" form="test-form" value="not set">
+    <button type="submit" form="test-form" name="submit_button" value="test">Submit outside form</button>
+    <form id="another" method="post" action="advanced_form_post.php"></form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/html5_radio.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/html5_radio.html
new file mode 100644
index 0000000..fd54c2d
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/html5_radio.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>HTML5 form attribute test</title>
+</head>
+<body>
+    <form action="advanced_form_post.php" method="POST" id="test-form">
+        <input name="sex" type="radio" value="m" id="sex_m">
+        <input name="sex" type="radio" value="invalid" form="another" id="sex_invalid" checked="checked">
+        <input type="submit" value="Submit in form">
+    </form>
+    <input name="sex" type="radio" form="test-form" value="f" id="sex_f" checked="checked">
+    <form id="another" method="post" action="advanced_form_post.php"></form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/html5_types.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/html5_types.html
new file mode 100644
index 0000000..bd46cfa
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/html5_types.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>HTML5 form attribute test</title>
+</head>
+<body>
+    <form action="advanced_form_post.php" method="POST">
+        <input name="url" type="url">
+        <input name="email" type="email">
+        <input name="number" type="number">
+        <input name="search" type="search">
+        <input name="color" type="color">
+        <input name="date" type="date">
+        <input type="submit" name="submit_button" value="Submit">
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/html_decoding.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/html_decoding.html
new file mode 100644
index 0000000..341f226
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/html_decoding.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>HTML Decoding Test</title>
+</head>
+<body>
+    <div>
+        <span custom-attr="&amp;">some text</span>
+
+        <form method="post" action="index.html">
+            <input value="&amp;"/>
+
+            <input type="submit" value="Send"/>
+        </form>
+    </div>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/iframe.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/iframe.html
new file mode 100644
index 0000000..c54797f
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/iframe.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<iframe src="iframe_inner.html" name="subframe"></iframe>
+
+<div id="text">
+    Main window div text
+</div>
+
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/iframe_inner.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/iframe_inner.html
new file mode 100644
index 0000000..512f058
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/iframe_inner.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+    <div id="text">
+        iFrame div text
+    </div>
+
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/index.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/index.html
new file mode 100644
index 0000000..6bb379c
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/index.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Index page</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <h1>Extremely useless page</h1>
+    <div id="core">
+        <strong>Lorem</strong> ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim <strong>veniam</strong>, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla <strong class="super-duper">pariatur</strong>. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+
+        <div id="some-element" data-href="http://mink.behat.org">
+            some <div>very
+            </div>
+<em>interesting</em>      text
+        </div>
+
+        <div class="attribute-testing">
+            <input type="text" id="attr-elem[with-value]" with-value="some-value"/>
+            <input type="text" id="attr-elem[without-value]" without-value/>
+            <input type="text" id="attr-elem[with-empty-value]" with-empty-value=""/>
+            <input type="text" id="attr-elem[with-missing]"/>
+        </div>
+
+        <div class="travers">
+            <div class="sub">el1</div>
+            <div class="sub">el2</div>
+            <div class="sub">
+                <a href="some_url">some <strong>deep</strong> url</a>
+            </div>
+        </div>
+
+        <div class="sub">el4</div>
+
+    </div>
+
+    <footer>
+        <form id="search-form">
+            <input type="text" placeholder="Search site..." />
+        </form>
+        <form id="profile">
+            <div data-custom="something">
+                <label>
+                    <input type="text" id="user-name" name="username" />
+                </label>
+            </div>
+            <input type="submit" />
+        </form>
+    </footer>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue130.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue130.php
new file mode 100644
index 0000000..201d982
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue130.php
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<body>
+    <?php
+    if ('1' === $_GET['p']) {
+        echo '<a href="issue130.php?p=2">Go to 2</a>';
+    } else {
+        echo '<strong>'.$_SERVER['HTTP_REFERER'].'</strong>';
+    }
+    ?>
+</body>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue131.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue131.html
new file mode 100644
index 0000000..fa3427a
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue131.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <title>Issue 131</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+    <h1>There is a non breaking&#160;space</h1>
+    <pre id="foobar">Some accentuÃ©s characters</pre>
+    <form>
+        <select name="foobar">
+          <option value="1">Gimme some accentuÃ©s characters</option>
+        </select>
+        <input type="submit" />
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue140.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue140.php
new file mode 100644
index 0000000..04a4caf
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue140.php
@@ -0,0 +1,16 @@
+<?php
+if (!empty($_POST)) {
+    setcookie("tc", $_POST['cookie_value'], null, '/');
+} elseif (isset($_GET["show_value"])) {
+    echo $_COOKIE["tc"];
+    die();
+}
+?>
+<!DOCTYPE html>
+<html>
+<body>
+    <form method="post">
+        <input name="cookie_value">
+        <input type="submit" value="Set cookie">
+    </form>
+</body>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue178.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue178.html
new file mode 100644
index 0000000..3efc743
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue178.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>Index page</title>
+</head>
+<body>
+
+<form action="#">
+	<div>
+		<input type="text" name="source" id="source"
+			onkeyup="document.getElementById('target').innerHTML = this.value" value="bar">
+	</div>
+</form>
+
+<div id="target"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue193.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue193.html
new file mode 100644
index 0000000..e722a43
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue193.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Index page</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+
+<form action="#">
+    <select id="options-without-values" name="without">
+        <option>none selected</option>
+        <option id="one">One</option>
+        <option id="two">Two</option>
+        <option>Three</option>
+    </select>
+
+    <select id="options-with-values" name="with">
+        <option value="none">none selected</option>
+        <option value="one">One</option>
+        <option value="two">Two</option>
+        <option value="three">Three</option>
+    </select>
+</form>
+
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue211.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue211.html
new file mode 100644
index 0000000..bb977ec
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue211.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Index page</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+
+<form action="#">
+    <p>
+        <label for="phone">TÃ©lÃ©phone</label>
+        <input type="text" name="phone" id="phone" />
+    </p>
+    <p>
+        <label for="daphone">DaPhone</label>
+        <input type="text" name="daphone" id="daphone" />
+    </p>
+
+    <input type="submit" value="Send" />
+</form>
+
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue212.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue212.html
new file mode 100644
index 0000000..24ae62f
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue212.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<body>
+  <form action="/" method="post" id="user-login-form">
+    <input type="submit" name="toto" id="jaguar-button" value="jaguar"/>
+    <input type="submit" name="toto" id="poney-button" value="poney"/>
+  </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue215.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue215.html
new file mode 100644
index 0000000..adff3fb
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue215.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>Index page</title>
+</head>
+<body>
+
+<form action="#">
+<textarea rows="10" cols="10" id="textarea">
+foo
+bar
+</textarea>
+</form>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue225.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue225.html
new file mode 100644
index 0000000..2178bba
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue225.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="fr">
+<head>
+    <title>Index page</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+    <script src="js/jquery-1.6.2-min.js"></script>
+</head>
+<body>
+
+<button id="btn">CrÃ©er un compte</button>
+
+<div id="panel"></div>
+
+<script type="text/javascript">
+    $('#btn').click(function (event) {
+        $('#panel').text('OH ' + 'AIH!');
+    });
+</script>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue255.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue255.html
new file mode 100644
index 0000000..d56a427
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/issue255.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <title>Issue 255</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+    <script src="js/jquery-1.6.2-min.js"></script>
+</head>
+<body>
+    <form>
+        <label for="foo_select">Foo</label>
+        <select name="foo_select" id="foo_select">
+            <option value="1" selected="selected">Option 1</option>
+            <option value="2">Option 2</option>
+            <option value="3">Option 3</option>
+        </select>
+        <input type="checkbox" id="foo_check" />
+        <input type="submit" />
+        <p id="output_foo_select"></p>
+        <p id="output_foo_check"></p>
+    </form>
+
+    <script type="text/javascript">
+        (function() {
+            $('#foo_select').change(function () {
+                $('#output_foo_select').text("onChangeSelect");
+            });
+            $('#foo_check').change(function () {
+                $('#output_foo_check').text("onChangeCheck");
+            });
+        })();
+    </script>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/js/jquery-1.6.2-min.js b/core/vendor/behat/mink/driver-testsuite/web-fixtures/js/jquery-1.6.2-min.js
new file mode 100644
index 0000000..8cdc80e
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/js/jquery-1.6.2-min.js
@@ -0,0 +1,18 @@
+/*!
+ * jQuery JavaScript Library v1.6.2
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Jun 30 14:16:56 2011 -0400
+ */
+(function(a,b){function cv(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cs(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bZ(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bY(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bC.test(a)?d(a,e):bY(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)bY(a+"["+e+"]",b[e],c,d);else d(a,b)}function bX(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bR,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bX(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bX(a,c,d,e,"*",g));return l}function bW(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bN),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bA(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bv:bw;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bg(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function W(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(R.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(x,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(H)return H.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g](h)}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u=/\:|^on/,v,w;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(o);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(o);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(n," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.
+shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,N(a.origType,a.selector),f.extend({},a,{handler:M,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,N(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?E:D):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=E;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=E;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=E,this.stopPropagation()},isDefaultPrevented:D,isPropagationStopped:D,isImmediatePropagationStopped:D};var F=function(a){var b=a.relatedTarget,c=!1,d=a.type;a.type=a.data,b!==this&&(b&&(c=f.contains(this,b)),c||(f.event.handle.apply(this,arguments),a.type=d))},G=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?G:F,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?G:F)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=b.type;(c==="submit"||c==="image")&&f(b).closest("form").length&&K("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=b.type;(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&K("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var H,I=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var L={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||D,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=x.exec(h),k="",j&&(k=j[0],h=h.replace(x,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,L[h]?(a.push(L[h]+k),h=h+k):h=(L[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+N(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+N(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var O=/Until$/,P=/^(?:parents|prevUntil|prevAll)/,Q=/,/,R=/^.[^:#\[\.,]*$/,S=Array.prototype.slice,T=f.expr.match.POS,U={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(W(this,a,!1),"not",a)},filter:function(a){return this.pushStack(W(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=T.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/<tbody/i,ba=/<|&#?\w+;/,bb=/<(?:script|object|embed|option|style)/i,bc=/checked\s*(?:[^=]|=\s*.checked.)/i,bd=/\/(java|ecma)script/i,be=/^\s*<!(?:\[CDATA\[|\-\-)/,bf={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bc.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bg(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bm)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i;b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!bb.test(a[0])&&(f.support.checkClone||!bc.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j
+)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1></$2>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bl(k[i]);else bl(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bd.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bn=/alpha\([^)]*\)/i,bo=/opacity=([^)]*)/,bp=/([A-Z]|^ms)/g,bq=/^-?\d+(?:px)?$/i,br=/^-?\d/,bs=/^[+\-]=/,bt=/[^+\-\.\de]+/g,bu={position:"absolute",visibility:"hidden",display:"block"},bv=["Left","Right"],bw=["Top","Bottom"],bx,by,bz;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bx(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d;if(h==="number"&&isNaN(d)||d==null)return;h==="string"&&bs.test(d)&&(d=+d.replace(bt,"")+parseFloat(f.css(a,c)),h="number"),h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bx)return bx(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bA(a,b,d);f.swap(a,bu,function(){e=bA(a,b,d)});return e}},set:function(a,b){if(!bq.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cs(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cr("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cr("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cs(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cj.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=ck.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cr("show",1),slideUp:cr("hide",1),slideToggle:cr("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function h(a){return d.step(a)}var d=this,e=f.fx,g;this.startTime=cn||cp(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,h.elem=this.elem,h()&&f.timers.push(h)&&!cl&&(co?(cl=!0,g=function(){cl&&(co(g),e.tick())},co(g)):cl=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cn||cp(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cl),cl=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var ct=/^t(?:able|d|h)$/i,cu=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cv(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!ct.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
\ No newline at end of file
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/js/jquery-ui-1.8.14.custom.min.js b/core/vendor/behat/mink/driver-testsuite/web-fixtures/js/jquery-ui-1.8.14.custom.min.js
new file mode 100644
index 0000000..1764e11
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/js/jquery-ui-1.8.14.custom.min.js
@@ -0,0 +1,127 @@
+/*!
+ * jQuery UI 1.8.14
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI
+ */
+(function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if("area"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:"a"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.14",
+keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();
+b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,
+"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",
+function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(n)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,
+outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,"tabindex")))},tabbable:function(a){var b=c.attr(a,"tabindex"),d=isNaN(b);
+return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=
+0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&&c.ui.isOverAxis(b,e,i)}})}})(jQuery);
+;/*!
+ * jQuery UI Widget 1.8.14
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Widget
+ */
+(function(b,j){if(b.cleanData){var k=b.cleanData;b.cleanData=function(a){for(var c=0,d;(d=a[c])!=null;c++)b(d).triggerHandler("remove");k(a)}}else{var l=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add([this]).each(function(){b(this).triggerHandler("remove")});return l.call(b(this),a,c)})}}b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,
+a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend(true,{},c.options);b[e][a].prototype=b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.charAt(0)==="_")return h;
+e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==j){h=i;return false}}):this.each(function(){var g=b.data(this,a);g?g.option(d||{})._init():b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){b.data(c,this.widgetName,this);this.element=b(c);this.options=b.extend(true,{},this.options,
+this._getCreateOptions(),a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},
+widget:function(){return this.element},option:function(a,c){var d=a;if(arguments.length===0)return b.extend({},this.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}this._setOptions(d);return this},_setOptions:function(a){var c=this;b.each(a,function(d,e){c._setOption(d,e)});return this},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},
+enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
+;/*!
+ * jQuery UI Mouse 1.8.14
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * Depends:
+ *	jquery.ui.widget.js
+ */
+(function(b){var d=false;b(document).mousedown(function(){d=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(c){return a._mouseDown(c)}).bind("click."+this.widgetName,function(c){if(true===b.data(c.target,a.widgetName+".preventClickEvent")){b.removeData(c.target,a.widgetName+".preventClickEvent");c.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+
+this.widgetName)},_mouseDown:function(a){if(!d){this._mouseStarted&&this._mouseUp(a);this._mouseDownEvent=a;var c=this,f=a.which==1,g=typeof this.options.cancel=="string"?b(a.target).closest(this.options.cancel).length:false;if(!f||g||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){c.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==
+false;if(!this._mouseStarted){a.preventDefault();return true}}true===b.data(a.target,this.widgetName+".preventClickEvent")&&b.removeData(a.target,this.widgetName+".preventClickEvent");this._mouseMoveDelegate=function(e){return c._mouseMove(e)};this._mouseUpDelegate=function(e){return c._mouseUp(e)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);a.preventDefault();return d=true}},_mouseMove:function(a){if(b.browser.msie&&
+!(document.documentMode>=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=
+false;a.target==this._mouseDownEvent.target&&b.data(a.target,this.widgetName+".preventClickEvent",true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
+;/*
+ * jQuery UI Draggable 1.8.14
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.mouse.js
+ *	jquery.ui.widget.js
+ */
+(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper==
+"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b=
+this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;d(b.iframeFix===true?"iframe":b.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")});return true},_mouseStart:function(a){var b=this.options;this.helper=
+this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});
+this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);d.ui.ddmanager&&d.ui.ddmanager.dragStart(this,a);return true},
+_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=
+false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,
+10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},_mouseUp:function(a){this.options.iframeFix===true&&d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)});d.ui.ddmanager&&d.ui.ddmanager.dragStop(this,a);return d.ui.mouse.prototype._mouseUp.call(this,a)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||
+!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone().removeAttr("id"):this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&
+a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=
+this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),
+10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),
+10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[a.containment=="document"?0:d(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,a.containment=="document"?0:d(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,
+(a.containment=="document"?0:d(window).scrollLeft())+d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a.containment=="document"?0:d(window).scrollTop())+(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&a.containment.constructor!=Array){a=d(a.containment);var b=a[0];if(b){a.offset();var c=d(b).css("overflow")!=
+"hidden";this.containment=[(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0),(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0),(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),
+10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom];this.relative_container=a}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+
+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&
+!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,h=a.pageY;if(this.originalPosition){var g;if(this.containment){if(this.relative_container){g=this.relative_container.offset();g=[this.containment[0]+g.left,this.containment[1]+g.top,this.containment[2]+g.left,this.containment[3]+g.top]}else g=this.containment;if(a.pageX-this.offset.click.left<g[0])e=g[0]+this.offset.click.left;
+if(a.pageY-this.offset.click.top<g[1])h=g[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>g[2])e=g[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>g[3])h=g[3]+this.offset.click.top}if(b.grid){h=b.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/b.grid[1])*b.grid[1]:this.originalPageY;h=g?!(h-this.offset.click.top<g[1]||h-this.offset.click.top>g[3])?h:!(h-this.offset.click.top<g[1])?h-b.grid[1]:h+b.grid[1]:h;e=b.grid[0]?this.originalPageX+Math.round((e-this.originalPageX)/
+b.grid[0])*b.grid[0]:this.originalPageX;e=g?!(e-this.offset.click.left<g[0]||e-this.offset.click.left>g[2])?e:!(e-this.offset.click.left<g[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<
+526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,
+c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.14"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var h=d.data(this,"sortable");if(h&&!h.options.disabled){c.sortables.push({instance:h,shouldRevert:h.options.revert});
+h.refreshPositions();h._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=
+false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=d(f).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",true);
+this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top;
+c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&
+this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("opacity"))b._opacity=
+a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){if(!c.axis||c.axis!=
+"x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-b.overflowOffset.left<
+c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()-
+c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable","snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this,
+width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),f=c.options,e=f.snapTolerance,h=b.offset.left,g=h+c.helperProportions.width,n=b.offset.top,o=n+c.helperProportions.height,i=c.snapElements.length-1;i>=0;i--){var j=c.snapElements[i].left,l=j+c.snapElements[i].width,k=c.snapElements[i].top,m=k+c.snapElements[i].height;if(j-e<h&&h<l+e&&k-e<n&&n<m+e||j-e<h&&h<l+e&&k-e<o&&o<m+e||j-e<g&&g<l+e&&k-e<n&&n<m+e||j-e<g&&g<l+e&&k-e<o&&
+o<m+e){if(f.snapMode!="inner"){var p=Math.abs(k-o)<=e,q=Math.abs(m-n)<=e,r=Math.abs(j-g)<=e,s=Math.abs(l-h)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:k-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:m,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:j-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:l}).left-c.margins.left}var t=
+p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(k-n)<=e;q=Math.abs(m-o)<=e;r=Math.abs(j-h)<=e;s=Math.abs(l-g)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:k,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:m-c.helperProportions.height,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:j}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:l-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[i].snapping&&
+(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[i].item}));c.snapElements[i].snapping=p||q||r||s||t}else{c.snapElements[i].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[i].item}));c.snapElements[i].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),
+10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
+;/*
+ * jQuery UI Droppable 1.8.14
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.widget.js
+ *	jquery.ui.mouse.js
+ *	jquery.ui.draggable.js
+ */
+(function(d){d.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var a=this.options,b=a.accept;this.isover=0;this.isout=1;this.accept=d.isFunction(b)?b:function(c){return c.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};d.ui.ddmanager.droppables[a.scope]=d.ui.ddmanager.droppables[a.scope]||[];d.ui.ddmanager.droppables[a.scope].push(this);
+a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var a=d.ui.ddmanager.droppables[this.options.scope],b=0;b<a.length;b++)a[b]==this&&a.splice(b,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(a,b){if(a=="accept")this.accept=d.isFunction(b)?b:function(c){return c.is(b)};d.Widget.prototype._setOption.apply(this,arguments)},_activate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&
+this.element.addClass(this.options.activeClass);b&&this._trigger("activate",a,this.ui(b))},_deactivate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);b&&this._trigger("deactivate",a,this.ui(b))},_over:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass);
+this._trigger("over",a,this.ui(b))}},_out:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",a,this.ui(b))}},_drop:function(a,b){var c=b||d.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return false;var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var g=
+d.data(this,"droppable");if(g.options.greedy&&!g.options.disabled&&g.options.scope==c.options.scope&&g.accept.call(g.element[0],c.currentItem||c.element)&&d.ui.intersect(c,d.extend(g,{offset:g.element.offset()}),g.options.tolerance)){e=true;return false}});if(e)return false;if(this.accept.call(this.element[0],c.currentItem||c.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop",
+a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.14"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height;
+switch(c){case "fit":return i<=e&&g<=k&&j<=f&&h<=l;case "intersect":return i<e+a.helperProportions.width/2&&g-a.helperProportions.width/2<k&&j<f+a.helperProportions.height/2&&h-a.helperProportions.height/2<l;case "pointer":return d.ui.isOver((a.positionAbs||a.position.absolute).top+(a.clickOffset||a.offset.click).top,(a.positionAbs||a.position.absolute).left+(a.clickOffset||a.offset.click).left,j,i,b.proportions.height,b.proportions.width);case "touch":return(f>=j&&f<=l||h>=j&&h<=l||f<j&&h>l)&&(e>=
+i&&e<=k||g>=i&&g<=k||e<i&&g>k);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f<c.length;f++)if(!(c[f].options.disabled||a&&!c[f].accept.call(c[f].element[0],a.currentItem||a.element))){for(var h=0;h<g.length;h++)if(g[h]==c[f].element[0]){c[f].proportions.height=0;continue a}c[f].visible=c[f].element.css("display")!=
+"none";if(c[f].visible){e=="mousedown"&&c[f]._activate.call(c[f],b);c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight}}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem||
+a.element)){this.isout=1;this.isover=0;this._deactivate.call(this,b)}}});return c},dragStart:function(a,b){a.element.parentsUntil("body").bind("scroll.droppable",function(){a.options.refreshPositions||d.ui.ddmanager.prepareOffsets(a,b)})},drag:function(a,b){a.options.refreshPositions&&d.ui.ddmanager.prepareOffsets(a,b);d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var c=d.ui.intersect(a,this,this.options.tolerance);if(c=
+!c&&this.isover==1?"isout":c&&this.isover==0?"isover":null){var e;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");if(g.length){e=d.data(g[0],"droppable");e.greedyChild=c=="isover"?1:0}}if(e&&c=="isover"){e.isover=0;e.isout=1;e._out.call(e,b)}this[c]=1;this[c=="isout"?"isover":"isout"]=0;this[c=="isover"?"_over":"_out"].call(this,b);if(e&&c=="isout"){e.isout=0;e.isover=1;e._over.call(e,b)}}}})},dragStop:function(a,b){a.element.parentsUntil("body").unbind("scroll.droppable");
+a.options.refreshPositions||d.ui.ddmanager.prepareOffsets(a,b)}}})(jQuery);
+;
\ No newline at end of file
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/js_test.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/js_test.html
new file mode 100644
index 0000000..e965a40
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/js_test.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>JS elements test</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+
+    <style>
+        #draggable {
+            width: 100px; height: 100px; padding: 0.5em; float: left; margin: 10px 10px 10px 0;
+            background:#ccc;
+            opacity:0.5;
+        }
+        #droppable {
+            width: 150px; height: 150px; padding: 0.5em; float: left; margin: 10px;
+            background:#eee;
+        }
+        #waitable {
+            width: 150px; height: 150px; padding: 0.5em; float: left; margin: 10px;
+            background:#eee;
+        }
+    </style>
+</head>
+<body>
+    <div class="elements">
+        <div id="clicker">not clicked</div>
+        <div id="mouseover-detector">no mouse action detected</div>
+        <div id="invisible" style="display: none">invisible man</div>
+        <input id="focus-blur-detector" type="text" value="no action detected"/>
+        <input class="input first" type="text" value="" />
+        <input class="input second" type="text" value="" />
+        <input class="input third" type="text" value="" />
+        <div class="text-event"></div>
+    </div>
+
+    <div id="draggable" class="ui-widget-content"></div>
+
+    <div id="droppable" class="ui-widget-header">
+        <p>Drop here</p>
+    </div>
+
+    <div id="waitable"></div>
+
+    <script src="js/jquery-1.6.2-min.js"></script>
+    <script src="js/jquery-ui-1.8.14.custom.min.js"></script>
+	<script>
+		$(document).ready(function() {
+            $('#clicker').click(function() {
+                $(this).text('single clicked');
+            });
+
+            $('#clicker').dblclick(function() {
+                $(this).text('double clicked');
+            });
+
+            $('#clicker').bind('contextmenu', function() {
+                $(this).text('right clicked');
+            });
+
+            $('#focus-blur-detector').focus(function() {
+                $(this).val('focused');
+            });
+
+            $('#focus-blur-detector').blur(function() {
+                $(this).val('blured');
+            });
+
+            $('#mouseover-detector').mouseover(function() {
+                $(this).text('mouse overed');
+            });
+
+            $('.elements input.input.first').keydown(function(ev) {
+                $('.text-event').text('key downed:' + ev.altKey * 1 + ' / ' + ev.ctrlKey * 1 + ' / ' + ev.shiftKey * 1 + ' / ' + ev.metaKey * 1);
+            });
+
+            $('.elements input.input.second').keypress(function(ev) {
+                $('.text-event').text('key pressed:' + ev.which + ' / ' + ev.altKey * 1 + ' / ' + ev.ctrlKey * 1 + ' / ' + ev.shiftKey * 1 + ' / ' + ev.metaKey * 1);
+            });
+
+            $('.elements input.input.third').keyup(function(ev) {
+                $('.text-event').text('key upped:' + ev.which + ' / ' + ev.altKey * 1 + ' / ' + ev.ctrlKey * 1 + ' / ' + ev.shiftKey * 1 + ' / ' + ev.metaKey * 1);
+            });
+
+            $( "#draggable" ).draggable();
+            $( "#droppable" ).droppable({
+                drop: function( event, ui ) {
+                    $( this ).find( "p" ).html( "Dropped!" );
+                }
+            });
+
+            var t1, t2;
+
+            $('#waitable').click(function() {
+                var el = $(this);
+
+                el.html('');
+                clearTimeout(t1);
+                clearTimeout(t2);
+
+                t1 = setTimeout(function() {
+                    el.html('<div>arrived</div>');
+                }, 1000);
+
+                t2 = setTimeout(function() {
+                    el.html('<div>timeout</div>');
+                }, 2000);
+            });
+		});
+	</script>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/json.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/json.php
new file mode 100644
index 0000000..173d358
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/json.php
@@ -0,0 +1,7 @@
+<?php
+
+echo json_encode(array(
+    'key1' => 'val1',
+    'key2' => 234,
+    'key3' => array(1, 2, 3)
+));
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/links.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/links.html
new file mode 100644
index 0000000..ec626bf
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/links.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Links page</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <a href="redirector.php">Redirect me to</a>
+    <a href="randomizer.php">Random number page</a>
+    <a href="links.html?quoted">Link with a '</a>
+    <a href="basic_form.html">
+        <img src="basic_form" alt="basic form image"/>
+    </a>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/multi_input_form.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/multi_input_form.html
new file mode 100644
index 0000000..600a500
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/multi_input_form.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Multi input Test</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <h1>Multi input Test</h1>
+
+    <form method="POST" action="advanced_form_post.php">
+        <label>
+            First
+            <input type="text" name="tags[]" value="tag1">
+        </label>
+        <label>
+            Second
+            <input type="text" name="tags[]" value="tag2">
+        </label>
+        <label>
+            Third
+            <input type="text" name="tags[]" value="tag1">
+        </label>
+
+        <input type="submit" name="submit" value="Register" />
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/multicheckbox_form.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/multicheckbox_form.html
new file mode 100644
index 0000000..a2ae375
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/multicheckbox_form.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Multicheckbox Test</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <h1>Multicheckbox Test</h1>
+
+    <form method="POST" action="advanced_form_post.php">
+        <input type="checkbox" name="mail_types[]" checked="checked" value="update"/>
+        <input type="checkbox" name="mail_types[]" value="spam"/>
+
+        <input type="submit" name="submit" value="Register" />
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/multiselect_form.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/multiselect_form.html
new file mode 100644
index 0000000..0d28986
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/multiselect_form.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Multiselect Test</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <h1>Multiselect Test</h1>
+
+    <form method="POST" action="advanced_form_post.php">
+        <select name="select_number">
+            <option value="10">ten</option>
+            <option selected="selected" value="20">twenty</option>
+            <option value="30">thirty</option>
+        </select>
+
+        <select name="select_multiple_numbers[]" multiple="multiple">
+            <option value="1">one</option>
+            <option value="2">two</option>
+            <option value="3">three</option>
+        </select>
+
+        <select name="select_multiple_values[]" multiple="multiple">
+            <option value="1">one</option>
+            <option value="2" selected="selected">two</option>
+            <option value="3" selected="selected">three</option>
+        </select>
+
+        <input type="submit" name="submit" value="Register" />
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/popup1.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/popup1.html
new file mode 100644
index 0000000..b8e3fe2
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/popup1.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>popup_1</title>
+</head>
+<body>
+
+    <div id="text">
+        Popup#1 div text
+    </div>
+
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/popup2.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/popup2.html
new file mode 100644
index 0000000..dae1932
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/popup2.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>popup_2</title>
+</head>
+<body>
+
+    <div id="text">
+        Popup#2 div text
+    </div>
+
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/print_cookies.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/print_cookies.php
new file mode 100644
index 0000000..eef496e
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/print_cookies.php
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Cookies page</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <?php echo str_replace('>', '', var_export($_COOKIE, true)); ?>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/radio.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/radio.html
new file mode 100644
index 0000000..69a916a
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/radio.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>Radio group</title>
+</head>
+<body>
+    <form id="form1">
+        <input name="group1" type="radio" value="set" id="first" checked="checked">
+        <input name="group1" type="radio" value="updated" id="second">
+
+        <input name="reused" type="radio" value="test" id="reused_form1">
+        <input name="reused" type="radio" value="test2" id="reused2_form1" checked="checked">
+    </form>
+
+    <form id="form2">
+        <input name="reused" type="radio" value="test3" id="reused_form2" checked="checked">
+        <input name="reused" type="radio" value="test4" id="reused2_form2">
+    </form>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/randomizer.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/randomizer.php
new file mode 100644
index 0000000..07a73ec
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/randomizer.php
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Index page</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+
+    <h1 id="number"><?php echo rand() ?></h1>
+
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/redirect_destination.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/redirect_destination.html
new file mode 100644
index 0000000..3de7481
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/redirect_destination.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Redirect destination</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    You were redirected!
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/redirector.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/redirector.php
new file mode 100644
index 0000000..44ac8f3
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/redirector.php
@@ -0,0 +1,3 @@
+<?php
+
+header('location: redirect_destination.html');
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/response_headers.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/response_headers.php
new file mode 100644
index 0000000..a9166b7
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/response_headers.php
@@ -0,0 +1,15 @@
+<?php
+
+header('X-Mink-Test: response-headers');
+
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <title>Response headers</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+    <h1>Response headers</h1>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/session_test.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/session_test.php
new file mode 100644
index 0000000..df1af6f
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/session_test.php
@@ -0,0 +1,18 @@
+<?php
+session_name('_SESS');
+session_start();
+
+if (isset($_GET['login'])) {
+    session_regenerate_id();
+}
+?>
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Session Test</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+</head>
+<body>
+    <div id="session-id"><?php echo session_id() ?></div>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/some_file.txt b/core/vendor/behat/mink/driver-testsuite/web-fixtures/some_file.txt
new file mode 100644
index 0000000..d515a02
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/some_file.txt
@@ -0,0 +1 @@
+1 uploaded file
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/sub-folder/cookie_page1.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/sub-folder/cookie_page1.php
new file mode 100644
index 0000000..750249b
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/sub-folder/cookie_page1.php
@@ -0,0 +1,4 @@
+<?php
+$cookieAtRootPath = false;
+$cookieValue = 'srv_var_is_set_sub_folder';
+require_once __DIR__ . '/../' . basename(__FILE__);
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/sub-folder/cookie_page2.php b/core/vendor/behat/mink/driver-testsuite/web-fixtures/sub-folder/cookie_page2.php
new file mode 100644
index 0000000..9747fe8
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/sub-folder/cookie_page2.php
@@ -0,0 +1,2 @@
+<?php
+require_once __DIR__ . '/../' . basename(__FILE__);
diff --git a/core/vendor/behat/mink/driver-testsuite/web-fixtures/window.html b/core/vendor/behat/mink/driver-testsuite/web-fixtures/window.html
new file mode 100644
index 0000000..d0a4594
--- /dev/null
+++ b/core/vendor/behat/mink/driver-testsuite/web-fixtures/window.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<script>
+function newPopup(url, title) {
+    popupWindow = window.open(
+        url, title,'height=100,width=200,left=10,top=10,resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=yes'
+    );
+}
+</script>
+
+<a href="popup1.html" onclick="newPopup(this.href, 'popup_1'); return false;">
+    Popup #1
+</a>
+
+<a href="popup2.html" onclick="newPopup(this.href, 'popup_2'); return false;">
+    Popup #2
+</a>
+
+<div id="text">
+    Main window div text
+</div>
+
+</body>
+</html>
diff --git a/core/vendor/behat/mink/phpdoc.ini.dist b/core/vendor/behat/mink/phpdoc.ini.dist
new file mode 100644
index 0000000..fd64fd9
--- /dev/null
+++ b/core/vendor/behat/mink/phpdoc.ini.dist
@@ -0,0 +1,125 @@
+; Default configuration file for PHPDoctor
+
+; This config file will cause PHPDoctor to generate API documentation of
+; itself.
+
+
+; PHPDoctor settings
+; -----------------------------------------------------------------------------
+
+; Names of files to parse. This can be a single filename, or a comma separated
+; list of filenames. Wildcards are allowed.
+
+files = "*.php"
+
+; Names of files or directories to ignore. This can be a single filename, or a
+; comma separated list of filenames. Wildcards are NOT allowed.
+
+ignore = "CVS, .svn, .git, _compiled"
+
+; The directory to look for files in, if not used the PHPDoctor will look in
+; the current directory (the directory it is run from).
+
+source_path = "./src"
+
+; If you do not want PHPDoctor to look in each sub directory for files
+; uncomment this line.
+
+;subdirs = off
+
+; Set how loud PHPDoctor is as it runs. Quiet mode suppresses all output other
+; than warnings and errors. Verbose mode outputs additional messages during
+; execution.
+
+;quiet = on
+;verbose = on
+
+; Select the doclet to use for generating output.
+
+doclet = standard
+;doclet = debug
+
+; The directory to find the doclet in. Doclets are expected to be in a
+; directory named after themselves at the location given.
+
+;doclet_path = ./doclets
+
+; The directory to find taglets in. Taglets allow you to make PHPDoctor handle
+; new tags and to alter the behavour of existing tags and their output.
+
+;taglet_path = ./taglets
+
+; If the code you are parsing does not use package tags or not all elements
+; have package tags, use this setting to place unbound elements into a
+; particular package.
+
+default_package = "Behat\Mink"
+
+; Specifies the name of a HTML file containing text for the overview
+; documentation to be placed on the overview page. The path is relative to
+; "source_path" unless an absolute path is given.
+
+overview = readme.html
+
+; Package comments will be looked for in a file named package.html in the same
+; directory as the first source file parsed in that package or in the directory
+; given below. If package comments are placed in the directory given below then
+; they should be named "<packageName>.html".
+
+package_comment_dir = ./
+
+; Parse out global variables and/or global constants?
+
+;globals = off
+;constants = off
+
+; Generate documentation for all class members
+
+;private = on
+
+; Generate documentation for public and protected class members
+
+;protected = on
+
+; Generate documentation for only public class members
+
+public = on
+
+; Use the PEAR compatible handling of the docblock first sentence
+
+;pear_compat = on
+
+; Standard doclet settings
+; -----------------------------------------------------------------------------
+
+; The directory to place generated documentation in. If the given path is
+; relative to it will be relative to "source_path".
+
+d = "api"
+
+; Specifies the title to be placed in the HTML <title> tag.
+
+windowtitle = "Behat\Mink"
+
+; Specifies the title to be placed near the top of the overview summary file.
+
+doctitle = "Behat\Mink: browser emulators abstraction library for PHP"
+
+; Specifies the header text to be placed at the top of each output file. The
+; header will be placed to the right of the upper navigation bar.
+
+header = "Behat\Mink"
+
+; Specifies the footer text to be placed at the bottom of each output file. The
+; footer will be placed to the right of the lower navigation bar.
+
+footer = "Behat\Mink"
+
+; Specifies the text to be placed at the bottom of each output file. The text
+; will be placed at the bottom of the page, below the lower navigation bar.
+
+;bottom = "This document was generated by <a href="http://phpdoctor.sourceforge.net/">PHPDoctor: The PHP Documentation Creator</a>"
+
+; Create a class tree?
+
+tree = on
diff --git a/core/vendor/behat/mink/phpunit.xml.dist b/core/vendor/behat/mink/phpunit.xml.dist
new file mode 100644
index 0000000..bf73a69
--- /dev/null
+++ b/core/vendor/behat/mink/phpunit.xml.dist
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit colors="true" bootstrap="vendor/autoload.php">
+    <testsuites>
+        <testsuite name="Behat Mink test suite">
+            <directory>tests</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory>./src/Behat/Mink/</directory>
+        </whitelist>
+    </filter>
+</phpunit>
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Driver/CoreDriver.php b/core/vendor/behat/mink/src/Behat/Mink/Driver/CoreDriver.php
new file mode 100644
index 0000000..248f291
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Driver/CoreDriver.php
@@ -0,0 +1,447 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Driver;
+
+use Behat\Mink\Exception\UnsupportedDriverActionException;
+use Behat\Mink\Session;
+
+/**
+ * Core driver.
+ * All other drivers should extend this class for future compatibility.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+abstract class CoreDriver implements DriverInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function setSession(Session $session)
+    {
+        throw new UnsupportedDriverActionException('Setting the session is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function start()
+    {
+        throw new UnsupportedDriverActionException('Starting the driver is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isStarted()
+    {
+        throw new UnsupportedDriverActionException('Checking the driver state is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function stop()
+    {
+        throw new UnsupportedDriverActionException('Stopping the driver is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function reset()
+    {
+        throw new UnsupportedDriverActionException('Resetting the driver is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function visit($url)
+    {
+        throw new UnsupportedDriverActionException('Visiting an url is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getCurrentUrl()
+    {
+        throw new UnsupportedDriverActionException('Getting the current url is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getContent()
+    {
+        throw new UnsupportedDriverActionException('Getting the page content is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function find($xpath)
+    {
+        throw new UnsupportedDriverActionException('Finding elements is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTagName($xpath)
+    {
+        throw new UnsupportedDriverActionException('Getting the tag name is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getText($xpath)
+    {
+        throw new UnsupportedDriverActionException('Getting the element text is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getHtml($xpath)
+    {
+        throw new UnsupportedDriverActionException('Getting the element inner HTML is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getOuterHtml($xpath)
+    {
+        throw new UnsupportedDriverActionException('Getting the element outer HTML is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getAttribute($xpath, $name)
+    {
+        throw new UnsupportedDriverActionException('Getting the element attribute is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getValue($xpath)
+    {
+        throw new UnsupportedDriverActionException('Getting the field value is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setValue($xpath, $value)
+    {
+        throw new UnsupportedDriverActionException('Setting the field value is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function check($xpath)
+    {
+        throw new UnsupportedDriverActionException('Checking a checkbox is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function uncheck($xpath)
+    {
+        throw new UnsupportedDriverActionException('Unchecking a checkbox is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isChecked($xpath)
+    {
+        throw new UnsupportedDriverActionException('Getting the state of a checkbox is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function selectOption($xpath, $value, $multiple = false)
+    {
+        throw new UnsupportedDriverActionException('Selecting an option is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function click($xpath)
+    {
+        throw new UnsupportedDriverActionException('Clicking on an element is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function attachFile($xpath, $path)
+    {
+        throw new UnsupportedDriverActionException('Attaching a file in an input is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function reload()
+    {
+        throw new UnsupportedDriverActionException('Page reloading is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function forward()
+    {
+        throw new UnsupportedDriverActionException('Forward action is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function back()
+    {
+        throw new UnsupportedDriverActionException('Backward action is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setBasicAuth($user, $password)
+    {
+        throw new UnsupportedDriverActionException('Basic auth setup is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function switchToWindow($name = null)
+    {
+        throw new UnsupportedDriverActionException('Windows management is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function switchToIFrame($name = null)
+    {
+        throw new UnsupportedDriverActionException('iFrames management is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setRequestHeader($name, $value)
+    {
+        throw new UnsupportedDriverActionException('Request headers manipulation is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getResponseHeaders()
+    {
+        throw new UnsupportedDriverActionException('Response headers are not available from %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setCookie($name, $value = null)
+    {
+        throw new UnsupportedDriverActionException('Cookies manipulation is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getCookie($name)
+    {
+        throw new UnsupportedDriverActionException('Cookies are not available from %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getStatusCode()
+    {
+        throw new UnsupportedDriverActionException('Status code is not available from %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getScreenshot()
+    {
+        throw new UnsupportedDriverActionException('Screenshots are not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getWindowNames()
+    {
+        throw new UnsupportedDriverActionException('Listing all window names is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getWindowName()
+    {
+        throw new UnsupportedDriverActionException('Listing this window name is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function doubleClick($xpath)
+    {
+        throw new UnsupportedDriverActionException('Double-clicking is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rightClick($xpath)
+    {
+        throw new UnsupportedDriverActionException('Right-clicking is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isVisible($xpath)
+    {
+        throw new UnsupportedDriverActionException('Element visibility check is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isSelected($xpath)
+    {
+        throw new UnsupportedDriverActionException('Element selection check is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function mouseOver($xpath)
+    {
+        throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function focus($xpath)
+    {
+        throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function blur($xpath)
+    {
+        throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function keyPress($xpath, $char, $modifier = null)
+    {
+        throw new UnsupportedDriverActionException('Keyboard manipulations are not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function keyDown($xpath, $char, $modifier = null)
+    {
+        throw new UnsupportedDriverActionException('Keyboard manipulations are not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function keyUp($xpath, $char, $modifier = null)
+    {
+        throw new UnsupportedDriverActionException('Keyboard manipulations are not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function dragTo($sourceXpath, $destinationXpath)
+    {
+        throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function executeScript($script)
+    {
+        throw new UnsupportedDriverActionException('JS is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function evaluateScript($script)
+    {
+        throw new UnsupportedDriverActionException('JS is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function wait($timeout, $condition)
+    {
+        throw new UnsupportedDriverActionException('JS is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function resizeWindow($width, $height, $name = null)
+    {
+        throw new UnsupportedDriverActionException('Window resizing is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function maximizeWindow($name = null)
+    {
+        throw new UnsupportedDriverActionException('Window maximize is not supported by %s', $this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function submitForm($xpath)
+    {
+        throw new UnsupportedDriverActionException('Form submission is not supported by %s', $this);
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Driver/DriverInterface.php b/core/vendor/behat/mink/src/Behat/Mink/Driver/DriverInterface.php
new file mode 100644
index 0000000..831d408
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Driver/DriverInterface.php
@@ -0,0 +1,637 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Driver;
+
+use Behat\Mink\Element\NodeElement;
+use Behat\Mink\Exception\DriverException;
+use Behat\Mink\Exception\UnsupportedDriverActionException;
+use Behat\Mink\Session;
+
+/**
+ * Driver interface.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface DriverInterface
+{
+    /**
+     * Sets driver's current session.
+     *
+     * @param Session $session
+     */
+    public function setSession(Session $session);
+
+    /**
+     * Starts driver.
+     *
+     * Once started, the driver should be ready to visit a page.
+     *
+     * Calling any action before visiting a page is an undefined behavior.
+     * The only supported method calls on a fresh driver are
+     * - visit()
+     * - setRequestHeader()
+     * - setBasicAuth()
+     * - reset()
+     * - stop()
+     *
+     * Calling start on a started driver is an undefined behavior. Driver
+     * implementations are free to handle it silently or to fail with an
+     * exception.
+     *
+     * @throws DriverException When the driver cannot be started
+     */
+    public function start();
+
+    /**
+     * Checks whether driver is started.
+     *
+     * @return Boolean
+     */
+    public function isStarted();
+
+    /**
+     * Stops driver.
+     *
+     * Once stopped, the driver should be started again before using it again.
+     *
+     * Calling any action on a stopped driver is an undefined behavior.
+     * The only supported method call after stopping a driver is starting it again.
+     *
+     * Calling stop on a stopped driver is an undefined behavior. Driver
+     * implementations are free to handle it silently or to fail with an
+     * exception.
+     *
+     * @throws DriverException When the driver cannot be closed
+     */
+    public function stop();
+
+    /**
+     * Resets driver state.
+     *
+     * This should reset cookies, request headers and basic authentication.
+     * When possible, the history should be reset as well, but this is not enforced
+     * as some implementations may not be able to reset it without restarting the
+     * driver entirely. Consumers requiring a clean history should restart the driver
+     * to enforce it.
+     *
+     * Once reset, the driver should be ready to visit a page.
+     * Calling any action before visiting a page is an undefined behavior.
+     * The only supported method calls on a fresh driver are
+     * - visit()
+     * - setRequestHeader()
+     * - setBasicAuth()
+     * - reset()
+     * - stop()
+     *
+     * Calling reset on a stopped driver is an undefined behavior.
+     */
+    public function reset();
+
+    /**
+     * Visit specified URL.
+     *
+     * @param string $url url of the page
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function visit($url);
+
+    /**
+     * Returns current URL address.
+     *
+     * @return string
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getCurrentUrl();
+
+    /**
+     * Reloads current page.
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function reload();
+
+    /**
+     * Moves browser forward 1 page.
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function forward();
+
+    /**
+     * Moves browser backward 1 page.
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function back();
+
+    /**
+     * Sets HTTP Basic authentication parameters
+     *
+     * @param string|Boolean $user     user name or false to disable authentication
+     * @param string         $password password
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function setBasicAuth($user, $password);
+
+    /**
+     * Switches to specific browser window.
+     *
+     * @param string $name window name (null for switching back to main window)
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function switchToWindow($name = null);
+
+    /**
+     * Switches to specific iFrame.
+     *
+     * @param string $name iframe name (null for switching back)
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function switchToIFrame($name = null);
+
+    /**
+     * Sets specific request header on client.
+     *
+     * @param string $name
+     * @param string $value
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function setRequestHeader($name, $value);
+
+    /**
+     * Returns last response headers.
+     *
+     * @return array
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getResponseHeaders();
+
+    /**
+     * Sets cookie.
+     *
+     * @param string $name
+     * @param string $value
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function setCookie($name, $value = null);
+
+    /**
+     * Returns cookie by name.
+     *
+     * @param string $name
+     *
+     * @return string|null
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getCookie($name);
+
+    /**
+     * Returns last response status code.
+     *
+     * @return integer
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getStatusCode();
+
+    /**
+     * Returns last response content.
+     *
+     * @return string
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getContent();
+
+    /**
+     * Capture a screenshot of the current window.
+     *
+     * @return string screenshot of MIME type image/* depending
+     *                on driver (e.g., image/png, image/jpeg)
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getScreenshot();
+
+    /**
+     * Return the names of all open windows.
+     *
+     * @return array array of all open windows
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getWindowNames();
+
+    /**
+     * Return the name of the currently active window.
+     *
+     * @return string the name of the current window
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getWindowName();
+
+    /**
+     * Finds elements with specified XPath query.
+     *
+     * @param string $xpath
+     *
+     * @return NodeElement[]
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function find($xpath);
+
+    /**
+     * Returns element's tag name by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @return string
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getTagName($xpath);
+
+    /**
+     * Returns element's text by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @return string
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getText($xpath);
+
+    /**
+     * Returns element's inner html by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @return string
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getHtml($xpath);
+
+    /**
+     * Returns element's outer html by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @return string
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getOuterHtml($xpath);
+
+    /**
+     * Returns element's attribute by it's XPath query.
+     *
+     * @param string $xpath
+     * @param string $name
+     *
+     * @return string|null
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function getAttribute($xpath, $name);
+
+    /**
+     * Returns element's value by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @return string|bool|array
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     *
+     * @see \Behat\Mink\Element\NodeElement::getValue
+     */
+    public function getValue($xpath);
+
+    /**
+     * Sets element's value by it's XPath query.
+     *
+     * @param string            $xpath
+     * @param string|bool|array $value
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     *
+     * @see \Behat\Mink\Element\NodeElement::setValue
+     */
+    public function setValue($xpath, $value);
+
+    /**
+     * Checks checkbox by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     *
+     * @see \Behat\Mink\Element\NodeElement::check
+     */
+    public function check($xpath);
+
+    /**
+     * Unchecks checkbox by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     *
+     * @see \Behat\Mink\Element\NodeElement::uncheck
+     */
+    public function uncheck($xpath);
+
+    /**
+     * Checks whether checkbox or radio button located by it's XPath query is checked.
+     *
+     * @param string $xpath
+     *
+     * @return Boolean
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     *
+     * @see \Behat\Mink\Element\NodeElement::isChecked
+     */
+    public function isChecked($xpath);
+
+    /**
+     * Selects option from select field or value in radio group located by it's XPath query.
+     *
+     * @param string  $xpath
+     * @param string  $value
+     * @param Boolean $multiple
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     *
+     * @see \Behat\Mink\Element\NodeElement::selectOption
+     */
+    public function selectOption($xpath, $value, $multiple = false);
+
+    /**
+     * Checks whether select option, located by it's XPath query, is selected.
+     *
+     * @param string $xpath
+     *
+     * @return Boolean
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     *
+     * @see \Behat\Mink\Element\NodeElement::isSelected
+     */
+    public function isSelected($xpath);
+
+    /**
+     * Clicks button or link located by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function click($xpath);
+
+    /**
+     * Double-clicks button or link located by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function doubleClick($xpath);
+
+    /**
+     * Right-clicks button or link located by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function rightClick($xpath);
+
+    /**
+     * Attaches file path to file field located by it's XPath query.
+     *
+     * @param string $xpath
+     * @param string $path
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     *
+     * @see \Behat\Mink\Element\NodeElement::attachFile
+     */
+    public function attachFile($xpath, $path);
+
+    /**
+     * Checks whether element visible located by it's XPath query.
+     *
+     * @param string $xpath
+     *
+     * @return Boolean
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function isVisible($xpath);
+
+    /**
+     * Simulates a mouse over on the element.
+     *
+     * @param string $xpath
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function mouseOver($xpath);
+
+    /**
+     * Brings focus to element.
+     *
+     * @param string $xpath
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function focus($xpath);
+
+    /**
+     * Removes focus from element.
+     *
+     * @param string $xpath
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function blur($xpath);
+
+    /**
+     * Presses specific keyboard key.
+     *
+     * @param string         $xpath
+     * @param string|integer $char     could be either char ('b') or char-code (98)
+     * @param string         $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function keyPress($xpath, $char, $modifier = null);
+
+    /**
+     * Pressed down specific keyboard key.
+     *
+     * @param string         $xpath
+     * @param string|integer $char     could be either char ('b') or char-code (98)
+     * @param string         $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function keyDown($xpath, $char, $modifier = null);
+
+    /**
+     * Pressed up specific keyboard key.
+     *
+     * @param string         $xpath
+     * @param string|integer $char     could be either char ('b') or char-code (98)
+     * @param string         $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function keyUp($xpath, $char, $modifier = null);
+
+    /**
+     * Drag one element onto another.
+     *
+     * @param string $sourceXpath
+     * @param string $destinationXpath
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function dragTo($sourceXpath, $destinationXpath);
+
+    /**
+     * Executes JS script.
+     *
+     * @param string $script
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function executeScript($script);
+
+    /**
+     * Evaluates JS script.
+     *
+     * The "return" keyword is optional in the script passed as argument. Driver implementations
+     * must accept the expression both with and without the keyword.
+     *
+     * @param string $script
+     *
+     * @return mixed
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function evaluateScript($script);
+
+    /**
+     * Waits some time or until JS condition turns true.
+     *
+     * @param integer $timeout   timeout in milliseconds
+     * @param string  $condition JS condition
+     *
+     * @return boolean
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function wait($timeout, $condition);
+
+    /**
+     * Set the dimensions of the window.
+     *
+     * @param integer $width  set the window width, measured in pixels
+     * @param integer $height set the window height, measured in pixels
+     * @param string  $name   window name (null for the main window)
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function resizeWindow($width, $height, $name = null);
+
+    /**
+     * Maximize the window if it is not maximized already
+     *
+     * @param string $name window name (null for the main window)
+     *
+     * @throws UnsupportedDriverActionException When operation not supported by the driver
+     * @throws DriverException                  When the operation cannot be done
+     */
+    public function maximizeWindow($name = null);
+
+     /**
+      * Submits the form.
+      *
+      * @param string $xpath Xpath.
+      *
+      * @throws UnsupportedDriverActionException When operation not supported by the driver
+      * @throws DriverException                  When the operation cannot be done
+      *
+      * @see \Behat\Mink\Element\NodeElement::submitForm
+      */
+    public function submitForm($xpath);
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Element/DocumentElement.php b/core/vendor/behat/mink/src/Behat/Mink/Element/DocumentElement.php
new file mode 100644
index 0000000..dc6bc6e
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Element/DocumentElement.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Element;
+
+/**
+ * Document element.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class DocumentElement extends TraversableElement
+{
+    /**
+     * Returns XPath for handled element.
+     *
+     * @return string
+     */
+    public function getXpath()
+    {
+        return '//html';
+    }
+
+    /**
+     * Returns document content.
+     *
+     * @return string
+     */
+    public function getContent()
+    {
+        return trim($this->getDriver()->getContent());
+    }
+
+    /**
+     * Check whether document has specified content.
+     *
+     * @param string $content
+     *
+     * @return Boolean
+     */
+    public function hasContent($content)
+    {
+        return $this->has('named', array(
+            'content', $this->getSelectorsHandler()->xpathLiteral($content)
+        ));
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Element/Element.php b/core/vendor/behat/mink/src/Behat/Mink/Element/Element.php
new file mode 100644
index 0000000..07e1e11
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Element/Element.php
@@ -0,0 +1,207 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Element;
+
+use Behat\Mink\Driver\DriverInterface;
+use Behat\Mink\Exception\ElementNotFoundException;
+use Behat\Mink\Selector\SelectorsHandler;
+use Behat\Mink\Selector\Xpath\Manipulator;
+use Behat\Mink\Session;
+
+/**
+ * Base element.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+abstract class Element implements ElementInterface
+{
+    /**
+     * @var Session
+     */
+    private $session;
+
+    /**
+     * Driver.
+     *
+     * @var DriverInterface
+     */
+    private $driver;
+
+    /**
+     * @var SelectorsHandler
+     */
+    private $selectorsHandler;
+
+    /**
+     * @var Manipulator
+     */
+    private $xpathManipulator;
+
+    /**
+     * Initialize element.
+     *
+     * @param Session $session
+     */
+    public function __construct(Session $session)
+    {
+        $this->xpathManipulator = new Manipulator();
+        $this->session = $session;
+
+        $this->driver = $session->getDriver();
+        $this->selectorsHandler = $session->getSelectorsHandler();
+    }
+
+    /**
+     * Returns element session.
+     *
+     * @return Session
+     *
+     * @deprecated Accessing the session from the element is deprecated as of 1.6 and will be impossible in 2.0.
+     */
+    public function getSession()
+    {
+        return $this->session;
+    }
+
+    /**
+     * Returns element's driver.
+     *
+     * @return DriverInterface
+     */
+    protected function getDriver()
+    {
+        return $this->driver;
+    }
+
+    /**
+     * Returns selectors handler.
+     *
+     * @return SelectorsHandler
+     */
+    protected function getSelectorsHandler()
+    {
+        return $this->selectorsHandler;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function has($selector, $locator)
+    {
+        return null !== $this->find($selector, $locator);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isValid()
+    {
+        return 1 === count($this->getDriver()->find($this->getXpath()));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function waitFor($timeout, $callback)
+    {
+        if (!is_callable($callback)) {
+            throw new \InvalidArgumentException('Given callback is not a valid callable');
+        }
+
+        $start = microtime(true);
+        $end = $start + $timeout;
+
+        do {
+            $result = call_user_func($callback, $this);
+
+            if ($result) {
+                break;
+            }
+
+            usleep(100000);
+        } while (microtime(true) < $end);
+
+        return $result;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function find($selector, $locator)
+    {
+        $items = $this->findAll($selector, $locator);
+
+        return count($items) ? current($items) : null;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function findAll($selector, $locator)
+    {
+        if ('named' === $selector) {
+            $items = $this->findAll('named_exact', $locator);
+            if (empty($items)) {
+                $items = $this->findAll('named_partial', $locator);
+            }
+
+            return $items;
+        }
+
+        $xpath = $this->getSelectorsHandler()->selectorToXpath($selector, $locator);
+        $xpath = $this->xpathManipulator->prepend($xpath, $this->getXpath());
+
+        return $this->getDriver()->find($xpath);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getText()
+    {
+        return $this->getDriver()->getText($this->getXpath());
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getHtml()
+    {
+        return $this->getDriver()->getHtml($this->getXpath());
+    }
+
+    /**
+     * Returns element outer html.
+     *
+     * @return string
+     */
+    public function getOuterHtml()
+    {
+        return $this->getDriver()->getOuterHtml($this->getXpath());
+    }
+
+    /**
+     * Builds an ElementNotFoundException
+     *
+     * This is an helper to build the ElementNotFoundException without
+     * needing to use the deprecated getSession accessor in child classes.
+     *
+     * @param string      $type
+     * @param string|null $selector
+     * @param string|null $locator
+     *
+     * @return ElementNotFoundException
+     */
+    protected function elementNotFound($type, $selector = null, $locator = null)
+    {
+        return new ElementNotFoundException($this->session, $type, $selector, $locator);
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Element/ElementInterface.php b/core/vendor/behat/mink/src/Behat/Mink/Element/ElementInterface.php
new file mode 100644
index 0000000..8c134b9
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Element/ElementInterface.php
@@ -0,0 +1,114 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Element;
+
+use Behat\Mink\Session;
+
+/**
+ * Element interface.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface ElementInterface
+{
+    /**
+     * Returns XPath for handled element.
+     *
+     * @return string
+     */
+    public function getXpath();
+
+    /**
+     * Returns element's session.
+     *
+     * @return Session
+     *
+     * @deprecated Accessing the session from the element is deprecated as of 1.6 and will be impossible in 2.0.
+     */
+    public function getSession();
+
+    /**
+     * Checks whether element with specified selector exists inside the current element.
+     *
+     * @param string       $selector selector engine name
+     * @param string|array $locator  selector locator
+     *
+     * @return Boolean
+     *
+     * @see ElementInterface::findAll for the supported selectors
+     */
+    public function has($selector, $locator);
+
+    /**
+     * Checks if an element still exists in the DOM.
+     *
+     * @return boolean
+     */
+    public function isValid();
+
+    /**
+     * Waits for an element(-s) to appear and returns it.
+     *
+     * @param int|float $timeout  Maximal allowed waiting time in seconds.
+     * @param callable  $callback Callback, which result is both used as waiting condition and returned.
+     *                            Will receive reference to `this element` as first argument.
+     *
+     * @return mixed
+     * @throws \InvalidArgumentException When invalid callback given.
+     */
+    public function waitFor($timeout, $callback);
+
+    /**
+     * Finds first element with specified selector inside the current element.
+     *
+     * @param string       $selector selector engine name
+     * @param string|array $locator  selector locator
+     *
+     * @return NodeElement|null
+     *
+     * @see ElementInterface::findAll for the supported selectors
+     */
+    public function find($selector, $locator);
+
+    /**
+     * Finds all elements with specified selector inside the current element.
+     *
+     * Valid selector engines are named, xpath, css, named_partial and named_exact.
+     *
+     * 'named' is a pseudo selector engine which prefers an exact match but
+     * will return a partial match if no exact match is found.
+     * 'xpath' is a pseudo selector engine supported by SelectorsHandler.
+     *
+     * More selector engines can be registered in the SelectorsHandler.
+     *
+     * @param string       $selector selector engine name
+     * @param string|array $locator  selector locator
+     *
+     * @return NodeElement[]
+     *
+     * @see NamedSelector for the locators supported by the named selectors
+     */
+    public function findAll($selector, $locator);
+
+    /**
+     * Returns element text (inside tag).
+     *
+     * @return string
+     */
+    public function getText();
+
+    /**
+     * Returns element inner html.
+     *
+     * @return string
+     */
+    public function getHtml();
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Element/NodeElement.php b/core/vendor/behat/mink/src/Behat/Mink/Element/NodeElement.php
new file mode 100644
index 0000000..1f867ed
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Element/NodeElement.php
@@ -0,0 +1,352 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Element;
+
+use Behat\Mink\Session;
+use Behat\Mink\Exception\ElementNotFoundException;
+
+/**
+ * Page element node.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class NodeElement extends TraversableElement
+{
+    private $xpath;
+
+    /**
+     * Initializes node element.
+     *
+     * @param string  $xpath   element xpath
+     * @param Session $session session instance
+     */
+    public function __construct($xpath, Session $session)
+    {
+        $this->xpath = $xpath;
+
+        parent::__construct($session);
+    }
+
+    /**
+     * Returns XPath for handled element.
+     *
+     * @return string
+     */
+    public function getXpath()
+    {
+        return $this->xpath;
+    }
+
+    /**
+     * Returns parent element to the current one.
+     *
+     * @return NodeElement
+     */
+    public function getParent()
+    {
+        return $this->find('xpath', '..');
+    }
+
+    /**
+     * Returns current node tag name.
+     *
+     * The value is always returned in lowercase to allow an easy comparison.
+     *
+     * @return string
+     */
+    public function getTagName()
+    {
+        return strtolower($this->getDriver()->getTagName($this->getXpath()));
+    }
+
+    /**
+     * Returns the value of the form field or option element.
+     *
+     * For checkbox fields, the value is a boolean indicating whether the checkbox is checked.
+     * For radio buttons, the value is the value of the selected button in the radio group
+     *      or null if no button is selected.
+     * For single select boxes, the value is the value of the selected option.
+     * For multiple select boxes, the value is an array of selected option values.
+     * for file inputs, the return value is undefined given that browsers don't allow accessing
+     *      the value of file inputs for security reasons. Some drivers may allow accessing the
+     *      path of the file set in the field, but this is not required if it cannot be implemented.
+     * For textarea elements and all textual fields, the value is the content of the field.
+     * Form option elements, the value is the value of the option (the value attribute or the text
+     *      content if the attribute is not set).
+     *
+     * Calling this method on other elements than form fields or option elements is not allowed.
+     *
+     * @return string|bool|array
+     */
+    public function getValue()
+    {
+        return $this->getDriver()->getValue($this->getXpath());
+    }
+
+    /**
+     * Sets the value of the form field.
+     *
+     * Calling this method on other elements than form fields is not allowed.
+     *
+     * @param string|bool|array $value
+     *
+     * @see NodeElement::getValue for the format of the value for each type of field
+     */
+    public function setValue($value)
+    {
+        $this->getDriver()->setValue($this->getXpath(), $value);
+    }
+
+    /**
+     * Checks whether element has attribute with specified name.
+     *
+     * @param string $name
+     *
+     * @return Boolean
+     */
+    public function hasAttribute($name)
+    {
+        return null !== $this->getDriver()->getAttribute($this->getXpath(), $name);
+    }
+
+    /**
+     * Returns specified attribute value.
+     *
+     * @param string $name
+     *
+     * @return string|null
+     */
+    public function getAttribute($name)
+    {
+        return $this->getDriver()->getAttribute($this->getXpath(), $name);
+    }
+
+    /**
+     * Checks whether an element has a named CSS class
+     *
+     * @param string $className Name of the class
+     *
+     * @return boolean
+     */
+    public function hasClass($className)
+    {
+        if ($this->hasAttribute('class')) {
+            return in_array($className, explode(' ', $this->getAttribute('class')));
+        }
+
+        return false;
+    }
+
+    /**
+     * Clicks current node.
+     */
+    public function click()
+    {
+        $this->getDriver()->click($this->getXpath());
+    }
+
+    /**
+     * Presses current button.
+     */
+    public function press()
+    {
+        $this->click();
+    }
+
+    /**
+     * Double-clicks current node.
+     */
+    public function doubleClick()
+    {
+        $this->getDriver()->doubleClick($this->getXpath());
+    }
+
+    /**
+     * Right-clicks current node.
+     */
+    public function rightClick()
+    {
+        $this->getDriver()->rightClick($this->getXpath());
+    }
+
+    /**
+     * Checks current node if it's a checkbox field.
+     */
+    public function check()
+    {
+        $this->getDriver()->check($this->getXpath());
+    }
+
+    /**
+     * Unchecks current node if it's a checkbox field.
+     */
+    public function uncheck()
+    {
+        $this->getDriver()->uncheck($this->getXpath());
+    }
+
+    /**
+     * Checks whether current node is checked if it's a checkbox or radio field.
+     *
+     * Calling this method on any other elements is not allowed.
+     *
+     * @return Boolean
+     */
+    public function isChecked()
+    {
+        return (Boolean) $this->getDriver()->isChecked($this->getXpath());
+    }
+
+    /**
+     * Selects specified option for select field or specified radio button in the group
+     *
+     * If the current node is a select box, this selects the option found by its value or
+     * its text.
+     * If the current node is a radio button, this selects the radio button with the given
+     * value in the radio button group of the current node.
+     *
+     * Calling this method on any other elements is not allowed.
+     *
+     * @param string  $option
+     * @param Boolean $multiple whether the option should be added to the selection for multiple selects
+     *
+     * @throws ElementNotFoundException when the option is not found in the select box
+     */
+    public function selectOption($option, $multiple = false)
+    {
+        if ('select' !== $this->getTagName()) {
+            $this->getDriver()->selectOption($this->getXpath(), $option, $multiple);
+
+            return;
+        }
+
+        $opt = $this->find('named', array(
+            'option', $this->getSelectorsHandler()->xpathLiteral($option)
+        ));
+
+        if (null === $opt) {
+            throw $this->elementNotFound('select option', 'value|text', $option);
+        }
+
+        $this->getDriver()->selectOption($this->getXpath(), $opt->getValue(), $multiple);
+    }
+
+    /**
+     * Checks whether current node is selected if it's a option field.
+     *
+     * Calling this method on any other elements is not allowed.
+     *
+     * @return Boolean
+     */
+    public function isSelected()
+    {
+        return (Boolean) $this->getDriver()->isSelected($this->getXpath());
+    }
+
+    /**
+     * Attach file to current node if it's a file input.
+     *
+     * Calling this method on any other elements than file input is not allowed.
+     *
+     * @param string $path path to file (local)
+     */
+    public function attachFile($path)
+    {
+        $this->getDriver()->attachFile($this->getXpath(), $path);
+    }
+
+    /**
+     * Checks whether current node is visible on page.
+     *
+     * @return Boolean
+     */
+    public function isVisible()
+    {
+        return (Boolean) $this->getDriver()->isVisible($this->getXpath());
+    }
+
+    /**
+     * Simulates a mouse over on the element.
+     */
+    public function mouseOver()
+    {
+        $this->getDriver()->mouseOver($this->getXpath());
+    }
+
+    /**
+     * Drags current node onto other node.
+     *
+     * @param ElementInterface $destination other node
+     */
+    public function dragTo(ElementInterface $destination)
+    {
+        $this->getDriver()->dragTo($this->getXpath(), $destination->getXpath());
+    }
+
+    /**
+     * Brings focus to element.
+     */
+    public function focus()
+    {
+        $this->getDriver()->focus($this->getXpath());
+    }
+
+    /**
+     * Removes focus from element.
+     */
+    public function blur()
+    {
+        $this->getDriver()->blur($this->getXpath());
+    }
+
+    /**
+     * Presses specific keyboard key.
+     *
+     * @param string|integer $char     could be either char ('b') or char-code (98)
+     * @param string         $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
+     */
+    public function keyPress($char, $modifier = null)
+    {
+        $this->getDriver()->keyPress($this->getXpath(), $char, $modifier);
+    }
+
+    /**
+     * Pressed down specific keyboard key.
+     *
+     * @param string|integer $char     could be either char ('b') or char-code (98)
+     * @param string         $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
+     */
+    public function keyDown($char, $modifier = null)
+    {
+        $this->getDriver()->keyDown($this->getXpath(), $char, $modifier);
+    }
+
+    /**
+     * Pressed up specific keyboard key.
+     *
+     * @param string|integer $char     could be either char ('b') or char-code (98)
+     * @param string         $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
+     */
+    public function keyUp($char, $modifier = null)
+    {
+        $this->getDriver()->keyUp($this->getXpath(), $char, $modifier);
+    }
+
+    /**
+     * Submits the form.
+     *
+     * Calling this method on anything else than form elements is not allowed.
+     */
+    public function submit()
+    {
+        $this->getDriver()->submitForm($this->getXpath());
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Element/TraversableElement.php b/core/vendor/behat/mink/src/Behat/Mink/Element/TraversableElement.php
new file mode 100644
index 0000000..27843d2
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Element/TraversableElement.php
@@ -0,0 +1,309 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Element;
+
+use Behat\Mink\Exception\ElementNotFoundException;
+
+/**
+ * Traversable element.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+abstract class TraversableElement extends Element
+{
+    /**
+     * Finds element by its id.
+     *
+     * @param string $id element id
+     *
+     * @return NodeElement|null
+     */
+    public function findById($id)
+    {
+        $id = $this->getSelectorsHandler()->xpathLiteral($id);
+
+        return $this->find('named', array('id', $id));
+    }
+
+    /**
+     * Checks whether element has a link with specified locator.
+     *
+     * @param string $locator link id, title, text or image alt
+     *
+     * @return Boolean
+     */
+    public function hasLink($locator)
+    {
+        return null !== $this->findLink($locator);
+    }
+
+    /**
+     * Finds link with specified locator.
+     *
+     * @param string $locator link id, title, text or image alt
+     *
+     * @return NodeElement|null
+     */
+    public function findLink($locator)
+    {
+        return $this->find('named', array(
+            'link', $this->getSelectorsHandler()->xpathLiteral($locator)
+        ));
+    }
+
+    /**
+     * Clicks link with specified locator.
+     *
+     * @param string $locator link id, title, text or image alt
+     *
+     * @throws ElementNotFoundException
+     */
+    public function clickLink($locator)
+    {
+        $link = $this->findLink($locator);
+
+        if (null === $link) {
+            throw $this->elementNotFound('link', 'id|title|alt|text', $locator);
+        }
+
+        $link->click();
+    }
+
+    /**
+     * Checks whether element has a button (input[type=submit|image|button|reset], button) with specified locator.
+     *
+     * @param string $locator button id, value or alt
+     *
+     * @return Boolean
+     */
+    public function hasButton($locator)
+    {
+        return null !== $this->findButton($locator);
+    }
+
+    /**
+     * Finds button (input[type=submit|image|button|reset], button) with specified locator.
+     *
+     * @param string $locator button id, value or alt
+     *
+     * @return NodeElement|null
+     */
+    public function findButton($locator)
+    {
+        return $this->find('named', array(
+            'button', $this->getSelectorsHandler()->xpathLiteral($locator)
+        ));
+    }
+
+    /**
+     * Presses button (input[type=submit|image|button|reset], button) with specified locator.
+     *
+     * @param string $locator button id, value or alt
+     *
+     * @throws ElementNotFoundException
+     */
+    public function pressButton($locator)
+    {
+        $button = $this->findButton($locator);
+
+        if (null === $button) {
+            throw $this->elementNotFound('button', 'id|name|title|alt|value', $locator);
+        }
+
+        $button->press();
+    }
+
+    /**
+     * Checks whether element has a field (input, textarea, select) with specified locator.
+     *
+     * @param string $locator input id, name or label
+     *
+     * @return Boolean
+     */
+    public function hasField($locator)
+    {
+        return null !== $this->findField($locator);
+    }
+
+    /**
+     * Finds field (input, textarea, select) with specified locator.
+     *
+     * @param string $locator input id, name or label
+     *
+     * @return NodeElement|null
+     */
+    public function findField($locator)
+    {
+        return $this->find('named', array(
+            'field', $this->getSelectorsHandler()->xpathLiteral($locator)
+        ));
+    }
+
+    /**
+     * Fills in field (input, textarea, select) with specified locator.
+     *
+     * @param string $locator input id, name or label
+     * @param string $value   value
+     *
+     * @throws ElementNotFoundException
+     *
+     * @see NodeElement::setValue
+     */
+    public function fillField($locator, $value)
+    {
+        $field = $this->findField($locator);
+
+        if (null === $field) {
+            throw $this->elementNotFound('form field', 'id|name|label|value', $locator);
+        }
+
+        $field->setValue($value);
+    }
+
+    /**
+     * Checks whether element has a checkbox with specified locator, which is checked.
+     *
+     * @param string $locator input id, name or label
+     *
+     * @return Boolean
+     *
+     * @see NodeElement::isChecked
+     */
+    public function hasCheckedField($locator)
+    {
+        $field = $this->findField($locator);
+
+        return null !== $field && $field->isChecked();
+    }
+
+    /**
+     * Checks whether element has a checkbox with specified locator, which is unchecked.
+     *
+     * @param string $locator input id, name or label
+     *
+     * @return Boolean
+     *
+     * @see NodeElement::isChecked
+     */
+    public function hasUncheckedField($locator)
+    {
+        $field = $this->findField($locator);
+
+        return null !== $field && !$field->isChecked();
+    }
+
+    /**
+     * Checks checkbox with specified locator.
+     *
+     * @param string $locator input id, name or label
+     *
+     * @throws ElementNotFoundException
+     */
+    public function checkField($locator)
+    {
+        $field = $this->findField($locator);
+
+        if (null === $field) {
+            throw $this->elementNotFound('form field', 'id|name|label|value', $locator);
+        }
+
+        $field->check();
+    }
+
+    /**
+     * Unchecks checkbox with specified locator.
+     *
+     * @param string $locator input id, name or label
+     *
+     * @throws ElementNotFoundException
+     */
+    public function uncheckField($locator)
+    {
+        $field = $this->findField($locator);
+
+        if (null === $field) {
+            throw $this->elementNotFound('form field', 'id|name|label|value', $locator);
+        }
+
+        $field->uncheck();
+    }
+
+    /**
+     * Checks whether element has a select field with specified locator.
+     *
+     * @param string $locator select id, name or label
+     *
+     * @return Boolean
+     */
+    public function hasSelect($locator)
+    {
+        return $this->has('named', array(
+            'select', $this->getSelectorsHandler()->xpathLiteral($locator)
+        ));
+    }
+
+    /**
+     * Selects option from select field with specified locator.
+     *
+     * @param string  $locator  input id, name or label
+     * @param string  $value    option value
+     * @param Boolean $multiple select multiple options
+     *
+     * @throws ElementNotFoundException
+     *
+     * @see NodeElement::selectOption
+     */
+    public function selectFieldOption($locator, $value, $multiple = false)
+    {
+        $field = $this->findField($locator);
+
+        if (null === $field) {
+            throw $this->elementNotFound('form field', 'id|name|label|value', $locator);
+        }
+
+        $field->selectOption($value, $multiple);
+    }
+
+    /**
+     * Checks whether element has a table with specified locator.
+     *
+     * @param string $locator table id or caption
+     *
+     * @return Boolean
+     */
+    public function hasTable($locator)
+    {
+        return $this->has('named', array(
+            'table', $this->getSelectorsHandler()->xpathLiteral($locator)
+        ));
+    }
+
+    /**
+     * Attach file to file field with specified locator.
+     *
+     * @param string $locator input id, name or label
+     * @param string $path    path to file
+     *
+     * @throws ElementNotFoundException
+     *
+     * @see NodeElement::attachFile
+     */
+    public function attachFileToField($locator, $path)
+    {
+        $field = $this->findField($locator);
+
+        if (null === $field) {
+            throw $this->elementNotFound('form field', 'id|name|label|value', $locator);
+        }
+
+        $field->attachFile($path);
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Exception/DriverException.php b/core/vendor/behat/mink/src/Behat/Mink/Exception/DriverException.php
new file mode 100644
index 0000000..840f8bd
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Exception/DriverException.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Exception;
+
+/**
+ * Exception thrown by drivers when they fail to perform an action.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class DriverException extends Exception
+{
+    /**
+     * Initializes exception.
+     *
+     * @param string          $message
+     * @param int             $code
+     * @param \Exception|null $previous
+     */
+    public function __construct($message, $code = 0, \Exception $previous = null)
+    {
+        parent::__construct($message, $code, $previous);
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementException.php b/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementException.php
new file mode 100644
index 0000000..49d5c6c
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementException.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Exception;
+
+use Behat\Mink\Element\Element;
+
+/**
+ * A standard way for elements to re-throw exceptions
+ *
+ * @deprecated This exception class is not used anymore in Mink 1.6 and will be removed in 2.0
+ *
+ * @author Chris Worfolk <xmeltrut@gmail.com>
+ */
+class ElementException extends Exception
+{
+    private $element;
+
+    /**
+     * Initialises exception.
+     *
+     * @param Element    $element   optional message
+     * @param \Exception $exception exception
+     */
+    public function __construct(Element $element, \Exception $exception)
+    {
+        $this->element = $element;
+
+        parent::__construct(sprintf("Exception thrown by %s\n%s", $element->getXpath(), $exception->getMessage()));
+    }
+
+    /**
+     * Override default toString so we don't send a full backtrace in verbose mode.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->getMessage();
+    }
+
+    /**
+     * Get the element that caused the exception
+     *
+     * @return Element
+     */
+    public function getElement()
+    {
+        return $this->element;
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementHtmlException.php b/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementHtmlException.php
new file mode 100644
index 0000000..99e2ea6
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementHtmlException.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Exception;
+
+use Behat\Mink\Session;
+use Behat\Mink\Element\Element;
+
+/**
+ * Exception thrown when an expectation on the HTML of an element fails.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ElementHtmlException extends ExpectationException
+{
+    /**
+     * Element instance.
+     *
+     * @var Element
+     */
+    protected $element;
+
+    /**
+     * Initializes exception.
+     *
+     * @param string     $message   optional message
+     * @param Session    $session   session instance
+     * @param Element    $element   element
+     * @param \Exception $exception expectation exception
+     */
+    public function __construct($message, Session $session, Element $element, \Exception $exception = null)
+    {
+        $this->element = $element;
+
+        parent::__construct($message, $session, $exception);
+    }
+
+    protected function getContext()
+    {
+        return $this->element->getOuterHtml();
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementNotFoundException.php b/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementNotFoundException.php
new file mode 100644
index 0000000..2d379a8
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementNotFoundException.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Exception;
+
+use Behat\Mink\Session;
+
+/**
+ * Exception thrown when an expected element is not found.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ElementNotFoundException extends ExpectationException
+{
+    /**
+     * Initializes exception.
+     *
+     * @param Session $session  session instance
+     * @param string  $type     element type
+     * @param string  $selector element selector type
+     * @param string  $locator  element locator
+     */
+    public function __construct(Session $session, $type = null, $selector = null, $locator = null)
+    {
+        $message = '';
+
+        if (null !== $type) {
+            $message .= ucfirst($type);
+        } else {
+            $message .= 'Tag';
+        }
+
+        if (null !== $locator) {
+            if (null === $selector || in_array($selector, array('css', 'xpath'))) {
+                $selector = 'matching '.($selector ?: 'locator');
+            } else {
+                $selector = 'with '.$selector;
+            }
+            $message .= ' '.$selector.' "' . $locator . '"';
+        }
+
+        $message .= ' not found.';
+
+        parent::__construct($message, $session);
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementTextException.php b/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementTextException.php
new file mode 100644
index 0000000..5efff0f
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Exception/ElementTextException.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Exception;
+
+/**
+ * Exception thrown when an expectation on the text of an element fails.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ElementTextException extends ElementHtmlException
+{
+    protected function getContext()
+    {
+        return $this->element->getText();
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Exception/Exception.php b/core/vendor/behat/mink/src/Behat/Mink/Exception/Exception.php
new file mode 100644
index 0000000..4662a5b
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Exception/Exception.php
@@ -0,0 +1,20 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Exception;
+
+/**
+ * Mink base exception class.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+abstract class Exception extends \Exception
+{
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Exception/ExpectationException.php b/core/vendor/behat/mink/src/Behat/Mink/Exception/ExpectationException.php
new file mode 100644
index 0000000..da1723c
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Exception/ExpectationException.php
@@ -0,0 +1,145 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Exception;
+
+use Behat\Mink\Session;
+
+/**
+ * Exception thrown for failed expectations.
+ *
+ * Some specialized child classes are available to customize the error rendering.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ExpectationException extends Exception
+{
+    private $session;
+
+    /**
+     * Initializes exception.
+     *
+     * @param string     $message   optional message
+     * @param Session    $session   session instance
+     * @param \Exception $exception expectation exception
+     */
+    public function __construct($message, Session $session, \Exception $exception = null)
+    {
+        $this->session = $session;
+
+        if (!$message && null !== $exception) {
+            $message = $exception->getMessage();
+        }
+
+        parent::__construct($message, 0, $exception);
+    }
+
+    /**
+     * Returns exception message with additional context info.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        try {
+            $pageText = $this->pipeString($this->trimString($this->getContext()) . "\n");
+            $string   = sprintf("%s\n\n%s%s", $this->getMessage(), $this->getResponseInfo(), $pageText);
+        } catch (\Exception $e) {
+            return $this->getMessage();
+        }
+
+        return $string;
+    }
+
+    /**
+     * Gets the context rendered for this exception
+     *
+     * @return string
+     */
+    protected function getContext()
+    {
+        return $this->trimBody($this->getSession()->getPage()->getContent());
+    }
+
+    /**
+     * Returns exception session.
+     *
+     * @return Session
+     */
+    protected function getSession()
+    {
+        return $this->session;
+    }
+
+    /**
+     * Prepends every line in a string with pipe (|).
+     *
+     * @param string $string
+     *
+     * @return string
+     */
+    protected function pipeString($string)
+    {
+        return '|  ' . strtr($string, array("\n" => "\n|  "));
+    }
+
+    /**
+     * Removes response header/footer, letting only <body /> content.
+     *
+     * @param string $string response content
+     *
+     * @return string
+     */
+    protected function trimBody($string)
+    {
+        $string = preg_replace(array('/^.*<body>/s', '/<\/body>.*$/s'), array('<body>', '</body>'), $string);
+
+        return $string;
+    }
+
+    /**
+     * Trims string to specified number of chars.
+     *
+     * @param string  $string response content
+     * @param integer $count  trim count
+     *
+     * @return string
+     */
+    protected function trimString($string, $count = 1000)
+    {
+        $string = trim($string);
+
+        if ($count < mb_strlen($string)) {
+            return mb_substr($string, 0, $count - 3) . '...';
+        }
+
+        return $string;
+    }
+
+    /**
+     * Returns response information string.
+     *
+     * @return string
+     */
+    protected function getResponseInfo()
+    {
+        $driver = basename(str_replace('\\', '/', get_class($this->session->getDriver())));
+
+        $info = '+--[ ';
+        try {
+            $info .= 'HTTP/1.1 '.$this->session->getStatusCode().' | ';
+        } catch (UnsupportedDriverActionException $e) {
+            // Ignore the status code when not supported
+        }
+        $info .= $this->session->getCurrentUrl().' | '.$driver." ]\n|\n";
+
+        return $info;
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Exception/ResponseTextException.php b/core/vendor/behat/mink/src/Behat/Mink/Exception/ResponseTextException.php
new file mode 100644
index 0000000..145ed6d
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Exception/ResponseTextException.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Exception;
+
+/**
+ * Exception thrown when an expectation on the response text fails.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ResponseTextException extends ExpectationException
+{
+    protected function getContext()
+    {
+        return $this->getSession()->getPage()->getText();
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Exception/UnsupportedDriverActionException.php b/core/vendor/behat/mink/src/Behat/Mink/Exception/UnsupportedDriverActionException.php
new file mode 100644
index 0000000..d02969b
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Exception/UnsupportedDriverActionException.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Exception;
+
+use Behat\Mink\Driver\DriverInterface;
+
+/**
+ * Exception thrown by drivers when they don't support the requested action.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class UnsupportedDriverActionException extends DriverException
+{
+    /**
+     * Initializes exception.
+     *
+     * @param string          $template what is unsupported?
+     * @param DriverInterface $driver   driver instance
+     * @param \Exception      $previous previous exception
+     */
+    public function __construct($template, DriverInterface $driver, \Exception $previous = null)
+    {
+        $message = sprintf($template, get_class($driver));
+
+        parent::__construct($message, 0, $previous);
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Mink.php b/core/vendor/behat/mink/src/Behat/Mink/Mink.php
new file mode 100644
index 0000000..d1621b1
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Mink.php
@@ -0,0 +1,216 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink;
+
+/**
+ * Mink sessions manager.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class Mink
+{
+    private $defaultSessionName;
+
+    /**
+     * Sessions.
+     *
+     * @var Session[]
+     */
+    private $sessions = array();
+
+    /**
+     * Initializes manager.
+     *
+     * @param Session[] $sessions
+     */
+    public function __construct(array $sessions = array())
+    {
+        foreach ($sessions as $name => $session) {
+            $this->registerSession($name, $session);
+        }
+    }
+
+    /**
+     * Stops all started sessions.
+     */
+    public function __destruct()
+    {
+        $this->stopSessions();
+    }
+
+    /**
+     * Registers new session.
+     *
+     * @param string  $name
+     * @param Session $session
+     */
+    public function registerSession($name, Session $session)
+    {
+        $name = strtolower($name);
+
+        $this->sessions[$name] = $session;
+    }
+
+    /**
+     * Checks whether session with specified name is registered.
+     *
+     * @param string $name
+     *
+     * @return Boolean
+     */
+    public function hasSession($name)
+    {
+        return isset($this->sessions[strtolower($name)]);
+    }
+
+    /**
+     * Sets default session name to use.
+     *
+     * @param string $name name of the registered session
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function setDefaultSessionName($name)
+    {
+        $name = strtolower($name);
+
+        if (!isset($this->sessions[$name])) {
+            throw new \InvalidArgumentException(sprintf('Session "%s" is not registered.', $name));
+        }
+
+        $this->defaultSessionName = $name;
+    }
+
+    /**
+     * Returns default session name or null if none.
+     *
+     * @return null|string
+     */
+    public function getDefaultSessionName()
+    {
+        return $this->defaultSessionName;
+    }
+
+    /**
+     * Returns registered session by it's name or active one and automatically starts it if required.
+     *
+     * @param string $name session name
+     *
+     * @return Session
+     *
+     * @throws \InvalidArgumentException If the named session is not registered
+     */
+    public function getSession($name = null)
+    {
+        $session = $this->locateSession($name);
+
+        // start session if needed
+        if (!$session->isStarted()) {
+            $session->start();
+        }
+
+        return $session;
+    }
+
+    /**
+     * Checks whether a named session (or the default session) has already been started
+     *
+     * @param string $name session name - if null then the default session will be checked
+     *
+     * @return bool whether the session has been started
+     *
+     * @throws \InvalidArgumentException If the named session is not registered
+     */
+    public function isSessionStarted($name = null)
+    {
+        $session = $this->locateSession($name);
+
+        return $session->isStarted();
+    }
+
+    /**
+     * Returns session asserter.
+     *
+     * @param Session|string $session session object or name
+     *
+     * @return WebAssert
+     */
+    public function assertSession($session = null)
+    {
+        if (!($session instanceof Session)) {
+            $session = $this->getSession($session);
+        }
+
+        return new WebAssert($session);
+    }
+
+    /**
+     * Resets all started sessions.
+     */
+    public function resetSessions()
+    {
+        foreach ($this->sessions as $session) {
+            if ($session->isStarted()) {
+                $session->reset();
+            }
+        }
+    }
+
+    /**
+     * Restarts all started sessions.
+     */
+    public function restartSessions()
+    {
+        foreach ($this->sessions as $session) {
+            if ($session->isStarted()) {
+                $session->restart();
+            }
+        }
+    }
+
+    /**
+     * Stops all started sessions.
+     */
+    public function stopSessions()
+    {
+        foreach ($this->sessions as $session) {
+            if ($session->isStarted()) {
+                $session->stop();
+            }
+        }
+    }
+
+    /**
+     * Returns the named or default session without starting it.
+     *
+     * @param string $name session name
+     *
+     * @return Session
+     *
+     * @throws \InvalidArgumentException If the named session is not registered
+     */
+    protected function locateSession($name = null)
+    {
+        $name = strtolower($name) ?: $this->defaultSessionName;
+
+        if (null === $name) {
+            throw new \InvalidArgumentException('Specify session name to get');
+        }
+
+        if (!isset($this->sessions[$name])) {
+            throw new \InvalidArgumentException(sprintf('Session "%s" is not registered.', $name));
+        }
+
+        $session = $this->sessions[$name];
+
+        return $session;
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Selector/CssSelector.php b/core/vendor/behat/mink/src/Behat/Mink/Selector/CssSelector.php
new file mode 100644
index 0000000..3636586
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Selector/CssSelector.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Selector;
+
+use Symfony\Component\CssSelector\CssSelector as CSS;
+
+/**
+ * CSS selector engine. Transforms CSS to XPath.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class CssSelector implements SelectorInterface
+{
+    /**
+     * Translates CSS into XPath.
+     *
+     * @param string|array $locator current selector locator
+     *
+     * @return string
+     */
+    public function translateToXPath($locator)
+    {
+        if (!is_string($locator)) {
+            throw new \InvalidArgumentException('The CssSelector expects to get a string as locator');
+        }
+
+        return CSS::toXPath($locator);
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Selector/ExactNamedSelector.php b/core/vendor/behat/mink/src/Behat/Mink/Selector/ExactNamedSelector.php
new file mode 100644
index 0000000..03315a9
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Selector/ExactNamedSelector.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Selector;
+
+/**
+ * Exact match selector engine. Like the Named selector engine but ignores partial matches.
+ */
+class ExactNamedSelector extends NamedSelector
+{
+    public function __construct()
+    {
+        $this->registerReplacement('%tagTextMatch%', 'normalize-space(string(.)) = %locator%');
+        $this->registerReplacement('%valueMatch%', './@value = %locator%');
+        $this->registerReplacement('%titleMatch%', './@title = %locator%');
+        $this->registerReplacement('%altMatch%', './@alt = %locator%');
+        $this->registerReplacement('%relMatch%', './@rel = %locator%');
+        $this->registerReplacement('%labelAttributeMatch%', './@label = %locator%');
+
+        parent::__construct();
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Selector/NamedSelector.php b/core/vendor/behat/mink/src/Behat/Mink/Selector/NamedSelector.php
new file mode 100644
index 0000000..4845f99
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Selector/NamedSelector.php
@@ -0,0 +1,238 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Selector;
+
+/**
+ * Named selectors engine. Uses registered XPath selectors to create new expressions.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class NamedSelector implements SelectorInterface
+{
+    private $replacements = array(
+        // simple replacements
+        '%lowercaseType%' => "translate(./@type, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')",
+        '%lowercaseRole%' => "translate(./@role, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')",
+        '%tagTextMatch%' => 'contains(normalize-space(string(.)), %locator%)',
+        '%labelTextMatch%' => './@id = //label[%tagTextMatch%]/@for',
+        '%idMatch%' => './@id = %locator%',
+        '%valueMatch%' => 'contains(./@value, %locator%)',
+        '%idOrValueMatch%' => '(%idMatch% or %valueMatch%)',
+        '%idOrNameMatch%' => '(%idMatch% or ./@name = %locator%)',
+        '%placeholderMatch%' => './@placeholder = %locator%',
+        '%titleMatch%' => 'contains(./@title, %locator%)',
+        '%altMatch%' => 'contains(./@alt, %locator%)',
+        '%relMatch%' => 'contains(./@rel, %locator%)',
+        '%labelAttributeMatch%' => 'contains(./@label, %locator%)',
+
+        // complex replacements
+        '%inputTypeWithoutPlaceholderFilter%' => "%lowercaseType% = 'radio' or %lowercaseType% = 'checkbox' or %lowercaseType% = 'file'",
+        '%fieldFilterWithPlaceholder%' => 'self::input[not(%inputTypeWithoutPlaceholderFilter%)] | self::textarea',
+        '%fieldMatchWithPlaceholder%' => '(%idOrNameMatch% or %labelTextMatch% or %placeholderMatch%)',
+        '%fieldMatchWithoutPlaceholder%' => '(%idOrNameMatch% or %labelTextMatch%)',
+        '%fieldFilterWithoutPlaceholder%' => 'self::input[%inputTypeWithoutPlaceholderFilter%] | self::select',
+        '%buttonTypeFilter%' => "%lowercaseType% = 'submit' or %lowercaseType% = 'image' or %lowercaseType% = 'button' or %lowercaseType% = 'reset'",
+        '%notFieldTypeFilter%' => "not(%buttonTypeFilter% or %lowercaseType% = 'hidden')",
+        '%buttonMatch%' => '%idOrNameMatch% or %valueMatch% or %titleMatch%',
+        '%linkMatch%' => '(%idMatch% or %tagTextMatch% or %titleMatch% or %relMatch%)',
+        '%imgAltMatch%' => './/img[%altMatch%]',
+    );
+
+    private $selectors = array(
+        'fieldset' => <<<XPATH
+.//fieldset
+[(%idMatch% or .//legend[%tagTextMatch%])]
+XPATH
+
+        ,'field' => <<<XPATH
+.//*
+[%fieldFilterWithPlaceholder%][%notFieldTypeFilter%][%fieldMatchWithPlaceholder%]
+|
+.//label[%tagTextMatch%]//.//*[%fieldFilterWithPlaceholder%][%notFieldTypeFilter%]
+|
+.//*
+[%fieldFilterWithoutPlaceholder%][%notFieldTypeFilter%][%fieldMatchWithoutPlaceholder%]
+|
+.//label[%tagTextMatch%]//.//*[%fieldFilterWithoutPlaceholder%][%notFieldTypeFilter%]
+XPATH
+
+        ,'link' => <<<XPATH
+.//a
+[./@href][(%linkMatch% or %imgAltMatch%)]
+|
+.//*
+[%lowercaseRole% = 'link'][(%idOrValueMatch% or %titleMatch% or %tagTextMatch%)]
+XPATH
+
+        ,'button' => <<<XPATH
+.//input
+[%buttonTypeFilter%][(%buttonMatch%)]
+|
+.//input
+[%lowercaseType% = 'image'][%altMatch%]
+|
+.//button
+[(%buttonMatch% or %tagTextMatch%)]
+|
+.//*
+[%lowercaseRole% = 'button'][(%buttonMatch% or %tagTextMatch%)]
+XPATH
+
+        ,'link_or_button' => <<<XPATH
+.//a
+[./@href][(%linkMatch% or %imgAltMatch%)]
+|
+.//input
+[%buttonTypeFilter%][(%idOrValueMatch% or %titleMatch%)]
+|
+.//input
+[%lowercaseType% = 'image'][%altMatch%]
+|
+.//button
+[(%idOrValueMatch% or %titleMatch% or %tagTextMatch%)]
+|
+.//*
+[(%lowercaseRole% = 'button' or %lowercaseRole% = 'link')][(%idOrValueMatch% or %titleMatch% or %tagTextMatch%)]
+XPATH
+
+        ,'content' => <<<XPATH
+./descendant-or-self::*
+[%tagTextMatch%]
+XPATH
+
+        ,'select' => <<<XPATH
+.//select
+[%fieldMatchWithoutPlaceholder%]
+|
+.//label[%tagTextMatch%]//.//select
+XPATH
+
+        ,'checkbox' => <<<XPATH
+.//input
+[%lowercaseType% = 'checkbox'][%fieldMatchWithoutPlaceholder%]
+|
+.//label[%tagTextMatch%]//.//input[%lowercaseType% = 'checkbox']
+XPATH
+
+        ,'radio' => <<<XPATH
+.//input
+[%lowercaseType% = 'radio'][%fieldMatchWithoutPlaceholder%]
+|
+.//label[%tagTextMatch%]//.//input[%lowercaseType% = 'radio']
+XPATH
+
+        ,'file' => <<<XPATH
+.//input
+[%lowercaseType% = 'file'][%fieldMatchWithoutPlaceholder%]
+|
+.//label[%tagTextMatch%]//.//input[%lowercaseType% = 'file']
+XPATH
+
+        ,'optgroup' => <<<XPATH
+.//optgroup
+[%labelAttributeMatch%]
+XPATH
+
+        ,'option' => <<<XPATH
+.//option
+[(./@value = %locator% or %tagTextMatch%)]
+XPATH
+
+        ,'table' => <<<XPATH
+.//table
+[(%idMatch% or .//caption[%tagTextMatch%])]
+XPATH
+        ,'id' => <<<XPATH
+.//*[%idMatch%]
+XPATH
+    ,'id_or_name' => <<<XPATH
+.//*[%idOrNameMatch%]
+XPATH
+    );
+
+    /**
+     * Creates selector instance.
+     */
+    public function __construct()
+    {
+        foreach ($this->replacements as $from => $to) {
+            $this->replacements[$from] = strtr($to, $this->replacements);
+        }
+
+        foreach ($this->selectors as $alias => $selector) {
+            $this->selectors[$alias] = strtr($selector, $this->replacements);
+        }
+    }
+
+    /**
+     * Registers new XPath selector with specified name.
+     *
+     * @param string $name  name for selector
+     * @param string $xpath xpath expression
+     */
+    public function registerNamedXpath($name, $xpath)
+    {
+        $this->selectors[$name] = $xpath;
+    }
+
+    /**
+     * Translates provided locator into XPath.
+     *
+     * @param string|array $locator selector name or array of (selector_name, locator)
+     *
+     * @return string
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function translateToXPath($locator)
+    {
+        if (2 < count($locator)) {
+            throw new \InvalidArgumentException('NamedSelector expects array(name, locator) as argument');
+        }
+
+        if (2 == count($locator)) {
+            $selector   = $locator[0];
+            $locator    = $locator[1];
+        } else {
+            $selector   = (string) $locator;
+            $locator    = null;
+        }
+
+        if (!isset($this->selectors[$selector])) {
+            throw new \InvalidArgumentException(sprintf(
+                'Unknown named selector provided: "%s". Expected one of (%s)',
+                $selector,
+                implode(', ', array_keys($this->selectors))
+            ));
+        }
+
+        $xpath = $this->selectors[$selector];
+
+        if (null !== $locator) {
+            $xpath = strtr($xpath, array('%locator%' => $locator));
+        }
+
+        return $xpath;
+    }
+
+    /**
+     * Registers a replacement in the list of replacements
+     *
+     * This method must be called in the constructor before calling the parent constructor.
+     *
+     * @param string $from
+     * @param string $to
+     */
+    protected function registerReplacement($from, $to)
+    {
+        $this->replacements[$from] = $to;
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Selector/PartialNamedSelector.php b/core/vendor/behat/mink/src/Behat/Mink/Selector/PartialNamedSelector.php
new file mode 100644
index 0000000..b864a22
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Selector/PartialNamedSelector.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Selector;
+
+/**
+ * Named selectors engine. Uses registered XPath selectors to create new expressions.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class PartialNamedSelector extends NamedSelector
+{
+    public function __construct()
+    {
+        $this->registerReplacement('%tagTextMatch%', 'contains(normalize-space(string(.)), %locator%)');
+        $this->registerReplacement('%valueMatch%', 'contains(./@value, %locator%)');
+        $this->registerReplacement('%titleMatch%', 'contains(./@title, %locator%)');
+        $this->registerReplacement('%altMatch%', 'contains(./@alt, %locator%)');
+        $this->registerReplacement('%relMatch%', 'contains(./@rel, %locator%)');
+        $this->registerReplacement('%labelAttributeMatch%', 'contains(./@label, %locator%)');
+
+        parent::__construct();
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Selector/SelectorInterface.php b/core/vendor/behat/mink/src/Behat/Mink/Selector/SelectorInterface.php
new file mode 100644
index 0000000..e4f5f17
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Selector/SelectorInterface.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Selector;
+
+/**
+ * Mink selector engine interface.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface SelectorInterface
+{
+    /**
+     * Translates provided locator into XPath.
+     *
+     * @param string|array $locator current selector locator
+     *
+     * @return string
+     */
+    public function translateToXPath($locator);
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Selector/SelectorsHandler.php b/core/vendor/behat/mink/src/Behat/Mink/Selector/SelectorsHandler.php
new file mode 100644
index 0000000..a19de67
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Selector/SelectorsHandler.php
@@ -0,0 +1,125 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Selector;
+
+use Behat\Mink\Selector\Xpath\Escaper;
+
+/**
+ * Selectors handler.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class SelectorsHandler
+{
+    private $selectors;
+    private $escaper;
+
+    /**
+     * Initializes selectors handler.
+     *
+     * @param SelectorInterface[] $selectors default selectors to register
+     */
+    public function __construct(array $selectors = array())
+    {
+        $this->escaper = new Escaper();
+
+        $this->registerSelector('named_partial', new PartialNamedSelector());
+        $this->registerSelector('named_exact', new ExactNamedSelector());
+        $this->registerSelector('css', new CssSelector());
+
+        foreach ($selectors as $name => $selector) {
+            $this->registerSelector($name, $selector);
+        }
+    }
+
+    /**
+     * Registers new selector engine with specified name.
+     *
+     * @param string            $name     selector engine name
+     * @param SelectorInterface $selector selector engine instance
+     */
+    public function registerSelector($name, SelectorInterface $selector)
+    {
+        $this->selectors[$name] = $selector;
+    }
+
+    /**
+     * Checks whether selector with specified name is registered on handler.
+     *
+     * @param string $name selector engine name
+     *
+     * @return Boolean
+     */
+    public function isSelectorRegistered($name)
+    {
+        return isset($this->selectors[$name]);
+    }
+
+    /**
+     * Returns selector engine with specified name.
+     *
+     * @param string $name selector engine name
+     *
+     * @return SelectorInterface
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function getSelector($name)
+    {
+        if ('named' === $name) {
+            trigger_error(
+                'Using the "named" selector directly from the handler is deprecated as of 1.6 and will be removed in 2.0.'
+                .' Use the "named_partial" or use the "named" selector through the Element API instead.',
+                E_USER_DEPRECATED
+            );
+            $name = 'named_partial';
+        }
+
+        if (!$this->isSelectorRegistered($name)) {
+            throw new \InvalidArgumentException("Selector \"$name\" is not registered.");
+        }
+
+        return $this->selectors[$name];
+    }
+
+    /**
+     * Translates selector with specified name to XPath.
+     *
+     * @param string       $selector selector engine name (registered)
+     * @param string|array $locator  selector locator (an array or a string depending of the selector being used)
+     *
+     * @return string
+     */
+    public function selectorToXpath($selector, $locator)
+    {
+        if ('xpath' === $selector) {
+            if (!is_string($locator)) {
+                throw new \InvalidArgumentException('The xpath selector expects to get a string as locator');
+            }
+
+            return $locator;
+        }
+
+        return $this->getSelector($selector)->translateToXPath($locator);
+    }
+
+    /**
+     * Translates string to XPath literal.
+     *
+     * @param string $s
+     *
+     * @return string
+     */
+    public function xpathLiteral($s)
+    {
+        return $this->escaper->escapeLiteral($s);
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Selector/Xpath/Escaper.php b/core/vendor/behat/mink/src/Behat/Mink/Selector/Xpath/Escaper.php
new file mode 100644
index 0000000..be35000
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Selector/Xpath/Escaper.php
@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Selector\Xpath;
+
+/**
+ * XPath escaper.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class Escaper
+{
+    /**
+     * Escapes the string as a XPath literal.
+     *
+     * @param string $s
+     *
+     * @return string
+     */
+    public function escapeLiteral($s)
+    {
+        if (false === strpos($s, "'")) {
+            return sprintf("'%s'", $s);
+        }
+
+        if (false === strpos($s, '"')) {
+            return sprintf('"%s"', $s);
+        }
+
+        $string = $s;
+        $parts = array();
+        while (true) {
+            if (false !== $pos = strpos($string, "'")) {
+                $parts[] = sprintf("'%s'", substr($string, 0, $pos));
+                $parts[] = "\"'\"";
+                $string = substr($string, $pos + 1);
+            } else {
+                $parts[] = "'$string'";
+                break;
+            }
+        }
+
+        return sprintf("concat(%s)", implode($parts, ','));
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Selector/Xpath/Manipulator.php b/core/vendor/behat/mink/src/Behat/Mink/Selector/Xpath/Manipulator.php
new file mode 100644
index 0000000..617b314
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Selector/Xpath/Manipulator.php
@@ -0,0 +1,69 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink\Selector\Xpath;
+
+/**
+ * XPath manipulation utility.
+ *
+ * @author Graham Bates
+ * @author Christophe Coevoet <stof@notk.org>
+ */
+class Manipulator
+{
+    /**
+     * Regex to find union operators not inside brackets.
+     */
+    const UNION_PATTERN = '/\|(?![^\[]*\])/';
+
+    /**
+     * Prepends the XPath prefix to the given XPath.
+     *
+     * The returned XPath will match elements matching the XPath inside an element
+     * matching the prefix.
+     *
+     * @param string $xpath
+     * @param string $prefix
+     *
+     * @return string
+     */
+    public function prepend($xpath, $prefix)
+    {
+        $expressions = array();
+
+        // If the xpath prefix contains a union we need to wrap it in parentheses.
+        if (preg_match(self::UNION_PATTERN, $prefix)) {
+            $prefix = '(' . $prefix . ')';
+        }
+
+        // Split any unions into individual expressions.
+        foreach (preg_split(self::UNION_PATTERN, $xpath) as $expression) {
+            $expression = trim($expression);
+            $parenthesis = '';
+
+            // If the union is inside some braces, we need to preserve the opening braces and apply
+            // the prefix only inside it.
+            if (preg_match('/^[\(\s*]+/', $expression, $matches)) {
+                $parenthesis = $matches[0];
+                $expression = substr($expression, strlen($parenthesis));
+            }
+
+            // add prefix before element selector
+            if (0 === strpos($expression, '/')) {
+                $expression = $prefix . $expression;
+            } else {
+                $expression = $prefix . '/' . $expression;
+            }
+            $expressions[] = $parenthesis . $expression;
+        }
+
+        return implode(' | ', $expressions);
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/Session.php b/core/vendor/behat/mink/src/Behat/Mink/Session.php
new file mode 100644
index 0000000..c67f7f9
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/Session.php
@@ -0,0 +1,352 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink;
+
+use Behat\Mink\Driver\DriverInterface;
+use Behat\Mink\Selector\SelectorsHandler;
+use Behat\Mink\Element\DocumentElement;
+
+/**
+ * Mink session.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class Session
+{
+    private $driver;
+    private $page;
+    private $selectorsHandler;
+
+    /**
+     * Initializes session.
+     *
+     * @param DriverInterface  $driver
+     * @param SelectorsHandler $selectorsHandler
+     */
+    public function __construct(DriverInterface $driver, SelectorsHandler $selectorsHandler = null)
+    {
+        $driver->setSession($this);
+
+        if (null === $selectorsHandler) {
+            $selectorsHandler = new SelectorsHandler();
+        }
+
+        $this->driver           = $driver;
+        $this->selectorsHandler = $selectorsHandler;
+        $this->page             = new DocumentElement($this);
+    }
+
+    /**
+     * Checks whether session (driver) was started.
+     *
+     * @return Boolean
+     */
+    public function isStarted()
+    {
+        return $this->driver->isStarted();
+    }
+
+    /**
+     * Starts session driver.
+     *
+     * Calling any action before visiting a page is an undefined behavior.
+     * The only supported method calls on a fresh driver are
+     * - visit()
+     * - setRequestHeader()
+     * - setBasicAuth()
+     * - reset()
+     * - stop()
+     */
+    public function start()
+    {
+        $this->driver->start();
+    }
+
+    /**
+     * Stops session driver.
+     */
+    public function stop()
+    {
+        $this->driver->stop();
+    }
+
+    /**
+     * Restart session driver.
+     */
+    public function restart()
+    {
+        $this->driver->stop();
+        $this->driver->start();
+    }
+
+    /**
+     * Reset session driver state.
+     *
+     * Calling any action before visiting a page is an undefined behavior.
+     * The only supported method calls on a fresh driver are
+     * - visit()
+     * - setRequestHeader()
+     * - setBasicAuth()
+     * - reset()
+     * - stop()
+     */
+    public function reset()
+    {
+        $this->driver->reset();
+    }
+
+    /**
+     * Returns session driver.
+     *
+     * @return DriverInterface
+     */
+    public function getDriver()
+    {
+        return $this->driver;
+    }
+
+    /**
+     * Returns page element.
+     *
+     * @return DocumentElement
+     */
+    public function getPage()
+    {
+        return $this->page;
+    }
+
+    /**
+     * Returns selectors handler.
+     *
+     * @return SelectorsHandler
+     */
+    public function getSelectorsHandler()
+    {
+        return $this->selectorsHandler;
+    }
+
+    /**
+     * Visit specified URL.
+     *
+     * @param string $url url of the page
+     */
+    public function visit($url)
+    {
+        $this->driver->visit($url);
+    }
+
+    /**
+     * Sets HTTP Basic authentication parameters
+     *
+     * @param string|Boolean $user     user name or false to disable authentication
+     * @param string         $password password
+     */
+    public function setBasicAuth($user, $password = '')
+    {
+        $this->driver->setBasicAuth($user, $password);
+    }
+
+    /**
+     * Sets specific request header.
+     *
+     * @param string $name
+     * @param string $value
+     */
+    public function setRequestHeader($name, $value)
+    {
+        $this->driver->setRequestHeader($name, $value);
+    }
+
+    /**
+     * Returns all response headers.
+     *
+     * @return array
+     */
+    public function getResponseHeaders()
+    {
+        return $this->driver->getResponseHeaders();
+    }
+
+    /**
+     * Sets cookie.
+     *
+     * @param string $name
+     * @param string $value
+     */
+    public function setCookie($name, $value = null)
+    {
+        $this->driver->setCookie($name, $value);
+    }
+
+    /**
+     * Returns cookie by name.
+     *
+     * @param string $name
+     *
+     * @return string|null
+     */
+    public function getCookie($name)
+    {
+        return $this->driver->getCookie($name);
+    }
+
+    /**
+     * Returns response status code.
+     *
+     * @return integer
+     */
+    public function getStatusCode()
+    {
+        return $this->driver->getStatusCode();
+    }
+
+    /**
+     * Returns current URL address.
+     *
+     * @return string
+     */
+    public function getCurrentUrl()
+    {
+        return $this->driver->getCurrentUrl();
+    }
+
+    /**
+     * Capture a screenshot of the current window.
+     *
+     * @return string screenshot of MIME type image/* depending
+     *                on driver (e.g., image/png, image/jpeg)
+     */
+    public function getScreenshot()
+    {
+        return $this->driver->getScreenshot();
+    }
+
+    /**
+     * Return the names of all open windows
+     *
+     * @return array Array of all open window's names.
+     */
+    public function getWindowNames()
+    {
+        return $this->driver->getWindowNames();
+    }
+
+    /**
+     * Return the name of the currently active window
+     *
+     * @return string The name of the current window.
+     */
+    public function getWindowName()
+    {
+        return $this->driver->getWindowName();
+    }
+
+    /**
+     * Reloads current session page.
+     */
+    public function reload()
+    {
+        $this->driver->reload();
+    }
+
+    /**
+     * Moves backward 1 page in history.
+     */
+    public function back()
+    {
+        $this->driver->back();
+    }
+
+    /**
+     * Moves forward 1 page in history.
+     */
+    public function forward()
+    {
+        $this->driver->forward();
+    }
+
+    /**
+     * Switches to specific browser window.
+     *
+     * @param string $name window name (null for switching back to main window)
+     */
+    public function switchToWindow($name = null)
+    {
+        $this->driver->switchToWindow($name);
+    }
+
+    /**
+     * Switches to specific iFrame.
+     *
+     * @param string $name iframe name (null for switching back)
+     */
+    public function switchToIFrame($name = null)
+    {
+        $this->driver->switchToIFrame($name);
+    }
+
+    /**
+     * Execute JS in browser.
+     *
+     * @param string $script javascript
+     */
+    public function executeScript($script)
+    {
+        $this->driver->executeScript($script);
+    }
+
+    /**
+     * Execute JS in browser and return it's response.
+     *
+     * @param string $script javascript
+     *
+     * @return string
+     */
+    public function evaluateScript($script)
+    {
+        return $this->driver->evaluateScript($script);
+    }
+
+    /**
+     * Waits some time or until JS condition turns true.
+     *
+     * @param integer $time      time in milliseconds
+     * @param string  $condition JS condition
+     *
+     * @return boolean
+     */
+    public function wait($time, $condition = 'false')
+    {
+        return $this->driver->wait($time, $condition);
+    }
+
+    /**
+     * Set the dimensions of the window.
+     *
+     * @param integer $width  set the window width, measured in pixels
+     * @param integer $height set the window height, measured in pixels
+     * @param string  $name   window name (null for the main window)
+     */
+    public function resizeWindow($width, $height, $name = null)
+    {
+        $this->driver->resizeWindow($width, $height, $name);
+    }
+
+    /**
+     * Maximize the window if it is not maximized already
+     *
+     * @param string $name window name (null for the main window)
+     */
+    public function maximizeWindow($name = null)
+    {
+        $this->driver->maximizeWindow($name);
+    }
+}
diff --git a/core/vendor/behat/mink/src/Behat/Mink/WebAssert.php b/core/vendor/behat/mink/src/Behat/Mink/WebAssert.php
new file mode 100644
index 0000000..8cb3659
--- /dev/null
+++ b/core/vendor/behat/mink/src/Behat/Mink/WebAssert.php
@@ -0,0 +1,748 @@
+<?php
+
+/*
+ * This file is part of the Mink package.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Mink;
+
+use Behat\Mink\Element\Element;
+use Behat\Mink\Element\ElementInterface;
+use Behat\Mink\Element\NodeElement;
+use Behat\Mink\Element\TraversableElement;
+use Behat\Mink\Exception\ElementNotFoundException;
+use Behat\Mink\Exception\ExpectationException;
+use Behat\Mink\Exception\ResponseTextException;
+use Behat\Mink\Exception\ElementHtmlException;
+use Behat\Mink\Exception\ElementTextException;
+
+/**
+ * Mink web assertions tool.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class WebAssert
+{
+    protected $session;
+
+    /**
+     * Initializes assertion engine.
+     *
+     * @param Session $session
+     */
+    public function __construct(Session $session)
+    {
+        $this->session = $session;
+    }
+
+    /**
+     * Checks that current session address is equals to provided one.
+     *
+     * @param string $page
+     *
+     * @throws ExpectationException
+     */
+    public function addressEquals($page)
+    {
+        $expected = $this->cleanUrl($page);
+        $actual   = $this->getCurrentUrlPath();
+
+        $this->assert($actual === $expected, sprintf('Current page is "%s", but "%s" expected.', $actual, $expected));
+    }
+
+    /**
+     * Checks that current session address is not equals to provided one.
+     *
+     * @param string $page
+     *
+     * @throws ExpectationException
+     */
+    public function addressNotEquals($page)
+    {
+        $expected = $this->cleanUrl($page);
+        $actual   = $this->getCurrentUrlPath();
+
+        $this->assert($actual !== $expected, sprintf('Current page is "%s", but should not be.', $actual));
+    }
+
+    /**
+     * Checks that current session address matches regex.
+     *
+     * @param string $regex
+     *
+     * @throws ExpectationException
+     */
+    public function addressMatches($regex)
+    {
+        $actual = $this->getCurrentUrlPath();
+        $message = sprintf('Current page "%s" does not match the regex "%s".', $actual, $regex);
+
+        $this->assert((bool) preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that specified cookie exists and its value equals to a given one
+     *
+     * @param string $name  cookie name
+     * @param string $value cookie value
+     *
+     * @throws ExpectationException
+     */
+    public function cookieEquals($name, $value)
+    {
+        $this->cookieExists($name);
+
+        $actualValue = $this->session->getCookie($name);
+        $message = sprintf('Cookie "%s" value is "%s", but should be "%s".', $name, $actualValue, $value);
+
+        $this->assert($actualValue == $value, $message);
+    }
+
+    /**
+     * Checks that specified cookie exists
+     *
+     * @param string $name cookie name
+     *
+     * @throws ExpectationException
+     */
+    public function cookieExists($name)
+    {
+        $message = sprintf('Cookie "%s" is not set, but should be.', $name);
+        $this->assert($this->session->getCookie($name) !== null, $message);
+    }
+
+    /**
+     * Checks that current response code equals to provided one.
+     *
+     * @param integer $code
+     *
+     * @throws ExpectationException
+     */
+    public function statusCodeEquals($code)
+    {
+        $actual = $this->session->getStatusCode();
+        $message = sprintf('Current response status code is %d, but %d expected.', $actual, $code);
+
+        $this->assert(intval($code) === intval($actual), $message);
+    }
+
+    /**
+     * Checks that current response code not equals to provided one.
+     *
+     * @param integer $code
+     *
+     * @throws ExpectationException
+     */
+    public function statusCodeNotEquals($code)
+    {
+        $actual = $this->session->getStatusCode();
+        $message = sprintf('Current response status code is %d, but should not be.', $actual);
+
+        $this->assert(intval($code) !== intval($actual), $message);
+    }
+
+    /**
+     * Checks that current page contains text.
+     *
+     * @param string $text
+     *
+     * @throws ResponseTextException
+     */
+    public function pageTextContains($text)
+    {
+        $actual = $this->session->getPage()->getText();
+        $actual = preg_replace('/\s+/u', ' ', $actual);
+        $regex  = '/'.preg_quote($text, '/').'/ui';
+        $message = sprintf('The text "%s" was not found anywhere in the text of the current page.', $text);
+
+        $this->assertResponseText((bool) preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that current page does not contains text.
+     *
+     * @param string $text
+     *
+     * @throws ResponseTextException
+     */
+    public function pageTextNotContains($text)
+    {
+        $actual = $this->session->getPage()->getText();
+        $actual = preg_replace('/\s+/u', ' ', $actual);
+        $regex  = '/'.preg_quote($text, '/').'/ui';
+        $message = sprintf('The text "%s" appears in the text of this page, but it should not.', $text);
+
+        $this->assertResponseText(!preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that current page text matches regex.
+     *
+     * @param string $regex
+     *
+     * @throws ResponseTextException
+     */
+    public function pageTextMatches($regex)
+    {
+        $actual = $this->session->getPage()->getText();
+        $message = sprintf('The pattern %s was not found anywhere in the text of the current page.', $regex);
+
+        $this->assertResponseText((bool) preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that current page text does not matches regex.
+     *
+     * @param string $regex
+     *
+     * @throws ResponseTextException
+     */
+    public function pageTextNotMatches($regex)
+    {
+        $actual = $this->session->getPage()->getText();
+        $message = sprintf('The pattern %s was found in the text of the current page, but it should not.', $regex);
+
+        $this->assertResponseText(!preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that page HTML (response content) contains text.
+     *
+     * @param string $text
+     *
+     * @throws ExpectationException
+     */
+    public function responseContains($text)
+    {
+        $actual = $this->session->getPage()->getContent();
+        $regex  = '/'.preg_quote($text, '/').'/ui';
+        $message = sprintf('The string "%s" was not found anywhere in the HTML response of the current page.', $text);
+
+        $this->assert((bool) preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that page HTML (response content) does not contains text.
+     *
+     * @param string $text
+     *
+     * @throws ExpectationException
+     */
+    public function responseNotContains($text)
+    {
+        $actual = $this->session->getPage()->getContent();
+        $regex  = '/'.preg_quote($text, '/').'/ui';
+        $message = sprintf('The string "%s" appears in the HTML response of this page, but it should not.', $text);
+
+        $this->assert(!preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that page HTML (response content) matches regex.
+     *
+     * @param string $regex
+     *
+     * @throws ExpectationException
+     */
+    public function responseMatches($regex)
+    {
+        $actual = $this->session->getPage()->getContent();
+        $message = sprintf('The pattern %s was not found anywhere in the HTML response of the page.', $regex);
+
+        $this->assert((bool) preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that page HTML (response content) does not matches regex.
+     *
+     * @param $regex
+     *
+     * @throws ExpectationException
+     */
+    public function responseNotMatches($regex)
+    {
+        $actual = $this->session->getPage()->getContent();
+        $message = sprintf('The pattern %s was found in the HTML response of the page, but it should not.', $regex);
+
+        $this->assert(!preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that there is specified number of specific elements on the page.
+     *
+     * @param string           $selectorType element selector type (css, xpath)
+     * @param string|array     $selector     element selector
+     * @param integer          $count        expected count
+     * @param ElementInterface $container    document to check against
+     *
+     * @throws ExpectationException
+     */
+    public function elementsCount($selectorType, $selector, $count, ElementInterface $container = null)
+    {
+        $container = $container ?: $this->session->getPage();
+        $nodes = $container->findAll($selectorType, $selector);
+
+        $message = sprintf(
+            '%d %s found on the page, but should be %d.',
+            count($nodes),
+            $this->getMatchingElementRepresentation($selectorType, $selector, count($nodes) !== 1),
+            $count
+        );
+
+        $this->assert(intval($count) === count($nodes), $message);
+    }
+
+    /**
+     * Checks that specific element exists on the current page.
+     *
+     * @param string           $selectorType element selector type (css, xpath)
+     * @param string|array     $selector     element selector
+     * @param ElementInterface $container    document to check against
+     *
+     * @return NodeElement
+     *
+     * @throws ElementNotFoundException
+     */
+    public function elementExists($selectorType, $selector, ElementInterface $container = null)
+    {
+        $container = $container ?: $this->session->getPage();
+        $node = $container->find($selectorType, $selector);
+
+        if (null === $node) {
+            if (is_array($selector)) {
+                $selector = implode(' ', $selector);
+            }
+
+            throw new ElementNotFoundException($this->session, 'element', $selectorType, $selector);
+        }
+
+        return $node;
+    }
+
+    /**
+     * Checks that specific element does not exists on the current page.
+     *
+     * @param string           $selectorType element selector type (css, xpath)
+     * @param string|array     $selector     element selector
+     * @param ElementInterface $container    document to check against
+     *
+     * @throws ExpectationException
+     */
+    public function elementNotExists($selectorType, $selector, ElementInterface $container = null)
+    {
+        $container = $container ?: $this->session->getPage();
+        $node = $container->find($selectorType, $selector);
+
+        $message = sprintf(
+            'An %s appears on this page, but it should not.',
+            $this->getMatchingElementRepresentation($selectorType, $selector)
+        );
+
+        $this->assert(null === $node, $message);
+    }
+
+    /**
+     * Checks that specific element contains text.
+     *
+     * @param string       $selectorType element selector type (css, xpath)
+     * @param string|array $selector     element selector
+     * @param string       $text         expected text
+     *
+     * @throws ElementTextException
+     */
+    public function elementTextContains($selectorType, $selector, $text)
+    {
+        $element = $this->elementExists($selectorType, $selector);
+        $actual  = $element->getText();
+        $regex   = '/'.preg_quote($text, '/').'/ui';
+
+        $message = sprintf(
+            'The text "%s" was not found in the text of the %s.',
+            $text,
+            $this->getMatchingElementRepresentation($selectorType, $selector)
+        );
+
+        $this->assertElementText((bool) preg_match($regex, $actual), $message, $element);
+    }
+
+    /**
+     * Checks that specific element does not contains text.
+     *
+     * @param string       $selectorType element selector type (css, xpath)
+     * @param string|array $selector     element selector
+     * @param string       $text         expected text
+     *
+     * @throws ElementTextException
+     */
+    public function elementTextNotContains($selectorType, $selector, $text)
+    {
+        $element = $this->elementExists($selectorType, $selector);
+        $actual  = $element->getText();
+        $regex   = '/'.preg_quote($text, '/').'/ui';
+
+        $message = sprintf(
+            'The text "%s" appears in the text of the %s, but it should not.',
+            $text,
+            $this->getMatchingElementRepresentation($selectorType, $selector)
+        );
+
+        $this->assertElementText(!preg_match($regex, $actual), $message, $element);
+    }
+
+    /**
+     * Checks that specific element contains HTML.
+     *
+     * @param string       $selectorType element selector type (css, xpath)
+     * @param string|array $selector     element selector
+     * @param string       $html         expected text
+     *
+     * @throws ElementHtmlException
+     */
+    public function elementContains($selectorType, $selector, $html)
+    {
+        $element = $this->elementExists($selectorType, $selector);
+        $actual  = $element->getHtml();
+        $regex   = '/'.preg_quote($html, '/').'/ui';
+
+        $message = sprintf(
+            'The string "%s" was not found in the HTML of the %s.',
+            $html,
+            $this->getMatchingElementRepresentation($selectorType, $selector)
+        );
+
+        $this->assertElement((bool) preg_match($regex, $actual), $message, $element);
+    }
+
+    /**
+     * Checks that specific element does not contains HTML.
+     *
+     * @param string       $selectorType element selector type (css, xpath)
+     * @param string|array $selector     element selector
+     * @param string       $html         expected text
+     *
+     * @throws ElementHtmlException
+     */
+    public function elementNotContains($selectorType, $selector, $html)
+    {
+        $element = $this->elementExists($selectorType, $selector);
+        $actual  = $element->getHtml();
+        $regex   = '/'.preg_quote($html, '/').'/ui';
+
+        $message = sprintf(
+            'The string "%s" appears in the HTML of the %s, but it should not.',
+            $html,
+            $this->getMatchingElementRepresentation($selectorType, $selector)
+        );
+
+        $this->assertElement(!preg_match($regex, $actual), $message, $element);
+    }
+
+    /**
+     * Checks that an attribute exists in an element.
+     *
+     * @param string       $selectorType
+     * @param string|array $selector
+     * @param string       $attribute
+     *
+     * @return NodeElement
+     *
+     * @throws ElementHtmlException
+     */
+    public function elementAttributeExists($selectorType, $selector, $attribute)
+    {
+        $element = $this->elementExists($selectorType, $selector);
+
+        $message = sprintf(
+            'The attribute "%s" was not found in the %s.',
+            $attribute,
+            $this->getMatchingElementRepresentation($selectorType, $selector)
+        );
+
+        $this->assertElement($element->hasAttribute($attribute), $message, $element);
+
+        return $element;
+    }
+
+    /**
+     * Checks that an attribute of a specific elements contains text.
+     *
+     * @param string       $selectorType
+     * @param string|array $selector
+     * @param string       $attribute
+     * @param string       $text
+     *
+     * @throws ElementHtmlException
+     */
+    public function elementAttributeContains($selectorType, $selector, $attribute, $text)
+    {
+        $element = $this->elementAttributeExists($selectorType, $selector, $attribute);
+        $actual  = $element->getAttribute($attribute);
+        $regex   = '/'.preg_quote($text, '/').'/ui';
+
+        $message = sprintf(
+            'The text "%s" was not found in the attribute "%s" of the %s.',
+            $text,
+            $attribute,
+            $this->getMatchingElementRepresentation($selectorType, $selector)
+        );
+
+        $this->assertElement((bool) preg_match($regex, $actual), $message, $element);
+    }
+
+    /**
+     * Checks that an attribute of a specific elements does not contain text.
+     *
+     * @param string       $selectorType
+     * @param string|array $selector
+     * @param string       $attribute
+     * @param string       $text
+     *
+     * @throws ElementHtmlException
+     */
+    public function elementAttributeNotContains($selectorType, $selector, $attribute, $text)
+    {
+        $element = $this->elementAttributeExists($selectorType, $selector, $attribute);
+        $actual  = $element->getAttribute($attribute);
+        $regex   = '/'.preg_quote($text, '/').'/ui';
+
+        $message = sprintf(
+            'The text "%s" was found in the attribute "%s" of the %s.',
+            $text,
+            $attribute,
+            $this->getMatchingElementRepresentation($selectorType, $selector)
+        );
+
+        $this->assertElement(!preg_match($regex, $actual), $message, $element);
+    }
+
+    /**
+     * Checks that specific field exists on the current page.
+     *
+     * @param string             $field     field id|name|label|value
+     * @param TraversableElement $container document to check against
+     *
+     * @return NodeElement
+     *
+     * @throws ElementNotFoundException
+     */
+    public function fieldExists($field, TraversableElement $container = null)
+    {
+        $container = $container ?: $this->session->getPage();
+        $node = $container->findField($field);
+
+        if (null === $node) {
+            throw new ElementNotFoundException($this->session, 'form field', 'id|name|label|value', $field);
+        }
+
+        return $node;
+    }
+
+    /**
+     * Checks that specific field does not exists on the current page.
+     *
+     * @param string             $field     field id|name|label|value
+     * @param TraversableElement $container document to check against
+     *
+     * @throws ExpectationException
+     */
+    public function fieldNotExists($field, TraversableElement $container = null)
+    {
+        $container = $container ?: $this->session->getPage();
+        $node = $container->findField($field);
+
+        $this->assert(null === $node, sprintf('A field "%s" appears on this page, but it should not.', $field));
+    }
+
+    /**
+     * Checks that specific field have provided value.
+     *
+     * @param string             $field     field id|name|label|value
+     * @param string             $value     field value
+     * @param TraversableElement $container document to check against
+     *
+     * @throws ExpectationException
+     */
+    public function fieldValueEquals($field, $value, TraversableElement $container = null)
+    {
+        $node   = $this->fieldExists($field, $container);
+        $actual = $node->getValue();
+        $regex  = '/^'.preg_quote($value, '/').'$/ui';
+
+        $message = sprintf('The field "%s" value is "%s", but "%s" expected.', $field, $actual, $value);
+
+        $this->assert((bool) preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that specific field have provided value.
+     *
+     * @param string             $field     field id|name|label|value
+     * @param string             $value     field value
+     * @param TraversableElement $container document to check against
+     *
+     * @throws ExpectationException
+     */
+    public function fieldValueNotEquals($field, $value, TraversableElement $container = null)
+    {
+        $node   = $this->fieldExists($field, $container);
+        $actual = $node->getValue();
+        $regex  = '/^'.preg_quote($value, '/').'$/ui';
+
+        $message = sprintf('The field "%s" value is "%s", but it should not be.', $field, $actual);
+
+        $this->assert(!preg_match($regex, $actual), $message);
+    }
+
+    /**
+     * Checks that specific checkbox is checked.
+     *
+     * @param string             $field     field id|name|label|value
+     * @param TraversableElement $container document to check against
+     *
+     * @throws ExpectationException
+     */
+    public function checkboxChecked($field, TraversableElement $container = null)
+    {
+        $node = $this->fieldExists($field, $container);
+
+        $this->assert($node->isChecked(), sprintf('Checkbox "%s" is not checked, but it should be.', $field));
+    }
+
+    /**
+     * Checks that specific checkbox is unchecked.
+     *
+     * @param string             $field     field id|name|label|value
+     * @param TraversableElement $container document to check against
+     *
+     * @throws ExpectationException
+     */
+    public function checkboxNotChecked($field, TraversableElement $container = null)
+    {
+        $node = $this->fieldExists($field, $container);
+
+        $this->assert(!$node->isChecked(), sprintf('Checkbox "%s" is checked, but it should not be.', $field));
+    }
+
+    /**
+     * Gets current url of the page.
+     *
+     * @return string
+     */
+    protected function getCurrentUrlPath()
+    {
+        return $this->cleanUrl($this->session->getCurrentUrl());
+    }
+
+    /**
+     * Trims scriptname from the URL.
+     *
+     * @param string $url
+     *
+     * @return string
+     */
+    protected function cleanUrl($url)
+    {
+        $parts = parse_url($url);
+        $fragment = empty($parts['fragment']) ? '' : '#' . $parts['fragment'];
+
+        return preg_replace('/^\/[^\.\/]+\.php/', '', $parts['path']) . $fragment;
+    }
+
+    /**
+     * Asserts a condition.
+     *
+     * @param bool   $condition
+     * @param string $message   Failure message
+     *
+     * @throws ExpectationException when the condition is not fulfilled
+     */
+    private function assert($condition, $message)
+    {
+        if ($condition) {
+            return;
+        }
+
+        throw new ExpectationException($message, $this->session);
+    }
+
+    /**
+     * Asserts a condition involving the response text.
+     *
+     * @param bool   $condition
+     * @param string $message   Failure message
+     *
+     * @throws ResponseTextException when the condition is not fulfilled
+     */
+    private function assertResponseText($condition, $message)
+    {
+        if ($condition) {
+            return;
+        }
+
+        throw new ResponseTextException($message, $this->session);
+    }
+
+    /**
+     * Asserts a condition on an element.
+     *
+     * @param bool    $condition
+     * @param string  $message   Failure message
+     * @param Element $element
+     *
+     * @throws ElementHtmlException when the condition is not fulfilled
+     */
+    private function assertElement($condition, $message, Element $element)
+    {
+        if ($condition) {
+            return;
+        }
+
+        throw new ElementHtmlException($message, $this->session, $element);
+    }
+
+    /**
+     * Asserts a condition involving the text of an element.
+     *
+     * @param bool    $condition
+     * @param string  $message   Failure message
+     * @param Element $element
+     *
+     * @throws ElementTextException when the condition is not fulfilled
+     */
+    private function assertElementText($condition, $message, Element $element)
+    {
+        if ($condition) {
+            return;
+        }
+
+        throw new ElementTextException($message, $this->session, $element);
+    }
+
+    /**
+     * @param string       $selectorType
+     * @param string|array $selector
+     * @param boolean      $plural
+     *
+     * @return string
+     */
+    private function getMatchingElementRepresentation($selectorType, $selector, $plural = false)
+    {
+        $pluralization = $plural ? 's' : '';
+
+        if (in_array($selectorType, array('named', 'named_exact', 'named_partial'))
+            && is_array($selector) && 2 === count($selector)
+        ) {
+            return sprintf('%s%s matching locator "%s"', $selector[0], $pluralization, $selector[1]);
+        }
+
+        if (is_array($selector)) {
+            $selector = implode(' ', $selector);
+        }
+
+        return sprintf('element%s matching %s "%s"', $pluralization, $selectorType, $selector);
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Driver/CoreDriverTest.php b/core/vendor/behat/mink/tests/Driver/CoreDriverTest.php
new file mode 100644
index 0000000..d99b17f
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Driver/CoreDriverTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Behat\Mink\Tests\Driver;
+
+class CoreDriverTest extends \PHPUnit_Framework_TestCase
+{
+    public function testNoExtraMethods()
+    {
+        $interfaceRef = new \ReflectionClass('Behat\Mink\Driver\DriverInterface');
+        $coreDriverRef = new \ReflectionClass('Behat\Mink\Driver\CoreDriver');
+
+        foreach ($coreDriverRef->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
+            $this->assertTrue(
+                $interfaceRef->hasMethod($method->getName()),
+                sprintf('CoreDriver should not implement methods which are not part of the DriverInterface but %s found', $method->getName())
+            );
+        }
+    }
+
+    /**
+     * @dataProvider getDriverInterfaceMethods
+     */
+    public function testInterfaceMethods(\ReflectionMethod $method)
+    {
+        $refl = new \ReflectionClass('Behat\Mink\Driver\CoreDriver');
+
+        $this->assertFalse(
+            $refl->getMethod($method->getName())->isAbstract(),
+            sprintf('CoreDriver should implement a dummy %s method', $method->getName())
+        );
+
+        $driver = $this->getMockForAbstractClass('Behat\Mink\Driver\CoreDriver');
+
+        $this->setExpectedException('Behat\Mink\Exception\UnsupportedDriverActionException');
+        call_user_func_array(array($driver, $method->getName()), $this->getArguments($method));
+    }
+
+    public function getDriverInterfaceMethods()
+    {
+        $ref = new \ReflectionClass('Behat\Mink\Driver\DriverInterface');
+
+        return array_map(function ($method) {
+            return array($method);
+        }, $ref->getMethods());
+    }
+
+    private function getArguments(\ReflectionMethod $method)
+    {
+        $arguments = array();
+
+        foreach ($method->getParameters() as $parameter) {
+            $arguments[] = $this->getArgument($parameter);
+        }
+
+        return $arguments;
+    }
+
+    private function getArgument(\ReflectionParameter $argument)
+    {
+        if ($argument->isOptional()) {
+            return $argument->getDefaultValue();
+        }
+
+        if ($argument->allowsNull()) {
+            return null;
+        }
+
+        if ($argument->getClass()) {
+            return $this->getMockBuilder($argument->getClass()->getName())
+                ->disableOriginalConstructor()
+                ->getMock();
+        }
+
+        return null;
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Element/DocumentElementTest.php b/core/vendor/behat/mink/tests/Element/DocumentElementTest.php
new file mode 100644
index 0000000..bb42b68
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Element/DocumentElementTest.php
@@ -0,0 +1,446 @@
+<?php
+
+namespace Behat\Mink\Tests\Element;
+
+use Behat\Mink\Element\DocumentElement;
+
+class DocumentElementTest extends ElementTest
+{
+    /**
+     * Page.
+     *
+     * @var DocumentElement
+     */
+    private $document;
+
+    protected function setUp()
+    {
+        parent::setUp();
+        $this->document = new DocumentElement($this->session);
+    }
+
+    public function testGetSession()
+    {
+        $this->assertEquals($this->session, $this->document->getSession());
+    }
+
+    public function testFindAll()
+    {
+        $xpath = 'h3[a]';
+        $css = 'h3 > a';
+
+        $this->driver
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->will($this->returnValueMap(array(
+                array('//html/' . $xpath, array(2, 3, 4)),
+                array('//html/' . $css, array(1, 2)),
+            )));
+
+        $this->selectors
+            ->expects($this->exactly(2))
+            ->method('selectorToXpath')
+            ->will($this->returnValueMap(array(
+                array('xpath', $xpath, $xpath),
+                array('css', $css, $css),
+            )));
+
+        $this->assertEquals(3, count($this->document->findAll('xpath', $xpath)));
+        $this->assertEquals(2, count($this->document->findAll('css', $css)));
+    }
+
+    public function testFind()
+    {
+        $this->driver
+            ->expects($this->exactly(3))
+            ->method('find')
+            ->with('//html/h3[a]')
+            ->will($this->onConsecutiveCalls(array(2, 3, 4), array(1, 2), array()));
+
+        $xpath = 'h3[a]';
+        $css = 'h3 > a';
+
+        $this->selectors
+            ->expects($this->exactly(3))
+            ->method('selectorToXpath')
+            ->will($this->returnValueMap(array(
+                array('xpath', $xpath, $xpath),
+                array('xpath', $xpath, $xpath),
+                array('css', $css, $xpath),
+            )));
+
+        $this->assertEquals(2, $this->document->find('xpath', $xpath));
+        $this->assertEquals(1, $this->document->find('css', $css));
+        $this->assertNull($this->document->find('xpath', $xpath));
+    }
+
+    public function testFindField()
+    {
+        $this->mockNamedFinder(
+            '//field',
+            array('field1', 'field2', 'field3'),
+            array('field', 'some field')
+        );
+
+        $this->assertEquals('field1', $this->document->findField('some field'));
+        $this->assertEquals(null, $this->document->findField('some field'));
+    }
+
+    public function testFindLink()
+    {
+        $this->mockNamedFinder(
+            '//link',
+            array('link1', 'link2', 'link3'),
+            array('link', 'some link')
+        );
+
+        $this->assertEquals('link1', $this->document->findLink('some link'));
+        $this->assertEquals(null, $this->document->findLink('some link'));
+    }
+
+    public function testFindButton()
+    {
+        $this->mockNamedFinder(
+            '//button',
+            array('button1', 'button2', 'button3'),
+            array('button', 'some button')
+        );
+
+        $this->assertEquals('button1', $this->document->findButton('some button'));
+        $this->assertEquals(null, $this->document->findButton('some button'));
+    }
+
+    public function testFindById()
+    {
+        $xpath = '//*[@id=some-item-2]';
+
+        $this->mockNamedFinder($xpath, array(array('id2', 'id3'), array()), array('id', 'some-item-2'));
+
+        $this->assertEquals('id2', $this->document->findById('some-item-2'));
+        $this->assertEquals(null, $this->document->findById('some-item-2'));
+    }
+
+    public function testHasSelector()
+    {
+        $this->driver
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('//html/some xpath')
+            ->will($this->onConsecutiveCalls(array('id2', 'id3'), array()));
+
+        $this->selectors
+            ->expects($this->exactly(2))
+            ->method('selectorToXpath')
+            ->with('xpath', 'some xpath')
+            ->will($this->returnValue('some xpath'));
+
+        $this->assertTrue($this->document->has('xpath', 'some xpath'));
+        $this->assertFalse($this->document->has('xpath', 'some xpath'));
+    }
+
+    public function testHasContent()
+    {
+        $this->mockNamedFinder(
+            '//some content',
+            array('item1', 'item2'),
+            array('content', 'some content')
+        );
+
+        $this->assertTrue($this->document->hasContent('some content'));
+        $this->assertFalse($this->document->hasContent('some content'));
+    }
+
+    public function testHasLink()
+    {
+        $this->mockNamedFinder(
+            '//link',
+            array('link1', 'link2', 'link3'),
+            array('link', 'some link')
+        );
+
+        $this->assertTrue($this->document->hasLink('some link'));
+        $this->assertFalse($this->document->hasLink('some link'));
+    }
+
+    public function testHasButton()
+    {
+        $this->mockNamedFinder(
+            '//button',
+            array('button1', 'button2', 'button3'),
+            array('button', 'some button')
+        );
+
+        $this->assertTrue($this->document->hasButton('some button'));
+        $this->assertFalse($this->document->hasButton('some button'));
+    }
+
+    public function testHasField()
+    {
+        $this->mockNamedFinder(
+            '//field',
+            array('field1', 'field2', 'field3'),
+            array('field', 'some field')
+        );
+
+        $this->assertTrue($this->document->hasField('some field'));
+        $this->assertFalse($this->document->hasField('some field'));
+    }
+
+    public function testHasCheckedField()
+    {
+        $checkbox = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $checkbox
+            ->expects($this->exactly(2))
+            ->method('isChecked')
+            ->will($this->onConsecutiveCalls(true, false));
+
+        $this->mockNamedFinder(
+            '//field',
+            array(array($checkbox), array(), array($checkbox)),
+            array('field', 'some checkbox'),
+            3
+        );
+
+        $this->assertTrue($this->document->hasCheckedField('some checkbox'));
+        $this->assertFalse($this->document->hasCheckedField('some checkbox'));
+        $this->assertFalse($this->document->hasCheckedField('some checkbox'));
+    }
+
+    public function testHasUncheckedField()
+    {
+        $checkbox = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $checkbox
+            ->expects($this->exactly(2))
+            ->method('isChecked')
+            ->will($this->onConsecutiveCalls(true, false));
+
+        $this->mockNamedFinder(
+            '//field',
+            array(array($checkbox), array(), array($checkbox)),
+            array('field', 'some checkbox'),
+            3
+        );
+
+        $this->assertFalse($this->document->hasUncheckedField('some checkbox'));
+        $this->assertFalse($this->document->hasUncheckedField('some checkbox'));
+        $this->assertTrue($this->document->hasUncheckedField('some checkbox'));
+    }
+
+    public function testHasSelect()
+    {
+        $this->mockNamedFinder(
+            '//select',
+            array('select'),
+            array('select', 'some select field')
+        );
+
+        $this->assertTrue($this->document->hasSelect('some select field'));
+        $this->assertFalse($this->document->hasSelect('some select field'));
+    }
+
+    public function testHasTable()
+    {
+        $this->mockNamedFinder(
+            '//table',
+            array('table'),
+            array('table', 'some table')
+        );
+
+        $this->assertTrue($this->document->hasTable('some table'));
+        $this->assertFalse($this->document->hasTable('some table'));
+    }
+
+    public function testClickLink()
+    {
+        $node = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $node
+            ->expects($this->once())
+            ->method('click');
+
+        $this->mockNamedFinder(
+            '//link',
+            array($node),
+            array('link', 'some link')
+        );
+
+        $this->document->clickLink('some link');
+        $this->setExpectedException('Behat\Mink\Exception\ElementNotFoundException');
+        $this->document->clickLink('some link');
+    }
+
+    public function testClickButton()
+    {
+        $node = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $node
+            ->expects($this->once())
+            ->method('press');
+
+        $this->mockNamedFinder(
+            '//button',
+            array($node),
+            array('button', 'some button')
+        );
+
+        $this->document->pressButton('some button');
+        $this->setExpectedException('Behat\Mink\Exception\ElementNotFoundException');
+        $this->document->pressButton('some button');
+    }
+
+    public function testFillField()
+    {
+        $node = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $node
+            ->expects($this->once())
+            ->method('setValue')
+            ->with('some val');
+
+        $this->mockNamedFinder(
+            '//field',
+            array($node),
+            array('field', 'some field')
+        );
+
+        $this->document->fillField('some field', 'some val');
+        $this->setExpectedException('Behat\Mink\Exception\ElementNotFoundException');
+        $this->document->fillField('some field', 'some val');
+    }
+
+    public function testCheckField()
+    {
+        $node = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $node
+            ->expects($this->once())
+            ->method('check');
+
+        $this->mockNamedFinder(
+            '//field',
+            array($node),
+            array('field', 'some field')
+        );
+
+        $this->document->checkField('some field');
+        $this->setExpectedException('Behat\Mink\Exception\ElementNotFoundException');
+        $this->document->checkField('some field');
+    }
+
+    public function testUncheckField()
+    {
+        $node = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $node
+            ->expects($this->once())
+            ->method('uncheck');
+
+        $this->mockNamedFinder(
+            '//field',
+            array($node),
+            array('field', 'some field')
+        );
+
+        $this->document->uncheckField('some field');
+        $this->setExpectedException('Behat\Mink\Exception\ElementNotFoundException');
+        $this->document->uncheckField('some field');
+    }
+
+    public function testSelectField()
+    {
+        $node = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $node
+            ->expects($this->once())
+            ->method('selectOption')
+            ->with('option2');
+
+        $this->mockNamedFinder(
+            '//field',
+            array($node),
+            array('field', 'some field')
+        );
+
+        $this->document->selectFieldOption('some field', 'option2');
+        $this->setExpectedException('Behat\Mink\Exception\ElementNotFoundException');
+        $this->document->selectFieldOption('some field', 'option2');
+    }
+
+    public function testAttachFileToField()
+    {
+        $node = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $node
+            ->expects($this->once())
+            ->method('attachFile')
+            ->with('/path/to/file');
+
+        $this->mockNamedFinder(
+            '//field',
+            array($node),
+            array('field', 'some field')
+        );
+
+        $this->document->attachFileToField('some field', '/path/to/file');
+        $this->setExpectedException('Behat\Mink\Exception\ElementNotFoundException');
+        $this->document->attachFileToField('some field', '/path/to/file');
+    }
+
+    public function testGetContent()
+    {
+        $expects = 'page content';
+        $this->driver
+            ->expects($this->once())
+            ->method('getContent')
+            ->will($this->returnValue($expects));
+
+        $this->assertEquals($expects, $this->document->getContent());
+    }
+
+    public function testGetText()
+    {
+        $expects = 'val1';
+        $this->driver
+            ->expects($this->once())
+            ->method('getText')
+            ->with('//html')
+            ->will($this->returnValue($expects));
+
+        $this->assertEquals($expects, $this->document->getText());
+    }
+
+    public function testGetHtml()
+    {
+        $expects = 'val1';
+        $this->driver
+            ->expects($this->once())
+            ->method('getHtml')
+            ->with('//html')
+            ->will($this->returnValue($expects));
+
+        $this->assertEquals($expects, $this->document->getHtml());
+    }
+
+    public function testGetOuterHtml()
+    {
+        $expects = 'val1';
+        $this->driver
+            ->expects($this->once())
+            ->method('getOuterHtml')
+            ->with('//html')
+            ->will($this->returnValue($expects));
+
+        $this->assertEquals($expects, $this->document->getOuterHtml());
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Element/ElementTest.php b/core/vendor/behat/mink/tests/Element/ElementTest.php
new file mode 100644
index 0000000..1f9240a
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Element/ElementTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Behat\Mink\Tests\Element;
+
+use Behat\Mink\Driver\DriverInterface;
+use Behat\Mink\Session;
+use Behat\Mink\Selector\SelectorsHandler;
+
+abstract class ElementTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Session.
+     *
+     * @var Session
+     */
+    protected $session;
+
+    /**
+     * @var DriverInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $driver;
+
+    /**
+     * Selectors.
+     *
+     * @var SelectorsHandler|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $selectors;
+
+    protected function setUp()
+    {
+        $this->driver = $this->getMockBuilder('Behat\Mink\Driver\DriverInterface')->getMock();
+        $this->driver
+            ->expects($this->once())
+            ->method('setSession');
+
+        $this->selectors = $this->getMockBuilder('Behat\Mink\Selector\SelectorsHandler')->getMock();
+        $this->session = new Session($this->driver, $this->selectors);
+
+        $this->selectors
+            ->expects($this->any())
+            ->method('xpathLiteral')
+            ->will($this->returnArgument(0));
+    }
+
+    protected function mockNamedFinder($xpath, array $results, $locator, $times = 2)
+    {
+        if (!is_array($results[0])) {
+            $results = array($results, array());
+        }
+
+        // In case of empty results, a second call will be done using the partial selector
+        $processedResults = array();
+        foreach ($results as $result) {
+            $processedResults[] = $result;
+            if (empty($result)) {
+                $processedResults[] = $result;
+                $times++;
+            }
+        }
+
+        $returnValue = call_user_func_array(array($this, 'onConsecutiveCalls'), $processedResults);
+
+        $this->driver
+            ->expects($this->exactly($times))
+            ->method('find')
+            ->with('//html' . $xpath)
+            ->will($returnValue);
+
+        $this->selectors
+            ->expects($this->exactly($times))
+            ->method('selectorToXpath')
+            ->with($this->logicalOr('named_exact', 'named_partial'), $locator)
+            ->will($this->returnValue($xpath));
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Element/NodeElementTest.php b/core/vendor/behat/mink/tests/Element/NodeElementTest.php
new file mode 100644
index 0000000..b6a8bde
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Element/NodeElementTest.php
@@ -0,0 +1,593 @@
+<?php
+
+namespace Behat\Mink\Tests\Element;
+
+use Behat\Mink\Element\NodeElement;
+
+class NodeElementTest extends ElementTest
+{
+    public function testGetXpath()
+    {
+        $node = new NodeElement('some custom xpath', $this->session);
+
+        $this->assertEquals('some custom xpath', $node->getXpath());
+        $this->assertNotEquals('not some custom xpath', $node->getXpath());
+    }
+
+    public function testGetText()
+    {
+        $expected = 'val1';
+        $node = new NodeElement('text_tag', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('getText')
+            ->with('text_tag')
+            ->will($this->returnValue($expected));
+
+        $this->assertEquals($expected, $node->getText());
+    }
+
+    public function testGetOuterHtml()
+    {
+        $expected = 'val1';
+        $node = new NodeElement('text_tag', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('getOuterHtml')
+            ->with('text_tag')
+            ->will($this->returnValue($expected));
+
+        $this->assertEquals($expected, $node->getOuterHtml());
+    }
+
+    public function testElementIsValid()
+    {
+        $elementXpath = 'some xpath';
+        $node = new NodeElement($elementXpath, $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('find')
+            ->with($elementXpath)
+            ->will($this->returnValue(array($elementXpath)));
+
+        $this->assertTrue($node->isValid());
+    }
+
+    public function testElementIsNotValid()
+    {
+        $node = new NodeElement('some xpath', $this->session);
+
+        $this->driver
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('some xpath')
+            ->will($this->onConsecutiveCalls(array(), array('xpath1', 'xpath2')));
+
+        $this->assertFalse($node->isValid(), 'no elements found is invalid element');
+        $this->assertFalse($node->isValid(), 'more then 1 element found is invalid element');
+    }
+
+    public function testWaitForSuccess()
+    {
+        $callCounter = 0;
+        $node = new NodeElement('some xpath', $this->session);
+
+        $result = $node->waitFor(5, function ($givenNode) use (&$callCounter) {
+            $callCounter++;
+
+            if (1 === $callCounter) {
+                return null;
+            } elseif (2 === $callCounter) {
+                return false;
+            } elseif (3 === $callCounter) {
+                return array();
+            }
+
+            return $givenNode;
+        });
+
+        $this->assertEquals(4, $callCounter, '->waitFor() tries to locate element several times before failing');
+        $this->assertSame($node, $result, '->waitFor() returns node found in callback');
+    }
+
+    public function testWaitForTimeout()
+    {
+        $node = new NodeElement('some xpath', $this->session);
+
+        $expectedTimeout = 2;
+        $startTime = microtime(true);
+        $result = $node->waitFor($expectedTimeout, function () {
+            return null;
+        });
+        $endTime = microtime(true);
+
+        $this->assertNull($result, '->waitFor() returns whatever callback gives');
+        $this->assertEquals($expectedTimeout, round($endTime - $startTime));
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testWaitForFailure()
+    {
+        $node = new NodeElement('some xpath', $this->session);
+        $node->waitFor(5, 'not a callable');
+    }
+
+    public function testHasAttribute()
+    {
+        $node = new NodeElement('input_tag', $this->session);
+
+        $this->driver
+            ->expects($this->exactly(2))
+            ->method('getAttribute')
+            ->with('input_tag', 'href')
+            ->will($this->onConsecutiveCalls(null, 'http://...'));
+
+        $this->assertFalse($node->hasAttribute('href'));
+        $this->assertTrue($node->hasAttribute('href'));
+    }
+
+    public function testGetAttribute()
+    {
+        $expected = 'http://...';
+        $node = new NodeElement('input_tag', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('getAttribute')
+            ->with('input_tag', 'href')
+            ->will($this->returnValue($expected));
+
+        $this->assertEquals($expected, $node->getAttribute('href'));
+    }
+
+    public function testHasClass()
+    {
+        $node = new NodeElement('input_tag', $this->session);
+
+        $this->driver
+            ->expects($this->exactly(6))
+            ->method('getAttribute')
+            ->with('input_tag', 'class')
+            ->will($this->returnValue('class1 class2'));
+
+        $this->assertTrue($node->hasClass('class1'));
+        $this->assertTrue($node->hasClass('class2'));
+        $this->assertFalse($node->hasClass('class3'));
+    }
+
+    public function testHasClassWithoutArgument()
+    {
+        $node = new NodeElement('input_tag', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('getAttribute')
+            ->with('input_tag', 'class')
+            ->will($this->returnValue(null));
+
+        $this->assertFalse($node->hasClass('class3'));
+    }
+
+    public function testGetValue()
+    {
+        $expected = 'val1';
+        $node = new NodeElement('input_tag', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('getValue')
+            ->with('input_tag')
+            ->will($this->returnValue($expected));
+
+        $this->assertEquals($expected, $node->getValue());
+    }
+
+    public function testSetValue()
+    {
+        $expected = 'new_val';
+        $node = new NodeElement('input_tag', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('setValue')
+            ->with('input_tag', $expected);
+
+        $node->setValue($expected);
+    }
+
+    public function testClick()
+    {
+        $node = new NodeElement('link_or_button', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('click')
+            ->with('link_or_button');
+
+        $node->click();
+    }
+
+    public function testPress()
+    {
+        $node = new NodeElement('link_or_button', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('click')
+            ->with('link_or_button');
+
+        $node->press();
+    }
+
+    public function testRightClick()
+    {
+        $node = new NodeElement('elem', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('rightClick')
+            ->with('elem');
+
+        $node->rightClick();
+    }
+
+    public function testDoubleClick()
+    {
+        $node = new NodeElement('elem', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('doubleClick')
+            ->with('elem');
+
+        $node->doubleClick();
+    }
+
+    public function testCheck()
+    {
+        $node = new NodeElement('checkbox_or_radio', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('check')
+            ->with('checkbox_or_radio');
+
+        $node->check();
+    }
+
+    public function testUncheck()
+    {
+        $node = new NodeElement('checkbox_or_radio', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('uncheck')
+            ->with('checkbox_or_radio');
+
+        $node->uncheck();
+    }
+
+    public function testSelectOption()
+    {
+        $node = new NodeElement('select', $this->session);
+        $option = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $option
+            ->expects($this->once())
+            ->method('getValue')
+            ->will($this->returnValue('item1'));
+
+        $this->driver
+            ->expects($this->once())
+            ->method('getTagName')
+            ->with('select')
+            ->will($this->returnValue('select'));
+
+        $this->driver
+            ->expects($this->once())
+            ->method('find')
+            ->with('select/option')
+            ->will($this->returnValue(array($option)));
+
+        $this->selectors
+            ->expects($this->once())
+            ->method('selectorToXpath')
+            ->with('named_exact', array('option', 'item1'))
+            ->will($this->returnValue('option'));
+
+        $this->driver
+            ->expects($this->once())
+            ->method('selectOption')
+            ->with('select', 'item1', false);
+
+        $node->selectOption('item1');
+    }
+
+    /**
+     * @expectedException \Behat\Mink\Exception\ElementNotFoundException
+     */
+    public function testSelectOptionNotFound()
+    {
+        $node = new NodeElement('select', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('getTagName')
+            ->with('select')
+            ->will($this->returnValue('select'));
+
+        $this->driver
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('select/option')
+            ->will($this->returnValue(array()));
+
+        $this->selectors
+            ->expects($this->exactly(2))
+            ->method('selectorToXpath')
+            ->with($this->logicalOr('named_exact', 'named_partial'), array('option', 'item1'))
+            ->will($this->returnValue('option'));
+
+        $node->selectOption('item1');
+    }
+
+    public function testSelectOptionOtherTag()
+    {
+        $node = new NodeElement('div', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('getTagName')
+            ->with('div')
+            ->will($this->returnValue('div'));
+
+        $this->driver
+            ->expects($this->once())
+            ->method('selectOption')
+            ->with('div', 'item1', false);
+
+        $node->selectOption('item1');
+    }
+
+    public function testGetTagName()
+    {
+        $node = new NodeElement('html//h3', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('getTagName')
+            ->with('html//h3')
+            ->will($this->returnValue('h3'));
+
+        $this->assertEquals('h3', $node->getTagName());
+    }
+
+    public function testGetParent()
+    {
+        $node = new NodeElement('elem', $this->session);
+        $parent = $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->driver
+            ->expects($this->once())
+            ->method('find')
+            ->with('elem/..')
+            ->will($this->returnValue(array($parent)));
+
+        $this->selectors
+            ->expects($this->once())
+            ->method('selectorToXpath')
+            ->with('xpath', '..')
+            ->will($this->returnValue('..'));
+
+        $this->assertSame($parent, $node->getParent());
+    }
+
+    public function testAttachFile()
+    {
+        $node = new NodeElement('elem', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('attachFile')
+            ->with('elem', 'path');
+
+        $node->attachFile('path');
+    }
+
+    public function testIsVisible()
+    {
+        $node = new NodeElement('some_xpath', $this->session);
+
+        $this->driver
+            ->expects($this->exactly(2))
+            ->method('isVisible')
+            ->with('some_xpath')
+            ->will($this->onConsecutiveCalls(true, false));
+
+        $this->assertTrue($node->isVisible());
+        $this->assertFalse($node->isVisible());
+    }
+
+    public function testIsChecked()
+    {
+        $node = new NodeElement('some_xpath', $this->session);
+
+        $this->driver
+            ->expects($this->exactly(2))
+            ->method('isChecked')
+            ->with('some_xpath')
+            ->will($this->onConsecutiveCalls(true, false));
+
+        $this->assertTrue($node->isChecked());
+        $this->assertFalse($node->isChecked());
+    }
+
+    public function testIsSelected()
+    {
+        $node = new NodeElement('some_xpath', $this->session);
+
+        $this->driver
+            ->expects($this->exactly(2))
+            ->method('isSelected')
+            ->with('some_xpath')
+            ->will($this->onConsecutiveCalls(true, false));
+
+        $this->assertTrue($node->isSelected());
+        $this->assertFalse($node->isSelected());
+    }
+
+    public function testFocus()
+    {
+        $node = new NodeElement('some-element', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('focus')
+            ->with('some-element');
+
+        $node->focus();
+    }
+
+    public function testBlur()
+    {
+        $node = new NodeElement('some-element', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('blur')
+            ->with('some-element');
+
+        $node->blur();
+    }
+
+    public function testMouseOver()
+    {
+        $node = new NodeElement('some-element', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('mouseOver')
+            ->with('some-element');
+
+        $node->mouseOver();
+    }
+
+    public function testDragTo()
+    {
+        $node = new NodeElement('some_tag1', $this->session);
+
+        $target = $this->getMock('Behat\Mink\Element\ElementInterface');
+        $target->expects($this->any())
+            ->method('getXPath')
+            ->will($this->returnValue('some_tag2'));
+
+        $this->driver
+            ->expects($this->once())
+            ->method('dragTo')
+            ->with('some_tag1', 'some_tag2');
+
+        $node->dragTo($target);
+    }
+
+    public function testKeyPress()
+    {
+        $node = new NodeElement('elem', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('keyPress')
+            ->with('elem', 'key');
+
+        $node->keyPress('key');
+    }
+
+    public function testKeyDown()
+    {
+        $node = new NodeElement('elem', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('keyDown')
+            ->with('elem', 'key');
+
+        $node->keyDown('key');
+    }
+
+    public function testKeyUp()
+    {
+        $node = new NodeElement('elem', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('keyUp')
+            ->with('elem', 'key');
+
+        $node->keyUp('key');
+    }
+
+    public function testSubmitForm()
+    {
+        $node = new NodeElement('some_xpath', $this->session);
+
+        $this->driver
+            ->expects($this->once())
+            ->method('submitForm')
+            ->with('some_xpath');
+
+        $node->submit();
+    }
+
+    public function testFindAllUnion()
+    {
+        $node = new NodeElement('some_xpath', $this->session);
+        $xpath = "some_tag1 | some_tag2[@foo =\n 'bar|'']\n | some_tag3[foo | bar]";
+        $expected = "some_xpath/some_tag1 | some_xpath/some_tag2[@foo =\n 'bar|''] | some_xpath/some_tag3[foo | bar]";
+
+        $this->driver
+            ->expects($this->exactly(1))
+            ->method('find')
+            ->will($this->returnValueMap(array(
+                array($expected, array(2, 3, 4)),
+            )));
+
+        $this->selectors
+            ->expects($this->exactly(1))
+            ->method('selectorToXpath')
+            ->will($this->returnValueMap(array(
+                array('xpath', $xpath, $xpath),
+            )));
+
+        $this->assertEquals(3, count($node->findAll('xpath', $xpath)));
+    }
+
+    public function testFindAllParentUnion()
+    {
+        $node = new NodeElement('some_xpath | another_xpath', $this->session);
+        $xpath = "some_tag1 | some_tag2";
+        $expectedPrefixed = "(some_xpath | another_xpath)/some_tag1 | (some_xpath | another_xpath)/some_tag2";
+
+        $this->driver
+            ->expects($this->exactly(1))
+            ->method('find')
+            ->will($this->returnValueMap(array(
+                array($expectedPrefixed, array(2, 3, 4)),
+            )));
+
+        $this->selectors
+            ->expects($this->exactly(1))
+            ->method('selectorToXpath')
+            ->will($this->returnValueMap(array(
+                array('xpath', $xpath, $xpath),
+            )));
+
+        $this->assertEquals(3, count($node->findAll('xpath', $xpath)));
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Exception/ElementExceptionTest.php b/core/vendor/behat/mink/tests/Exception/ElementExceptionTest.php
new file mode 100644
index 0000000..021e8d5
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Exception/ElementExceptionTest.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Behat\Mink\Tests\Exception;
+
+use Behat\Mink\Exception\ElementException;
+
+class ElementExceptionTest extends \PHPUnit_Framework_TestCase
+{
+    public function testMessage()
+    {
+        $exception = new ElementException($this->getElementMock(), new \Exception('Something went wrong'));
+
+        $expectedMessage = "Exception thrown by element XPath\nSomething went wrong";
+        $this->assertEquals($expectedMessage, $exception->getMessage());
+        $this->assertEquals($expectedMessage, (string) $exception);
+    }
+
+    public function testElement()
+    {
+        $element = $this->getElementMock();
+
+        $exception = new ElementException($element, new \Exception('Something went wrong'));
+
+        $this->assertSame($element, $exception->getElement());
+    }
+
+    private function getElementMock()
+    {
+        $mock = $this->getMockBuilder('Behat\Mink\Element\Element')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $mock->expects($this->any())
+            ->method('getXPath')
+            ->will($this->returnValue('element XPath'));
+
+        return $mock;
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Exception/ElementHtmlExceptionTest.php b/core/vendor/behat/mink/tests/Exception/ElementHtmlExceptionTest.php
new file mode 100644
index 0000000..63d39dd
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Exception/ElementHtmlExceptionTest.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Behat\Mink\Tests\Exception;
+
+use Behat\Mink\Exception\ElementHtmlException;
+
+class ElementHtmlExceptionTest extends \PHPUnit_Framework_TestCase
+{
+    public function testExceptionToString()
+    {
+        $driver = $this->getMock('Behat\Mink\Driver\DriverInterface');
+        $element = $this->getElementMock();
+
+        $session = $this->getSessionMock();
+        $session->expects($this->any())
+            ->method('getDriver')
+            ->will($this->returnValue($driver));
+        $session->expects($this->any())
+            ->method('getStatusCode')
+            ->will($this->returnValue(200));
+        $session->expects($this->any())
+            ->method('getCurrentUrl')
+            ->will($this->returnValue('http://localhost/test'));
+
+        $element->expects($this->any())
+            ->method('getOuterHtml')
+            ->will($this->returnValue("<div>\n    <h1>Hello world</h1>\n    <p>Test</p>\n</div>"));
+
+        $expected = <<<'TXT'
+Html error
+
++--[ HTTP/1.1 200 | http://localhost/test | %s ]
+|
+|  <div>
+|      <h1>Hello world</h1>
+|      <p>Test</p>
+|  </div>
+|
+TXT;
+
+        $expected = sprintf($expected.'  ', get_class($driver));
+
+        $exception = new ElementHtmlException('Html error', $session, $element);
+
+        $this->assertEquals($expected, $exception->__toString());
+    }
+
+    private function getSessionMock()
+    {
+        return $this->getMockBuilder('Behat\Mink\Session')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+
+    private function getElementMock()
+    {
+        return $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Exception/ElementNotFoundExceptionTest.php b/core/vendor/behat/mink/tests/Exception/ElementNotFoundExceptionTest.php
new file mode 100644
index 0000000..8cb4e5d
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Exception/ElementNotFoundExceptionTest.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Behat\Mink\Tests\Exception;
+
+use Behat\Mink\Exception\ElementNotFoundException;
+
+class ElementNotFoundExceptionTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider provideExceptionMessage
+     */
+    public function testBuildMessage($message, $type, $selector = null, $locator = null)
+    {
+        $session = $this->getMockBuilder('Behat\Mink\Session')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $exception = new ElementNotFoundException($session, $type, $selector, $locator);
+
+        $this->assertEquals($message, $exception->getMessage());
+    }
+
+    public function provideExceptionMessage()
+    {
+        return array(
+            array('Tag not found.', null),
+            array('Field not found.', 'field'),
+            array('Tag matching locator "foobar" not found.', null, null, 'foobar'),
+            array('Tag matching css "foobar" not found.', null, 'css', 'foobar'),
+            array('Field matching xpath "foobar" not found.', 'Field', 'xpath', 'foobar'),
+            array('Tag with name "foobar" not found.', null, 'name', 'foobar'),
+        );
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Exception/ElementTextExceptionTest.php b/core/vendor/behat/mink/tests/Exception/ElementTextExceptionTest.php
new file mode 100644
index 0000000..73cef5b
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Exception/ElementTextExceptionTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Behat\Mink\Tests\Exception;
+
+use Behat\Mink\Exception\ElementTextException;
+
+class ElementTextExceptionTest extends \PHPUnit_Framework_TestCase
+{
+    public function testExceptionToString()
+    {
+        $driver = $this->getMock('Behat\Mink\Driver\DriverInterface');
+        $element = $this->getElementMock();
+
+        $session = $this->getSessionMock();
+        $session->expects($this->any())
+            ->method('getDriver')
+            ->will($this->returnValue($driver));
+        $session->expects($this->any())
+            ->method('getStatusCode')
+            ->will($this->returnValue(200));
+        $session->expects($this->any())
+            ->method('getCurrentUrl')
+            ->will($this->returnValue('http://localhost/test'));
+
+        $element->expects($this->any())
+            ->method('getText')
+            ->will($this->returnValue("Hello world\nTest\n"));
+
+        $expected = <<<'TXT'
+Text error
+
++--[ HTTP/1.1 200 | http://localhost/test | %s ]
+|
+|  Hello world
+|  Test
+|
+TXT;
+
+        $expected = sprintf($expected.'  ', get_class($driver));
+
+        $exception = new ElementTextException('Text error', $session, $element);
+
+        $this->assertEquals($expected, $exception->__toString());
+    }
+
+    private function getSessionMock()
+    {
+        return $this->getMockBuilder('Behat\Mink\Session')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+
+    private function getElementMock()
+    {
+        return $this->getMockBuilder('Behat\Mink\Element\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Exception/ExpectationExceptionTest.php b/core/vendor/behat/mink/tests/Exception/ExpectationExceptionTest.php
new file mode 100644
index 0000000..23e53bc
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Exception/ExpectationExceptionTest.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace Behat\Mink\Tests\Exception;
+
+use Behat\Mink\Exception\ExpectationException;
+
+class ExpectationExceptionTest extends \PHPUnit_Framework_TestCase
+{
+    public function testEmptyMessageAndPreviousException()
+    {
+        $exception = new ExpectationException('', $this->getSessionMock(), new \Exception('Something failed'));
+
+        $this->assertEquals('Something failed', $exception->getMessage());
+    }
+
+    public function testExceptionToString()
+    {
+        $driver = $this->getMock('Behat\Mink\Driver\DriverInterface');
+        $page = $this->getPageMock();
+
+        $session = $this->getSessionMock();
+        $session->expects($this->any())
+            ->method('getDriver')
+            ->will($this->returnValue($driver));
+        $session->expects($this->any())
+            ->method('getPage')
+            ->will($this->returnValue($page));
+        $session->expects($this->any())
+            ->method('getStatusCode')
+            ->will($this->returnValue(200));
+        $session->expects($this->any())
+            ->method('getCurrentUrl')
+            ->will($this->returnValue('http://localhost/test'));
+
+        $html = "<html><head><title>Hello</title></head>\n<body>\n<h1>Hello world</h1>\n<p>Test</p>\n</body></html>";
+        $page->expects($this->any())
+            ->method('getContent')
+            ->will($this->returnValue($html));
+
+        $expected = <<<'TXT'
+Expectation failure
+
++--[ HTTP/1.1 200 | http://localhost/test | %s ]
+|
+|  <body>
+|  <h1>Hello world</h1>
+|  <p>Test</p>
+|  </body>
+|
+TXT;
+
+        $expected = sprintf($expected.'  ', get_class($driver));
+
+        $exception = new ExpectationException('Expectation failure', $session);
+
+        $this->assertEquals($expected, $exception->__toString());
+    }
+
+    public function testExceptionWhileRenderingString()
+    {
+        $session = $this->getSessionMock();
+        $session->expects($this->any())
+            ->method('getPage')
+            ->will($this->throwException(new \Exception('Broken page')));
+
+        $exception = new ExpectationException('Expectation failure', $session);
+
+        $this->assertEquals('Expectation failure', $exception->__toString());
+    }
+
+    private function getSessionMock()
+    {
+        return $this->getMockBuilder('Behat\Mink\Session')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+
+    private function getPageMock()
+    {
+        return $this->getMockBuilder('Behat\Mink\Element\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Exception/ResponseTextExceptionTest.php b/core/vendor/behat/mink/tests/Exception/ResponseTextExceptionTest.php
new file mode 100644
index 0000000..4651b7c
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Exception/ResponseTextExceptionTest.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Behat\Mink\Tests\Exception;
+
+use Behat\Mink\Exception\ResponseTextException;
+
+class ResponseTextExceptionTest extends \PHPUnit_Framework_TestCase
+{
+    public function testExceptionToString()
+    {
+        $driver = $this->getMock('Behat\Mink\Driver\DriverInterface');
+        $page = $this->getPageMock();
+
+        $session = $this->getSessionMock();
+        $session->expects($this->any())
+            ->method('getDriver')
+            ->will($this->returnValue($driver));
+        $session->expects($this->any())
+            ->method('getPage')
+            ->will($this->returnValue($page));
+        $session->expects($this->any())
+            ->method('getStatusCode')
+            ->will($this->returnValue(200));
+        $session->expects($this->any())
+            ->method('getCurrentUrl')
+            ->will($this->returnValue('http://localhost/test'));
+
+        $page->expects($this->any())
+            ->method('getText')
+            ->will($this->returnValue("Hello world\nTest\n"));
+
+        $expected = <<<'TXT'
+Text error
+
++--[ HTTP/1.1 200 | http://localhost/test | %s ]
+|
+|  Hello world
+|  Test
+|
+TXT;
+
+        $expected = sprintf($expected.'  ', get_class($driver));
+
+        $exception = new ResponseTextException('Text error', $session);
+
+        $this->assertEquals($expected, $exception->__toString());
+    }
+
+    private function getSessionMock()
+    {
+        return $this->getMockBuilder('Behat\Mink\Session')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+
+    private function getPageMock()
+    {
+        return $this->getMockBuilder('Behat\Mink\Element\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+}
diff --git a/core/vendor/behat/mink/tests/MinkTest.php b/core/vendor/behat/mink/tests/MinkTest.php
new file mode 100644
index 0000000..11d6466
--- /dev/null
+++ b/core/vendor/behat/mink/tests/MinkTest.php
@@ -0,0 +1,246 @@
+<?php
+
+namespace Behat\Mink\Tests;
+
+use Behat\Mink\Mink;
+
+class MinkTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Mink
+     */
+    private $mink;
+
+    protected function setUp()
+    {
+        $this->mink = new Mink();
+    }
+
+    public function testRegisterSession()
+    {
+        $session = $this->getSessionMock();
+
+        $this->assertFalse($this->mink->hasSession('not_registered'));
+        $this->assertFalse($this->mink->hasSession('js'));
+        $this->assertFalse($this->mink->hasSession('my'));
+
+        $this->mink->registerSession('my', $session);
+
+        $this->assertTrue($this->mink->hasSession('my'));
+        $this->assertFalse($this->mink->hasSession('not_registered'));
+        $this->assertFalse($this->mink->hasSession('js'));
+    }
+
+    public function testRegisterSessionThroughConstructor()
+    {
+        $mink = new Mink(array('my' => $this->getSessionMock()));
+
+        $this->assertTrue($mink->hasSession('my'));
+    }
+
+    public function testSessionAutostop()
+    {
+        $session1 = $this->getSessionMock();
+        $session2 = $this->getSessionMock();
+        $this->mink->registerSession('my1', $session1);
+        $this->mink->registerSession('my2', $session2);
+
+        $session1
+            ->expects($this->once())
+            ->method('isStarted')
+            ->will($this->returnValue(true));
+        $session1
+            ->expects($this->once())
+            ->method('stop');
+        $session2
+            ->expects($this->once())
+            ->method('isStarted')
+            ->will($this->returnValue(false));
+        $session2
+            ->expects($this->never())
+            ->method('stop');
+
+        unset($this->mink);
+    }
+
+    public function testNotStartedSession()
+    {
+        $session = $this->getSessionMock();
+
+        $session
+            ->expects($this->once())
+            ->method('isStarted')
+            ->will($this->returnValue(false));
+        $session
+            ->expects($this->once())
+            ->method('start');
+
+        $this->mink->registerSession('mock_session', $session);
+        $this->assertSame($session, $this->mink->getSession('mock_session'));
+
+        $this->setExpectedException('InvalidArgumentException');
+
+        $this->mink->getSession('not_registered');
+    }
+
+    public function testGetAlreadyStartedSession()
+    {
+        $session = $this->getSessionMock();
+
+        $session
+            ->expects($this->once())
+            ->method('isStarted')
+            ->will($this->returnValue(true));
+        $session
+            ->expects($this->never())
+            ->method('start');
+
+        $this->mink->registerSession('mock_session', $session);
+        $this->assertSame($session, $this->mink->getSession('mock_session'));
+    }
+
+    public function testSetDefaultSessionName()
+    {
+        $this->assertNull($this->mink->getDefaultSessionName());
+
+        $session = $this->getSessionMock();
+        $this->mink->registerSession('session_name', $session);
+        $this->mink->setDefaultSessionName('session_name');
+
+        $this->assertEquals('session_name', $this->mink->getDefaultSessionName());
+
+        $this->setExpectedException('InvalidArgumentException');
+
+        $this->mink->setDefaultSessionName('not_registered');
+    }
+
+    public function testGetDefaultSession()
+    {
+        $session1 = $this->getSessionMock();
+        $session2 = $this->getSessionMock();
+
+        $this->assertNotSame($session1, $session2);
+
+        $this->mink->registerSession('session_1', $session1);
+        $this->mink->registerSession('session_2', $session2);
+        $this->mink->setDefaultSessionName('session_2');
+
+        $this->assertSame($session1, $this->mink->getSession('session_1'));
+        $this->assertSame($session2, $this->mink->getSession('session_2'));
+        $this->assertSame($session2, $this->mink->getSession());
+
+        $this->mink->setDefaultSessionName('session_1');
+
+        $this->assertSame($session1, $this->mink->getSession());
+    }
+
+    public function testGetNoDefaultSession()
+    {
+        $session1 = $this->getSessionMock();
+
+        $this->mink->registerSession('session_1', $session1);
+
+        $this->setExpectedException('InvalidArgumentException');
+
+        $this->mink->getSession();
+    }
+
+    public function testIsSessionStarted()
+    {
+        $session_1 = $this->getSessionMock();
+        $session_2 = $this->getSessionMock();
+
+        $session_1
+            ->expects($this->any())
+            ->method('isStarted')
+            ->will($this->returnValue(false));
+        $session_1
+            ->expects($this->never())
+            ->method('start');
+
+        $session_2
+            ->expects($this->any())
+            ->method('isStarted')
+            ->will($this->returnValue(true));
+        $session_2
+            ->expects($this->never())
+            ->method('start');
+
+        $this->mink->registerSession('not_started', $session_1);
+        $this->assertFalse($this->mink->isSessionStarted('not_started'));
+
+        $this->mink->registerSession('started', $session_2);
+        $this->assertTrue($this->mink->isSessionStarted('started'));
+
+        $this->setExpectedException('InvalidArgumentException');
+
+        $this->mink->getSession('not_registered');
+    }
+
+    public function testAssertSession()
+    {
+        $session = $this->getSessionMock();
+
+        $this->mink->registerSession('my', $session);
+
+        $this->assertInstanceOf('Behat\Mink\WebAssert', $this->mink->assertSession('my'));
+    }
+
+    public function testAssertSessionNotRegistered()
+    {
+        $session = $this->getSessionMock();
+
+        $this->assertInstanceOf('Behat\Mink\WebAssert', $this->mink->assertSession($session));
+    }
+
+    public function testResetSessions()
+    {
+        $session1 = $this->getSessionMock();
+        $session1->expects($this->once())
+            ->method('isStarted')
+            ->will($this->returnValue(false));
+        $session1->expects($this->never())
+            ->method('reset');
+
+        $session2 = $this->getSessionMock();
+        $session2->expects($this->once())
+            ->method('isStarted')
+            ->will($this->returnValue(true));
+        $session2->expects($this->once())
+            ->method('reset');
+
+        $this->mink->registerSession('not started', $session1);
+        $this->mink->registerSession('started', $session2);
+
+        $this->mink->resetSessions();
+    }
+
+    public function testRestartSessions()
+    {
+        $session1 = $this->getSessionMock();
+        $session1->expects($this->once())
+            ->method('isStarted')
+            ->will($this->returnValue(false));
+        $session1->expects($this->never())
+            ->method('restart');
+
+        $session2 = $this->getSessionMock();
+        $session2->expects($this->once())
+            ->method('isStarted')
+            ->will($this->returnValue(true));
+        $session2->expects($this->once())
+            ->method('restart');
+
+        $this->mink->registerSession('not started', $session1);
+        $this->mink->registerSession('started', $session2);
+
+        $this->mink->restartSessions();
+    }
+
+    private function getSessionMock()
+    {
+        return $this->getMockBuilder('Behat\Mink\Session')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Selector/CssSelectorTest.php b/core/vendor/behat/mink/tests/Selector/CssSelectorTest.php
new file mode 100644
index 0000000..ea80d93
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Selector/CssSelectorTest.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Behat\Mink\Tests\Selector;
+
+use Behat\Mink\Selector\CssSelector;
+
+class CssSelectorTest extends \PHPUnit_Framework_TestCase
+{
+    protected function setUp()
+    {
+        if (!class_exists('Symfony\Component\CssSelector\CssSelector')) {
+            $this->markTestSkipped('Symfony2 CssSelector component not installed');
+        }
+    }
+
+    public function testSelector()
+    {
+        $selector = new CssSelector();
+
+        $this->assertEquals('descendant-or-self::h3', $selector->translateToXPath('h3'));
+        $this->assertEquals('descendant-or-self::h3/span', $selector->translateToXPath('h3 > span'));
+
+        if (interface_exists('Symfony\Component\CssSelector\XPath\TranslatorInterface')) {
+            // The rewritten component of Symfony 2.3 checks for attribute existence first for the class.
+            $expectation = "descendant-or-self::h3/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' my_div ')]";
+        } else {
+            $expectation = "descendant-or-self::h3/*[contains(concat(' ', normalize-space(@class), ' '), ' my_div ')]";
+        }
+        $this->assertEquals($expectation, $selector->translateToXPath('h3 > .my_div'));
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testThrowsForArrayLocator()
+    {
+        $selector = new CssSelector();
+
+        $selector->translateToXPath(array('h3'));
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Selector/ExactNamedSelectorTest.php b/core/vendor/behat/mink/tests/Selector/ExactNamedSelectorTest.php
new file mode 100644
index 0000000..df51f0f
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Selector/ExactNamedSelectorTest.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Behat\Mink\Tests\Selector;
+
+use Behat\Mink\Selector\ExactNamedSelector;
+
+class ExactNamedSelectorTest extends NamedSelectorTest
+{
+    protected function getSelector()
+    {
+        return new ExactNamedSelector();
+    }
+
+    protected function allowPartialMatch()
+    {
+        return false;
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Selector/NamedSelectorTest.php b/core/vendor/behat/mink/tests/Selector/NamedSelectorTest.php
new file mode 100644
index 0000000..1ce2faa
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Selector/NamedSelectorTest.php
@@ -0,0 +1,157 @@
+<?php
+
+namespace Behat\Mink\Tests\Selector;
+
+use Behat\Mink\Selector\NamedSelector;
+use Behat\Mink\Selector\SelectorsHandler;
+
+abstract class NamedSelectorTest extends \PHPUnit_Framework_TestCase
+{
+    public function testRegisterXpath()
+    {
+        $selector = $this->getSelector();
+
+        $selector->registerNamedXpath('some', 'my_xpath');
+        $this->assertEquals('my_xpath', $selector->translateToXPath('some'));
+
+        $this->setExpectedException('InvalidArgumentException');
+
+        $selector->translateToXPath('custom');
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testInvalidLocator()
+    {
+        $namedSelector = $this->getSelector();
+
+        $namedSelector->translateToXPath(array('foo', 'bar', 'baz'));
+    }
+
+    /**
+     * @dataProvider getSelectorTests
+     */
+    public function testSelectors($fixtureFile, $selector, $locator, $expectedExactCount, $expectedPartialCount = null)
+    {
+        $expectedCount = $this->allowPartialMatch() && null !== $expectedPartialCount
+            ? $expectedPartialCount
+            : $expectedExactCount;
+
+        $dom = new \DOMDocument('1.0', 'UTF-8');
+        $dom->loadHTMLFile(__DIR__.'/fixtures/'.$fixtureFile);
+
+        // Escape the locator as Mink 1.x expects the caller of the NamedSelector to handle it
+        $selectorsHandler = new SelectorsHandler();
+        $locator = $selectorsHandler->xpathLiteral($locator);
+
+        $namedSelector = $this->getSelector();
+
+        $xpath = $namedSelector->translateToXPath(array($selector, $locator));
+
+        $domXpath = new \DOMXPath($dom);
+        $nodeList = $domXpath->query($xpath);
+
+        $this->assertEquals($expectedCount, $nodeList->length);
+    }
+
+    public function getSelectorTests()
+    {
+        $fieldCount = 8; // fields without `type` attribute
+        $fieldCount += 4; // fields with `type=checkbox` attribute
+        $fieldCount += 4; // fields with `type=radio` attribute
+        $fieldCount += 4; // fields with `type=file` attribute
+
+        // Fixture file,  selector name,  locator,  expected number of exact matched elements, expected number of partial matched elements if different
+        return array(
+            'fieldset' => array('test.html', 'fieldset', 'fieldset-text', 2, 3),
+
+            'field (name/placeholder/label)' => array('test.html', 'field', 'the-field', $fieldCount),
+            'field (input, with-id)' => array('test.html', 'field', 'the-field-input', 1),
+            'field (textarea, with-id)' => array('test.html', 'field', 'the-field-textarea', 1),
+            'field (select, with-id)' => array('test.html', 'field', 'the-field-select', 1),
+            'field (input type=submit, with-id) ignored' => array('test.html', 'field', 'the-field-submit-button', 0),
+            'field (input type=image, with-id) ignored' => array('test.html', 'field', 'the-field-image-button', 0),
+            'field (input type=button, with-id) ignored' => array('test.html', 'field', 'the-field-button-button', 0),
+            'field (input type=reset, with-id) ignored' => array('test.html', 'field', 'the-field-reset-button', 0),
+            'field (input type=hidden, with-id) ignored' => array('test.html', 'field', 'the-field-hidden', 0),
+
+            'link (with-href)' => array('test.html', 'link', 'link-text', 5, 9),
+            'link (without-href) ignored' => array('test.html', 'link', 'bad-link-text', 0),
+            'link* (role=link)' => array('test.html', 'link', 'link-role-text', 4, 7),
+
+            'button (input, name/value/title)' => array('test.html', 'button', 'button-text', 25, 42),
+            'button (type=image, with-alt)' => array('test.html', 'button', 'button-alt-text', 1, 2),
+            'button (input type=submit, with-id)' => array('test.html', 'button', 'input-submit-button', 1),
+            'button (input type=image, with-id)' => array('test.html', 'button', 'input-image-button', 1),
+            'button (input type=button, with-id)' => array('test.html', 'button', 'input-button-button', 1),
+            'button (input type=reset, with-id)' => array('test.html', 'button', 'input-reset-button', 1),
+            'button (button type=submit, with-id)' => array('test.html', 'button', 'button-submit-button', 1),
+            'button (button type=image, with-id)' => array('test.html', 'button', 'button-image-button', 1),
+            'button (button type=button, with-id)' => array('test.html', 'button', 'button-button-button', 1),
+            'button (button type=reset, with-id)' => array('test.html', 'button', 'button-reset-button', 1),
+            'button* (role=button, name/value/title)' => array('test.html', 'button', 'button-role-text', 12, 20),
+            'button* (role=button type=submit, with-id)' => array('test.html', 'button', 'role-button-submit-button', 1),
+            'button* (role=button type=image, with-id)' => array('test.html', 'button', 'role-button-image-button', 1),
+            'button* (role=button type=button, with-id)' => array('test.html', 'button', 'role-button-button-button', 1),
+            'button* (role=button type=reset, with-id)' => array('test.html', 'button', 'role-button-reset-button', 1),
+
+            'link_or_button (with-href)' => array('test.html', 'link_or_button', 'link-text', 5, 9),
+            'link_or_button (without-href) ignored' => array('test.html', 'link_or_button', 'bad-link-text', 0),
+            'link_or_button* (role=link)' => array('test.html', 'link_or_button', 'link-role-text', 4, 7),
+
+            // bug in selector: 17 instead of 25 and 34 instead of 42, because 8 buttons with `name` attribute were not matched
+            'link_or_button (input, name/value/title)' => array('test.html', 'link_or_button', 'button-text', 17, 34),
+            'link_or_button (type=image, with-alt)' => array('test.html', 'link_or_button', 'button-alt-text', 1, 2),
+            'link_or_button (input type=submit, with-id)' => array('test.html', 'link_or_button', 'input-submit-button', 1),
+            'link_or_button (input type=image, with-id)' => array('test.html', 'link_or_button', 'input-image-button', 1),
+            'link_or_button (input type=button, with-id)' => array('test.html', 'link_or_button', 'input-button-button', 1),
+            'link_or_button (input type=reset, with-id)' => array('test.html', 'link_or_button', 'input-reset-button', 1),
+            'link_or_button (button type=submit, with-id)' => array('test.html', 'link_or_button', 'button-submit-button', 1),
+            'link_or_button (button type=image, with-id)' => array('test.html', 'link_or_button', 'button-image-button', 1),
+            'link_or_button (button type=button, with-id)' => array('test.html', 'link_or_button', 'button-button-button', 1),
+            'link_or_button (button type=reset, with-id)' => array('test.html', 'link_or_button', 'button-reset-button', 1),
+
+            // bug in selector: 8 instead of 12 and 16 instead of 20, because 4 buttons with `name` attribute were not matched
+            'link_or_button* (role=button, name/value/title)' => array('test.html', 'link_or_button', 'button-role-text', 8, 16),
+            'link_or_button* (role=button type=submit, with-id)' => array('test.html', 'link_or_button', 'role-button-submit-button', 1),
+            'link_or_button* (role=button type=image, with-id)' => array('test.html', 'link_or_button', 'role-button-image-button', 1),
+            'link_or_button* (role=button type=button, with-id)' => array('test.html', 'link_or_button', 'role-button-button-button', 1),
+            'link_or_button* (role=button type=reset, with-id)' => array('test.html', 'link_or_button', 'role-button-reset-button', 1),
+
+            // 3 matches, because matches every HTML node in path: html > body > div
+            'content' => array('test.html', 'content', 'content-text', 1, 4),
+
+            'select (name/label)' => array('test.html', 'select', 'the-field', 3),
+            'select (with-id)' => array('test.html', 'select', 'the-field-select', 1),
+
+            'checkbox (name/label)' => array('test.html', 'checkbox', 'the-field', 3),
+            'checkbox (with-id)' => array('test.html', 'checkbox', 'the-field-checkbox', 1),
+
+            'radio (name/label)' => array('test.html', 'radio', 'the-field', 3),
+            'radio (with-id)' => array('test.html', 'radio', 'the-field-radio', 1),
+
+            'file (name/label)' => array('test.html', 'file', 'the-field', 3),
+            'file (with-id)' => array('test.html', 'file', 'the-field-file', 1),
+
+            'optgroup' => array('test.html', 'optgroup', 'group-label', 1, 2),
+
+            'option' => array('test.html', 'option', 'option-value', 2, 3),
+
+            'table' => array('test.html', 'table', 'the-table', 2, 3),
+
+            'id' => array('test.html', 'id', 'bad-link-text', 1),
+            'id or name' => array('test.html', 'id_or_name', 'the-table', 2),
+        );
+    }
+
+    /**
+     * @return NamedSelector
+     */
+    abstract protected function getSelector();
+
+    /**
+     * @return boolean
+     */
+    abstract protected function allowPartialMatch();
+}
diff --git a/core/vendor/behat/mink/tests/Selector/PartialNamedSelectorTest.php b/core/vendor/behat/mink/tests/Selector/PartialNamedSelectorTest.php
new file mode 100644
index 0000000..c3e631a
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Selector/PartialNamedSelectorTest.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Behat\Mink\Tests\Selector;
+
+use Behat\Mink\Selector\PartialNamedSelector;
+
+class PartialNamedSelectorTest extends NamedSelectorTest
+{
+    protected function getSelector()
+    {
+        return new PartialNamedSelector();
+    }
+
+    protected function allowPartialMatch()
+    {
+        return true;
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Selector/SelectorsHandlerTest.php b/core/vendor/behat/mink/tests/Selector/SelectorsHandlerTest.php
new file mode 100644
index 0000000..8bcb379
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Selector/SelectorsHandlerTest.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace Behat\Mink\Tests\Selector;
+
+use Behat\Mink\Selector\SelectorsHandler;
+
+class SelectorsHandlerTest extends \PHPUnit_Framework_TestCase
+{
+    public function testRegisterSelector()
+    {
+        $selector = $this->getMockBuilder('Behat\Mink\Selector\SelectorInterface')->getMock();
+        $handler = new SelectorsHandler();
+
+        $this->assertFalse($handler->isSelectorRegistered('custom'));
+
+        $handler->registerSelector('custom', $selector);
+
+        $this->assertTrue($handler->isSelectorRegistered('custom'));
+        $this->assertSame($selector, $handler->getSelector('custom'));
+    }
+
+    public function testRegisterSelectorThroughConstructor()
+    {
+        $selector = $this->getMockBuilder('Behat\Mink\Selector\SelectorInterface')->getMock();
+        $handler = new SelectorsHandler(array('custom' => $selector));
+
+        $this->assertTrue($handler->isSelectorRegistered('custom'));
+        $this->assertSame($selector, $handler->getSelector('custom'));
+    }
+
+    public function testRegisterDefaultSelectors()
+    {
+        $handler = new SelectorsHandler();
+
+        $this->assertTrue($handler->isSelectorRegistered('css'));
+        $this->assertTrue($handler->isSelectorRegistered('named_exact'));
+        $this->assertTrue($handler->isSelectorRegistered('named_partial'));
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testXpathSelectorThrowsExceptionForArrayLocator()
+    {
+        $handler = new SelectorsHandler();
+        $handler->selectorToXpath('xpath', array('some_xpath'));
+    }
+
+    public function testXpathSelectorIsReturnedAsIs()
+    {
+        $handler = new SelectorsHandler();
+        $this->assertEquals('some_xpath', $handler->selectorToXpath('xpath', 'some_xpath'));
+    }
+
+    public function testSelectorToXpath()
+    {
+        $selector = $this->getMockBuilder('Behat\Mink\Selector\SelectorInterface')->getMock();
+        $handler = new SelectorsHandler();
+
+        $handler->registerSelector('custom_selector', $selector);
+
+        $selector
+            ->expects($this->once())
+            ->method('translateToXPath')
+            ->with($locator = 'some[locator]')
+            ->will($this->returnValue($ret = '[]some[]locator'));
+
+        $this->assertEquals($ret, $handler->selectorToXpath('custom_selector', $locator));
+
+        $this->setExpectedException('InvalidArgumentException');
+        $handler->selectorToXpath('undefined', 'asd');
+    }
+
+    public function testXpathLiteral()
+    {
+        $handler = new SelectorsHandler();
+
+        $this->assertEquals("'some simple string'", $handler->xpathLiteral('some simple string'));
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Selector/Xpath/EscaperTest.php b/core/vendor/behat/mink/tests/Selector/Xpath/EscaperTest.php
new file mode 100644
index 0000000..535dac6
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Selector/Xpath/EscaperTest.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Behat\Mink\Tests\Selector\Xpath;
+
+use Behat\Mink\Selector\Xpath\Escaper;
+
+class EscaperTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider getXpathLiterals
+     */
+    public function testXpathLiteral($string, $expected)
+    {
+        $escaper = new Escaper();
+
+        $this->assertEquals($expected, $escaper->escapeLiteral($string));
+    }
+
+    public function getXpathLiterals()
+    {
+        return array(
+            array('some simple string', "'some simple string'"),
+            array('some "d-brackets" string', "'some \"d-brackets\" string'"),
+            array('some \'s-brackets\' string', "\"some 's-brackets' string\""),
+            array(
+                'some \'s-brackets\' and "d-brackets" string',
+                'concat(\'some \',"\'",\'s-brackets\',"\'",\' and "d-brackets" string\')',
+            ),
+        );
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Selector/Xpath/ManipulatorTest.php b/core/vendor/behat/mink/tests/Selector/Xpath/ManipulatorTest.php
new file mode 100644
index 0000000..7c20561
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Selector/Xpath/ManipulatorTest.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace Behat\Mink\Tests\Selector\Xpath;
+
+use Behat\Mink\Selector\Xpath\Manipulator;
+
+class ManipulatorTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider getPrependedXpath
+     */
+    public function testPrepend($prefix, $xpath, $expectedXpath)
+    {
+        $manipulator = new Manipulator();
+
+        $this->assertEquals($expectedXpath, $manipulator->prepend($xpath, $prefix));
+    }
+
+    public function getPrependedXpath()
+    {
+        return array(
+            'simple' => array(
+                'some_xpath',
+                'some_tag1',
+                'some_xpath/some_tag1',
+            ),
+            'with slash' => array(
+                'some_xpath',
+                '/some_tag1',
+                'some_xpath/some_tag1',
+            ),
+            'union' => array(
+                'some_xpath',
+                'some_tag1 | some_tag2',
+                'some_xpath/some_tag1 | some_xpath/some_tag2',
+            ),
+            'wrapped union' => array(
+                'some_xpath',
+                '(some_tag1 | some_tag2)/some_child',
+                '(some_xpath/some_tag1 | some_xpath/some_tag2)/some_child',
+            ),
+            'multiple wrapped union' => array(
+                'some_xpath',
+                '( ( some_tag1 | some_tag2)/some_child | some_tag3)/leaf',
+                '( ( some_xpath/some_tag1 | some_xpath/some_tag2)/some_child | some_xpath/some_tag3)/leaf',
+            ),
+            'parent union' => array(
+                'some_xpath | another_xpath',
+                'some_tag1 | some_tag2',
+                '(some_xpath | another_xpath)/some_tag1 | (some_xpath | another_xpath)/some_tag2',
+            ),
+            'complex condition' => array(
+                'some_xpath',
+                'some_tag1 | some_tag2[@foo = "bar|"] | some_tag3[foo | bar]',
+                'some_xpath/some_tag1 | some_xpath/some_tag2[@foo = "bar|"] | some_xpath/some_tag3[foo | bar]',
+            ),
+            'multiline' => array(
+                'some_xpath',
+                "some_tag1 | some_tag2[@foo =\n 'bar|'']\n | some_tag3[foo | bar]",
+                "some_xpath/some_tag1 | some_xpath/some_tag2[@foo =\n 'bar|''] | some_xpath/some_tag3[foo | bar]",
+            ),
+        );
+    }
+}
diff --git a/core/vendor/behat/mink/tests/Selector/fixtures/test.html b/core/vendor/behat/mink/tests/Selector/fixtures/test.html
new file mode 100644
index 0000000..c64ae10
--- /dev/null
+++ b/core/vendor/behat/mink/tests/Selector/fixtures/test.html
@@ -0,0 +1,310 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title></title>
+</head>
+<body>
+    <div id="test-for-link-selector">
+        <!-- match links with `href` attribute -->
+        <a href="#" id="link-text"></a>
+        <a href="#">link-text</a>
+        <a href="#" title="link-text"></a>
+        <a href="#" rel="link-text"></a>
+        <a href="#">
+            <img src="#" alt="link-text"/>
+        </a>
+        <!-- partial match -->
+        <a href="#">some link-text</a>
+        <a href="#" title="some link-text"></a>
+        <a href="#" rel="some link-text"></a>
+        <a href="#">
+            <img src="#" alt="some link-text"/>
+        </a>
+
+        <!-- don't match links without `href` attribute -->
+        <a id="bad-link-text"></a>
+        <a>bad-link-text</a>
+        <a title="bad-link-text"></a>
+        <a rel="bad-link-text"></a>
+        <a>
+            <img src="#" alt="bad-link-text"/>
+        </a>
+
+        <!-- match links with `role=link` attribute -->
+        <span role="Link" id="link-role-text"></span>
+        <span role="lInk" value="link-role-text"></span>
+        <span role="liNk" title="link-role-text"></span>
+        <span role="linK">link-role-text</span>
+        <!-- partial match -->
+        <span role="link" value="some link-role-text"></span>
+        <span role="link" title="some link-role-text"></span>
+        <span role="link">some link-role-text</span>
+    </div>
+
+    <div id="test-for-fieldset-selector">
+        <!-- match fieldsets -->
+        <fieldset id="fieldset-text"></fieldset>
+
+        <fieldset>
+            <legend>fieldset-text</legend>
+        </fieldset>
+        <!-- partial match -->
+        <fieldset>
+            <legend>fieldset-text sample</legend>
+        </fieldset>
+
+        <!-- don't match fieldsets -->
+        <fieldset>fieldset-text</fieldset>
+        <fieldset></fieldset>
+    </div>
+
+    <div id="test-for-content-selector">
+        content-text
+    </div>
+    <!-- partial match -->
+    <div id="test-for-partial-content-selector">
+        some content-text
+    </div>
+
+    <form>
+        <div id="test-for-field-selector">
+            <!-- match fields by `id` attribute -->
+            <input id="the-field-input"/>
+            <textarea id="the-field-textarea"></textarea>
+            <select id="the-field-select"></select>
+
+            <!-- match fields by `name` attribute -->
+            <input name="the-field"/>
+            <textarea name="the-field"></textarea>
+            <select name="the-field"></select>
+
+            <!-- match fields by `placeholder` attribute -->
+            <input placeholder="the-field"/>
+            <textarea placeholder="the-field"></textarea>
+            <select placeholder="the-field"></select>
+
+            <!-- match fields by associated label -->
+            <label for="label-for-input">the-field</label><input id="label-for-input"/>
+            <label for="label-for-textarea">the-field</label><textarea id="label-for-textarea"></textarea>
+            <label for="label-for-select">the-field</label><select id="label-for-select"></select>
+
+            <!-- match fields, surrounded by matching label -->
+            <label>the-field<input/></label>
+            <label>the-field<textarea></textarea></label>
+            <label>the-field<select></select></label>
+
+            <!-- don't match fields by `id` attribute -->
+            <input type="Submit" id="the-field-submit-button"/>
+            <input type="iMage" id="the-field-image-button"/>
+            <input type="butTon" id="the-field-button-button"/>
+            <input type="resEt" id="the-field-reset-button"/>
+            <input type="hidDen" id="the-field-hidden"/>
+
+            <!-- don't match fields by `name` attribute -->
+            <input type="submit" name="the-field"/>
+            <input type="image" name="the-field"/>
+            <input type="button" name="the-field"/>
+            <input type="reset" name="the-field"/>
+            <input type="hidden" name="the-field"/>
+
+            <!-- don't match fields by `placeholder` attribute -->
+            <input type="submit" placeholder="the-field"/>
+            <input type="image" placeholder="the-field"/>
+            <input type="button" placeholder="the-field"/>
+            <input type="reset" placeholder="the-field"/>
+            <input type="hidden" placeholder="the-field"/>
+
+            <!-- don't match fields by associated label -->
+            <label for="label-for-the-field-submit-button">the-field</label><input type="submit" id="label-for-the-field-submit-button"/>
+            <label for="label-for-the-field-image-button">the-field</label><input type="image" id="label-for-the-field-image-button"/>
+            <label for="label-for-the-field-button-button">the-field</label><input type="button" id="label-for-the-field-button-button"/>
+            <label for="label-for-the-field-reset-button">the-field</label><input type="reset" id="label-for-the-field-reset-button"/>
+            <label for="label-for-the-field-hidden">the-field</label><input type="hidden" id="label-for-the-field-hidden"/>
+
+            <!-- don't match fields, surrounded by matching label -->
+            <label>the-field<input type="submit"/></label>
+            <label>the-field<input type="image"/></label>
+            <label>the-field<input type="button"/></label>
+            <label>the-field<input type="reset"/></label>
+            <label>the-field<input type="hidden"/></label>
+        </div>
+
+        <div id="test-for-button-selector">
+            <!-- match buttons by `id` attribute -->
+            <input type="Submit" id="input-submit-button"/>
+            <input type="iMage" id="input-image-button"/>
+            <input type="butTon" id="input-button-button"/>
+            <input type="resEt" id="input-reset-button"/>
+
+            <button type="submit" id="button-submit-button"></button>
+            <button type="image" id="button-image-button"></button>
+            <button type="button" id="button-button-button"></button>
+            <button type="reset" id="button-reset-button"></button>
+
+            <!-- match buttons by `name` attribute -->
+            <input type="submit" name="button-text"/>
+            <input type="image" name="button-text"/>
+            <input type="button" name="button-text"/>
+            <input type="reset" name="button-text"/>
+            <button type="submit" name="button-text"></button>
+            <button type="image" name="button-text"></button>
+            <button type="button" name="button-text"></button>
+            <button type="reset" name="button-text"></button>
+
+            <!-- match buttons by `value` attribute -->
+            <input type="submit" value="button-text"/>
+            <input type="image" value="button-text"/>
+            <input type="button" value="button-text"/>
+            <input type="reset" value="button-text"/>
+            <button type="submit" value="button-text"></button>
+            <button type="image" value="button-text"></button>
+            <button type="button" value="button-text"></button>
+            <button type="reset" value="button-text"></button>
+            <!-- Partial match -->
+            <input type="submit" value="some button-text"/>
+            <input type="image" value="some button-text"/>
+            <input type="button" value="some button-text"/>
+            <input type="reset" value="some button-text"/>
+            <button type="submit" value="some button-text"></button>
+            <button type="image" value="some button-text"></button>
+            <button type="button" value="some button-text"></button>
+            <button type="reset" value="some button-text"></button>
+
+            <!-- match buttons by `title` attribute -->
+            <input type="submit" title="button-text"/>
+            <input type="image" title="button-text"/>
+            <input type="button" title="button-text"/>
+            <input type="reset" title="button-text"/>
+            <button type="submit" title="button-text"></button>
+            <button type="image" title="button-text"></button>
+            <button type="button" title="button-text"></button>
+            <button type="reset" title="button-text"></button>
+            <!-- partial match -->
+            <input type="submit" title="some button-text"/>
+            <input type="image" title="some button-text"/>
+            <input type="button" title="some button-text"/>
+            <input type="reset" title="some button-text"/>
+            <button type="submit" title="some button-text"></button>
+            <button type="image" title="some button-text"></button>
+            <button type="button" title="some button-text"></button>
+            <button type="reset" title="some button-text"></button>
+
+            <!-- match some buttons by `alt` attribute -->
+            <input type="submit" alt="button-alt-text"/>
+            <input type="imaGe" alt="button-alt-text"/>
+            <input type="button" alt="button-alt-text"/>
+            <input type="reset" alt="button-alt-text"/>
+            <!-- partial match -->
+            <input type="submit" alt="some button-alt-text"/>
+            <input type="image" alt="some button-alt-text"/>
+            <input type="button" alt="some button-alt-text"/>
+            <input type="reset" alt="some button-alt-text"/>
+
+            <!-- match by `button` text -->
+            <button>button-text</button>
+            <!-- partial match -->
+            <button>some button-text</button>
+
+            <!-- match buttons with `role=button` & `id` attribute -->
+            <span role="Button" type="submit" id="role-button-submit-button"></span>
+            <span role="bUtton" type="image" id="role-button-image-button"></span>
+            <span role="buTton" type="button" id="role-button-button-button"></span>
+            <span role="butTon" type="reset" id="role-button-reset-button"></span>
+
+            <!-- match buttons with `role=button` & `name` attribute -->
+            <span role="buttOn" type="submit" name="button-role-text"></span>
+            <span role="buttoN" type="image" name="button-role-text"></span>
+            <span role="button" type="button" name="button-role-text"></span>
+            <span role="button" type="reset" name="button-role-text"></span>
+
+            <!-- match buttons with `role=button` & `value` attribute -->
+            <span role="button" type="submit" value="button-role-text"></span>
+            <span role="button" type="image" value="button-role-text"></span>
+            <span role="button" type="button" value="button-role-text"></span>
+            <span role="button" type="reset" value="button-role-text"></span>
+            <!-- partial match -->
+            <span role="button" type="submit" value="some button-role-text"></span>
+            <span role="button" type="image" value="some button-role-text"></span>
+            <span role="button" type="button" value="some button-role-text"></span>
+            <span role="button" type="reset" value="some button-role-text"></span>
+
+            <!-- match buttons with `role=button` & `title` attribute -->
+            <span role="button" type="submit" title="button-role-text"></span>
+            <span role="button" type="image" title="button-role-text"></span>
+            <span role="button" type="button" title="button-role-text"></span>
+            <span role="button" type="reset" title="button-role-text"></span>
+            <!-- partial match -->
+            <span role="button" type="submit" title="some button-role-text"></span>
+            <span role="button" type="image" title="some button-role-text"></span>
+            <span role="button" type="button" title="some button-role-text"></span>
+            <span role="button" type="reset" title="some button-role-text"></span>
+        </div>
+
+        <div id="test-for-checkbox-selector">
+            <input type="Checkbox" id="the-field-checkbox"/>
+            <input type="checkBox" name="the-field"/>
+            <input type="cheCkbox" placeholder="the-field"/>
+            <label for="label-for-checkbox">the-field</label><input type="checkboX" id="label-for-checkbox"/>
+            <label>the-field<input type="chEckbox"/></label>
+        </div>
+
+        <div id="test-for-radio-selector">
+            <input type="Radio" id="the-field-radio"/>
+            <input type="raDio" name="the-field"/>
+            <input type="radIo" placeholder="the-field"/>
+            <label for="label-for-radio">the-field</label><input type="radiO" id="label-for-radio"/>
+            <label>the-field<input type="radIo"/></label>
+        </div>
+
+        <div id="test-for-file-selector">
+            <input type="File" id="the-field-file"/>
+            <input type="fIle" name="the-field"/>
+            <input type="fiLe" placeholder="the-field"/>
+            <label for="label-for-file">the-field</label><input type="filE" id="label-for-file"/>
+            <label>the-field<input type="fiLe"/></label>
+        </div>
+
+        <div id="test-for-select-related-stuff">
+            <!-- match select stuff -->
+            <select name="the-select-stuff-test">
+                <optgroup label="group-label">
+                    <option value="option-value"></option>
+                </optgroup>
+                <option value="">option-value</option>
+                <!-- partial match -->
+                <optgroup label="some group-label">
+                    <option value="">some option-value</option>
+                </optgroup>
+            </select>
+
+            <!-- don't match select stuff -->
+            <select name="the-select-stuff-test">
+                <optgroup label="">some group-label</optgroup>
+                <option value="some option-value"></option>
+            </select>
+        </div>
+    </form>
+
+    <div id="test-for-table-selector">
+        <!-- match tables -->
+        <table id="the-table"></table>
+        <table>
+            <caption>the-table</caption>
+        </table>
+        <!-- partial match -->
+        <table>
+            <caption>some the-table</caption>
+        </table>
+
+        <!-- don't match tables -->
+        <table>
+            <tr>
+                <th>the-table</th>
+                <td>the-table</td>
+            </tr>
+        </table>
+    </div>
+
+    <input name="the-table"/>
+</body>
+</html>
diff --git a/core/vendor/behat/mink/tests/SessionTest.php b/core/vendor/behat/mink/tests/SessionTest.php
new file mode 100644
index 0000000..b000ba6
--- /dev/null
+++ b/core/vendor/behat/mink/tests/SessionTest.php
@@ -0,0 +1,282 @@
+<?php
+
+namespace Behat\Mink\Tests;
+
+use Behat\Mink\Session;
+
+class SessionTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $driver;
+    private $selectorsHandler;
+
+    /**
+     * Session.
+     *
+     * @var Session
+     */
+    private $session;
+
+    protected function setUp()
+    {
+        $this->driver           = $this->getMockBuilder('Behat\Mink\Driver\DriverInterface')->getMock();
+        $this->selectorsHandler = $this->getMockBuilder('Behat\Mink\Selector\SelectorsHandler')->getMock();
+        $this->session  = new Session($this->driver, $this->selectorsHandler);
+    }
+
+    public function testGetDriver()
+    {
+        $this->assertSame($this->driver, $this->session->getDriver());
+    }
+
+    public function testGetPage()
+    {
+        $this->assertInstanceOf('Behat\Mink\Element\DocumentElement', $this->session->getPage());
+    }
+
+    public function testGetSelectorsHandler()
+    {
+        $this->assertSame($this->selectorsHandler, $this->session->getSelectorsHandler());
+    }
+
+    public function testIsStarted()
+    {
+        $this->driver->expects($this->once())
+            ->method('isStarted')
+            ->will($this->returnValue(true));
+
+        $this->assertTrue($this->session->isStarted());
+    }
+
+    public function testStart()
+    {
+        $this->driver->expects($this->once())
+            ->method('start');
+
+        $this->session->start();
+    }
+
+    public function testStop()
+    {
+        $this->driver->expects($this->once())
+            ->method('stop');
+
+        $this->session->stop();
+    }
+
+    public function testRestart()
+    {
+        $this->driver->expects($this->at(0))
+            ->method('stop');
+        $this->driver->expects($this->at(1))
+            ->method('start');
+
+        $this->session->restart();
+    }
+
+    public function testVisit()
+    {
+        $this->driver
+            ->expects($this->once())
+            ->method('visit')
+            ->with($url = 'some_url');
+
+        $this->session->visit($url);
+    }
+
+    public function testReset()
+    {
+        $this->driver
+            ->expects($this->once())
+            ->method('reset');
+
+        $this->session->reset();
+    }
+
+    public function testSetBasicAuth()
+    {
+        $this->driver->expects($this->once())
+            ->method('setBasicAuth')
+            ->with('user', 'pass');
+
+        $this->session->setBasicAuth('user', 'pass');
+    }
+
+    public function testSetRequestHeader()
+    {
+        $this->driver->expects($this->once())
+            ->method('setRequestHeader')
+            ->with('name', 'value');
+
+        $this->session->setRequestHeader('name', 'value');
+    }
+
+    public function testGetResponseHeaders()
+    {
+        $this->driver
+            ->expects($this->once())
+            ->method('getResponseHeaders')
+            ->will($this->returnValue($ret = array(2, 3, 4)));
+
+        $this->assertEquals($ret, $this->session->getResponseHeaders());
+    }
+
+    public function testSetCookie()
+    {
+        $this->driver->expects($this->once())
+            ->method('setCookie')
+            ->with('name', 'value');
+
+        $this->session->setCookie('name', 'value');
+    }
+
+    public function testGetCookie()
+    {
+        $this->driver->expects($this->once())
+            ->method('getCookie')
+            ->with('name')
+            ->will($this->returnValue('value'));
+
+        $this->assertEquals('value', $this->session->getCookie('name'));
+    }
+
+    public function testGetStatusCode()
+    {
+        $this->driver
+            ->expects($this->once())
+            ->method('getStatusCode')
+            ->will($this->returnValue($ret = 404));
+
+        $this->assertEquals($ret, $this->session->getStatusCode());
+    }
+
+    public function testGetCurrentUrl()
+    {
+        $this->driver
+            ->expects($this->once())
+            ->method('getCurrentUrl')
+            ->will($this->returnValue($ret = 'http://some.url'));
+
+        $this->assertEquals($ret, $this->session->getCurrentUrl());
+    }
+
+    public function testGetScreenshot()
+    {
+        $this->driver->expects($this->once())
+            ->method('getScreenshot')
+            ->will($this->returnValue('screenshot'));
+
+        $this->assertEquals('screenshot', $this->session->getScreenshot());
+    }
+
+    public function testGetWindowNames()
+    {
+        $this->driver->expects($this->once())
+            ->method('getWindowNames')
+            ->will($this->returnValue($names = array('window 1', 'window 2')));
+
+        $this->assertEquals($names, $this->session->getWindowNames());
+    }
+
+    public function testGetWindowName()
+    {
+        $this->driver->expects($this->once())
+            ->method('getWindowName')
+            ->will($this->returnValue('name'));
+
+        $this->assertEquals('name', $this->session->getWindowName());
+    }
+
+    public function testReload()
+    {
+        $this->driver->expects($this->once())
+            ->method('reload');
+
+        $this->session->reload();
+    }
+
+    public function testBack()
+    {
+        $this->driver->expects($this->once())
+            ->method('back');
+
+        $this->session->back();
+    }
+
+    public function testForward()
+    {
+        $this->driver->expects($this->once())
+            ->method('forward');
+
+        $this->session->forward();
+    }
+
+    public function testSwitchToWindow()
+    {
+        $this->driver->expects($this->once())
+            ->method('switchToWindow')
+            ->with('test');
+
+        $this->session->switchToWindow('test');
+    }
+
+    public function testSwitchToIFrame()
+    {
+        $this->driver->expects($this->once())
+            ->method('switchToIFrame')
+            ->with('test');
+
+        $this->session->switchToIFrame('test');
+    }
+
+    public function testExecuteScript()
+    {
+        $this->driver
+            ->expects($this->once())
+            ->method('executeScript')
+            ->with($arg = 'JS');
+
+        $this->session->executeScript($arg);
+    }
+
+    public function testEvaluateScript()
+    {
+        $this->driver
+            ->expects($this->once())
+            ->method('evaluateScript')
+            ->with($arg = 'JS func')
+            ->will($this->returnValue($ret = '23'));
+
+        $this->assertEquals($ret, $this->session->evaluateScript($arg));
+    }
+
+    public function testWait()
+    {
+        $this->driver
+            ->expects($this->once())
+            ->method('wait')
+            ->with(1000, 'function () {}');
+
+        $this->session->wait(1000, 'function () {}');
+    }
+
+    public function testResizeWindow()
+    {
+        $this->driver->expects($this->once())
+            ->method('resizeWindow')
+            ->with(800, 600, 'test');
+
+        $this->session->resizeWindow(800, 600, 'test');
+    }
+
+    public function testMaximizeWindow()
+    {
+        $this->driver->expects($this->once())
+            ->method('maximizeWindow')
+            ->with('test');
+
+        $this->session->maximizeWindow('test');
+    }
+}
diff --git a/core/vendor/behat/mink/tests/WebAssertTest.php b/core/vendor/behat/mink/tests/WebAssertTest.php
new file mode 100644
index 0000000..9ce5d22
--- /dev/null
+++ b/core/vendor/behat/mink/tests/WebAssertTest.php
@@ -0,0 +1,1123 @@
+<?php
+
+namespace Behat\Mink\Tests;
+
+use Behat\Mink\WebAssert;
+
+class WebAssertTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $session;
+    /**
+     * @var WebAssert
+     */
+    private $assert;
+
+    public function setUp()
+    {
+        $this->session = $this->getMockBuilder('Behat\\Mink\\Session')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->assert  = new WebAssert($this->session);
+    }
+
+    public function testAddressEquals()
+    {
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getCurrentUrl')
+            ->will($this->returnValue('http://example.com/script.php/sub/url?param=true#webapp/nav'))
+        ;
+
+        $this->assertCorrectAssertion('addressEquals', array('/sub/url#webapp/nav'));
+        $this->assertWrongAssertion(
+            'addressEquals',
+            array('sub_url'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'Current page is "/sub/url#webapp/nav", but "sub_url" expected.'
+        );
+    }
+
+    public function testAddressNotEquals()
+    {
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getCurrentUrl')
+            ->will($this->returnValue('http://example.com/script.php/sub/url'))
+        ;
+
+        $this->assertCorrectAssertion('addressNotEquals', array('sub_url'));
+        $this->assertWrongAssertion(
+            'addressNotEquals',
+            array('/sub/url'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'Current page is "/sub/url", but should not be.'
+        );
+    }
+
+    public function testAddressMatches()
+    {
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getCurrentUrl')
+            ->will($this->returnValue('http://example.com/script.php/sub/url'))
+        ;
+
+        $this->assertCorrectAssertion('addressMatches', array('/su.*rl/'));
+        $this->assertWrongAssertion(
+            'addressMatches',
+            array('/suburl/'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'Current page "/sub/url" does not match the regex "/suburl/".'
+        );
+    }
+
+    /**
+     * @covers Behat\Mink\WebAssert::cookieEquals
+     */
+    public function testCookieEquals()
+    {
+        $this->session->
+            expects($this->any())->
+            method('getCookie')->
+            will($this->returnValueMap(
+                array(
+                    array('foo', 'bar'),
+                    array('bar', 'baz'),
+                )
+            ));
+
+        $this->assertCorrectAssertion('cookieEquals', array('foo', 'bar'));
+        $this->assertWrongAssertion(
+            'cookieEquals',
+            array('bar', 'foo'),
+            'Behat\Mink\Exception\ExpectationException',
+            'Cookie "bar" value is "baz", but should be "foo".'
+        );
+    }
+
+    /**
+     * @covers Behat\Mink\WebAssert::cookieExists
+     */
+    public function testCookieExists()
+    {
+        $this->session->
+            expects($this->any())->
+            method('getCookie')->
+            will($this->returnValueMap(
+                array(
+                    array('foo', '1'),
+                    array('bar', null),
+                )
+            ));
+
+        $this->assertCorrectAssertion('cookieExists', array('foo'));
+        $this->assertWrongAssertion(
+            'cookieExists',
+            array('bar'),
+            'Behat\Mink\Exception\ExpectationException',
+            'Cookie "bar" is not set, but should be.'
+        );
+    }
+
+    public function testStatusCodeEquals()
+    {
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getStatusCode')
+            ->will($this->returnValue(200))
+        ;
+
+        $this->assertCorrectAssertion('statusCodeEquals', array(200));
+        $this->assertWrongAssertion(
+            'statusCodeEquals',
+            array(404),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'Current response status code is 200, but 404 expected.'
+        );
+    }
+
+    public function testStatusCodeNotEquals()
+    {
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getStatusCode')
+            ->will($this->returnValue(404))
+        ;
+
+        $this->assertCorrectAssertion('statusCodeNotEquals', array(200));
+        $this->assertWrongAssertion(
+            'statusCodeNotEquals',
+            array(404),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'Current response status code is 404, but should not be.'
+        );
+    }
+
+    public function testPageTextContains()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('getText')
+            ->will($this->returnValue("Some  page\n\ttext"))
+        ;
+
+        $this->assertCorrectAssertion('pageTextContains', array('PAGE text'));
+        $this->assertWrongAssertion(
+            'pageTextContains',
+            array('html text'),
+            'Behat\\Mink\\Exception\\ResponseTextException',
+            'The text "html text" was not found anywhere in the text of the current page.'
+        );
+    }
+
+    public function testPageTextNotContains()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('getText')
+            ->will($this->returnValue("Some  html\n\ttext"))
+        ;
+
+        $this->assertCorrectAssertion('pageTextNotContains', array('PAGE text'));
+        $this->assertWrongAssertion(
+            'pageTextNotContains',
+            array('HTML text'),
+            'Behat\\Mink\\Exception\\ResponseTextException',
+            'The text "HTML text" appears in the text of this page, but it should not.'
+        );
+    }
+
+    public function testPageTextMatches()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('getText')
+            ->will($this->returnValue('Some page text'))
+        ;
+
+        $this->assertCorrectAssertion('pageTextMatches', array('/PA.E/i'));
+        $this->assertWrongAssertion(
+            'pageTextMatches',
+            array('/html/'),
+            'Behat\\Mink\\Exception\\ResponseTextException',
+            'The pattern /html/ was not found anywhere in the text of the current page.'
+        );
+    }
+
+    public function testPageTextNotMatches()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('getText')
+            ->will($this->returnValue('Some html text'))
+        ;
+
+        $this->assertCorrectAssertion('pageTextNotMatches', array('/PA.E/i'));
+        $this->assertWrongAssertion(
+            'pageTextNotMatches',
+            array('/HTML/i'),
+            'Behat\\Mink\\Exception\\ResponseTextException',
+            'The pattern /HTML/i was found in the text of the current page, but it should not.'
+        );
+    }
+
+    public function testResponseContains()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('getContent')
+            ->will($this->returnValue('Some page text'))
+        ;
+
+        $this->assertCorrectAssertion('responseContains', array('PAGE text'));
+        $this->assertWrongAssertion(
+            'responseContains',
+            array('html text'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The string "html text" was not found anywhere in the HTML response of the current page.'
+        );
+    }
+
+    public function testResponseNotContains()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('getContent')
+            ->will($this->returnValue('Some html text'))
+        ;
+
+        $this->assertCorrectAssertion('responseNotContains', array('PAGE text'));
+        $this->assertWrongAssertion(
+            'responseNotContains',
+            array('HTML text'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The string "HTML text" appears in the HTML response of this page, but it should not.'
+        );
+    }
+
+    public function testResponseMatches()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('getContent')
+            ->will($this->returnValue('Some page text'))
+        ;
+
+        $this->assertCorrectAssertion('responseMatches', array('/PA.E/i'));
+        $this->assertWrongAssertion(
+            'responseMatches',
+            array('/html/'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The pattern /html/ was not found anywhere in the HTML response of the page.'
+        );
+    }
+
+    public function testResponseNotMatches()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('getContent')
+            ->will($this->returnValue('Some html text'))
+        ;
+
+        $this->assertCorrectAssertion('responseNotMatches', array('/PA.E/i'));
+        $this->assertWrongAssertion(
+            'responseNotMatches',
+            array('/HTML/i'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The pattern /HTML/i was found in the HTML response of the page, but it should not.'
+        );
+    }
+
+    public function testElementsCount()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('findAll')
+            ->with('css', 'h2 > span')
+            ->will($this->returnValue(array(1, 2)))
+        ;
+
+        $this->assertCorrectAssertion('elementsCount', array('css', 'h2 > span', 2));
+        $this->assertWrongAssertion(
+            'elementsCount',
+            array('css', 'h2 > span', 3),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            '2 elements matching css "h2 > span" found on the page, but should be 3.'
+        );
+    }
+
+    public function testElementExists()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(4))
+            ->method('find')
+            ->with('css', 'h2 > span')
+            ->will($this->onConsecutiveCalls(1, null, 1, null))
+        ;
+
+        $this->assertCorrectAssertion('elementExists', array('css', 'h2 > span'));
+        $this->assertWrongAssertion(
+            'elementExists',
+            array('css', 'h2 > span'),
+            'Behat\\Mink\\Exception\\ElementNotFoundException',
+            'Element matching css "h2 > span" not found.'
+        );
+
+        $this->assertCorrectAssertion('elementExists', array('css', 'h2 > span', $page));
+        $this->assertWrongAssertion(
+            'elementExists',
+            array('css', 'h2 > span', $page),
+            'Behat\\Mink\\Exception\\ElementNotFoundException',
+            'Element matching css "h2 > span" not found.'
+        );
+    }
+
+    public function testElementExistsWithArrayLocator()
+    {
+        $container = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session->expects($this->never())
+            ->method('getPage')
+        ;
+
+        $container
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('named', array('element', 'Test'))
+            ->will($this->onConsecutiveCalls(1, null))
+        ;
+
+        $this->assertCorrectAssertion('elementExists', array('named', array('element', 'Test'), $container));
+        $this->assertWrongAssertion(
+            'elementExists',
+            array('named', array('element', 'Test'), $container),
+            'Behat\\Mink\\Exception\\ElementNotFoundException',
+            'Element with named "element Test" not found.'
+        );
+    }
+
+    public function testElementNotExists()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(4))
+            ->method('find')
+            ->with('css', 'h2 > span')
+            ->will($this->onConsecutiveCalls(null, 1, null, 1))
+        ;
+
+        $this->assertCorrectAssertion('elementNotExists', array('css', 'h2 > span'));
+        $this->assertWrongAssertion(
+            'elementNotExists',
+            array('css', 'h2 > span'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'An element matching css "h2 > span" appears on this page, but it should not.'
+        );
+
+        $this->assertCorrectAssertion('elementNotExists', array('css', 'h2 > span', $page));
+        $this->assertWrongAssertion(
+            'elementNotExists',
+            array('css', 'h2 > span', $page),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'An element matching css "h2 > span" appears on this page, but it should not.'
+        );
+    }
+
+    /**
+     * @dataProvider getArrayLocatorFormats
+     */
+    public function testElementNotExistsArrayLocator($selector, $locator, $expectedMessage)
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->once())
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->once())
+            ->method('find')
+            ->with($selector, $locator)
+            ->will($this->returnValue(1))
+        ;
+
+        $this->assertWrongAssertion(
+            'elementNotExists',
+            array($selector, $locator),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            $expectedMessage
+        );
+    }
+
+    public function getArrayLocatorFormats()
+    {
+        return array(
+            'named' => array(
+                'named',
+                array('button', 'Test'),
+                'An button matching locator "Test" appears on this page, but it should not.',
+            ),
+            'custom' => array(
+                'custom',
+                array('test', 'foo'),
+                'An element matching custom "test foo" appears on this page, but it should not.',
+            ),
+        );
+    }
+
+    public function testElementTextContains()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('css', 'h2 > span')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->exactly(2))
+            ->method('getText')
+            ->will($this->returnValue('element text'))
+        ;
+
+        $this->assertCorrectAssertion('elementTextContains', array('css', 'h2 > span', 'text'));
+        $this->assertWrongAssertion(
+            'elementTextContains',
+            array('css', 'h2 > span', 'html'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The text "html" was not found in the text of the element matching css "h2 > span".'
+        );
+    }
+
+    public function testElementTextNotContains()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('css', 'h2 > span')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->exactly(2))
+            ->method('getText')
+            ->will($this->returnValue('element text'))
+        ;
+
+        $this->assertCorrectAssertion('elementTextNotContains', array('css', 'h2 > span', 'html'));
+        $this->assertWrongAssertion(
+            'elementTextNotContains',
+            array('css', 'h2 > span', 'text'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The text "text" appears in the text of the element matching css "h2 > span", but it should not.'
+        );
+    }
+
+    public function testElementContains()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('css', 'h2 > span')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->exactly(2))
+            ->method('getHtml')
+            ->will($this->returnValue('element html'))
+        ;
+
+        $this->assertCorrectAssertion('elementContains', array('css', 'h2 > span', 'html'));
+        $this->assertWrongAssertion(
+            'elementContains',
+            array('css', 'h2 > span', 'text'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The string "text" was not found in the HTML of the element matching css "h2 > span".'
+        );
+    }
+
+    public function testElementNotContains()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('css', 'h2 > span')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->exactly(2))
+            ->method('getHtml')
+            ->will($this->returnValue('element html'))
+        ;
+
+        $this->assertCorrectAssertion('elementNotContains', array('css', 'h2 > span', 'text'));
+        $this->assertWrongAssertion(
+            'elementNotContains',
+            array('css', 'h2 > span', 'html'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The string "html" appears in the HTML of the element matching css "h2 > span", but it should not.'
+        );
+    }
+
+    public function testElementAttributeContains()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('css', 'h2 > span')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->exactly(2))
+            ->method('hasAttribute')
+            ->will($this->returnValue(true))
+        ;
+
+        $element
+            ->expects($this->exactly(2))
+            ->method('getAttribute')
+            ->with('name')
+            ->will($this->returnValue('foo'))
+        ;
+
+        $this->assertCorrectAssertion('elementAttributeContains', array('css', 'h2 > span', 'name', 'foo'));
+        $this->assertWrongAssertion(
+            'elementAttributeContains',
+            array('css', 'h2 > span', 'name', 'bar'),
+            'Behat\\Mink\\Exception\\ElementHtmlException',
+            'The text "bar" was not found in the attribute "name" of the element matching css "h2 > span".'
+        );
+    }
+
+    public function testElementAttributeExists()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('css', 'h2 > span')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->at(0))
+            ->method('hasAttribute')
+            ->with('name')
+            ->will($this->returnValue(true))
+        ;
+
+        $element
+            ->expects($this->at(1))
+            ->method('hasAttribute')
+            ->with('name')
+            ->will($this->returnValue(false))
+        ;
+
+        $this->assertCorrectAssertion('elementAttributeExists', array('css', 'h2 > span', 'name'));
+        $this->assertWrongAssertion(
+            'elementAttributeExists',
+            array('css', 'h2 > span', 'name'),
+            'Behat\\Mink\\Exception\\ElementHtmlException',
+            'The attribute "name" was not found in the element matching css "h2 > span".'
+        );
+    }
+
+    public function testElementAttributeNotContains()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('find')
+            ->with('css', 'h2 > span')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->exactly(2))
+            ->method('hasAttribute')
+            ->will($this->returnValue(true))
+        ;
+
+        $element
+            ->expects($this->exactly(2))
+            ->method('getAttribute')
+            ->with('name')
+            ->will($this->returnValue('foo'))
+        ;
+
+        $this->assertCorrectAssertion('elementAttributeNotContains', array('css', 'h2 > span', 'name', 'bar'));
+        $this->assertWrongAssertion(
+            'elementAttributeNotContains',
+            array('css', 'h2 > span', 'name', 'foo'),
+            'Behat\\Mink\\Exception\\ElementHtmlException',
+            'The text "foo" was found in the attribute "name" of the element matching css "h2 > span".'
+        );
+    }
+
+    public function testFieldExists()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('findField')
+            ->with('username')
+            ->will($this->onConsecutiveCalls($element, null))
+        ;
+
+        $this->assertCorrectAssertion('fieldExists', array('username'));
+        $this->assertWrongAssertion(
+            'fieldExists',
+            array('username'),
+            'Behat\\Mink\\Exception\\ElementNotFoundException',
+            'Form field with id|name|label|value "username" not found.'
+        );
+    }
+
+    public function testFieldNotExists()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('findField')
+            ->with('username')
+            ->will($this->onConsecutiveCalls(null, $element))
+        ;
+
+        $this->assertCorrectAssertion('fieldNotExists', array('username'));
+        $this->assertWrongAssertion(
+            'fieldNotExists',
+            array('username'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'A field "username" appears on this page, but it should not.'
+        );
+    }
+
+    public function testFieldValueEquals()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(4))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(4))
+            ->method('findField')
+            ->with('username')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->exactly(4))
+            ->method('getValue')
+            ->will($this->returnValue(234))
+        ;
+
+        $this->assertCorrectAssertion('fieldValueEquals', array('username', 234));
+        $this->assertWrongAssertion(
+            'fieldValueEquals',
+            array('username', 235),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The field "username" value is "234", but "235" expected.'
+        );
+        $this->assertWrongAssertion(
+            'fieldValueEquals',
+            array('username', 23),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The field "username" value is "234", but "23" expected.'
+        );
+        $this->assertWrongAssertion(
+            'fieldValueEquals',
+            array('username', ''),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The field "username" value is "234", but "" expected.'
+        );
+    }
+
+    public function testFieldValueNotEquals()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(4))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(4))
+            ->method('findField')
+            ->with('username')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->exactly(4))
+            ->method('getValue')
+            ->will($this->returnValue(235))
+        ;
+
+        $this->assertCorrectAssertion('fieldValueNotEquals', array('username', 234));
+        $this->assertWrongAssertion(
+            'fieldValueNotEquals',
+            array('username', 235),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'The field "username" value is "235", but it should not be.'
+        );
+        $this->assertCorrectAssertion('fieldValueNotEquals', array('username', 23));
+        $this->assertCorrectAssertion('fieldValueNotEquals', array('username', ''));
+    }
+
+    public function testCheckboxChecked()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('findField')
+            ->with('remember_me')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->exactly(2))
+            ->method('isChecked')
+            ->will($this->onConsecutiveCalls(true, false))
+        ;
+
+        $this->assertCorrectAssertion('checkboxChecked', array('remember_me'));
+        $this->assertWrongAssertion(
+            'checkboxChecked',
+            array('remember_me'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'Checkbox "remember_me" is not checked, but it should be.'
+        );
+    }
+
+    public function testCheckboxNotChecked()
+    {
+        $page = $this->getMockBuilder('Behat\\Mink\\Element\\DocumentElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $element = $this->getMockBuilder('Behat\\Mink\\Element\\NodeElement')
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $this->session
+            ->expects($this->exactly(2))
+            ->method('getPage')
+            ->will($this->returnValue($page))
+        ;
+
+        $page
+            ->expects($this->exactly(2))
+            ->method('findField')
+            ->with('remember_me')
+            ->will($this->returnValue($element))
+        ;
+
+        $element
+            ->expects($this->exactly(2))
+            ->method('isChecked')
+            ->will($this->onConsecutiveCalls(false, true))
+        ;
+
+        $this->assertCorrectAssertion('checkboxNotChecked', array('remember_me'));
+        $this->assertWrongAssertion(
+            'checkboxNotChecked',
+            array('remember_me'),
+            'Behat\\Mink\\Exception\\ExpectationException',
+            'Checkbox "remember_me" is checked, but it should not be.'
+        );
+    }
+
+    protected function assertCorrectAssertion($assertion, $arguments)
+    {
+        try {
+            call_user_func_array(array($this->assert, $assertion), $arguments);
+        } catch (\Exception $e) {
+            $this->fail('Correct assertion should not throw an exception: '.$e->getMessage());
+        }
+    }
+
+    protected function assertWrongAssertion($assertion, $arguments, $exceptionClass, $exceptionMessage)
+    {
+        try {
+            call_user_func_array(array($this->assert, $assertion), $arguments);
+            $this->fail('Wrong assertion should throw an exception');
+        } catch (\Exception $e) {
+            $this->assertInstanceOf($exceptionClass, $e);
+            $this->assertSame($exceptionMessage, $e->getMessage());
+        }
+    }
+}
diff --git a/core/vendor/composer/autoload_namespaces.php b/core/vendor/composer/autoload_namespaces.php
index ffe0cd5..f27e31a 100644
--- a/core/vendor/composer/autoload_namespaces.php
+++ b/core/vendor/composer/autoload_namespaces.php
@@ -19,13 +19,21 @@
     'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
     'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
     'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
+    'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
     'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
+    'Symfony\\Component\\DomCrawler\\' => array($vendorDir . '/symfony/dom-crawler'),
     'Symfony\\Component\\DependencyInjection\\' => array($vendorDir . '/symfony/dependency-injection'),
     'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
     'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'),
     'Symfony\\Component\\ClassLoader\\' => array($vendorDir . '/symfony/class-loader'),
+    'Symfony\\Component\\BrowserKit\\' => array($vendorDir . '/symfony/browser-kit'),
     'Stack' => array($vendorDir . '/stack/builder/src'),
     'Psr\\Log\\' => array($vendorDir . '/psr/log'),
+    'Guzzle\\Stream' => array($vendorDir . '/guzzle/stream'),
+    'Guzzle\\Parser' => array($vendorDir . '/guzzle/parser'),
+    'Guzzle\\Http' => array($vendorDir . '/guzzle/http'),
+    'Guzzle\\Common' => array($vendorDir . '/guzzle/common'),
+    'Goutte' => array($vendorDir . '/fabpot/goutte'),
     'Gliph' => array($vendorDir . '/sdboyer/gliph/src'),
     'Egulias\\' => array($vendorDir . '/egulias/email-validator/src'),
     'EasyRdf_' => array($vendorDir . '/easyrdf/easyrdf/lib'),
@@ -36,4 +44,6 @@
     'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib'),
     'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib'),
     'Doctrine\\Common\\' => array($vendorDir . '/doctrine/common/lib'),
+    'Behat\\Mink\\Driver' => array($vendorDir . '/behat/mink-browserkit-driver/src', $vendorDir . '/behat/mink-goutte-driver/src'),
+    'Behat\\Mink' => array($vendorDir . '/behat/mink/src'),
 );
diff --git a/core/vendor/composer/installed.json b/core/vendor/composer/installed.json
index 2e99ee1..0a45918 100644
--- a/core/vendor/composer/installed.json
+++ b/core/vendor/composer/installed.json
@@ -2735,5 +2735,598 @@
         ],
         "description": "Symfony Yaml Component",
         "homepage": "http://symfony.com"
+    },
+    {
+        "name": "symfony/finder",
+        "version": "v2.6.4",
+        "version_normalized": "2.6.4.0",
+        "target-dir": "Symfony/Component/Finder",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony/Finder.git",
+            "reference": "16513333bca64186c01609961a2bb1b95b5e1355"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/symfony/Finder/zipball/16513333bca64186c01609961a2bb1b95b5e1355",
+            "reference": "16513333bca64186c01609961a2bb1b95b5e1355",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.3"
+        },
+        "time": "2015-01-03 08:01:59",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.6-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Symfony\\Component\\Finder\\": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Symfony Community",
+                "homepage": "http://symfony.com/contributors"
+            },
+            {
+                "name": "Fabien Potencier",
+                "email": "fabien@symfony.com"
+            }
+        ],
+        "description": "Symfony Finder Component",
+        "homepage": "http://symfony.com"
+    },
+    {
+        "name": "symfony/dom-crawler",
+        "version": "v2.6.4",
+        "version_normalized": "2.6.4.0",
+        "target-dir": "Symfony/Component/DomCrawler",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony/DomCrawler.git",
+            "reference": "26a9eb302decd828990e1015afaa11b78b016073"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/26a9eb302decd828990e1015afaa11b78b016073",
+            "reference": "26a9eb302decd828990e1015afaa11b78b016073",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.3"
+        },
+        "require-dev": {
+            "symfony/css-selector": "~2.3"
+        },
+        "suggest": {
+            "symfony/css-selector": ""
+        },
+        "time": "2015-01-03 08:01:59",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.6-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Symfony\\Component\\DomCrawler\\": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Symfony Community",
+                "homepage": "http://symfony.com/contributors"
+            },
+            {
+                "name": "Fabien Potencier",
+                "email": "fabien@symfony.com"
+            }
+        ],
+        "description": "Symfony DomCrawler Component",
+        "homepage": "http://symfony.com"
+    },
+    {
+        "name": "symfony/browser-kit",
+        "version": "v2.6.4",
+        "version_normalized": "2.6.4.0",
+        "target-dir": "Symfony/Component/BrowserKit",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony/BrowserKit.git",
+            "reference": "2ecec44ed5047020c65dd6e4a4b2f3cf13ae3c04"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/2ecec44ed5047020c65dd6e4a4b2f3cf13ae3c04",
+            "reference": "2ecec44ed5047020c65dd6e4a4b2f3cf13ae3c04",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.3",
+            "symfony/dom-crawler": "~2.0,>=2.0.5"
+        },
+        "require-dev": {
+            "symfony/css-selector": "~2.0,>=2.0.5",
+            "symfony/process": "~2.0,>=2.0.5"
+        },
+        "suggest": {
+            "symfony/process": ""
+        },
+        "time": "2015-01-03 08:01:59",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.6-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Symfony\\Component\\BrowserKit\\": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Symfony Community",
+                "homepage": "http://symfony.com/contributors"
+            },
+            {
+                "name": "Fabien Potencier",
+                "email": "fabien@symfony.com"
+            }
+        ],
+        "description": "Symfony BrowserKit Component",
+        "homepage": "http://symfony.com"
+    },
+    {
+        "name": "guzzle/common",
+        "version": "v3.9.2",
+        "version_normalized": "3.9.2.0",
+        "target-dir": "Guzzle/Common",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/guzzle/common.git",
+            "reference": "2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/guzzle/common/zipball/2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc",
+            "reference": "2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.2",
+            "symfony/event-dispatcher": ">=2.1"
+        },
+        "time": "2014-08-11 04:32:36",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "3.7-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Guzzle\\Common": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "description": "Common libraries used by Guzzle",
+        "homepage": "http://guzzlephp.org/",
+        "keywords": [
+            "collection",
+            "common",
+            "event",
+            "exception"
+        ]
+    },
+    {
+        "name": "guzzle/stream",
+        "version": "v3.9.2",
+        "version_normalized": "3.9.2.0",
+        "target-dir": "Guzzle/Stream",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/guzzle/stream.git",
+            "reference": "60c7fed02e98d2c518dae8f97874c8f4622100f0"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/guzzle/stream/zipball/60c7fed02e98d2c518dae8f97874c8f4622100f0",
+            "reference": "60c7fed02e98d2c518dae8f97874c8f4622100f0",
+            "shasum": ""
+        },
+        "require": {
+            "guzzle/common": "self.version",
+            "php": ">=5.3.2"
+        },
+        "suggest": {
+            "guzzle/http": "To convert Guzzle request objects to PHP streams"
+        },
+        "time": "2014-05-01 21:36:02",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "3.7-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Guzzle\\Stream": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Michael Dowling",
+                "email": "mtdowling@gmail.com",
+                "homepage": "https://github.com/mtdowling"
+            }
+        ],
+        "description": "Guzzle stream wrapper component",
+        "homepage": "http://guzzlephp.org/",
+        "keywords": [
+            "Guzzle",
+            "component",
+            "stream"
+        ]
+    },
+    {
+        "name": "guzzle/parser",
+        "version": "v3.9.2",
+        "version_normalized": "3.9.2.0",
+        "target-dir": "Guzzle/Parser",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/guzzle/parser.git",
+            "reference": "6874d171318a8e93eb6d224cf85e4678490b625c"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/guzzle/parser/zipball/6874d171318a8e93eb6d224cf85e4678490b625c",
+            "reference": "6874d171318a8e93eb6d224cf85e4678490b625c",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.2"
+        },
+        "time": "2014-02-05 18:29:46",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "3.7-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Guzzle\\Parser": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "description": "Interchangeable parsers used by Guzzle",
+        "homepage": "http://guzzlephp.org/",
+        "keywords": [
+            "URI Template",
+            "cookie",
+            "http",
+            "message",
+            "url"
+        ]
+    },
+    {
+        "name": "guzzle/http",
+        "version": "v3.9.2",
+        "version_normalized": "3.9.2.0",
+        "target-dir": "Guzzle/Http",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/guzzle/http.git",
+            "reference": "1e8dd1e2ba9dc42332396f39fbfab950b2301dc5"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/guzzle/http/zipball/1e8dd1e2ba9dc42332396f39fbfab950b2301dc5",
+            "reference": "1e8dd1e2ba9dc42332396f39fbfab950b2301dc5",
+            "shasum": ""
+        },
+        "require": {
+            "guzzle/common": "self.version",
+            "guzzle/parser": "self.version",
+            "guzzle/stream": "self.version",
+            "php": ">=5.3.2"
+        },
+        "suggest": {
+            "ext-curl": "*"
+        },
+        "time": "2014-08-11 04:32:36",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "3.7-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Guzzle\\Http": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Michael Dowling",
+                "email": "mtdowling@gmail.com",
+                "homepage": "https://github.com/mtdowling"
+            }
+        ],
+        "description": "HTTP libraries used by Guzzle",
+        "homepage": "http://guzzlephp.org/",
+        "keywords": [
+            "Guzzle",
+            "client",
+            "curl",
+            "http",
+            "http client"
+        ]
+    },
+    {
+        "name": "fabpot/goutte",
+        "version": "v1.0.7",
+        "version_normalized": "1.0.7.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/FriendsOfPHP/Goutte.git",
+            "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/794b196e76bdd37b5155cdecbad311f0a3b07625",
+            "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625",
+            "shasum": ""
+        },
+        "require": {
+            "ext-curl": "*",
+            "guzzle/http": "~3.1",
+            "php": ">=5.3.0",
+            "symfony/browser-kit": "~2.1",
+            "symfony/css-selector": "~2.1",
+            "symfony/dom-crawler": "~2.1",
+            "symfony/finder": "~2.1",
+            "symfony/process": "~2.1"
+        },
+        "require-dev": {
+            "guzzle/plugin-history": "~3.1",
+            "guzzle/plugin-mock": "~3.1"
+        },
+        "time": "2014-10-09 15:52:51",
+        "type": "application",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Goutte": "."
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Fabien Potencier",
+                "email": "fabien@symfony.com"
+            }
+        ],
+        "description": "A simple PHP Web Scraper",
+        "homepage": "https://github.com/fabpot/Goutte",
+        "keywords": [
+            "scraper"
+        ]
+    },
+    {
+        "name": "behat/mink",
+        "version": "v1.6.0",
+        "version_normalized": "1.6.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/minkphp/Mink.git",
+            "reference": "090900a0049c441f1e072bbd837db4079b2250c5"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/minkphp/Mink/zipball/090900a0049c441f1e072bbd837db4079b2250c5",
+            "reference": "090900a0049c441f1e072bbd837db4079b2250c5",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.1",
+            "symfony/css-selector": "~2.0"
+        },
+        "suggest": {
+            "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)",
+            "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation",
+            "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)",
+            "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)"
+        },
+        "time": "2014-09-26 09:25:05",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.6.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Behat\\Mink": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Konstantin Kudryashov",
+                "email": "ever.zet@gmail.com",
+                "homepage": "http://everzet.com"
+            }
+        ],
+        "description": "Web acceptance testing framework for PHP 5.3",
+        "homepage": "http://mink.behat.org/",
+        "keywords": [
+            "browser",
+            "testing",
+            "web"
+        ]
+    },
+    {
+        "name": "behat/mink-browserkit-driver",
+        "version": "v1.2.0",
+        "version_normalized": "1.2.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/minkphp/MinkBrowserKitDriver.git",
+            "reference": "aed8f4a596b79014a75254c3e337511c33e38cbd"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/aed8f4a596b79014a75254c3e337511c33e38cbd",
+            "reference": "aed8f4a596b79014a75254c3e337511c33e38cbd",
+            "shasum": ""
+        },
+        "require": {
+            "behat/mink": "~1.6@dev",
+            "php": ">=5.3.1",
+            "symfony/browser-kit": "~2.0",
+            "symfony/dom-crawler": "~2.0"
+        },
+        "require-dev": {
+            "silex/silex": "~1.2"
+        },
+        "time": "2014-09-26 11:35:19",
+        "type": "mink-driver",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.2.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Behat\\Mink\\Driver": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Konstantin Kudryashov",
+                "email": "ever.zet@gmail.com",
+                "homepage": "http://everzet.com"
+            }
+        ],
+        "description": "Symfony2 BrowserKit driver for Mink framework",
+        "homepage": "http://mink.behat.org/",
+        "keywords": [
+            "Mink",
+            "Symfony2",
+            "browser",
+            "testing"
+        ]
+    },
+    {
+        "name": "behat/mink-goutte-driver",
+        "version": "v1.1.0",
+        "version_normalized": "1.1.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/minkphp/MinkGoutteDriver.git",
+            "reference": "2bf327b4166694ecaa8ae7f956cb6ae252ecf03e"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/2bf327b4166694ecaa8ae7f956cb6ae252ecf03e",
+            "reference": "2bf327b4166694ecaa8ae7f956cb6ae252ecf03e",
+            "shasum": ""
+        },
+        "require": {
+            "behat/mink": "~1.6@dev",
+            "behat/mink-browserkit-driver": "~1.2@dev",
+            "fabpot/goutte": "~1.0.4|~2.0",
+            "php": ">=5.3.1"
+        },
+        "time": "2014-10-09 09:21:12",
+        "type": "mink-driver",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.1.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Behat\\Mink\\Driver": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Konstantin Kudryashov",
+                "email": "ever.zet@gmail.com",
+                "homepage": "http://everzet.com"
+            }
+        ],
+        "description": "Goutte driver for Mink framework",
+        "homepage": "http://mink.behat.org/",
+        "keywords": [
+            "browser",
+            "goutte",
+            "headless",
+            "testing"
+        ]
     }
 ]
diff --git a/core/vendor/fabpot/goutte/.gitignore b/core/vendor/fabpot/goutte/.gitignore
new file mode 100644
index 0000000..81b9258
--- /dev/null
+++ b/core/vendor/fabpot/goutte/.gitignore
@@ -0,0 +1,3 @@
+composer.lock
+phpunit.xml
+vendor
diff --git a/core/vendor/fabpot/goutte/.travis.yml b/core/vendor/fabpot/goutte/.travis.yml
new file mode 100644
index 0000000..e85a7b4
--- /dev/null
+++ b/core/vendor/fabpot/goutte/.travis.yml
@@ -0,0 +1,18 @@
+language: php
+
+php:
+    - '5.6'
+    - '5.5'
+    - '5.4'
+    - '5.3'
+    - hhvm
+
+before_script:
+    - composer install -n
+
+script:
+    - phpunit
+
+matrix:
+    allow_failures:
+        - php: hhvm
diff --git a/core/vendor/fabpot/goutte/Goutte/Client.php b/core/vendor/fabpot/goutte/Goutte/Client.php
new file mode 100644
index 0000000..b962c55
--- /dev/null
+++ b/core/vendor/fabpot/goutte/Goutte/Client.php
@@ -0,0 +1,187 @@
+<?php
+
+/*
+ * This file is part of the Goutte package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Goutte;
+
+use Symfony\Component\BrowserKit\Client as BaseClient;
+use Symfony\Component\BrowserKit\Response;
+
+use Guzzle\Http\Exception\CurlException;
+use Guzzle\Http\Exception\BadResponseException;
+use Guzzle\Http\Message\Response as GuzzleResponse;
+use Guzzle\Http\ClientInterface as GuzzleClientInterface;
+use Guzzle\Http\Client as GuzzleClient;
+use Guzzle\Http\Message\EntityEnclosingRequestInterface;
+
+/**
+ * Client.
+ *
+ * @package Goutte
+ * @author  Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author  Michael Dowling <michael@guzzlephp.org>
+ */
+class Client extends BaseClient
+{
+    const VERSION = '0.2';
+
+    protected $headers = array();
+    protected $auth = null;
+    protected $client;
+
+    public function setClient(GuzzleClientInterface $client)
+    {
+        $this->client = $client;
+
+        return $this;
+    }
+
+    public function getClient()
+    {
+        if (!$this->client) {
+            $this->client = new GuzzleClient('', array(GuzzleClient::DISABLE_REDIRECTS => true));
+        }
+
+        return $this->client;
+    }
+
+    public function setHeader($name, $value)
+    {
+        $this->headers[$name] = $value;
+
+        return $this;
+    }
+
+    public function removeHeader($name)
+    {
+        unset($this->headers[$name]);
+    }
+
+    public function setAuth($user, $password = '', $type = CURLAUTH_BASIC)
+    {
+        $this->auth = array(
+            'user' => $user,
+            'password' => $password,
+            'type'     => $type
+        );
+
+        return $this;
+    }
+
+    public function resetAuth()
+    {
+        $this->auth = null;
+
+        return $this;
+    }
+
+    protected function doRequest($request)
+    {
+        $headers = array();
+        foreach ($request->getServer() as $key => $val) {
+            $key = implode('-', array_map('ucfirst', explode('-', strtolower(str_replace(array('_', 'HTTP-'), array('-', ''), $key)))));
+            if (!isset($headers[$key])) {
+                $headers[$key] = $val;
+            }
+        }
+
+        $body = null;
+        if (!in_array($request->getMethod(), array('GET','HEAD'))) {
+            if (null !== $request->getContent()) {
+                $body = $request->getContent();
+            } else {
+                $body = $request->getParameters();
+            }
+        }
+
+        $guzzleRequest = $this->getClient()->createRequest(
+            $request->getMethod(),
+            $request->getUri(),
+            $headers,
+            $body
+        );
+
+        foreach ($this->headers as $name => $value) {
+            $guzzleRequest->setHeader($name, $value);
+        }
+
+        if ($this->auth !== null) {
+            $guzzleRequest->setAuth(
+                $this->auth['user'],
+                $this->auth['password'],
+                $this->auth['type']
+            );
+        }
+
+        foreach ($this->getCookieJar()->allRawValues($request->getUri()) as $name => $value) {
+            $guzzleRequest->addCookie($name, $value);
+        }
+
+        if ('POST' == $request->getMethod() || 'PUT' == $request->getMethod()) {
+            $this->addPostFiles($guzzleRequest, $request->getFiles());
+        }
+
+        $guzzleRequest->getParams()->set('redirect.disable', true);
+        $curlOptions = $guzzleRequest->getCurlOptions();
+
+        if (!$curlOptions->hasKey(CURLOPT_TIMEOUT)) {
+            $curlOptions->set(CURLOPT_TIMEOUT, 30);
+        }
+
+        // Let BrowserKit handle redirects
+        try {
+            $response = $guzzleRequest->send();
+        } catch (CurlException $e) {
+            if (!strpos($e->getMessage(), 'redirects')) {
+                throw $e;
+            }
+
+            $response = $e->getResponse();
+        } catch (BadResponseException $e) {
+            $response = $e->getResponse();
+        }
+
+        return $this->createResponse($response);
+    }
+
+    protected function addPostFiles($request, array $files, $arrayName = '')
+    {
+        if (!$request instanceof EntityEnclosingRequestInterface) {
+            return;
+        }
+
+        foreach ($files as $name => $info) {
+            if (!empty($arrayName)) {
+                $name = $arrayName . '[' . $name . ']';
+            }
+
+            if (is_array($info)) {
+                if (isset($info['tmp_name'])) {
+                    if ('' !== $info['tmp_name']) {
+                        $request->addPostFile($name, $info['tmp_name'], null, isset($info['name']) ? $info['name'] : null);
+                    } else {
+                        continue;
+                    }
+                } else {
+                    $this->addPostFiles($request, $info, $name);
+                }
+            } else {
+                $request->addPostFile($name, $info);
+            }
+        }
+    }
+
+    protected function createResponse(GuzzleResponse $response)
+    {
+        $headers = $response->getHeaders()->toArray();
+
+        return new Response($response->getBody(true), $response->getStatusCode(), $headers);
+    }
+}
diff --git a/core/vendor/fabpot/goutte/Goutte/Resources/phar-stub.php b/core/vendor/fabpot/goutte/Goutte/Resources/phar-stub.php
new file mode 100644
index 0000000..b9c3b44
--- /dev/null
+++ b/core/vendor/fabpot/goutte/Goutte/Resources/phar-stub.php
@@ -0,0 +1,14 @@
+<?php
+
+/*
+ * This file is part of the Goutte utility.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+require_once 'phar://'.__FILE__.'/vendor/autoload.php';
+
+__HALT_COMPILER();
diff --git a/core/vendor/fabpot/goutte/Goutte/Tests/ClientTest.php b/core/vendor/fabpot/goutte/Goutte/Tests/ClientTest.php
new file mode 100644
index 0000000..654dd9d
--- /dev/null
+++ b/core/vendor/fabpot/goutte/Goutte/Tests/ClientTest.php
@@ -0,0 +1,283 @@
+<?php
+
+/*
+ * This file is part of the Goutte package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Goutte\Tests;
+
+use Goutte\Client;
+use Symfony\Component\BrowserKit\Cookie;
+
+use Guzzle\Http\Message\Response as GuzzleResponse;
+use Guzzle\Http\Message\Header as GuzzleHeader;
+use Guzzle\Http\Client as GuzzleClient;
+use Guzzle\Plugin\Mock\MockPlugin;
+use Guzzle\Plugin\History\HistoryPlugin;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Message\PostFile;
+
+/**
+ * Goutte Client Test
+ *
+ * @author Michael Dowling <michael@guzzlephp.org>
+ */
+class ClientTest extends \PHPUnit_Framework_TestCase
+{
+    protected $historyPlugin;
+    protected $mockPlugin;
+
+    protected function getGuzzle()
+    {
+        $this->historyPlugin = new HistoryPlugin();
+        $this->mockPlugin = new MockPlugin();
+        $this->mockPlugin->addResponse(new GuzzleResponse(200, null, '<html><body><p>Hi</p></body></html>'));
+        $guzzle = new GuzzleClient('', array('redirect.disable' => true));
+        $guzzle->getEventDispatcher()->addSubscriber($this->mockPlugin);
+        $guzzle->getEventDispatcher()->addSubscriber($this->historyPlugin);
+
+        return $guzzle;
+    }
+
+    public function testCreatesDefaultClient()
+    {
+        $client = new Client();
+        $this->assertInstanceOf('Guzzle\\Http\\ClientInterface', $client->getClient());
+    }
+
+    public function testUsesCustomClient()
+    {
+        $guzzle = new GuzzleClient();
+        $client = new Client();
+        $this->assertSame($client, $client->setClient($guzzle));
+        $this->assertSame($guzzle, $client->getClient());
+    }
+
+    public function testUsesCustomHeaders()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $client->setHeader('X-Test', 'test');
+        $crawler = $client->request('GET', 'http://www.example.com/');
+        $this->assertEquals('test', $this->historyPlugin->getLastRequest()->getHeader('X-Test'));
+    }
+
+    public function testCustomUserAgent()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $client->setHeader('User-Agent', 'foo');
+        $crawler = $client->request('GET', 'http://www.example.com/');
+        $this->assertEquals('foo', $this->historyPlugin->getLastRequest()->getHeader('User-Agent'));
+    }
+
+    public function testUsesAuth()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $client->setAuth('me', '**');
+        $crawler = $client->request('GET', 'http://www.example.com/');
+        $request = $this->historyPlugin->getLastRequest();
+        $this->assertEquals('me', $request->getUsername());
+        $this->assertEquals('**', $request->getPassword());
+    }
+
+    public function testResetsAuth()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $client->setAuth('me', '**');
+        $client->resetAuth();
+        $crawler = $client->request('GET', 'http://www.example.com/');
+        $request = $this->historyPlugin->getLastRequest();
+        $this->assertNull($request->getUsername());
+        $this->assertNull($request->getPassword());
+    }
+
+    public function testUsesCookies()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $client->getCookieJar()->set(new Cookie('test', '123'));
+        $crawler = $client->request('GET', 'http://www.example.com/');
+        $request = $this->historyPlugin->getLastRequest();
+        $this->assertEquals('123', $request->getCookie('test'));
+    }
+
+    public function testUsesPostFiles()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $files = array(
+            'test' => array(
+                'name' => 'test.txt',
+                'tmp_name' => __FILE__
+            )
+        );
+
+        $crawler = $client->request('POST', 'http://www.example.com/', array(), $files);
+        $request = $this->historyPlugin->getLastRequest();
+
+        $this->assertEquals(array(
+            'test' => array(
+                new PostFile('test', __FILE__, 'text/x-php', 'test.txt')
+            )
+        ), $request->getPostFiles());
+    }
+
+    public function testUsesPostNamedFiles()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $files = array(
+            'test' => __FILE__
+        );
+
+        $crawler = $client->request('POST', 'http://www.example.com/', array(), $files);
+        $request = $this->historyPlugin->getLastRequest();
+
+        $this->assertEquals(array(
+            'test' => array(
+                new PostFile('test', __FILE__, 'text/x-php')
+            )
+        ), $request->getPostFiles());
+    }
+
+    public function testUsesPostFilesNestedFields()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $files = array(
+            'form' => array(
+                'test' => array(
+                    'name' => 'test.txt',
+                    'tmp_name' => __FILE__
+                ),
+            ),
+        );
+
+        $crawler = $client->request('POST', 'http://www.example.com/', array(), $files);
+        $request = $this->historyPlugin->getLastRequest();
+
+        $this->assertEquals(array(
+            'form[test]' => array(
+                new PostFile('form[test]', __FILE__, 'text/x-php', 'test.txt')
+            )
+        ), $request->getPostFiles());
+    }
+
+    public function testUsesPostFilesOnClientSide()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $files = array(
+            'test' => __FILE__,
+        );
+
+        $crawler = $client->request('POST', 'http://www.example.com/', array(), $files);
+        $request = $this->historyPlugin->getLastRequest();
+
+        $this->assertEquals(array(
+            'test' => array(
+                new PostFile('test', __FILE__, 'text/x-php')
+            )
+        ), $request->getPostFiles());
+    }
+
+    public function testUsesPostFilesUploadError()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $files = array(
+            'test' => array(
+                'name' => '',
+                'type' => '',
+                'tmp_name' => '',
+                'error' => 4,
+                'size' => 0,
+            ),
+        );
+
+        $crawler = $client->request('POST', 'http://www.example.com/', array(), $files);
+        $request = $this->historyPlugin->getLastRequest();
+
+        $this->assertEquals(array(), $request->getPostFiles());
+    }
+
+    public function testUsesCurlOptions()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $crawler = $client->request('GET', 'http://www.example.com/');
+        $request = $this->historyPlugin->getLastRequest();
+        $this->assertEquals(0, $request->getCurlOptions()->get(CURLOPT_MAXREDIRS));
+        $this->assertEquals(30, $request->getCurlOptions()->get(CURLOPT_TIMEOUT));
+    }
+
+    public function testCreatesResponse()
+    {
+        $guzzle = $this->getGuzzle();
+        $client = new Client();
+        $client->setClient($guzzle);
+        $crawler = $client->request('GET', 'http://www.example.com/');
+        $this->assertEquals('Hi', $crawler->filter('p')->text());
+    }
+
+    public function testHandlesRedirectsCorrectly()
+    {
+        $guzzle = $this->getGuzzle();
+
+        $this->mockPlugin->clearQueue();
+        $this->mockPlugin->addResponse(new GuzzleResponse(301, array(
+            'Location' => 'http://www.example.com/'
+        )));
+        $this->mockPlugin->addResponse(new GuzzleResponse(200, null, '<html><body><p>Test</p></body></html>'));
+
+        $client = new Client();
+        $client->setClient($guzzle);
+
+        $crawler = $client->request('GET', 'http://www.example.com/');
+        $this->assertEquals('Test', $crawler->filter('p')->text());
+
+        // Ensure that two requests were sent
+        $this->assertEquals(2, count($this->historyPlugin));
+    }
+
+    public function testConvertsGuzzleHeadersToArrays()
+    {
+        if (!class_exists("Guzzle\Http\Message\Header")) {
+            $this->markTestSkipped("Guzzle ~3.6 required");
+        }
+
+        $guzzle = $this->getGuzzle();
+
+        $this->mockPlugin->clearQueue();
+        $this->mockPlugin->addResponse(new GuzzleResponse(200, array(
+            new GuzzleHeader('Date', 'Tue, 04 Jun 2013 13:22:41 GMT'),
+        )));
+
+        $client = new Client();
+        $client->setClient($guzzle);
+        $client->request('GET', 'http://www.example.com/');
+        $response = $client->getResponse();
+        $headers = $response->getHeaders();
+
+        $this->assertInternalType("array", array_shift($headers), "Header not converted from Guzzle\Http\Message\Header to array");
+    }
+}
diff --git a/core/vendor/fabpot/goutte/LICENSE b/core/vendor/fabpot/goutte/LICENSE
new file mode 100644
index 0000000..ff727f4
--- /dev/null
+++ b/core/vendor/fabpot/goutte/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010-2013 Fabien Potencier
+
+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:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+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.
diff --git a/core/vendor/fabpot/goutte/README.rst b/core/vendor/fabpot/goutte/README.rst
new file mode 100644
index 0000000..1fc247c
--- /dev/null
+++ b/core/vendor/fabpot/goutte/README.rst
@@ -0,0 +1,105 @@
+Goutte, a simple PHP Web Scraper
+================================
+
+Goutte is a screen scraping and web crawling library for PHP.
+
+Goutte provides a nice API to crawl websites and extract data from the HTML/XML
+responses.
+
+Requirements
+------------
+
+Goutte works with PHP 5.3.3 or later.
+
+Installation
+------------
+
+Add ``fabpot/goutte`` as a require dependency in your ``composer.json`` file:
+
+.. code-block:: bash
+
+    php composer.phar require fabpot/goutte:~1.0
+
+.. tip::
+
+    You can also download the `Goutte.phar`_ file:
+
+    .. code-block:: php
+
+        require_once '/path/to/goutte.phar';
+
+Usage
+-----
+
+Create a Goutte Client instance (which extends
+``Symfony\Component\BrowserKit\Client``):
+
+.. code-block:: php
+
+    use Goutte\Client;
+
+    $client = new Client();
+
+Make requests with the ``request()`` method:
+
+.. code-block:: php
+
+    // Go to the symfony.com website
+    $crawler = $client->request('GET', 'http://www.symfony.com/blog/');
+
+The method returns a ``Crawler`` object
+(``Symfony\Component\DomCrawler\Crawler``).
+
+Click on links:
+
+.. code-block:: php
+
+    // Click on the "Security Advisories" link
+    $link = $crawler->selectLink('Security Advisories')->link();
+    $crawler = $client->click($link);
+
+Extract data:
+
+.. code-block:: php
+
+    // Get the latest post in this category and display the titles
+    $crawler->filter('h2.post > a')->each(function ($node) {
+        print $node->text()."\n";
+    });
+
+Submit forms:
+
+.. code-block:: php
+
+    $crawler = $client->request('GET', 'http://github.com/');
+    $crawler = $client->click($crawler->selectLink('Sign in')->link());
+    $form = $crawler->selectButton('Sign in')->form();
+    $crawler = $client->submit($form, array('login' => 'fabpot', 'password' => 'xxxxxx'));
+    $crawler->filter('.flash-error')->each(function ($node) {
+        print $node->text()."\n";
+    });
+
+More Information
+----------------
+
+Read the documentation of the BrowserKit and DomCrawler Symfony Components for
+more information about what you can do with Goutte.
+
+Technical Information
+---------------------
+
+Goutte is a thin wrapper around the following fine PHP libraries:
+
+* Symfony Components: BrowserKit, ClassLoader, CssSelector, DomCrawler, Finder,
+  and Process;
+
+*  `Guzzle`_ HTTP Component.
+
+License
+-------
+
+Goutte is licensed under the MIT license.
+
+.. _`Composer`:    http://getcomposer.org
+.. _`Goutte.phar`: http://get.sensiolabs.org/goutte.phar
+.. _`Guzzle`:      http://docs.guzzlephp.org
diff --git a/core/vendor/fabpot/goutte/box.json b/core/vendor/fabpot/goutte/box.json
new file mode 100644
index 0000000..943c61e
--- /dev/null
+++ b/core/vendor/fabpot/goutte/box.json
@@ -0,0 +1,21 @@
+{
+    "output": "goutte.phar",
+    "chmod": "0755",
+    "compactors": [
+        "Herrera\\Box\\Compactor\\Php"
+    ],
+    "extract": false,
+    "files": [
+        "LICENSE",
+        "Goutte/Client.php"
+    ],
+    "finder": [
+        {
+            "name": ["*.php", "*.pem*"],
+            "exclude": ["Tests", "tests"],
+            "in": "vendor"
+        }
+    ],
+    "stub": "Goutte/Resources/phar-stub.php",
+    "web": false
+}
diff --git a/core/vendor/fabpot/goutte/composer.json b/core/vendor/fabpot/goutte/composer.json
new file mode 100644
index 0000000..7f24635
--- /dev/null
+++ b/core/vendor/fabpot/goutte/composer.json
@@ -0,0 +1,36 @@
+{
+    "name": "fabpot/goutte",
+    "type": "application",
+    "description": "A simple PHP Web Scraper",
+    "keywords": ["scraper"],
+    "homepage": "https://github.com/fabpot/Goutte",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Fabien Potencier",
+            "email": "fabien@symfony.com"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.0",
+        "ext-curl": "*",
+        "symfony/browser-kit": "~2.1",
+        "symfony/css-selector": "~2.1",
+        "symfony/dom-crawler": "~2.1",
+        "symfony/finder": "~2.1",
+        "symfony/process": "~2.1",
+        "guzzle/http": "~3.1"
+    },
+    "require-dev": {
+        "guzzle/plugin-history": "~3.1",
+        "guzzle/plugin-mock": "~3.1"
+    },
+    "autoload": {
+        "psr-0": { "Goutte": "." }
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.0-dev"
+        }
+    }
+}
diff --git a/core/vendor/fabpot/goutte/phpunit.xml.dist b/core/vendor/fabpot/goutte/phpunit.xml.dist
new file mode 100644
index 0000000..9e7ff98
--- /dev/null
+++ b/core/vendor/fabpot/goutte/phpunit.xml.dist
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit backupGlobals="false"
+         backupStaticAttributes="false"
+         colors="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         processIsolation="false"
+         stopOnFailure="false"
+         syntaxCheck="false"
+         bootstrap="./vendor/autoload.php">
+    <testsuites>
+        <testsuite name="Goutte Test Suite">
+            <directory>./Goutte/Tests</directory>
+        </testsuite>
+    </testsuites>
+</phpunit>
diff --git a/core/vendor/guzzle/common/Guzzle/Common/AbstractHasDispatcher.php b/core/vendor/guzzle/common/Guzzle/Common/AbstractHasDispatcher.php
new file mode 100644
index 0000000..d1e842b
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/AbstractHasDispatcher.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Guzzle\Common;
+
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Class that holds an event dispatcher
+ */
+class AbstractHasDispatcher implements HasDispatcherInterface
+{
+    /** @var EventDispatcherInterface */
+    protected $eventDispatcher;
+
+    public static function getAllEvents()
+    {
+        return array();
+    }
+
+    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
+    {
+        $this->eventDispatcher = $eventDispatcher;
+
+        return $this;
+    }
+
+    public function getEventDispatcher()
+    {
+        if (!$this->eventDispatcher) {
+            $this->eventDispatcher = new EventDispatcher();
+        }
+
+        return $this->eventDispatcher;
+    }
+
+    public function dispatch($eventName, array $context = array())
+    {
+        return $this->getEventDispatcher()->dispatch($eventName, new Event($context));
+    }
+
+    public function addSubscriber(EventSubscriberInterface $subscriber)
+    {
+        $this->getEventDispatcher()->addSubscriber($subscriber);
+
+        return $this;
+    }
+}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/Collection.php b/core/vendor/guzzle/common/Guzzle/Common/Collection.php
new file mode 100644
index 0000000..5cb1535
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/Collection.php
@@ -0,0 +1,403 @@
+<?php
+
+namespace Guzzle\Common;
+
+use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Common\Exception\RuntimeException;
+
+/**
+ * Key value pair collection object
+ */
+class Collection implements \ArrayAccess, \IteratorAggregate, \Countable, ToArrayInterface
+{
+    /** @var array Data associated with the object. */
+    protected $data;
+
+    /**
+     * @param array $data Associative array of data to set
+     */
+    public function __construct(array $data = array())
+    {
+        $this->data = $data;
+    }
+
+    /**
+     * Create a new collection from an array, validate the keys, and add default values where missing
+     *
+     * @param array $config   Configuration values to apply.
+     * @param array $defaults Default parameters
+     * @param array $required Required parameter names
+     *
+     * @return self
+     * @throws InvalidArgumentException if a parameter is missing
+     */
+    public static function fromConfig(array $config = array(), array $defaults = array(), array $required = array())
+    {
+        $data = $config + $defaults;
+
+        if ($missing = array_diff($required, array_keys($data))) {
+            throw new InvalidArgumentException('Config is missing the following keys: ' . implode(', ', $missing));
+        }
+
+        return new self($data);
+    }
+
+    public function count()
+    {
+        return count($this->data);
+    }
+
+    public function getIterator()
+    {
+        return new \ArrayIterator($this->data);
+    }
+
+    public function toArray()
+    {
+        return $this->data;
+    }
+
+    /**
+     * Removes all key value pairs
+     *
+     * @return Collection
+     */
+    public function clear()
+    {
+        $this->data = array();
+
+        return $this;
+    }
+
+    /**
+     * Get all or a subset of matching key value pairs
+     *
+     * @param array $keys Pass an array of keys to retrieve only a subset of key value pairs
+     *
+     * @return array Returns an array of all matching key value pairs
+     */
+    public function getAll(array $keys = null)
+    {
+        return $keys ? array_intersect_key($this->data, array_flip($keys)) : $this->data;
+    }
+
+    /**
+     * Get a specific key value.
+     *
+     * @param string $key Key to retrieve.
+     *
+     * @return mixed|null Value of the key or NULL
+     */
+    public function get($key)
+    {
+        return isset($this->data[$key]) ? $this->data[$key] : null;
+    }
+
+    /**
+     * Set a key value pair
+     *
+     * @param string $key   Key to set
+     * @param mixed  $value Value to set
+     *
+     * @return Collection Returns a reference to the object
+     */
+    public function set($key, $value)
+    {
+        $this->data[$key] = $value;
+
+        return $this;
+    }
+
+    /**
+     * Add a value to a key.  If a key of the same name has already been added, the key value will be converted into an
+     * array and the new value will be pushed to the end of the array.
+     *
+     * @param string $key   Key to add
+     * @param mixed  $value Value to add to the key
+     *
+     * @return Collection Returns a reference to the object.
+     */
+    public function add($key, $value)
+    {
+        if (!array_key_exists($key, $this->data)) {
+            $this->data[$key] = $value;
+        } elseif (is_array($this->data[$key])) {
+            $this->data[$key][] = $value;
+        } else {
+            $this->data[$key] = array($this->data[$key], $value);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Remove a specific key value pair
+     *
+     * @param string $key A key to remove
+     *
+     * @return Collection
+     */
+    public function remove($key)
+    {
+        unset($this->data[$key]);
+
+        return $this;
+    }
+
+    /**
+     * Get all keys in the collection
+     *
+     * @return array
+     */
+    public function getKeys()
+    {
+        return array_keys($this->data);
+    }
+
+    /**
+     * Returns whether or not the specified key is present.
+     *
+     * @param string $key The key for which to check the existence.
+     *
+     * @return bool
+     */
+    public function hasKey($key)
+    {
+        return array_key_exists($key, $this->data);
+    }
+
+    /**
+     * Case insensitive search the keys in the collection
+     *
+     * @param string $key Key to search for
+     *
+     * @return bool|string Returns false if not found, otherwise returns the key
+     */
+    public function keySearch($key)
+    {
+        foreach (array_keys($this->data) as $k) {
+            if (!strcasecmp($k, $key)) {
+                return $k;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks if any keys contains a certain value
+     *
+     * @param string $value Value to search for
+     *
+     * @return mixed Returns the key if the value was found FALSE if the value was not found.
+     */
+    public function hasValue($value)
+    {
+        return array_search($value, $this->data);
+    }
+
+    /**
+     * Replace the data of the object with the value of an array
+     *
+     * @param array $data Associative array of data
+     *
+     * @return Collection Returns a reference to the object
+     */
+    public function replace(array $data)
+    {
+        $this->data = $data;
+
+        return $this;
+    }
+
+    /**
+     * Add and merge in a Collection or array of key value pair data.
+     *
+     * @param Collection|array $data Associative array of key value pair data
+     *
+     * @return Collection Returns a reference to the object.
+     */
+    public function merge($data)
+    {
+        foreach ($data as $key => $value) {
+            $this->add($key, $value);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Over write key value pairs in this collection with all of the data from an array or collection.
+     *
+     * @param array|\Traversable $data Values to override over this config
+     *
+     * @return self
+     */
+    public function overwriteWith($data)
+    {
+        if (is_array($data)) {
+            $this->data = $data + $this->data;
+        } elseif ($data instanceof Collection) {
+            $this->data = $data->toArray() + $this->data;
+        } else {
+            foreach ($data as $key => $value) {
+                $this->data[$key] = $value;
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns a Collection containing all the elements of the collection after applying the callback function to each
+     * one. The Closure should accept three parameters: (string) $key, (string) $value, (array) $context and return a
+     * modified value
+     *
+     * @param \Closure $closure Closure to apply
+     * @param array    $context Context to pass to the closure
+     * @param bool     $static  Set to TRUE to use the same class as the return rather than returning a Collection
+     *
+     * @return Collection
+     */
+    public function map(\Closure $closure, array $context = array(), $static = true)
+    {
+        $collection = $static ? new static() : new self();
+        foreach ($this as $key => $value) {
+            $collection->add($key, $closure($key, $value, $context));
+        }
+
+        return $collection;
+    }
+
+    /**
+     * Iterates over each key value pair in the collection passing them to the Closure. If the  Closure function returns
+     * true, the current value from input is returned into the result Collection.  The Closure must accept three
+     * parameters: (string) $key, (string) $value and return Boolean TRUE or FALSE for each value.
+     *
+     * @param \Closure $closure Closure evaluation function
+     * @param bool     $static  Set to TRUE to use the same class as the return rather than returning a Collection
+     *
+     * @return Collection
+     */
+    public function filter(\Closure $closure, $static = true)
+    {
+        $collection = ($static) ? new static() : new self();
+        foreach ($this->data as $key => $value) {
+            if ($closure($key, $value)) {
+                $collection->add($key, $value);
+            }
+        }
+
+        return $collection;
+    }
+
+    public function offsetExists($offset)
+    {
+        return isset($this->data[$offset]);
+    }
+
+    public function offsetGet($offset)
+    {
+        return isset($this->data[$offset]) ? $this->data[$offset] : null;
+    }
+
+    public function offsetSet($offset, $value)
+    {
+        $this->data[$offset] = $value;
+    }
+
+    public function offsetUnset($offset)
+    {
+        unset($this->data[$offset]);
+    }
+
+    /**
+     * Set a value into a nested array key. Keys will be created as needed to set the value.
+     *
+     * @param string $path  Path to set
+     * @param mixed  $value Value to set at the key
+     *
+     * @return self
+     * @throws RuntimeException when trying to setPath using a nested path that travels through a scalar value
+     */
+    public function setPath($path, $value)
+    {
+        $current =& $this->data;
+        $queue = explode('/', $path);
+        while (null !== ($key = array_shift($queue))) {
+            if (!is_array($current)) {
+                throw new RuntimeException("Trying to setPath {$path}, but {$key} is set and is not an array");
+            } elseif (!$queue) {
+                $current[$key] = $value;
+            } elseif (isset($current[$key])) {
+                $current =& $current[$key];
+            } else {
+                $current[$key] = array();
+                $current =& $current[$key];
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Gets a value from the collection using an array path (e.g. foo/baz/bar would retrieve bar from two nested arrays)
+     * Allows for wildcard searches which recursively combine matches up to the level at which the wildcard occurs. This
+     * can be useful for accepting any key of a sub-array and combining matching keys from each diverging path.
+     *
+     * @param string $path      Path to traverse and retrieve a value from
+     * @param string $separator Character used to add depth to the search
+     * @param mixed  $data      Optional data to descend into (used when wildcards are encountered)
+     *
+     * @return mixed|null
+     */
+    public function getPath($path, $separator = '/', $data = null)
+    {
+        if ($data === null) {
+            $data =& $this->data;
+        }
+
+        $path = is_array($path) ? $path : explode($separator, $path);
+        while (null !== ($part = array_shift($path))) {
+            if (!is_array($data)) {
+                return null;
+            } elseif (isset($data[$part])) {
+                $data =& $data[$part];
+            } elseif ($part != '*') {
+                return null;
+            } else {
+                // Perform a wildcard search by diverging and merging paths
+                $result = array();
+                foreach ($data as $value) {
+                    if (!$path) {
+                        $result = array_merge_recursive($result, (array) $value);
+                    } elseif (null !== ($test = $this->getPath($path, $separator, $value))) {
+                        $result = array_merge_recursive($result, (array) $test);
+                    }
+                }
+                return $result;
+            }
+        }
+
+        return $data;
+    }
+
+    /**
+     * Inject configuration settings into an input string
+     *
+     * @param string $input Input to inject
+     *
+     * @return string
+     * @deprecated
+     */
+    public function inject($input)
+    {
+        Version::warn(__METHOD__ . ' is deprecated');
+        $replace = array();
+        foreach ($this->data as $key => $val) {
+            $replace['{' . $key . '}'] = $val;
+        }
+
+        return strtr($input, $replace);
+    }
+}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/Event.php b/core/vendor/guzzle/common/Guzzle/Common/Event.php
new file mode 100644
index 0000000..fad76a9
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/Event.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace Guzzle\Common;
+
+use Symfony\Component\EventDispatcher\Event as SymfonyEvent;
+
+/**
+ * Default event for Guzzle notifications
+ */
+class Event extends SymfonyEvent implements ToArrayInterface, \ArrayAccess, \IteratorAggregate
+{
+    /** @var array */
+    private $context;
+
+    /**
+     * @param array $context Contextual information
+     */
+    public function __construct(array $context = array())
+    {
+        $this->context = $context;
+    }
+
+    public function getIterator()
+    {
+        return new \ArrayIterator($this->context);
+    }
+
+    public function offsetGet($offset)
+    {
+        return isset($this->context[$offset]) ? $this->context[$offset] : null;
+    }
+
+    public function offsetSet($offset, $value)
+    {
+        $this->context[$offset] = $value;
+    }
+
+    public function offsetExists($offset)
+    {
+        return isset($this->context[$offset]);
+    }
+
+    public function offsetUnset($offset)
+    {
+        unset($this->context[$offset]);
+    }
+
+    public function toArray()
+    {
+        return $this->context;
+    }
+}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/Exception/BadMethodCallException.php b/core/vendor/guzzle/common/Guzzle/Common/Exception/BadMethodCallException.php
new file mode 100644
index 0000000..08d1c72
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/Exception/BadMethodCallException.php
@@ -0,0 +1,5 @@
+<?php
+
+namespace Guzzle\Common\Exception;
+
+class BadMethodCallException extends \BadMethodCallException implements GuzzleException {}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/Exception/ExceptionCollection.php b/core/vendor/guzzle/common/Guzzle/Common/Exception/ExceptionCollection.php
new file mode 100644
index 0000000..750e483
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/Exception/ExceptionCollection.php
@@ -0,0 +1,108 @@
+<?php
+
+namespace Guzzle\Common\Exception;
+
+/**
+ * Collection of exceptions
+ */
+class ExceptionCollection extends \Exception implements GuzzleException, \IteratorAggregate, \Countable
+{
+    /** @var array Array of Exceptions */
+    protected $exceptions = array();
+
+    /** @var string Succinct exception message not including sub-exceptions */
+    private $shortMessage;
+
+    public function __construct($message = '', $code = 0, \Exception $previous = null)
+    {
+        parent::__construct($message, $code, $previous);
+        $this->shortMessage = $message;
+    }
+
+    /**
+     * Set all of the exceptions
+     *
+     * @param array $exceptions Array of exceptions
+     *
+     * @return self
+     */
+    public function setExceptions(array $exceptions)
+    {
+        $this->exceptions = array();
+        foreach ($exceptions as $exception) {
+            $this->add($exception);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Add exceptions to the collection
+     *
+     * @param ExceptionCollection|\Exception $e Exception to add
+     *
+     * @return ExceptionCollection;
+     */
+    public function add($e)
+    {
+        $this->exceptions[] = $e;
+        if ($this->message) {
+            $this->message .= "\n";
+        }
+
+        $this->message .= $this->getExceptionMessage($e, 0);
+
+        return $this;
+    }
+
+    /**
+     * Get the total number of request exceptions
+     *
+     * @return int
+     */
+    public function count()
+    {
+        return count($this->exceptions);
+    }
+
+    /**
+     * Allows array-like iteration over the request exceptions
+     *
+     * @return \ArrayIterator
+     */
+    public function getIterator()
+    {
+        return new \ArrayIterator($this->exceptions);
+    }
+
+    /**
+     * Get the first exception in the collection
+     *
+     * @return \Exception
+     */
+    public function getFirst()
+    {
+        return $this->exceptions ? $this->exceptions[0] : null;
+    }
+
+    private function getExceptionMessage(\Exception $e, $depth = 0)
+    {
+        static $sp = '    ';
+        $prefix = $depth ? str_repeat($sp, $depth) : '';
+        $message = "{$prefix}(" . get_class($e) . ') ' . $e->getFile() . ' line ' . $e->getLine() . "\n";
+
+        if ($e instanceof self) {
+            if ($e->shortMessage) {
+                $message .= "\n{$prefix}{$sp}" . str_replace("\n", "\n{$prefix}{$sp}", $e->shortMessage) . "\n";
+            }
+            foreach ($e as $ee) {
+                $message .= "\n" . $this->getExceptionMessage($ee, $depth + 1);
+            }
+        }  else {
+            $message .= "\n{$prefix}{$sp}" . str_replace("\n", "\n{$prefix}{$sp}", $e->getMessage()) . "\n";
+            $message .= "\n{$prefix}{$sp}" . str_replace("\n", "\n{$prefix}{$sp}", $e->getTraceAsString()) . "\n";
+        }
+
+        return str_replace(getcwd(), '.', $message);
+    }
+}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/Exception/GuzzleException.php b/core/vendor/guzzle/common/Guzzle/Common/Exception/GuzzleException.php
new file mode 100644
index 0000000..458e6f2
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/Exception/GuzzleException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Guzzle\Common\Exception;
+
+/**
+ * Guzzle exception
+ */
+interface GuzzleException {}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/Exception/InvalidArgumentException.php b/core/vendor/guzzle/common/Guzzle/Common/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000..ae674be
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/Exception/InvalidArgumentException.php
@@ -0,0 +1,5 @@
+<?php
+
+namespace Guzzle\Common\Exception;
+
+class InvalidArgumentException extends \InvalidArgumentException implements GuzzleException {}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/Exception/RuntimeException.php b/core/vendor/guzzle/common/Guzzle/Common/Exception/RuntimeException.php
new file mode 100644
index 0000000..9254094
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/Exception/RuntimeException.php
@@ -0,0 +1,5 @@
+<?php
+
+namespace Guzzle\Common\Exception;
+
+class RuntimeException extends \RuntimeException implements GuzzleException {}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/Exception/UnexpectedValueException.php b/core/vendor/guzzle/common/Guzzle/Common/Exception/UnexpectedValueException.php
new file mode 100644
index 0000000..843c017
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/Exception/UnexpectedValueException.php
@@ -0,0 +1,5 @@
+<?php
+
+namespace Guzzle\Common\Exception;
+
+class UnexpectedValueException extends \UnexpectedValueException implements GuzzleException {}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/FromConfigInterface.php b/core/vendor/guzzle/common/Guzzle/Common/FromConfigInterface.php
new file mode 100644
index 0000000..c8b1317
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/FromConfigInterface.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Guzzle\Common;
+
+/**
+ * Interfaces that adds a factory method which is used to instantiate a class from an array of configuration options.
+ */
+interface FromConfigInterface
+{
+    /**
+     * Static factory method used to turn an array or collection of configuration data into an instantiated object.
+     *
+     * @param array|Collection $config Configuration data
+     *
+     * @return FromConfigInterface
+     */
+    public static function factory($config = array());
+}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/HasDispatcherInterface.php b/core/vendor/guzzle/common/Guzzle/Common/HasDispatcherInterface.php
new file mode 100644
index 0000000..8067598
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/HasDispatcherInterface.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Guzzle\Common;
+
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Holds an event dispatcher
+ */
+interface HasDispatcherInterface
+{
+    /**
+     * Get a list of all of the events emitted from the class
+     *
+     * @return array
+     */
+    public static function getAllEvents();
+
+    /**
+     * Set the EventDispatcher of the request
+     *
+     * @param EventDispatcherInterface $eventDispatcher
+     *
+     * @return self
+     */
+    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher);
+
+    /**
+     * Get the EventDispatcher of the request
+     *
+     * @return EventDispatcherInterface
+     */
+    public function getEventDispatcher();
+
+    /**
+     * Helper to dispatch Guzzle events and set the event name on the event
+     *
+     * @param string $eventName Name of the event to dispatch
+     * @param array  $context   Context of the event
+     *
+     * @return Event Returns the created event object
+     */
+    public function dispatch($eventName, array $context = array());
+
+    /**
+     * Add an event subscriber to the dispatcher
+     *
+     * @param EventSubscriberInterface $subscriber Event subscriber
+     *
+     * @return self
+     */
+    public function addSubscriber(EventSubscriberInterface $subscriber);
+}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/ToArrayInterface.php b/core/vendor/guzzle/common/Guzzle/Common/ToArrayInterface.php
new file mode 100644
index 0000000..245328c
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/ToArrayInterface.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace Guzzle\Common;
+
+/**
+ * An object that can be represented as an array
+ */
+interface ToArrayInterface
+{
+    /**
+     * Get the array representation of an object
+     *
+     * @return array
+     */
+    public function toArray();
+}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/Version.php b/core/vendor/guzzle/common/Guzzle/Common/Version.php
new file mode 100644
index 0000000..d018c1e
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/Version.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Guzzle\Common;
+
+/**
+ * Guzzle version information
+ */
+class Version
+{
+    const VERSION = '3.9.2';
+
+    /**
+     * @var bool Set this value to true to enable warnings for deprecated functionality use. This should be on in your
+     *           unit tests, but probably not in production.
+     */
+    public static $emitWarnings = false;
+
+    /**
+     * Emit a deprecation warning
+     *
+     * @param string $message Warning message
+     */
+    public static function warn($message)
+    {
+        if (self::$emitWarnings) {
+            trigger_error('Deprecation warning: ' . $message, E_USER_DEPRECATED);
+        }
+    }
+}
diff --git a/core/vendor/guzzle/common/Guzzle/Common/composer.json b/core/vendor/guzzle/common/Guzzle/Common/composer.json
new file mode 100644
index 0000000..c02fa69
--- /dev/null
+++ b/core/vendor/guzzle/common/Guzzle/Common/composer.json
@@ -0,0 +1,20 @@
+{
+    "name": "guzzle/common",
+    "homepage": "http://guzzlephp.org/",
+    "description": "Common libraries used by Guzzle",
+    "keywords": ["common", "event", "exception", "collection"],
+    "license": "MIT",
+    "require": {
+        "php": ">=5.3.2",
+        "symfony/event-dispatcher": ">=2.1"
+    },
+    "autoload": {
+        "psr-0": { "Guzzle\\Common": "" }
+    },
+    "target-dir": "Guzzle/Common",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "3.7-dev"
+        }
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/AbstractEntityBodyDecorator.php b/core/vendor/guzzle/http/Guzzle/Http/AbstractEntityBodyDecorator.php
new file mode 100644
index 0000000..5005a88
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/AbstractEntityBodyDecorator.php
@@ -0,0 +1,221 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Stream\Stream;
+
+/**
+ * Abstract decorator used to wrap entity bodies
+ */
+class AbstractEntityBodyDecorator implements EntityBodyInterface
+{
+    /** @var EntityBodyInterface Decorated entity body */
+    protected $body;
+
+    /**
+     * @param EntityBodyInterface $body Entity body to decorate
+     */
+    public function __construct(EntityBodyInterface $body)
+    {
+        $this->body = $body;
+    }
+
+    public function __toString()
+    {
+        return (string) $this->body;
+    }
+
+    /**
+     * Allow decorators to implement custom methods
+     *
+     * @param string $method Missing method name
+     * @param array  $args   Method arguments
+     *
+     * @return mixed
+     */
+    public function __call($method, array $args)
+    {
+        return call_user_func_array(array($this->body, $method), $args);
+    }
+
+    public function close()
+    {
+        return $this->body->close();
+    }
+
+    public function setRewindFunction($callable)
+    {
+        $this->body->setRewindFunction($callable);
+
+        return $this;
+    }
+
+    public function rewind()
+    {
+        return $this->body->rewind();
+    }
+
+    public function compress($filter = 'zlib.deflate')
+    {
+        return $this->body->compress($filter);
+    }
+
+    public function uncompress($filter = 'zlib.inflate')
+    {
+        return $this->body->uncompress($filter);
+    }
+
+    public function getContentLength()
+    {
+        return $this->getSize();
+    }
+
+    public function getContentType()
+    {
+        return $this->body->getContentType();
+    }
+
+    public function getContentMd5($rawOutput = false, $base64Encode = false)
+    {
+        $hash = Stream::getHash($this, 'md5', $rawOutput);
+
+        return $hash && $base64Encode ? base64_encode($hash) : $hash;
+    }
+
+    public function getContentEncoding()
+    {
+        return $this->body->getContentEncoding();
+    }
+
+    public function getMetaData($key = null)
+    {
+        return $this->body->getMetaData($key);
+    }
+
+    public function getStream()
+    {
+        return $this->body->getStream();
+    }
+
+    public function setStream($stream, $size = 0)
+    {
+        $this->body->setStream($stream, $size);
+
+        return $this;
+    }
+
+    public function detachStream()
+    {
+        $this->body->detachStream();
+
+        return $this;
+    }
+
+    public function getWrapper()
+    {
+        return $this->body->getWrapper();
+    }
+
+    public function getWrapperData()
+    {
+        return $this->body->getWrapperData();
+    }
+
+    public function getStreamType()
+    {
+        return $this->body->getStreamType();
+    }
+
+    public function getUri()
+    {
+        return $this->body->getUri();
+    }
+
+    public function getSize()
+    {
+        return $this->body->getSize();
+    }
+
+    public function isReadable()
+    {
+        return $this->body->isReadable();
+    }
+
+    public function isRepeatable()
+    {
+        return $this->isSeekable() && $this->isReadable();
+    }
+
+    public function isWritable()
+    {
+        return $this->body->isWritable();
+    }
+
+    public function isConsumed()
+    {
+        return $this->body->isConsumed();
+    }
+
+    /**
+     * Alias of isConsumed()
+     * {@inheritdoc}
+     */
+    public function feof()
+    {
+        return $this->isConsumed();
+    }
+
+    public function isLocal()
+    {
+        return $this->body->isLocal();
+    }
+
+    public function isSeekable()
+    {
+        return $this->body->isSeekable();
+    }
+
+    public function setSize($size)
+    {
+        $this->body->setSize($size);
+
+        return $this;
+    }
+
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        return $this->body->seek($offset, $whence);
+    }
+
+    public function read($length)
+    {
+        return $this->body->read($length);
+    }
+
+    public function write($string)
+    {
+        return $this->body->write($string);
+    }
+
+    public function readLine($maxLength = null)
+    {
+        return $this->body->readLine($maxLength);
+    }
+
+    public function ftell()
+    {
+        return $this->body->ftell();
+    }
+
+    public function getCustomData($key)
+    {
+        return $this->body->getCustomData($key);
+    }
+
+    public function setCustomData($key, $value)
+    {
+        $this->body->setCustomData($key, $value);
+
+        return $this;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/CachingEntityBody.php b/core/vendor/guzzle/http/Guzzle/Http/CachingEntityBody.php
new file mode 100644
index 0000000..c65c136
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/CachingEntityBody.php
@@ -0,0 +1,229 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Common\Exception\RuntimeException;
+
+/**
+ * EntityBody decorator that can cache previously read bytes from a sequentially read tstream
+ */
+class CachingEntityBody extends AbstractEntityBodyDecorator
+{
+    /** @var EntityBody Remote stream used to actually pull data onto the buffer */
+    protected $remoteStream;
+
+    /** @var int The number of bytes to skip reading due to a write on the temporary buffer */
+    protected $skipReadBytes = 0;
+
+    /**
+     * We will treat the buffer object as the body of the entity body
+     * {@inheritdoc}
+     */
+    public function __construct(EntityBodyInterface $body)
+    {
+        $this->remoteStream = $body;
+        $this->body = new EntityBody(fopen('php://temp', 'r+'));
+    }
+
+    /**
+     * Will give the contents of the buffer followed by the exhausted remote stream.
+     *
+     * Warning: Loads the entire stream into memory
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        $pos = $this->ftell();
+        $this->rewind();
+
+        $str = '';
+        while (!$this->isConsumed()) {
+            $str .= $this->read(16384);
+        }
+
+        $this->seek($pos);
+
+        return $str;
+    }
+
+    public function getSize()
+    {
+        return max($this->body->getSize(), $this->remoteStream->getSize());
+    }
+
+    /**
+     * {@inheritdoc}
+     * @throws RuntimeException When seeking with SEEK_END or when seeking past the total size of the buffer stream
+     */
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        if ($whence == SEEK_SET) {
+            $byte = $offset;
+        } elseif ($whence == SEEK_CUR) {
+            $byte = $offset + $this->ftell();
+        } else {
+            throw new RuntimeException(__CLASS__ . ' supports only SEEK_SET and SEEK_CUR seek operations');
+        }
+
+        // You cannot skip ahead past where you've read from the remote stream
+        if ($byte > $this->body->getSize()) {
+            throw new RuntimeException(
+                "Cannot seek to byte {$byte} when the buffered stream only contains {$this->body->getSize()} bytes"
+            );
+        }
+
+        return $this->body->seek($byte);
+    }
+
+    public function rewind()
+    {
+        return $this->seek(0);
+    }
+
+    /**
+     * Does not support custom rewind functions
+     *
+     * @throws RuntimeException
+     */
+    public function setRewindFunction($callable)
+    {
+        throw new RuntimeException(__CLASS__ . ' does not support custom stream rewind functions');
+    }
+
+    public function read($length)
+    {
+        // Perform a regular read on any previously read data from the buffer
+        $data = $this->body->read($length);
+        $remaining = $length - strlen($data);
+
+        // More data was requested so read from the remote stream
+        if ($remaining) {
+            // If data was written to the buffer in a position that would have been filled from the remote stream,
+            // then we must skip bytes on the remote stream to emulate overwriting bytes from that position. This
+            // mimics the behavior of other PHP stream wrappers.
+            $remoteData = $this->remoteStream->read($remaining + $this->skipReadBytes);
+
+            if ($this->skipReadBytes) {
+                $len = strlen($remoteData);
+                $remoteData = substr($remoteData, $this->skipReadBytes);
+                $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
+            }
+
+            $data .= $remoteData;
+            $this->body->write($remoteData);
+        }
+
+        return $data;
+    }
+
+    public function write($string)
+    {
+        // When appending to the end of the currently read stream, you'll want to skip bytes from being read from
+        // the remote stream to emulate other stream wrappers. Basically replacing bytes of data of a fixed length.
+        $overflow = (strlen($string) + $this->ftell()) - $this->remoteStream->ftell();
+        if ($overflow > 0) {
+            $this->skipReadBytes += $overflow;
+        }
+
+        return $this->body->write($string);
+    }
+
+    /**
+     * {@inheritdoc}
+     * @link http://php.net/manual/en/function.fgets.php
+     */
+    public function readLine($maxLength = null)
+    {
+        $buffer = '';
+        $size = 0;
+        while (!$this->isConsumed()) {
+            $byte = $this->read(1);
+            $buffer .= $byte;
+            // Break when a new line is found or the max length - 1 is reached
+            if ($byte == PHP_EOL || ++$size == $maxLength - 1) {
+                break;
+            }
+        }
+
+        return $buffer;
+    }
+
+    public function isConsumed()
+    {
+        return $this->body->isConsumed() && $this->remoteStream->isConsumed();
+    }
+
+    /**
+     * Close both the remote stream and buffer stream
+     */
+    public function close()
+    {
+        return $this->remoteStream->close() && $this->body->close();
+    }
+
+    public function setStream($stream, $size = 0)
+    {
+        $this->remoteStream->setStream($stream, $size);
+    }
+
+    public function getContentType()
+    {
+        return $this->remoteStream->getContentType();
+    }
+
+    public function getContentEncoding()
+    {
+        return $this->remoteStream->getContentEncoding();
+    }
+
+    public function getMetaData($key = null)
+    {
+        return $this->remoteStream->getMetaData($key);
+    }
+
+    public function getStream()
+    {
+        return $this->remoteStream->getStream();
+    }
+
+    public function getWrapper()
+    {
+        return $this->remoteStream->getWrapper();
+    }
+
+    public function getWrapperData()
+    {
+        return $this->remoteStream->getWrapperData();
+    }
+
+    public function getStreamType()
+    {
+        return $this->remoteStream->getStreamType();
+    }
+
+    public function getUri()
+    {
+        return $this->remoteStream->getUri();
+    }
+
+    /**
+     * Always retrieve custom data from the remote stream
+     * {@inheritdoc}
+     */
+    public function getCustomData($key)
+    {
+        return $this->remoteStream->getCustomData($key);
+    }
+
+    /**
+     * Always set custom data on the remote stream
+     * {@inheritdoc}
+     */
+    public function setCustomData($key, $value)
+    {
+        $this->remoteStream->setCustomData($key, $value);
+
+        return $this;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Client.php b/core/vendor/guzzle/http/Guzzle/Http/Client.php
new file mode 100644
index 0000000..3d7298d
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Client.php
@@ -0,0 +1,524 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Common\Collection;
+use Guzzle\Common\AbstractHasDispatcher;
+use Guzzle\Common\Exception\ExceptionCollection;
+use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Common\Exception\RuntimeException;
+use Guzzle\Common\Version;
+use Guzzle\Parser\ParserRegistry;
+use Guzzle\Parser\UriTemplate\UriTemplateInterface;
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\RequestFactory;
+use Guzzle\Http\Message\RequestFactoryInterface;
+use Guzzle\Http\Curl\CurlMultiInterface;
+use Guzzle\Http\Curl\CurlMultiProxy;
+use Guzzle\Http\Curl\CurlHandle;
+use Guzzle\Http\Curl\CurlVersion;
+
+/**
+ * HTTP client
+ */
+class Client extends AbstractHasDispatcher implements ClientInterface
+{
+    /** @deprecated Use [request.options][params] */
+    const REQUEST_PARAMS = 'request.params';
+
+    const REQUEST_OPTIONS = 'request.options';
+    const CURL_OPTIONS = 'curl.options';
+    const SSL_CERT_AUTHORITY = 'ssl.certificate_authority';
+    const DISABLE_REDIRECTS = RedirectPlugin::DISABLE;
+    const DEFAULT_SELECT_TIMEOUT = 1.0;
+    const MAX_HANDLES = 3;
+
+    /** @var Collection Default HTTP headers to set on each request */
+    protected $defaultHeaders;
+
+    /** @var string The user agent string to set on each request */
+    protected $userAgent;
+
+    /** @var Collection Parameter object holding configuration data */
+    private $config;
+
+    /** @var Url Base URL of the client */
+    private $baseUrl;
+
+    /** @var CurlMultiInterface CurlMulti object used internally */
+    private $curlMulti;
+
+    /** @var UriTemplateInterface URI template owned by the client */
+    private $uriTemplate;
+
+    /** @var RequestFactoryInterface Request factory used by the client */
+    protected $requestFactory;
+
+    public static function getAllEvents()
+    {
+        return array(self::CREATE_REQUEST);
+    }
+
+    /**
+     * @param string           $baseUrl Base URL of the web service
+     * @param array|Collection $config  Configuration settings
+     *
+     * @throws RuntimeException if cURL is not installed
+     */
+    public function __construct($baseUrl = '', $config = null)
+    {
+        if (!extension_loaded('curl')) {
+            // @codeCoverageIgnoreStart
+            throw new RuntimeException('The PHP cURL extension must be installed to use Guzzle.');
+            // @codeCoverageIgnoreEnd
+        }
+        $this->setConfig($config ?: new Collection());
+        $this->initSsl();
+        $this->setBaseUrl($baseUrl);
+        $this->defaultHeaders = new Collection();
+        $this->setRequestFactory(RequestFactory::getInstance());
+        $this->userAgent = $this->getDefaultUserAgent();
+        if (!$this->config[self::DISABLE_REDIRECTS]) {
+            $this->addSubscriber(new RedirectPlugin());
+        }
+    }
+
+    final public function setConfig($config)
+    {
+        if ($config instanceof Collection) {
+            $this->config = $config;
+        } elseif (is_array($config)) {
+            $this->config = new Collection($config);
+        } else {
+            throw new InvalidArgumentException('Config must be an array or Collection');
+        }
+
+        return $this;
+    }
+
+    final public function getConfig($key = false)
+    {
+        return $key ? $this->config[$key] : $this->config;
+    }
+
+    /**
+     * Set a default request option on the client that will be used as a default for each request
+     *
+     * @param string $keyOrPath request.options key (e.g. allow_redirects) or path to a nested key (e.g. headers/foo)
+     * @param mixed  $value     Value to set
+     *
+     * @return $this
+     */
+    public function setDefaultOption($keyOrPath, $value)
+    {
+        $keyOrPath = self::REQUEST_OPTIONS . '/' . $keyOrPath;
+        $this->config->setPath($keyOrPath, $value);
+
+        return $this;
+    }
+
+    /**
+     * Retrieve a default request option from the client
+     *
+     * @param string $keyOrPath request.options key (e.g. allow_redirects) or path to a nested key (e.g. headers/foo)
+     *
+     * @return mixed|null
+     */
+    public function getDefaultOption($keyOrPath)
+    {
+        $keyOrPath = self::REQUEST_OPTIONS . '/' . $keyOrPath;
+
+        return $this->config->getPath($keyOrPath);
+    }
+
+    final public function setSslVerification($certificateAuthority = true, $verifyPeer = true, $verifyHost = 2)
+    {
+        $opts = $this->config[self::CURL_OPTIONS] ?: array();
+
+        if ($certificateAuthority === true) {
+            // use bundled CA bundle, set secure defaults
+            $opts[CURLOPT_CAINFO] = __DIR__ . '/Resources/cacert.pem';
+            $opts[CURLOPT_SSL_VERIFYPEER] = true;
+            $opts[CURLOPT_SSL_VERIFYHOST] = 2;
+        } elseif ($certificateAuthority === false) {
+            unset($opts[CURLOPT_CAINFO]);
+            $opts[CURLOPT_SSL_VERIFYPEER] = false;
+            $opts[CURLOPT_SSL_VERIFYHOST] = 0;
+        } elseif ($verifyPeer !== true && $verifyPeer !== false && $verifyPeer !== 1 && $verifyPeer !== 0) {
+            throw new InvalidArgumentException('verifyPeer must be 1, 0 or boolean');
+        } elseif ($verifyHost !== 0 && $verifyHost !== 1 && $verifyHost !== 2) {
+            throw new InvalidArgumentException('verifyHost must be 0, 1 or 2');
+        } else {
+            $opts[CURLOPT_SSL_VERIFYPEER] = $verifyPeer;
+            $opts[CURLOPT_SSL_VERIFYHOST] = $verifyHost;
+            if (is_file($certificateAuthority)) {
+                unset($opts[CURLOPT_CAPATH]);
+                $opts[CURLOPT_CAINFO] = $certificateAuthority;
+            } elseif (is_dir($certificateAuthority)) {
+                unset($opts[CURLOPT_CAINFO]);
+                $opts[CURLOPT_CAPATH] = $certificateAuthority;
+            } else {
+                throw new RuntimeException(
+                    'Invalid option passed to ' . self::SSL_CERT_AUTHORITY . ': ' . $certificateAuthority
+                );
+            }
+        }
+
+        $this->config->set(self::CURL_OPTIONS, $opts);
+
+        return $this;
+    }
+
+    public function createRequest($method = 'GET', $uri = null, $headers = null, $body = null, array $options = array())
+    {
+        if (!$uri) {
+            $url = $this->getBaseUrl();
+        } else {
+            if (!is_array($uri)) {
+                $templateVars = null;
+            } else {
+                list($uri, $templateVars) = $uri;
+            }
+            if (strpos($uri, '://')) {
+                // Use absolute URLs as-is
+                $url = $this->expandTemplate($uri, $templateVars);
+            } else {
+                $url = Url::factory($this->getBaseUrl())->combine($this->expandTemplate($uri, $templateVars));
+            }
+        }
+
+        // If default headers are provided, then merge them under any explicitly provided headers for the request
+        if (count($this->defaultHeaders)) {
+            if (!$headers) {
+                $headers = $this->defaultHeaders->toArray();
+            } elseif (is_array($headers)) {
+                $headers += $this->defaultHeaders->toArray();
+            } elseif ($headers instanceof Collection) {
+                $headers = $headers->toArray() + $this->defaultHeaders->toArray();
+            }
+        }
+
+        return $this->prepareRequest($this->requestFactory->create($method, (string) $url, $headers, $body), $options);
+    }
+
+    public function getBaseUrl($expand = true)
+    {
+        return $expand ? $this->expandTemplate($this->baseUrl) : $this->baseUrl;
+    }
+
+    public function setBaseUrl($url)
+    {
+        $this->baseUrl = $url;
+
+        return $this;
+    }
+
+    public function setUserAgent($userAgent, $includeDefault = false)
+    {
+        if ($includeDefault) {
+            $userAgent .= ' ' . $this->getDefaultUserAgent();
+        }
+        $this->userAgent = $userAgent;
+
+        return $this;
+    }
+
+    /**
+     * Get the default User-Agent string to use with Guzzle
+     *
+     * @return string
+     */
+    public function getDefaultUserAgent()
+    {
+        return 'Guzzle/' . Version::VERSION
+            . ' curl/' . CurlVersion::getInstance()->get('version')
+            . ' PHP/' . PHP_VERSION;
+    }
+
+    public function get($uri = null, $headers = null, $options = array())
+    {
+        // BC compat: $options can be a string, resource, etc to specify where the response body is downloaded
+        return is_array($options)
+            ? $this->createRequest('GET', $uri, $headers, null, $options)
+            : $this->createRequest('GET', $uri, $headers, $options);
+    }
+
+    public function head($uri = null, $headers = null, array $options = array())
+    {
+        return $this->createRequest('HEAD', $uri, $headers, null, $options);
+    }
+
+    public function delete($uri = null, $headers = null, $body = null, array $options = array())
+    {
+        return $this->createRequest('DELETE', $uri, $headers, $body, $options);
+    }
+
+    public function put($uri = null, $headers = null, $body = null, array $options = array())
+    {
+        return $this->createRequest('PUT', $uri, $headers, $body, $options);
+    }
+
+    public function patch($uri = null, $headers = null, $body = null, array $options = array())
+    {
+        return $this->createRequest('PATCH', $uri, $headers, $body, $options);
+    }
+
+    public function post($uri = null, $headers = null, $postBody = null, array $options = array())
+    {
+        return $this->createRequest('POST', $uri, $headers, $postBody, $options);
+    }
+
+    public function options($uri = null, array $options = array())
+    {
+        return $this->createRequest('OPTIONS', $uri, $options);
+    }
+
+    public function send($requests)
+    {
+        if (!($requests instanceof RequestInterface)) {
+            return $this->sendMultiple($requests);
+        }
+
+        try {
+            /** @var $requests RequestInterface  */
+            $this->getCurlMulti()->add($requests)->send();
+            return $requests->getResponse();
+        } catch (ExceptionCollection $e) {
+            throw $e->getFirst();
+        }
+    }
+
+    /**
+     * Set a curl multi object to be used internally by the client for transferring requests.
+     *
+     * @param CurlMultiInterface $curlMulti Multi object
+     *
+     * @return self
+     */
+    public function setCurlMulti(CurlMultiInterface $curlMulti)
+    {
+        $this->curlMulti = $curlMulti;
+
+        return $this;
+    }
+
+    /**
+     * @return CurlMultiInterface|CurlMultiProxy
+     */
+    public function getCurlMulti()
+    {
+        if (!$this->curlMulti) {
+            $this->curlMulti = new CurlMultiProxy(
+                self::MAX_HANDLES,
+                $this->getConfig('select_timeout') ?: self::DEFAULT_SELECT_TIMEOUT
+            );
+        }
+
+        return $this->curlMulti;
+    }
+
+    public function setRequestFactory(RequestFactoryInterface $factory)
+    {
+        $this->requestFactory = $factory;
+
+        return $this;
+    }
+
+    /**
+     * Set the URI template expander to use with the client
+     *
+     * @param UriTemplateInterface $uriTemplate URI template expander
+     *
+     * @return self
+     */
+    public function setUriTemplate(UriTemplateInterface $uriTemplate)
+    {
+        $this->uriTemplate = $uriTemplate;
+
+        return $this;
+    }
+
+    /**
+     * Expand a URI template while merging client config settings into the template variables
+     *
+     * @param string $template  Template to expand
+     * @param array  $variables Variables to inject
+     *
+     * @return string
+     */
+    protected function expandTemplate($template, array $variables = null)
+    {
+        $expansionVars = $this->getConfig()->toArray();
+        if ($variables) {
+            $expansionVars = $variables + $expansionVars;
+        }
+
+        return $this->getUriTemplate()->expand($template, $expansionVars);
+    }
+
+    /**
+     * Get the URI template expander used by the client
+     *
+     * @return UriTemplateInterface
+     */
+    protected function getUriTemplate()
+    {
+        if (!$this->uriTemplate) {
+            $this->uriTemplate = ParserRegistry::getInstance()->getParser('uri_template');
+        }
+
+        return $this->uriTemplate;
+    }
+
+    /**
+     * Send multiple requests in parallel
+     *
+     * @param array $requests Array of RequestInterface objects
+     *
+     * @return array Returns an array of Response objects
+     */
+    protected function sendMultiple(array $requests)
+    {
+        $curlMulti = $this->getCurlMulti();
+        foreach ($requests as $request) {
+            $curlMulti->add($request);
+        }
+        $curlMulti->send();
+
+        /** @var $request RequestInterface */
+        $result = array();
+        foreach ($requests as $request) {
+            $result[] = $request->getResponse();
+        }
+
+        return $result;
+    }
+
+    /**
+     * Prepare a request to be sent from the Client by adding client specific behaviors and properties to the request.
+     *
+     * @param RequestInterface $request Request to prepare for the client
+     * @param array            $options Options to apply to the request
+     *
+     * @return RequestInterface
+     */
+    protected function prepareRequest(RequestInterface $request, array $options = array())
+    {
+        $request->setClient($this)->setEventDispatcher(clone $this->getEventDispatcher());
+
+        if ($curl = $this->config[self::CURL_OPTIONS]) {
+            $request->getCurlOptions()->overwriteWith(CurlHandle::parseCurlConfig($curl));
+        }
+
+        if ($params = $this->config[self::REQUEST_PARAMS]) {
+            Version::warn('request.params is deprecated. Use request.options to add default request options.');
+            $request->getParams()->overwriteWith($params);
+        }
+
+        if ($this->userAgent && !$request->hasHeader('User-Agent')) {
+            $request->setHeader('User-Agent', $this->userAgent);
+        }
+
+        if ($defaults = $this->config[self::REQUEST_OPTIONS]) {
+            $this->requestFactory->applyOptions($request, $defaults, RequestFactoryInterface::OPTIONS_AS_DEFAULTS);
+        }
+
+        if ($options) {
+            $this->requestFactory->applyOptions($request, $options);
+        }
+
+        $this->dispatch('client.create_request', array('client' => $this, 'request' => $request));
+
+        return $request;
+    }
+
+    /**
+     * Initializes SSL settings
+     */
+    protected function initSsl()
+    {
+        $authority = $this->config[self::SSL_CERT_AUTHORITY];
+
+        if ($authority === 'system') {
+            return;
+        }
+
+        if ($authority === null) {
+            $authority = true;
+        }
+
+        if ($authority === true && substr(__FILE__, 0, 7) == 'phar://') {
+            $authority = self::extractPharCacert(__DIR__ . '/Resources/cacert.pem');
+        }
+
+        $this->setSslVerification($authority);
+    }
+
+    /**
+     * @deprecated
+     */
+    public function getDefaultHeaders()
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use the request.options array to retrieve default request options');
+        return $this->defaultHeaders;
+    }
+
+    /**
+     * @deprecated
+     */
+    public function setDefaultHeaders($headers)
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use the request.options array to specify default request options');
+        if ($headers instanceof Collection) {
+            $this->defaultHeaders = $headers;
+        } elseif (is_array($headers)) {
+            $this->defaultHeaders = new Collection($headers);
+        } else {
+            throw new InvalidArgumentException('Headers must be an array or Collection');
+        }
+
+        return $this;
+    }
+
+    /**
+     * @deprecated
+     */
+    public function preparePharCacert($md5Check = true)
+    {
+        return sys_get_temp_dir() . '/guzzle-cacert.pem';
+    }
+
+    /**
+     * Copies the phar cacert from a phar into the temp directory.
+     *
+     * @param string $pharCacertPath Path to the phar cacert. For example:
+     *                               'phar://aws.phar/Guzzle/Http/Resources/cacert.pem'
+     *
+     * @return string Returns the path to the extracted cacert file.
+     * @throws \RuntimeException Throws if the phar cacert cannot be found or
+     *                           the file cannot be copied to the temp dir.
+     */
+    public static function extractPharCacert($pharCacertPath)
+    {
+        // Copy the cacert.pem file from the phar if it is not in the temp
+        // folder.
+        $certFile = sys_get_temp_dir() . '/guzzle-cacert.pem';
+
+        if (!file_exists($pharCacertPath)) {
+            throw new \RuntimeException("Could not find $pharCacertPath");
+        }
+
+        if (!file_exists($certFile) ||
+            filesize($certFile) != filesize($pharCacertPath)
+        ) {
+            if (!copy($pharCacertPath, $certFile)) {
+                throw new \RuntimeException(
+                    "Could not copy {$pharCacertPath} to {$certFile}: "
+                    . var_export(error_get_last(), true)
+                );
+            }
+        }
+
+        return $certFile;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/ClientInterface.php b/core/vendor/guzzle/http/Guzzle/Http/ClientInterface.php
new file mode 100644
index 0000000..10e4de2
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/ClientInterface.php
@@ -0,0 +1,223 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Common\HasDispatcherInterface;
+use Guzzle\Common\Collection;
+use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Http\Message\EntityEnclosingRequestInterface;
+use Guzzle\Http\Message\RequestInterface;
+
+/**
+ * Client interface for send HTTP requests
+ */
+interface ClientInterface extends HasDispatcherInterface
+{
+    const CREATE_REQUEST = 'client.create_request';
+
+    /** @var string RFC 1123 HTTP-Date */
+    const HTTP_DATE = 'D, d M Y H:i:s \G\M\T';
+
+    /**
+     * Set the configuration object to use with the client
+     *
+     * @param array|Collection $config Parameters that define how the client behaves
+     *
+     * @return self
+     */
+    public function setConfig($config);
+
+    /**
+     * Get a configuration setting or all of the configuration settings. The Collection result of this method can be
+     * modified to change the configuration settings of a client.
+     *
+     * A client should honor the following special values:
+     *
+     * - request.options: Associative array of default RequestFactory options to apply to each request
+     * - request.params: Associative array of request parameters (data values) to apply to each request
+     * - curl.options: Associative array of cURL configuration settings to apply to each request
+     * - ssl.certificate_authority: Path a CAINFO, CAPATH, true to use strict defaults, or false to disable verification
+     * - redirect.disable: Set to true to disable redirects
+     *
+     * @param bool|string $key Configuration value to retrieve. Set to FALSE to retrieve all values of the client.
+     *                         The object return can be modified, and modifications will affect the client's config.
+     * @return mixed|Collection
+     * @see \Guzzle\Http\Message\RequestFactoryInterface::applyOptions for a full list of request.options options
+     */
+    public function getConfig($key = false);
+
+    /**
+     * Create and return a new {@see RequestInterface} configured for the client.
+     *
+     * Use an absolute path to override the base path of the client, or a relative path to append to the base path of
+     * the client. The URI can contain the query string as well. Use an array to provide a URI template and additional
+     * variables to use in the URI template expansion.
+     *
+     * @param string                                    $method  HTTP method. Defaults to GET
+     * @param string|array                              $uri     Resource URI.
+     * @param array|Collection                          $headers HTTP headers
+     * @param string|resource|array|EntityBodyInterface $body    Entity body of request (POST/PUT) or response (GET)
+     * @param array                                     $options Array of options to apply to the request
+     *
+     * @return RequestInterface
+     * @throws InvalidArgumentException if a URI array is passed that does not contain exactly two elements: the URI
+     *                                  followed by template variables
+     */
+    public function createRequest(
+        $method = RequestInterface::GET,
+        $uri = null,
+        $headers = null,
+        $body = null,
+        array $options = array()
+    );
+
+    /**
+     * Create a GET request for the client
+     *
+     * @param string|array     $uri     Resource URI
+     * @param array|Collection $headers HTTP headers
+     * @param array            $options Options to apply to the request. For BC compatibility, you can also pass a
+     *                                  string to tell Guzzle to download the body of the response to a particular
+     *                                  location. Use the 'body' option instead for forward compatibility.
+     * @return RequestInterface
+     * @see    Guzzle\Http\ClientInterface::createRequest()
+     */
+    public function get($uri = null, $headers = null, $options = array());
+
+    /**
+     * Create a HEAD request for the client
+     *
+     * @param string|array     $uri     Resource URI
+     * @param array|Collection $headers HTTP headers
+     * @param array            $options Options to apply to the request
+     *
+     * @return RequestInterface
+     * @see    Guzzle\Http\ClientInterface::createRequest()
+     */
+    public function head($uri = null, $headers = null, array $options = array());
+
+    /**
+     * Create a DELETE request for the client
+     *
+     * @param string|array                        $uri     Resource URI
+     * @param array|Collection                    $headers HTTP headers
+     * @param string|resource|EntityBodyInterface $body    Body to send in the request
+     * @param array                               $options Options to apply to the request
+     *
+     * @return EntityEnclosingRequestInterface
+     * @see    Guzzle\Http\ClientInterface::createRequest()
+     */
+    public function delete($uri = null, $headers = null, $body = null, array $options = array());
+
+    /**
+     * Create a PUT request for the client
+     *
+     * @param string|array                        $uri     Resource URI
+     * @param array|Collection                    $headers HTTP headers
+     * @param string|resource|EntityBodyInterface $body    Body to send in the request
+     * @param array                               $options Options to apply to the request
+     *
+     * @return EntityEnclosingRequestInterface
+     * @see    Guzzle\Http\ClientInterface::createRequest()
+     */
+    public function put($uri = null, $headers = null, $body = null, array $options = array());
+
+    /**
+     * Create a PATCH request for the client
+     *
+     * @param string|array                        $uri     Resource URI
+     * @param array|Collection                    $headers HTTP headers
+     * @param string|resource|EntityBodyInterface $body    Body to send in the request
+     * @param array                               $options Options to apply to the request
+     *
+     * @return EntityEnclosingRequestInterface
+     * @see    Guzzle\Http\ClientInterface::createRequest()
+     */
+    public function patch($uri = null, $headers = null, $body = null, array $options = array());
+
+    /**
+     * Create a POST request for the client
+     *
+     * @param string|array                                $uri      Resource URI
+     * @param array|Collection                            $headers  HTTP headers
+     * @param array|Collection|string|EntityBodyInterface $postBody POST body. Can be a string, EntityBody, or
+     *                                                    associative array of POST fields to send in the body of the
+     *                                                    request. Prefix a value in the array with the @ symbol to
+     *                                                    reference a file.
+     * @param array                                       $options Options to apply to the request
+     *
+     * @return EntityEnclosingRequestInterface
+     * @see    Guzzle\Http\ClientInterface::createRequest()
+     */
+    public function post($uri = null, $headers = null, $postBody = null, array $options = array());
+
+    /**
+     * Create an OPTIONS request for the client
+     *
+     * @param string|array $uri     Resource URI
+     * @param array        $options Options to apply to the request
+     *
+     * @return RequestInterface
+     * @see    Guzzle\Http\ClientInterface::createRequest()
+     */
+    public function options($uri = null, array $options = array());
+
+    /**
+     * Sends a single request or an array of requests in parallel
+     *
+     * @param array|RequestInterface $requests One or more RequestInterface objects to send
+     *
+     * @return \Guzzle\Http\Message\Response|array Returns a single Response or an array of Response objects
+     */
+    public function send($requests);
+
+    /**
+     * Get the client's base URL as either an expanded or raw URI template
+     *
+     * @param bool $expand Set to FALSE to get the raw base URL without URI template expansion
+     *
+     * @return string|null
+     */
+    public function getBaseUrl($expand = true);
+
+    /**
+     * Set the base URL of the client
+     *
+     * @param string $url The base service endpoint URL of the webservice
+     *
+     * @return self
+     */
+    public function setBaseUrl($url);
+
+    /**
+     * Set the User-Agent header to be used on all requests from the client
+     *
+     * @param string $userAgent      User agent string
+     * @param bool   $includeDefault Set to true to prepend the value to Guzzle's default user agent string
+     *
+     * @return self
+     */
+    public function setUserAgent($userAgent, $includeDefault = false);
+
+    /**
+     * Set SSL verification options.
+     *
+     * Setting $certificateAuthority to TRUE will result in the bundled cacert.pem being used to verify against the
+     * remote host.
+     *
+     * Alternate certificates to verify against can be specified with the $certificateAuthority option set to the full
+     * path to a certificate file, or the path to a directory containing certificates.
+     *
+     * Setting $certificateAuthority to FALSE will turn off peer verification, unset the bundled cacert.pem, and
+     * disable host verification. Please don't do this unless you really know what you're doing, and why you're doing
+     * it.
+     *
+     * @param string|bool $certificateAuthority bool, file path, or directory path
+     * @param bool        $verifyPeer           FALSE to stop from verifying the peer's certificate.
+     * @param int         $verifyHost           Set to 1 to check the existence of a common name in the SSL peer
+     *                                          certificate. 2 to check the existence of a common name and also verify
+     *                                          that it matches the hostname provided.
+     * @return self
+     */
+    public function setSslVerification($certificateAuthority = true, $verifyPeer = true, $verifyHost = 2);
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlHandle.php b/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlHandle.php
new file mode 100644
index 0000000..63c6d42
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlHandle.php
@@ -0,0 +1,464 @@
+<?php
+
+namespace Guzzle\Http\Curl;
+
+use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Common\Exception\RuntimeException;
+use Guzzle\Common\Collection;
+use Guzzle\Http\Message\EntityEnclosingRequest;
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Parser\ParserRegistry;
+use Guzzle\Http\Url;
+
+/**
+ * Immutable wrapper for a cURL handle
+ */
+class CurlHandle
+{
+    const BODY_AS_STRING = 'body_as_string';
+    const PROGRESS = 'progress';
+    const DEBUG = 'debug';
+
+    /** @var Collection Curl options */
+    protected $options;
+
+    /** @var resource Curl resource handle */
+    protected $handle;
+
+    /** @var int CURLE_* error */
+    protected $errorNo = CURLE_OK;
+
+    /**
+     * Factory method to create a new curl handle based on an HTTP request.
+     *
+     * There are some helpful options you can set to enable specific behavior:
+     * - debug:    Set to true to enable cURL debug functionality to track the actual headers sent over the wire.
+     * - progress: Set to true to enable progress function callbacks.
+     *
+     * @param RequestInterface $request Request
+     *
+     * @return CurlHandle
+     * @throws RuntimeException
+     */
+    public static function factory(RequestInterface $request)
+    {
+        $requestCurlOptions = $request->getCurlOptions();
+        $mediator = new RequestMediator($request, $requestCurlOptions->get('emit_io'));
+        $tempContentLength = null;
+        $method = $request->getMethod();
+        $bodyAsString = $requestCurlOptions->get(self::BODY_AS_STRING);
+
+        // Prepare url
+        $url = (string)$request->getUrl();
+        if(($pos = strpos($url, '#')) !== false ){
+            // strip fragment from url
+            $url = substr($url, 0, $pos);
+        }
+
+        // Array of default cURL options.
+        $curlOptions = array(
+            CURLOPT_URL            => $url,
+            CURLOPT_CONNECTTIMEOUT => 150,
+            CURLOPT_RETURNTRANSFER => false,
+            CURLOPT_HEADER         => false,
+            CURLOPT_PORT           => $request->getPort(),
+            CURLOPT_HTTPHEADER     => array(),
+            CURLOPT_WRITEFUNCTION  => array($mediator, 'writeResponseBody'),
+            CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader'),
+            CURLOPT_HTTP_VERSION   => $request->getProtocolVersion() === '1.0'
+                ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1,
+            // Verifies the authenticity of the peer's certificate
+            CURLOPT_SSL_VERIFYPEER => 1,
+            // Certificate must indicate that the server is the server to which you meant to connect
+            CURLOPT_SSL_VERIFYHOST => 2
+        );
+
+        if (defined('CURLOPT_PROTOCOLS')) {
+            // Allow only HTTP and HTTPS protocols
+            $curlOptions[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
+        }
+
+        // Add CURLOPT_ENCODING if Accept-Encoding header is provided
+        if ($acceptEncodingHeader = $request->getHeader('Accept-Encoding')) {
+            $curlOptions[CURLOPT_ENCODING] = (string) $acceptEncodingHeader;
+            // Let cURL set the Accept-Encoding header, prevents duplicate values
+            $request->removeHeader('Accept-Encoding');
+        }
+
+        // Enable curl debug information if the 'debug' param was set
+        if ($requestCurlOptions->get('debug')) {
+            $curlOptions[CURLOPT_STDERR] = fopen('php://temp', 'r+');
+            // @codeCoverageIgnoreStart
+            if (false === $curlOptions[CURLOPT_STDERR]) {
+                throw new RuntimeException('Unable to create a stream for CURLOPT_STDERR');
+            }
+            // @codeCoverageIgnoreEnd
+            $curlOptions[CURLOPT_VERBOSE] = true;
+        }
+
+        // Specify settings according to the HTTP method
+        if ($method == 'GET') {
+            $curlOptions[CURLOPT_HTTPGET] = true;
+        } elseif ($method == 'HEAD') {
+            $curlOptions[CURLOPT_NOBODY] = true;
+            // HEAD requests do not use a write function
+            unset($curlOptions[CURLOPT_WRITEFUNCTION]);
+        } elseif (!($request instanceof EntityEnclosingRequest)) {
+            $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
+        } else {
+
+            $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
+
+            // Handle sending raw bodies in a request
+            if ($request->getBody()) {
+                // You can send the body as a string using curl's CURLOPT_POSTFIELDS
+                if ($bodyAsString) {
+                    $curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getBody();
+                    // Allow curl to add the Content-Length for us to account for the times when
+                    // POST redirects are followed by GET requests
+                    if ($tempContentLength = $request->getHeader('Content-Length')) {
+                        $tempContentLength = (int) (string) $tempContentLength;
+                    }
+                    // Remove the curl generated Content-Type header if none was set manually
+                    if (!$request->hasHeader('Content-Type')) {
+                        $curlOptions[CURLOPT_HTTPHEADER][] = 'Content-Type:';
+                    }
+                } else {
+                    $curlOptions[CURLOPT_UPLOAD] = true;
+                    // Let cURL handle setting the Content-Length header
+                    if ($tempContentLength = $request->getHeader('Content-Length')) {
+                        $tempContentLength = (int) (string) $tempContentLength;
+                        $curlOptions[CURLOPT_INFILESIZE] = $tempContentLength;
+                    }
+                    // Add a callback for curl to read data to send with the request only if a body was specified
+                    $curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody');
+                    // Attempt to seek to the start of the stream
+                    $request->getBody()->seek(0);
+                }
+
+            } else {
+
+                // Special handling for POST specific fields and files
+                $postFields = false;
+                if (count($request->getPostFiles())) {
+                    $postFields = $request->getPostFields()->useUrlEncoding(false)->urlEncode();
+                    foreach ($request->getPostFiles() as $key => $data) {
+                        $prefixKeys = count($data) > 1;
+                        foreach ($data as $index => $file) {
+                            // Allow multiple files in the same key
+                            $fieldKey = $prefixKeys ? "{$key}[{$index}]" : $key;
+                            $postFields[$fieldKey] = $file->getCurlValue();
+                        }
+                    }
+                } elseif (count($request->getPostFields())) {
+                    $postFields = (string) $request->getPostFields()->useUrlEncoding(true);
+                }
+
+                if ($postFields !== false) {
+                    if ($method == 'POST') {
+                        unset($curlOptions[CURLOPT_CUSTOMREQUEST]);
+                        $curlOptions[CURLOPT_POST] = true;
+                    }
+                    $curlOptions[CURLOPT_POSTFIELDS] = $postFields;
+                    $request->removeHeader('Content-Length');
+                }
+            }
+
+            // If the Expect header is not present, prevent curl from adding it
+            if (!$request->hasHeader('Expect')) {
+                $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:';
+            }
+        }
+
+        // If a Content-Length header was specified but we want to allow curl to set one for us
+        if (null !== $tempContentLength) {
+            $request->removeHeader('Content-Length');
+        }
+
+        // Set custom cURL options
+        foreach ($requestCurlOptions->toArray() as $key => $value) {
+            if (is_numeric($key)) {
+                $curlOptions[$key] = $value;
+            }
+        }
+
+        // Do not set an Accept header by default
+        if (!isset($curlOptions[CURLOPT_ENCODING])) {
+            $curlOptions[CURLOPT_HTTPHEADER][] = 'Accept:';
+        }
+
+        // Add any custom headers to the request. Empty headers will cause curl to not send the header at all.
+        foreach ($request->getHeaderLines() as $line) {
+            $curlOptions[CURLOPT_HTTPHEADER][] = $line;
+        }
+
+        // Add the content-length header back if it was temporarily removed
+        if ($tempContentLength) {
+            $request->setHeader('Content-Length', $tempContentLength);
+        }
+
+        // Apply the options to a new cURL handle.
+        $handle = curl_init();
+
+        // Enable the progress function if the 'progress' param was set
+        if ($requestCurlOptions->get('progress')) {
+            // Wrap the function in a function that provides the curl handle to the mediator's progress function
+            // Using this rather than injecting the handle into the mediator prevents a circular reference
+            $curlOptions[CURLOPT_PROGRESSFUNCTION] = function () use ($mediator, $handle) {
+                $args = func_get_args();
+                $args[] = $handle;
+
+                // PHP 5.5 pushed the handle onto the start of the args
+                if (is_resource($args[0])) {
+                    array_shift($args);
+                }
+
+                call_user_func_array(array($mediator, 'progress'), $args);
+            };
+            $curlOptions[CURLOPT_NOPROGRESS] = false;
+        }
+
+        curl_setopt_array($handle, $curlOptions);
+
+        return new static($handle, $curlOptions);
+    }
+
+    /**
+     * Construct a new CurlHandle object that wraps a cURL handle
+     *
+     * @param resource         $handle  Configured cURL handle resource
+     * @param Collection|array $options Curl options to use with the handle
+     *
+     * @throws InvalidArgumentException
+     */
+    public function __construct($handle, $options)
+    {
+        if (!is_resource($handle)) {
+            throw new InvalidArgumentException('Invalid handle provided');
+        }
+        if (is_array($options)) {
+            $this->options = new Collection($options);
+        } elseif ($options instanceof Collection) {
+            $this->options = $options;
+        } else {
+            throw new InvalidArgumentException('Expected array or Collection');
+        }
+        $this->handle = $handle;
+    }
+
+    /**
+     * Destructor
+     */
+    public function __destruct()
+    {
+        $this->close();
+    }
+
+    /**
+     * Close the curl handle
+     */
+    public function close()
+    {
+        if (is_resource($this->handle)) {
+            curl_close($this->handle);
+        }
+        $this->handle = null;
+    }
+
+    /**
+     * Check if the handle is available and still OK
+     *
+     * @return bool
+     */
+    public function isAvailable()
+    {
+        return is_resource($this->handle);
+    }
+
+    /**
+     * Get the last error that occurred on the cURL handle
+     *
+     * @return string
+     */
+    public function getError()
+    {
+        return $this->isAvailable() ? curl_error($this->handle) : '';
+    }
+
+    /**
+     * Get the last error number that occurred on the cURL handle
+     *
+     * @return int
+     */
+    public function getErrorNo()
+    {
+        if ($this->errorNo) {
+            return $this->errorNo;
+        }
+
+        return $this->isAvailable() ? curl_errno($this->handle) : CURLE_OK;
+    }
+
+    /**
+     * Set the curl error number
+     *
+     * @param int $error Error number to set
+     *
+     * @return CurlHandle
+     */
+    public function setErrorNo($error)
+    {
+        $this->errorNo = $error;
+
+        return $this;
+    }
+
+    /**
+     * Get cURL curl_getinfo data
+     *
+     * @param int $option Option to retrieve. Pass null to retrieve all data as an array.
+     *
+     * @return array|mixed
+     */
+    public function getInfo($option = null)
+    {
+        if (!is_resource($this->handle)) {
+            return null;
+        }
+
+        if (null !== $option) {
+            return curl_getinfo($this->handle, $option) ?: null;
+        }
+
+        return curl_getinfo($this->handle) ?: array();
+    }
+
+    /**
+     * Get the stderr output
+     *
+     * @param bool $asResource Set to TRUE to get an fopen resource
+     *
+     * @return string|resource|null
+     */
+    public function getStderr($asResource = false)
+    {
+        $stderr = $this->getOptions()->get(CURLOPT_STDERR);
+        if (!$stderr) {
+            return null;
+        }
+
+        if ($asResource) {
+            return $stderr;
+        }
+
+        fseek($stderr, 0);
+        $e = stream_get_contents($stderr);
+        fseek($stderr, 0, SEEK_END);
+
+        return $e;
+    }
+
+    /**
+     * Get the URL that this handle is connecting to
+     *
+     * @return Url
+     */
+    public function getUrl()
+    {
+        return Url::factory($this->options->get(CURLOPT_URL));
+    }
+
+    /**
+     * Get the wrapped curl handle
+     *
+     * @return resource|null Returns the cURL handle or null if it was closed
+     */
+    public function getHandle()
+    {
+        return $this->isAvailable() ? $this->handle : null;
+    }
+
+    /**
+     * Get the cURL setopt options of the handle. Changing values in the return object will have no effect on the curl
+     * handle after it is created.
+     *
+     * @return Collection
+     */
+    public function getOptions()
+    {
+        return $this->options;
+    }
+
+    /**
+     * Update a request based on the log messages of the CurlHandle
+     *
+     * @param RequestInterface $request Request to update
+     */
+    public function updateRequestFromTransfer(RequestInterface $request)
+    {
+        if (!$request->getResponse()) {
+            return;
+        }
+
+        // Update the transfer stats of the response
+        $request->getResponse()->setInfo($this->getInfo());
+
+        if (!$log = $this->getStderr(true)) {
+            return;
+        }
+
+        // Parse the cURL stderr output for outgoing requests
+        $headers = '';
+        fseek($log, 0);
+        while (($line = fgets($log)) !== false) {
+            if ($line && $line[0] == '>') {
+                $headers = substr(trim($line), 2) . "\r\n";
+                while (($line = fgets($log)) !== false) {
+                    if ($line[0] == '*' || $line[0] == '<') {
+                        break;
+                    } else {
+                        $headers .= trim($line) . "\r\n";
+                    }
+                }
+            }
+        }
+
+        // Add request headers to the request exactly as they were sent
+        if ($headers) {
+            $parsed = ParserRegistry::getInstance()->getParser('message')->parseRequest($headers);
+            if (!empty($parsed['headers'])) {
+                $request->setHeaders(array());
+                foreach ($parsed['headers'] as $name => $value) {
+                    $request->setHeader($name, $value);
+                }
+            }
+            if (!empty($parsed['version'])) {
+                $request->setProtocolVersion($parsed['version']);
+            }
+        }
+    }
+
+    /**
+     * Parse the config and replace curl.* configurators into the constant based values so it can be used elsewhere
+     *
+     * @param array|Collection $config The configuration we want to parse
+     *
+     * @return array
+     */
+    public static function parseCurlConfig($config)
+    {
+        $curlOptions = array();
+        foreach ($config as $key => $value) {
+            if (is_string($key) && defined($key)) {
+                // Convert constants represented as string to constant int values
+                $key = constant($key);
+            }
+            if (is_string($value) && defined($value)) {
+                $value = constant($value);
+            }
+            $curlOptions[$key] = $value;
+        }
+
+        return $curlOptions;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlMulti.php b/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlMulti.php
new file mode 100644
index 0000000..9e4e637
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlMulti.php
@@ -0,0 +1,423 @@
+<?php
+
+namespace Guzzle\Http\Curl;
+
+use Guzzle\Common\AbstractHasDispatcher;
+use Guzzle\Common\Event;
+use Guzzle\Http\Exception\MultiTransferException;
+use Guzzle\Http\Exception\CurlException;
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\EntityEnclosingRequestInterface;
+use Guzzle\Http\Exception\RequestException;
+
+/**
+ * Send {@see RequestInterface} objects in parallel using curl_multi
+ */
+class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface
+{
+    /** @var resource cURL multi handle. */
+    protected $multiHandle;
+
+    /** @var array Attached {@see RequestInterface} objects. */
+    protected $requests;
+
+    /** @var \SplObjectStorage RequestInterface to CurlHandle hash */
+    protected $handles;
+
+    /** @var array Hash mapping curl handle resource IDs to request objects */
+    protected $resourceHash;
+
+    /** @var array Queued exceptions */
+    protected $exceptions = array();
+
+    /** @var array Requests that succeeded */
+    protected $successful = array();
+
+    /** @var array cURL multi error values and codes */
+    protected $multiErrors = array(
+        CURLM_BAD_HANDLE      => array('CURLM_BAD_HANDLE', 'The passed-in handle is not a valid CURLM handle.'),
+        CURLM_BAD_EASY_HANDLE => array('CURLM_BAD_EASY_HANDLE', "An easy handle was not good/valid. It could mean that it isn't an easy handle at all, or possibly that the handle already is in used by this or another multi handle."),
+        CURLM_OUT_OF_MEMORY   => array('CURLM_OUT_OF_MEMORY', 'You are doomed.'),
+        CURLM_INTERNAL_ERROR  => array('CURLM_INTERNAL_ERROR', 'This can only be returned if libcurl bugs. Please report it to us!')
+    );
+
+    /** @var float */
+    protected $selectTimeout;
+
+    public function __construct($selectTimeout = 1.0)
+    {
+        $this->selectTimeout = $selectTimeout;
+        $this->multiHandle = curl_multi_init();
+        // @codeCoverageIgnoreStart
+        if ($this->multiHandle === false) {
+            throw new CurlException('Unable to create multi handle');
+        }
+        // @codeCoverageIgnoreEnd
+        $this->reset();
+    }
+
+    public function __destruct()
+    {
+        if (is_resource($this->multiHandle)) {
+            curl_multi_close($this->multiHandle);
+        }
+    }
+
+    public function add(RequestInterface $request)
+    {
+        $this->requests[] = $request;
+        // If requests are currently transferring and this is async, then the
+        // request must be prepared now as the send() method is not called.
+        $this->beforeSend($request);
+        $this->dispatch(self::ADD_REQUEST, array('request' => $request));
+
+        return $this;
+    }
+
+    public function all()
+    {
+        return $this->requests;
+    }
+
+    public function remove(RequestInterface $request)
+    {
+        $this->removeHandle($request);
+        if (($index = array_search($request, $this->requests, true)) !== false) {
+            $request = $this->requests[$index];
+            unset($this->requests[$index]);
+            $this->requests = array_values($this->requests);
+            $this->dispatch(self::REMOVE_REQUEST, array('request' => $request));
+            return true;
+        }
+
+        return false;
+    }
+
+    public function reset($hard = false)
+    {
+        // Remove each request
+        if ($this->requests) {
+            foreach ($this->requests as $request) {
+                $this->remove($request);
+            }
+        }
+
+        $this->handles = new \SplObjectStorage();
+        $this->requests = $this->resourceHash = $this->exceptions = $this->successful = array();
+    }
+
+    public function send()
+    {
+        $this->perform();
+        $exceptions = $this->exceptions;
+        $successful = $this->successful;
+        $this->reset();
+
+        if ($exceptions) {
+            $this->throwMultiException($exceptions, $successful);
+        }
+    }
+
+    public function count()
+    {
+        return count($this->requests);
+    }
+
+    /**
+     * Build and throw a MultiTransferException
+     *
+     * @param array $exceptions Exceptions encountered
+     * @param array $successful Successful requests
+     * @throws MultiTransferException
+     */
+    protected function throwMultiException(array $exceptions, array $successful)
+    {
+        $multiException = new MultiTransferException('Errors during multi transfer');
+
+        while ($e = array_shift($exceptions)) {
+            $multiException->addFailedRequestWithException($e['request'], $e['exception']);
+        }
+
+        // Add successful requests
+        foreach ($successful as $request) {
+            if (!$multiException->containsRequest($request)) {
+                $multiException->addSuccessfulRequest($request);
+            }
+        }
+
+        throw $multiException;
+    }
+
+    /**
+     * Prepare for sending
+     *
+     * @param RequestInterface $request Request to prepare
+     * @throws \Exception on error preparing the request
+     */
+    protected function beforeSend(RequestInterface $request)
+    {
+        try {
+            $state = $request->setState(RequestInterface::STATE_TRANSFER);
+            if ($state == RequestInterface::STATE_TRANSFER) {
+                $this->addHandle($request);
+            } else {
+                // Requests might decide they don't need to be sent just before
+                // transfer (e.g. CachePlugin)
+                $this->remove($request);
+                if ($state == RequestInterface::STATE_COMPLETE) {
+                    $this->successful[] = $request;
+                }
+            }
+        } catch (\Exception $e) {
+            // Queue the exception to be thrown when sent
+            $this->removeErroredRequest($request, $e);
+        }
+    }
+
+    private function addHandle(RequestInterface $request)
+    {
+        $handle = $this->createCurlHandle($request)->getHandle();
+        $this->checkCurlResult(
+            curl_multi_add_handle($this->multiHandle, $handle)
+        );
+    }
+
+    /**
+     * Create a curl handle for a request
+     *
+     * @param RequestInterface $request Request
+     *
+     * @return CurlHandle
+     */
+    protected function createCurlHandle(RequestInterface $request)
+    {
+        $wrapper = CurlHandle::factory($request);
+        $this->handles[$request] = $wrapper;
+        $this->resourceHash[(int) $wrapper->getHandle()] = $request;
+
+        return $wrapper;
+    }
+
+    /**
+     * Get the data from the multi handle
+     */
+    protected function perform()
+    {
+        $event = new Event(array('curl_multi' => $this));
+
+        while ($this->requests) {
+            // Notify each request as polling
+            $blocking = $total = 0;
+            foreach ($this->requests as $request) {
+                ++$total;
+                $event['request'] = $request;
+                $request->getEventDispatcher()->dispatch(self::POLLING_REQUEST, $event);
+                // The blocking variable just has to be non-falsey to block the loop
+                if ($request->getParams()->hasKey(self::BLOCKING)) {
+                    ++$blocking;
+                }
+            }
+            if ($blocking == $total) {
+                // Sleep to prevent eating CPU because no requests are actually pending a select call
+                usleep(500);
+            } else {
+                $this->executeHandles();
+            }
+        }
+    }
+
+    /**
+     * Execute and select curl handles
+     */
+    private function executeHandles()
+    {
+        // The first curl_multi_select often times out no matter what, but is usually required for fast transfers
+        $selectTimeout = 0.001;
+        $active = false;
+        do {
+            while (($mrc = curl_multi_exec($this->multiHandle, $active)) == CURLM_CALL_MULTI_PERFORM);
+            $this->checkCurlResult($mrc);
+            $this->processMessages();
+            if ($active && curl_multi_select($this->multiHandle, $selectTimeout) === -1) {
+                // Perform a usleep if a select returns -1: https://bugs.php.net/bug.php?id=61141
+                usleep(150);
+            }
+            $selectTimeout = $this->selectTimeout;
+        } while ($active);
+    }
+
+    /**
+     * Process any received curl multi messages
+     */
+    private function processMessages()
+    {
+        while ($done = curl_multi_info_read($this->multiHandle)) {
+            $request = $this->resourceHash[(int) $done['handle']];
+            try {
+                $this->processResponse($request, $this->handles[$request], $done);
+                $this->successful[] = $request;
+            } catch (\Exception $e) {
+                $this->removeErroredRequest($request, $e);
+            }
+        }
+    }
+
+    /**
+     * Remove a request that encountered an exception
+     *
+     * @param RequestInterface $request Request to remove
+     * @param \Exception       $e       Exception encountered
+     */
+    protected function removeErroredRequest(RequestInterface $request, \Exception $e = null)
+    {
+        $this->exceptions[] = array('request' => $request, 'exception' => $e);
+        $this->remove($request);
+        $this->dispatch(self::MULTI_EXCEPTION, array('exception' => $e, 'all_exceptions' => $this->exceptions));
+    }
+
+    /**
+     * Check for errors and fix headers of a request based on a curl response
+     *
+     * @param RequestInterface $request Request to process
+     * @param CurlHandle       $handle  Curl handle object
+     * @param array            $curl    Array returned from curl_multi_info_read
+     *
+     * @throws CurlException on Curl error
+     */
+    protected function processResponse(RequestInterface $request, CurlHandle $handle, array $curl)
+    {
+        // Set the transfer stats on the response
+        $handle->updateRequestFromTransfer($request);
+        // Check if a cURL exception occurred, and if so, notify things
+        $curlException = $this->isCurlException($request, $handle, $curl);
+
+        // Always remove completed curl handles.  They can be added back again
+        // via events if needed (e.g. ExponentialBackoffPlugin)
+        $this->removeHandle($request);
+
+        if (!$curlException) {
+            if ($this->validateResponseWasSet($request)) {
+                $state = $request->setState(
+                    RequestInterface::STATE_COMPLETE,
+                    array('handle' => $handle)
+                );
+                // Only remove the request if it wasn't resent as a result of
+                // the state change
+                if ($state != RequestInterface::STATE_TRANSFER) {
+                    $this->remove($request);
+                }
+            }
+            return;
+        }
+
+        // Set the state of the request to an error
+        $state = $request->setState(RequestInterface::STATE_ERROR, array('exception' => $curlException));
+        // Allow things to ignore the error if possible
+        if ($state != RequestInterface::STATE_TRANSFER) {
+            $this->remove($request);
+        }
+
+        // The error was not handled, so fail
+        if ($state == RequestInterface::STATE_ERROR) {
+            /** @var CurlException $curlException */
+            throw $curlException;
+        }
+    }
+
+    /**
+     * Remove a curl handle from the curl multi object
+     *
+     * @param RequestInterface $request Request that owns the handle
+     */
+    protected function removeHandle(RequestInterface $request)
+    {
+        if (isset($this->handles[$request])) {
+            $handle = $this->handles[$request];
+            curl_multi_remove_handle($this->multiHandle, $handle->getHandle());
+            unset($this->handles[$request]);
+            unset($this->resourceHash[(int) $handle->getHandle()]);
+            $handle->close();
+        }
+    }
+
+    /**
+     * Check if a cURL transfer resulted in what should be an exception
+     *
+     * @param RequestInterface $request Request to check
+     * @param CurlHandle       $handle  Curl handle object
+     * @param array            $curl    Array returned from curl_multi_info_read
+     *
+     * @return CurlException|bool
+     */
+    private function isCurlException(RequestInterface $request, CurlHandle $handle, array $curl)
+    {
+        if (CURLM_OK == $curl['result'] || CURLM_CALL_MULTI_PERFORM == $curl['result']) {
+            return false;
+        }
+
+        $handle->setErrorNo($curl['result']);
+        $e = new CurlException(sprintf('[curl] %s: %s [url] %s',
+            $handle->getErrorNo(), $handle->getError(), $handle->getUrl()));
+        $e->setCurlHandle($handle)
+            ->setRequest($request)
+            ->setCurlInfo($handle->getInfo())
+            ->setError($handle->getError(), $handle->getErrorNo());
+
+        return $e;
+    }
+
+    /**
+     * Throw an exception for a cURL multi response if needed
+     *
+     * @param int $code Curl response code
+     * @throws CurlException
+     */
+    private function checkCurlResult($code)
+    {
+        if ($code != CURLM_OK && $code != CURLM_CALL_MULTI_PERFORM) {
+            throw new CurlException(isset($this->multiErrors[$code])
+                ? "cURL error: {$code} ({$this->multiErrors[$code][0]}): cURL message: {$this->multiErrors[$code][1]}"
+                : 'Unexpected cURL error: ' . $code
+            );
+        }
+    }
+
+    /**
+     * @link https://github.com/guzzle/guzzle/issues/710
+     */
+    private function validateResponseWasSet(RequestInterface $request)
+    {
+        if ($request->getResponse()) {
+            return true;
+        }
+
+        $body = $request instanceof EntityEnclosingRequestInterface
+            ? $request->getBody()
+            : null;
+
+        if (!$body) {
+            $rex = new RequestException(
+                'No response was received for a request with no body. This'
+                . ' could mean that you are saturating your network.'
+            );
+            $rex->setRequest($request);
+            $this->removeErroredRequest($request, $rex);
+        } elseif (!$body->isSeekable() || !$body->seek(0)) {
+            // Nothing we can do with this. Sorry!
+            $rex = new RequestException(
+                'The connection was unexpectedly closed. The request would'
+                . ' have been retried, but attempting to rewind the'
+                . ' request body failed.'
+            );
+            $rex->setRequest($request);
+            $this->removeErroredRequest($request, $rex);
+        } else {
+            $this->remove($request);
+            // Add the request back to the batch to retry automatically.
+            $this->requests[] = $request;
+            $this->addHandle($request);
+        }
+
+        return false;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlMultiInterface.php b/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlMultiInterface.php
new file mode 100644
index 0000000..0ead757
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlMultiInterface.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace Guzzle\Http\Curl;
+
+use Guzzle\Common\HasDispatcherInterface;
+use Guzzle\Common\Exception\ExceptionCollection;
+use Guzzle\Http\Message\RequestInterface;
+
+/**
+ * Interface for sending a pool of {@see RequestInterface} objects in parallel
+ */
+interface CurlMultiInterface extends \Countable, HasDispatcherInterface
+{
+    const POLLING_REQUEST = 'curl_multi.polling_request';
+    const ADD_REQUEST = 'curl_multi.add_request';
+    const REMOVE_REQUEST = 'curl_multi.remove_request';
+    const MULTI_EXCEPTION = 'curl_multi.exception';
+    const BLOCKING = 'curl_multi.blocking';
+
+    /**
+     * Add a request to the pool.
+     *
+     * @param RequestInterface $request Request to add
+     *
+     * @return CurlMultiInterface
+     */
+    public function add(RequestInterface $request);
+
+    /**
+     * Get an array of attached {@see RequestInterface} objects
+     *
+     * @return array
+     */
+    public function all();
+
+    /**
+     * Remove a request from the pool.
+     *
+     * @param RequestInterface $request Request to remove
+     *
+     * @return bool Returns true on success or false on failure
+     */
+    public function remove(RequestInterface $request);
+
+    /**
+     * Reset the state and remove any attached RequestInterface objects
+     *
+     * @param bool $hard Set to true to close and reopen any open multi handles
+     */
+    public function reset($hard = false);
+
+    /**
+     * Send a pool of {@see RequestInterface} requests.
+     *
+     * @throws ExceptionCollection if any requests threw exceptions during the transfer.
+     */
+    public function send();
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlMultiProxy.php b/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlMultiProxy.php
new file mode 100644
index 0000000..c5b80a7
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlMultiProxy.php
@@ -0,0 +1,150 @@
+<?php
+
+namespace Guzzle\Http\Curl;
+
+use Guzzle\Common\AbstractHasDispatcher;
+use Guzzle\Http\Message\RequestInterface;
+
+/**
+ * Proxies requests and connections to a pool of internal curl_multi handles. Each recursive call will add requests
+ * to the next available CurlMulti handle.
+ */
+class CurlMultiProxy extends AbstractHasDispatcher implements CurlMultiInterface
+{
+    protected $handles = array();
+    protected $groups = array();
+    protected $queued = array();
+    protected $maxHandles;
+    protected $selectTimeout;
+
+    /**
+     * @param int   $maxHandles The maximum number of idle CurlMulti handles to allow to remain open
+     * @param float $selectTimeout timeout for curl_multi_select
+     */
+    public function __construct($maxHandles = 3, $selectTimeout = 1.0)
+    {
+        $this->maxHandles = $maxHandles;
+        $this->selectTimeout = $selectTimeout;
+        // You can get some weird "Too many open files" errors when sending a large amount of requests in parallel.
+        // These two statements autoload classes before a system runs out of file descriptors so that you can get back
+        // valuable error messages if you run out.
+        class_exists('Guzzle\Http\Message\Response');
+        class_exists('Guzzle\Http\Exception\CurlException');
+    }
+
+    public function add(RequestInterface $request)
+    {
+        $this->queued[] = $request;
+
+        return $this;
+    }
+
+    public function all()
+    {
+        $requests = $this->queued;
+        foreach ($this->handles as $handle) {
+            $requests = array_merge($requests, $handle->all());
+        }
+
+        return $requests;
+    }
+
+    public function remove(RequestInterface $request)
+    {
+        foreach ($this->queued as $i => $r) {
+            if ($request === $r) {
+                unset($this->queued[$i]);
+                return true;
+            }
+        }
+
+        foreach ($this->handles as $handle) {
+            if ($handle->remove($request)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public function reset($hard = false)
+    {
+        $this->queued = array();
+        $this->groups = array();
+        foreach ($this->handles as $handle) {
+            $handle->reset();
+        }
+        if ($hard) {
+            $this->handles = array();
+        }
+
+        return $this;
+    }
+
+    public function send()
+    {
+        if ($this->queued) {
+            $group = $this->getAvailableHandle();
+            // Add this handle to a list of handles than is claimed
+            $this->groups[] = $group;
+            while ($request = array_shift($this->queued)) {
+                $group->add($request);
+            }
+            try {
+                $group->send();
+                array_pop($this->groups);
+                $this->cleanupHandles();
+            } catch (\Exception $e) {
+                // Remove the group and cleanup if an exception was encountered and no more requests in group
+                if (!$group->count()) {
+                    array_pop($this->groups);
+                    $this->cleanupHandles();
+                }
+                throw $e;
+            }
+        }
+    }
+
+    public function count()
+    {
+        return count($this->all());
+    }
+
+    /**
+     * Get an existing available CurlMulti handle or create a new one
+     *
+     * @return CurlMulti
+     */
+    protected function getAvailableHandle()
+    {
+        // Grab a handle that is not claimed
+        foreach ($this->handles as $h) {
+            if (!in_array($h, $this->groups, true)) {
+                return $h;
+            }
+        }
+
+        // All are claimed, so create one
+        $handle = new CurlMulti($this->selectTimeout);
+        $handle->setEventDispatcher($this->getEventDispatcher());
+        $this->handles[] = $handle;
+
+        return $handle;
+    }
+
+    /**
+     * Trims down unused CurlMulti handles to limit the number of open connections
+     */
+    protected function cleanupHandles()
+    {
+        if ($diff = max(0, count($this->handles) - $this->maxHandles)) {
+            for ($i = count($this->handles) - 1; $i > 0 && $diff > 0; $i--) {
+                if (!count($this->handles[$i])) {
+                    unset($this->handles[$i]);
+                    $diff--;
+                }
+            }
+            $this->handles = array_values($this->handles);
+        }
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlVersion.php b/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlVersion.php
new file mode 100644
index 0000000..c3f99dd
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Curl/CurlVersion.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace Guzzle\Http\Curl;
+
+/**
+ * Class used for querying curl_version data
+ */
+class CurlVersion
+{
+    /** @var array curl_version() information */
+    protected $version;
+
+    /** @var CurlVersion */
+    protected static $instance;
+
+    /** @var string Default user agent */
+    protected $userAgent;
+
+    /**
+     * @return CurlVersion
+     */
+    public static function getInstance()
+    {
+        if (!self::$instance) {
+            self::$instance = new self();
+        }
+
+        return self::$instance;
+    }
+
+    /**
+     * Get all of the curl_version() data
+     *
+     * @return array
+     */
+    public function getAll()
+    {
+        if (!$this->version) {
+            $this->version = curl_version();
+        }
+
+        return $this->version;
+    }
+
+    /**
+     * Get a specific type of curl information
+     *
+     * @param string $type Version information to retrieve. This value is one of:
+     *     - version_number:     cURL 24 bit version number
+     *     - version:            cURL version number, as a string
+     *     - ssl_version_number: OpenSSL 24 bit version number
+     *     - ssl_version:        OpenSSL version number, as a string
+     *     - libz_version:       zlib version number, as a string
+     *     - host:               Information about the host where cURL was built
+     *     - features:           A bitmask of the CURL_VERSION_XXX constants
+     *     - protocols:          An array of protocols names supported by cURL
+     *
+     * @return string|float|bool if the $type is found, and false if not found
+     */
+    public function get($type)
+    {
+        $version = $this->getAll();
+
+        return isset($version[$type]) ? $version[$type] : false;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Curl/RequestMediator.php b/core/vendor/guzzle/http/Guzzle/Http/Curl/RequestMediator.php
new file mode 100644
index 0000000..5d1a0cd
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Curl/RequestMediator.php
@@ -0,0 +1,147 @@
+<?php
+
+namespace Guzzle\Http\Curl;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\EntityBody;
+use Guzzle\Http\Message\Response;
+
+/**
+ * Mediator between curl handles and request objects
+ */
+class RequestMediator
+{
+    /** @var RequestInterface */
+    protected $request;
+
+    /** @var bool Whether or not to emit read/write events */
+    protected $emitIo;
+
+    /**
+     * @param RequestInterface $request Request to mediate
+     * @param bool             $emitIo  Set to true to dispatch events on input and output
+     */
+    public function __construct(RequestInterface $request, $emitIo = false)
+    {
+        $this->request = $request;
+        $this->emitIo = $emitIo;
+    }
+
+    /**
+     * Receive a response header from curl
+     *
+     * @param resource $curl   Curl handle
+     * @param string   $header Received header
+     *
+     * @return int
+     */
+    public function receiveResponseHeader($curl, $header)
+    {
+        static $normalize = array("\r", "\n");
+        $length = strlen($header);
+        $header = str_replace($normalize, '', $header);
+
+        if (strpos($header, 'HTTP/') === 0) {
+
+            $startLine = explode(' ', $header, 3);
+            $code = $startLine[1];
+            $status = isset($startLine[2]) ? $startLine[2] : '';
+
+            // Only download the body of the response to the specified response
+            // body when a successful response is received.
+            if ($code >= 200 && $code < 300) {
+                $body = $this->request->getResponseBody();
+            } else {
+                $body = EntityBody::factory();
+            }
+
+            $response = new Response($code, null, $body);
+            $response->setStatus($code, $status);
+            $this->request->startResponse($response);
+
+            $this->request->dispatch('request.receive.status_line', array(
+                'request'       => $this,
+                'line'          => $header,
+                'status_code'   => $code,
+                'reason_phrase' => $status
+            ));
+
+        } elseif ($pos = strpos($header, ':')) {
+            $this->request->getResponse()->addHeader(
+                trim(substr($header, 0, $pos)),
+                trim(substr($header, $pos + 1))
+            );
+        }
+
+        return $length;
+    }
+
+    /**
+     * Received a progress notification
+     *
+     * @param int        $downloadSize Total download size
+     * @param int        $downloaded   Amount of bytes downloaded
+     * @param int        $uploadSize   Total upload size
+     * @param int        $uploaded     Amount of bytes uploaded
+     * @param resource   $handle       CurlHandle object
+     */
+    public function progress($downloadSize, $downloaded, $uploadSize, $uploaded, $handle = null)
+    {
+        $this->request->dispatch('curl.callback.progress', array(
+            'request'       => $this->request,
+            'handle'        => $handle,
+            'download_size' => $downloadSize,
+            'downloaded'    => $downloaded,
+            'upload_size'   => $uploadSize,
+            'uploaded'      => $uploaded
+        ));
+    }
+
+    /**
+     * Write data to the response body of a request
+     *
+     * @param resource $curl  Curl handle
+     * @param string   $write Data that was received
+     *
+     * @return int
+     */
+    public function writeResponseBody($curl, $write)
+    {
+        if ($this->emitIo) {
+            $this->request->dispatch('curl.callback.write', array(
+                'request' => $this->request,
+                'write'   => $write
+            ));
+        }
+
+        if ($response = $this->request->getResponse()) {
+            return $response->getBody()->write($write);
+        } else {
+            // Unexpected data received before response headers - abort transfer
+            return 0;
+        }
+    }
+
+    /**
+     * Read data from the request body and send it to curl
+     *
+     * @param resource $ch     Curl handle
+     * @param resource $fd     File descriptor
+     * @param int      $length Amount of data to read
+     *
+     * @return string
+     */
+    public function readRequestBody($ch, $fd, $length)
+    {
+        if (!($body = $this->request->getBody())) {
+            return '';
+        }
+
+        $read = (string) $body->read($length);
+        if ($this->emitIo) {
+            $this->request->dispatch('curl.callback.read', array('request' => $this->request, 'read' => $read));
+        }
+
+        return $read;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/EntityBody.php b/core/vendor/guzzle/http/Guzzle/Http/EntityBody.php
new file mode 100644
index 0000000..b60d170
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/EntityBody.php
@@ -0,0 +1,201 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Common\Version;
+use Guzzle\Stream\Stream;
+use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Http\Mimetypes;
+
+/**
+ * Entity body used with an HTTP request or response
+ */
+class EntityBody extends Stream implements EntityBodyInterface
+{
+    /** @var bool Content-Encoding of the entity body if known */
+    protected $contentEncoding = false;
+
+    /** @var callable Method to invoke for rewinding a stream */
+    protected $rewindFunction;
+
+    /**
+     * Create a new EntityBody based on the input type
+     *
+     * @param resource|string|EntityBody $resource Entity body data
+     * @param int                        $size     Size of the data contained in the resource
+     *
+     * @return EntityBody
+     * @throws InvalidArgumentException if the $resource arg is not a resource or string
+     */
+    public static function factory($resource = '', $size = null)
+    {
+        if ($resource instanceof EntityBodyInterface) {
+            return $resource;
+        }
+
+        switch (gettype($resource)) {
+            case 'string':
+                return self::fromString($resource);
+            case 'resource':
+                return new static($resource, $size);
+            case 'object':
+                if (method_exists($resource, '__toString')) {
+                    return self::fromString((string) $resource);
+                }
+                break;
+            case 'array':
+                return self::fromString(http_build_query($resource));
+        }
+
+        throw new InvalidArgumentException('Invalid resource type');
+    }
+
+    public function setRewindFunction($callable)
+    {
+        if (!is_callable($callable)) {
+            throw new InvalidArgumentException('Must specify a callable');
+        }
+
+        $this->rewindFunction = $callable;
+
+        return $this;
+    }
+
+    public function rewind()
+    {
+        return $this->rewindFunction ? call_user_func($this->rewindFunction, $this) : parent::rewind();
+    }
+
+    /**
+     * Create a new EntityBody from a string
+     *
+     * @param string $string String of data
+     *
+     * @return EntityBody
+     */
+    public static function fromString($string)
+    {
+        $stream = fopen('php://temp', 'r+');
+        if ($string !== '') {
+            fwrite($stream, $string);
+            rewind($stream);
+        }
+
+        return new static($stream);
+    }
+
+    public function compress($filter = 'zlib.deflate')
+    {
+        $result = $this->handleCompression($filter);
+        $this->contentEncoding = $result ? $filter : false;
+
+        return $result;
+    }
+
+    public function uncompress($filter = 'zlib.inflate')
+    {
+        $offsetStart = 0;
+
+        // When inflating gzipped data, the first 10 bytes must be stripped
+        // if a gzip header is present
+        if ($filter == 'zlib.inflate') {
+            // @codeCoverageIgnoreStart
+            if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
+                return false;
+            }
+            // @codeCoverageIgnoreEnd
+            if (stream_get_contents($this->stream, 3, 0) === "\x1f\x8b\x08") {
+                $offsetStart = 10;
+            }
+        }
+
+        $this->contentEncoding = false;
+
+        return $this->handleCompression($filter, $offsetStart);
+    }
+
+    public function getContentLength()
+    {
+        return $this->getSize();
+    }
+
+    public function getContentType()
+    {
+        return $this->getUri() ? Mimetypes::getInstance()->fromFilename($this->getUri()) : null;
+    }
+
+    public function getContentMd5($rawOutput = false, $base64Encode = false)
+    {
+        if ($hash = self::getHash($this, 'md5', $rawOutput)) {
+            return $hash && $base64Encode ? base64_encode($hash) : $hash;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Calculate the MD5 hash of an entity body
+     *
+     * @param EntityBodyInterface $body         Entity body to calculate the hash for
+     * @param bool                $rawOutput    Whether or not to use raw output
+     * @param bool                $base64Encode Whether or not to base64 encode raw output (only if raw output is true)
+     *
+     * @return bool|string Returns an MD5 string on success or FALSE on failure
+     * @deprecated This will be deprecated soon
+     * @codeCoverageIgnore
+     */
+    public static function calculateMd5(EntityBodyInterface $body, $rawOutput = false, $base64Encode = false)
+    {
+        Version::warn(__CLASS__ . ' is deprecated. Use getContentMd5()');
+        return $body->getContentMd5($rawOutput, $base64Encode);
+    }
+
+    public function setStreamFilterContentEncoding($streamFilterContentEncoding)
+    {
+        $this->contentEncoding = $streamFilterContentEncoding;
+
+        return $this;
+    }
+
+    public function getContentEncoding()
+    {
+        return strtr($this->contentEncoding, array(
+            'zlib.deflate' => 'gzip',
+            'bzip2.compress' => 'compress'
+        )) ?: false;
+    }
+
+    protected function handleCompression($filter, $offsetStart = 0)
+    {
+        // @codeCoverageIgnoreStart
+        if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
+            return false;
+        }
+        // @codeCoverageIgnoreEnd
+
+        $handle = fopen('php://temp', 'r+');
+        $filter = @stream_filter_append($handle, $filter, STREAM_FILTER_WRITE);
+        if (!$filter) {
+            return false;
+        }
+
+        // Seek to the offset start if possible
+        $this->seek($offsetStart);
+        while ($data = fread($this->stream, 8096)) {
+            fwrite($handle, $data);
+        }
+
+        fclose($this->stream);
+        $this->stream = $handle;
+        stream_filter_remove($filter);
+        $stat = fstat($this->stream);
+        $this->size = $stat['size'];
+        $this->rebuildCache();
+        $this->seek(0);
+
+        // Remove any existing rewind function as the underlying stream has been replaced
+        $this->rewindFunction = null;
+
+        return true;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/EntityBodyInterface.php b/core/vendor/guzzle/http/Guzzle/Http/EntityBodyInterface.php
new file mode 100644
index 0000000..e640f57
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/EntityBodyInterface.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Stream\StreamInterface;
+
+/**
+ * Entity body used with an HTTP request or response
+ */
+interface EntityBodyInterface extends StreamInterface
+{
+    /**
+     * Specify a custom callback used to rewind a non-seekable stream. This can be useful entity enclosing requests
+     * that are redirected.
+     *
+     * @param mixed $callable Callable to invoke to rewind a non-seekable stream. The callback must accept an
+     *                        EntityBodyInterface object, perform the rewind if possible, and return a boolean
+     *                        representing whether or not the rewind was successful.
+     * @return self
+     */
+    public function setRewindFunction($callable);
+
+    /**
+     * If the stream is readable, compress the data in the stream using deflate compression. The uncompressed stream is
+     * then closed, and the compressed stream then becomes the wrapped stream.
+     *
+     * @param string $filter Compression filter
+     *
+     * @return bool Returns TRUE on success or FALSE on failure
+     */
+    public function compress($filter = 'zlib.deflate');
+
+    /**
+     * Decompress a deflated string. Once uncompressed, the uncompressed string is then used as the wrapped stream.
+     *
+     * @param string $filter De-compression filter
+     *
+     * @return bool Returns TRUE on success or FALSE on failure
+     */
+    public function uncompress($filter = 'zlib.inflate');
+
+    /**
+     * Get the Content-Length of the entity body if possible (alias of getSize)
+     *
+     * @return int|bool Returns the Content-Length or false on failure
+     */
+    public function getContentLength();
+
+    /**
+     * Guess the Content-Type of a local stream
+     *
+     * @return string|null
+     * @see http://www.php.net/manual/en/function.finfo-open.php
+     */
+    public function getContentType();
+
+    /**
+     * Get an MD5 checksum of the stream's contents
+     *
+     * @param bool $rawOutput    Whether or not to use raw output
+     * @param bool $base64Encode Whether or not to base64 encode raw output (only if raw output is true)
+     *
+     * @return bool|string Returns an MD5 string on success or FALSE on failure
+     */
+    public function getContentMd5($rawOutput = false, $base64Encode = false);
+
+    /**
+     * Get the Content-Encoding of the EntityBody
+     *
+     * @return bool|string
+     */
+    public function getContentEncoding();
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Exception/BadResponseException.php b/core/vendor/guzzle/http/Guzzle/Http/Exception/BadResponseException.php
new file mode 100644
index 0000000..0ed0b47
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Exception/BadResponseException.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+
+/**
+ * Http request exception thrown when a bad response is received
+ */
+class BadResponseException extends RequestException
+{
+    /** @var Response */
+    private $response;
+
+    /**
+     * Factory method to create a new response exception based on the response code.
+     *
+     * @param RequestInterface $request  Request
+     * @param Response         $response Response received
+     *
+     * @return BadResponseException
+     */
+    public static function factory(RequestInterface $request, Response $response)
+    {
+        if ($response->isClientError()) {
+            $label = 'Client error response';
+            $class = __NAMESPACE__ . '\\ClientErrorResponseException';
+        } elseif ($response->isServerError()) {
+            $label = 'Server error response';
+            $class = __NAMESPACE__ . '\\ServerErrorResponseException';
+        } else {
+            $label = 'Unsuccessful response';
+            $class = __CLASS__;
+        }
+
+        $message = $label . PHP_EOL . implode(PHP_EOL, array(
+            '[status code] ' . $response->getStatusCode(),
+            '[reason phrase] ' . $response->getReasonPhrase(),
+            '[url] ' . $request->getUrl(),
+        ));
+
+        $e = new $class($message);
+        $e->setResponse($response);
+        $e->setRequest($request);
+
+        return $e;
+    }
+
+    /**
+     * Set the response that caused the exception
+     *
+     * @param Response $response Response to set
+     */
+    public function setResponse(Response $response)
+    {
+        $this->response = $response;
+    }
+
+    /**
+     * Get the response that caused the exception
+     *
+     * @return Response
+     */
+    public function getResponse()
+    {
+        return $this->response;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Exception/ClientErrorResponseException.php b/core/vendor/guzzle/http/Guzzle/Http/Exception/ClientErrorResponseException.php
new file mode 100644
index 0000000..04d7ddc
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Exception/ClientErrorResponseException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+/**
+ * Exception when a client error is encountered (4xx codes)
+ */
+class ClientErrorResponseException extends BadResponseException {}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Exception/CouldNotRewindStreamException.php b/core/vendor/guzzle/http/Guzzle/Http/Exception/CouldNotRewindStreamException.php
new file mode 100644
index 0000000..63e4ec7
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Exception/CouldNotRewindStreamException.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+use Guzzle\Common\Exception\RuntimeException;
+
+class CouldNotRewindStreamException extends RuntimeException implements HttpException {}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Exception/CurlException.php b/core/vendor/guzzle/http/Guzzle/Http/Exception/CurlException.php
new file mode 100644
index 0000000..a6a744a
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Exception/CurlException.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+use Guzzle\Http\Curl\CurlHandle;
+
+/**
+ * cURL request exception
+ */
+class CurlException extends RequestException
+{
+    private $curlError;
+    private $curlErrorNo;
+    private $handle;
+    private $curlInfo = array();
+
+    /**
+     * Set the cURL error message
+     *
+     * @param string $error  Curl error
+     * @param int    $number Curl error number
+     *
+     * @return self
+     */
+    public function setError($error, $number)
+    {
+        $this->curlError = $error;
+        $this->curlErrorNo = $number;
+
+        return $this;
+    }
+
+    /**
+     * Set the associated curl handle
+     *
+     * @param CurlHandle $handle Curl handle
+     *
+     * @return self
+     */
+    public function setCurlHandle(CurlHandle $handle)
+    {
+        $this->handle = $handle;
+
+        return $this;
+    }
+
+    /**
+     * Get the associated cURL handle
+     *
+     * @return CurlHandle|null
+     */
+    public function getCurlHandle()
+    {
+        return $this->handle;
+    }
+
+    /**
+     * Get the associated cURL error message
+     *
+     * @return string|null
+     */
+    public function getError()
+    {
+        return $this->curlError;
+    }
+
+    /**
+     * Get the associated cURL error number
+     *
+     * @return int|null
+     */
+    public function getErrorNo()
+    {
+        return $this->curlErrorNo;
+    }
+
+    /**
+     * Returns curl information about the transfer
+     *
+     * @return array
+     */
+    public function getCurlInfo()
+    {
+        return $this->curlInfo;
+    }
+
+    /**
+     * Set curl transfer information
+     *
+     * @param array $info Array of curl transfer information
+     *
+     * @return self
+     * @link http://php.net/manual/en/function.curl-getinfo.php
+     */
+    public function setCurlInfo(array $info)
+    {
+        $this->curlInfo = $info;
+
+        return $this;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Exception/HttpException.php b/core/vendor/guzzle/http/Guzzle/Http/Exception/HttpException.php
new file mode 100644
index 0000000..ee87295
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Exception/HttpException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+use Guzzle\Common\Exception\GuzzleException;
+
+/**
+ * Http exception interface
+ */
+interface HttpException extends GuzzleException {}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Exception/MultiTransferException.php b/core/vendor/guzzle/http/Guzzle/Http/Exception/MultiTransferException.php
new file mode 100644
index 0000000..91e384d
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Exception/MultiTransferException.php
@@ -0,0 +1,145 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+use Guzzle\Common\Exception\ExceptionCollection;
+use Guzzle\Http\Message\RequestInterface;
+
+/**
+ * Exception encountered during a multi transfer
+ */
+class MultiTransferException extends ExceptionCollection
+{
+    protected $successfulRequests = array();
+    protected $failedRequests = array();
+    protected $exceptionForRequest = array();
+
+    /**
+     * Get all of the requests in the transfer
+     *
+     * @return array
+     */
+    public function getAllRequests()
+    {
+        return array_merge($this->successfulRequests, $this->failedRequests);
+    }
+
+    /**
+     * Add to the array of successful requests
+     *
+     * @param RequestInterface $request Successful request
+     *
+     * @return self
+     */
+    public function addSuccessfulRequest(RequestInterface $request)
+    {
+        $this->successfulRequests[] = $request;
+
+        return $this;
+    }
+
+    /**
+     * Add to the array of failed requests
+     *
+     * @param RequestInterface $request Failed request
+     *
+     * @return self
+     */
+    public function addFailedRequest(RequestInterface $request)
+    {
+        $this->failedRequests[] = $request;
+
+        return $this;
+    }
+
+    /**
+     * Add to the array of failed requests and associate with exceptions
+     *
+     * @param RequestInterface $request   Failed request
+     * @param \Exception       $exception Exception to add and associate with
+     *
+     * @return self
+     */
+    public function addFailedRequestWithException(RequestInterface $request, \Exception $exception)
+    {
+        $this->add($exception)
+             ->addFailedRequest($request)
+             ->exceptionForRequest[spl_object_hash($request)] = $exception;
+
+        return $this;
+    }
+
+    /**
+     * Get the Exception that caused the given $request to fail
+     *
+     * @param RequestInterface $request Failed command
+     *
+     * @return \Exception|null
+     */
+    public function getExceptionForFailedRequest(RequestInterface $request)
+    {
+        $oid = spl_object_hash($request);
+
+        return isset($this->exceptionForRequest[$oid]) ? $this->exceptionForRequest[$oid] : null;
+    }
+
+    /**
+     * Set all of the successful requests
+     *
+     * @param array Array of requests
+     *
+     * @return self
+     */
+    public function setSuccessfulRequests(array $requests)
+    {
+        $this->successfulRequests = $requests;
+
+        return $this;
+    }
+
+    /**
+     * Set all of the failed requests
+     *
+     * @param array Array of requests
+     *
+     * @return self
+     */
+    public function setFailedRequests(array $requests)
+    {
+        $this->failedRequests = $requests;
+
+        return $this;
+    }
+
+    /**
+     * Get an array of successful requests sent in the multi transfer
+     *
+     * @return array
+     */
+    public function getSuccessfulRequests()
+    {
+        return $this->successfulRequests;
+    }
+
+    /**
+     * Get an array of failed requests sent in the multi transfer
+     *
+     * @return array
+     */
+    public function getFailedRequests()
+    {
+        return $this->failedRequests;
+    }
+
+    /**
+     * Check if the exception object contains a request
+     *
+     * @param RequestInterface $request Request to check
+     *
+     * @return bool
+     */
+    public function containsRequest(RequestInterface $request)
+    {
+        return in_array($request, $this->failedRequests, true) || in_array($request, $this->successfulRequests, true);
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Exception/RequestException.php b/core/vendor/guzzle/http/Guzzle/Http/Exception/RequestException.php
new file mode 100644
index 0000000..274df2c
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Exception/RequestException.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+use Guzzle\Common\Exception\RuntimeException;
+use Guzzle\Http\Message\RequestInterface;
+
+/**
+ * Http request exception
+ */
+class RequestException extends RuntimeException implements HttpException
+{
+    /** @var RequestInterface */
+    protected $request;
+
+    /**
+     * Set the request that caused the exception
+     *
+     * @param RequestInterface $request Request to set
+     *
+     * @return RequestException
+     */
+    public function setRequest(RequestInterface $request)
+    {
+        $this->request = $request;
+
+        return $this;
+    }
+
+    /**
+     * Get the request that caused the exception
+     *
+     * @return RequestInterface
+     */
+    public function getRequest()
+    {
+        return $this->request;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Exception/ServerErrorResponseException.php b/core/vendor/guzzle/http/Guzzle/Http/Exception/ServerErrorResponseException.php
new file mode 100644
index 0000000..f0f7cfe
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Exception/ServerErrorResponseException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+/**
+ * Exception when a server error is encountered (5xx codes)
+ */
+class ServerErrorResponseException extends BadResponseException {}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Exception/TooManyRedirectsException.php b/core/vendor/guzzle/http/Guzzle/Http/Exception/TooManyRedirectsException.php
new file mode 100644
index 0000000..2aa43d1
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Exception/TooManyRedirectsException.php
@@ -0,0 +1,5 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+class TooManyRedirectsException extends BadResponseException {}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/IoEmittingEntityBody.php b/core/vendor/guzzle/http/Guzzle/Http/IoEmittingEntityBody.php
new file mode 100644
index 0000000..4cc17a8
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/IoEmittingEntityBody.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Common\Event;
+use Guzzle\Common\HasDispatcherInterface;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+/**
+ * EntityBody decorator that emits events for read and write methods
+ */
+class IoEmittingEntityBody extends AbstractEntityBodyDecorator implements HasDispatcherInterface
+{
+    /** @var EventDispatcherInterface */
+    protected $eventDispatcher;
+
+    public static function getAllEvents()
+    {
+        return array('body.read', 'body.write');
+    }
+
+    /**
+     * {@inheritdoc}
+     * @codeCoverageIgnore
+     */
+    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
+    {
+        $this->eventDispatcher = $eventDispatcher;
+
+        return $this;
+    }
+
+    public function getEventDispatcher()
+    {
+        if (!$this->eventDispatcher) {
+            $this->eventDispatcher = new EventDispatcher();
+        }
+
+        return $this->eventDispatcher;
+    }
+
+    public function dispatch($eventName, array $context = array())
+    {
+        return $this->getEventDispatcher()->dispatch($eventName, new Event($context));
+    }
+
+    /**
+     * {@inheritdoc}
+     * @codeCoverageIgnore
+     */
+    public function addSubscriber(EventSubscriberInterface $subscriber)
+    {
+        $this->getEventDispatcher()->addSubscriber($subscriber);
+
+        return $this;
+    }
+
+    public function read($length)
+    {
+        $event = array(
+            'body'   => $this,
+            'length' => $length,
+            'read'   => $this->body->read($length)
+        );
+        $this->dispatch('body.read', $event);
+
+        return $event['read'];
+    }
+
+    public function write($string)
+    {
+        $event = array(
+            'body'   => $this,
+            'write'  => $string,
+            'result' => $this->body->write($string)
+        );
+        $this->dispatch('body.write', $event);
+
+        return $event['result'];
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/AbstractMessage.php b/core/vendor/guzzle/http/Guzzle/Http/Message/AbstractMessage.php
new file mode 100644
index 0000000..0d066ff
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/AbstractMessage.php
@@ -0,0 +1,220 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Common\Version;
+use Guzzle\Common\Collection;
+use Guzzle\Http\Message\Header\HeaderCollection;
+use Guzzle\Http\Message\Header\HeaderFactory;
+use Guzzle\Http\Message\Header\HeaderFactoryInterface;
+use Guzzle\Http\Message\Header\HeaderInterface;
+
+/**
+ * Abstract HTTP request/response message
+ */
+abstract class AbstractMessage implements MessageInterface
+{
+    /** @var array HTTP header collection */
+    protected $headers;
+
+    /** @var HeaderFactoryInterface $headerFactory */
+    protected $headerFactory;
+
+    /** @var Collection Custom message parameters that are extendable by plugins */
+    protected $params;
+
+    /** @var string Message protocol */
+    protected $protocol = 'HTTP';
+
+    /** @var string HTTP protocol version of the message */
+    protected $protocolVersion = '1.1';
+
+    public function __construct()
+    {
+        $this->params = new Collection();
+        $this->headerFactory = new HeaderFactory();
+        $this->headers = new HeaderCollection();
+    }
+
+    /**
+     * Set the header factory to use to create headers
+     *
+     * @param HeaderFactoryInterface $factory
+     *
+     * @return self
+     */
+    public function setHeaderFactory(HeaderFactoryInterface $factory)
+    {
+        $this->headerFactory = $factory;
+
+        return $this;
+    }
+
+    public function getParams()
+    {
+        return $this->params;
+    }
+
+    public function addHeader($header, $value)
+    {
+        if (isset($this->headers[$header])) {
+            $this->headers[$header]->add($value);
+        } elseif ($value instanceof HeaderInterface) {
+            $this->headers[$header] = $value;
+        } else {
+            $this->headers[$header] = $this->headerFactory->createHeader($header, $value);
+        }
+
+        return $this;
+    }
+
+    public function addHeaders(array $headers)
+    {
+        foreach ($headers as $key => $value) {
+            $this->addHeader($key, $value);
+        }
+
+        return $this;
+    }
+
+    public function getHeader($header)
+    {
+        return $this->headers[$header];
+    }
+
+    public function getHeaders()
+    {
+        return $this->headers;
+    }
+
+    public function getHeaderLines()
+    {
+        $headers = array();
+        foreach ($this->headers as $value) {
+            $headers[] = $value->getName() . ': ' . $value;
+        }
+
+        return $headers;
+    }
+
+    public function setHeader($header, $value)
+    {
+        unset($this->headers[$header]);
+        $this->addHeader($header, $value);
+
+        return $this;
+    }
+
+    public function setHeaders(array $headers)
+    {
+        $this->headers->clear();
+        foreach ($headers as $key => $value) {
+            $this->addHeader($key, $value);
+        }
+
+        return $this;
+    }
+
+    public function hasHeader($header)
+    {
+        return isset($this->headers[$header]);
+    }
+
+    public function removeHeader($header)
+    {
+        unset($this->headers[$header]);
+
+        return $this;
+    }
+
+    /**
+     * @deprecated Use $message->getHeader()->parseParams()
+     * @codeCoverageIgnore
+     */
+    public function getTokenizedHeader($header, $token = ';')
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader()->parseParams()');
+        if ($this->hasHeader($header)) {
+            $data = new Collection();
+            foreach ($this->getHeader($header)->parseParams() as $values) {
+                foreach ($values as $key => $value) {
+                    if ($value === '') {
+                        $data->set($data->count(), $key);
+                    } else {
+                        $data->add($key, $value);
+                    }
+                }
+            }
+            return $data;
+        }
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function setTokenizedHeader($header, $data, $token = ';')
+    {
+        Version::warn(__METHOD__ . ' is deprecated.');
+        return $this;
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function getCacheControlDirective($directive)
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->getDirective()');
+        if (!($header = $this->getHeader('Cache-Control'))) {
+            return null;
+        }
+
+        return $header->getDirective($directive);
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function hasCacheControlDirective($directive)
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->hasDirective()');
+        if ($header = $this->getHeader('Cache-Control')) {
+            return $header->hasDirective($directive);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function addCacheControlDirective($directive, $value = true)
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->addDirective()');
+        if (!($header = $this->getHeader('Cache-Control'))) {
+            $this->addHeader('Cache-Control', '');
+            $header = $this->getHeader('Cache-Control');
+        }
+
+        $header->addDirective($directive, $value);
+
+        return $this;
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function removeCacheControlDirective($directive)
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->removeDirective()');
+        if ($header = $this->getHeader('Cache-Control')) {
+            $header->removeDirective($directive);
+        }
+
+        return $this;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/EntityEnclosingRequest.php b/core/vendor/guzzle/http/Guzzle/Http/Message/EntityEnclosingRequest.php
new file mode 100644
index 0000000..212850a
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/EntityEnclosingRequest.php
@@ -0,0 +1,247 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Http\EntityBody;
+use Guzzle\Http\EntityBodyInterface;
+use Guzzle\Http\QueryString;
+use Guzzle\Http\RedirectPlugin;
+use Guzzle\Http\Exception\RequestException;
+
+/**
+ * HTTP request that sends an entity-body in the request message (POST, PUT, PATCH, DELETE)
+ */
+class EntityEnclosingRequest extends Request implements EntityEnclosingRequestInterface
+{
+    /** @var int When the size of the body is greater than 1MB, then send Expect: 100-Continue */
+    protected $expectCutoff = 1048576;
+
+    /** @var EntityBodyInterface $body Body of the request */
+    protected $body;
+
+    /** @var QueryString POST fields to use in the EntityBody */
+    protected $postFields;
+
+    /** @var array POST files to send with the request */
+    protected $postFiles = array();
+
+    public function __construct($method, $url, $headers = array())
+    {
+        $this->postFields = new QueryString();
+        parent::__construct($method, $url, $headers);
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        // Only attempt to include the POST data if it's only fields
+        if (count($this->postFields) && empty($this->postFiles)) {
+            return parent::__toString() . (string) $this->postFields;
+        }
+
+        return parent::__toString() . $this->body;
+    }
+
+    public function setState($state, array $context = array())
+    {
+        parent::setState($state, $context);
+        if ($state == self::STATE_TRANSFER && !$this->body && !count($this->postFields) && !count($this->postFiles)) {
+            $this->setHeader('Content-Length', 0)->removeHeader('Transfer-Encoding');
+        }
+
+        return $this->state;
+    }
+
+    public function setBody($body, $contentType = null)
+    {
+        $this->body = EntityBody::factory($body);
+
+        // Auto detect the Content-Type from the path of the request if possible
+        if ($contentType === null && !$this->hasHeader('Content-Type')) {
+            $contentType = $this->body->getContentType();
+        }
+
+        if ($contentType) {
+            $this->setHeader('Content-Type', $contentType);
+        }
+
+        // Always add the Expect 100-Continue header if the body cannot be rewound. This helps with redirects.
+        if (!$this->body->isSeekable() && $this->expectCutoff !== false) {
+            $this->setHeader('Expect', '100-Continue');
+        }
+
+        // Set the Content-Length header if it can be determined
+        $size = $this->body->getContentLength();
+        if ($size !== null && $size !== false) {
+            $this->setHeader('Content-Length', $size);
+            if ($size > $this->expectCutoff) {
+                $this->setHeader('Expect', '100-Continue');
+            }
+        } elseif (!$this->hasHeader('Content-Length')) {
+            if ('1.1' == $this->protocolVersion) {
+                $this->setHeader('Transfer-Encoding', 'chunked');
+            } else {
+                throw new RequestException(
+                    'Cannot determine Content-Length and cannot use chunked Transfer-Encoding when using HTTP/1.0'
+                );
+            }
+        }
+
+        return $this;
+    }
+
+    public function getBody()
+    {
+        return $this->body;
+    }
+
+    /**
+     * Set the size that the entity body of the request must exceed before adding the Expect: 100-Continue header.
+     *
+     * @param int|bool $size Cutoff in bytes. Set to false to never send the expect header (even with non-seekable data)
+     *
+     * @return self
+     */
+    public function setExpectHeaderCutoff($size)
+    {
+        $this->expectCutoff = $size;
+        if ($size === false || !$this->body) {
+            $this->removeHeader('Expect');
+        } elseif ($this->body && $this->body->getSize() && $this->body->getSize() > $size) {
+            $this->setHeader('Expect', '100-Continue');
+        }
+
+        return $this;
+    }
+
+    public function configureRedirects($strict = false, $maxRedirects = 5)
+    {
+        $this->getParams()->set(RedirectPlugin::STRICT_REDIRECTS, $strict);
+        if ($maxRedirects == 0) {
+            $this->getParams()->set(RedirectPlugin::DISABLE, true);
+        } else {
+            $this->getParams()->set(RedirectPlugin::MAX_REDIRECTS, $maxRedirects);
+        }
+
+        return $this;
+    }
+
+    public function getPostField($field)
+    {
+        return $this->postFields->get($field);
+    }
+
+    public function getPostFields()
+    {
+        return $this->postFields;
+    }
+
+    public function setPostField($key, $value)
+    {
+        $this->postFields->set($key, $value);
+        $this->processPostFields();
+
+        return $this;
+    }
+
+    public function addPostFields($fields)
+    {
+        $this->postFields->merge($fields);
+        $this->processPostFields();
+
+        return $this;
+    }
+
+    public function removePostField($field)
+    {
+        $this->postFields->remove($field);
+        $this->processPostFields();
+
+        return $this;
+    }
+
+    public function getPostFiles()
+    {
+        return $this->postFiles;
+    }
+
+    public function getPostFile($fieldName)
+    {
+        return isset($this->postFiles[$fieldName]) ? $this->postFiles[$fieldName] : null;
+    }
+
+    public function removePostFile($fieldName)
+    {
+        unset($this->postFiles[$fieldName]);
+        $this->processPostFields();
+
+        return $this;
+    }
+
+    public function addPostFile($field, $filename = null, $contentType = null, $postname = null)
+    {
+        $data = null;
+
+        if ($field instanceof PostFileInterface) {
+            $data = $field;
+        } elseif (is_array($filename)) {
+            // Allow multiple values to be set in a single key
+            foreach ($filename as $file) {
+                $this->addPostFile($field, $file, $contentType);
+            }
+            return $this;
+        } elseif (!is_string($filename)) {
+            throw new RequestException('The path to a file must be a string');
+        } elseif (!empty($filename)) {
+            // Adding an empty file will cause cURL to error out
+            $data = new PostFile($field, $filename, $contentType, $postname);
+        }
+
+        if ($data) {
+            if (!isset($this->postFiles[$data->getFieldName()])) {
+                $this->postFiles[$data->getFieldName()] = array($data);
+            } else {
+                $this->postFiles[$data->getFieldName()][] = $data;
+            }
+            $this->processPostFields();
+        }
+
+        return $this;
+    }
+
+    public function addPostFiles(array $files)
+    {
+        foreach ($files as $key => $file) {
+            if ($file instanceof PostFileInterface) {
+                $this->addPostFile($file, null, null, false);
+            } elseif (is_string($file)) {
+                // Convert non-associative array keys into 'file'
+                if (is_numeric($key)) {
+                    $key = 'file';
+                }
+                $this->addPostFile($key, $file, null, false);
+            } else {
+                throw new RequestException('File must be a string or instance of PostFileInterface');
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Determine what type of request should be sent based on post fields
+     */
+    protected function processPostFields()
+    {
+        if (!$this->postFiles) {
+            $this->removeHeader('Expect')->setHeader('Content-Type', self::URL_ENCODED);
+        } else {
+            $this->setHeader('Content-Type', self::MULTIPART);
+            if ($this->expectCutoff !== false) {
+                $this->setHeader('Expect', '100-Continue');
+            }
+        }
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/EntityEnclosingRequestInterface.php b/core/vendor/guzzle/http/Guzzle/Http/Message/EntityEnclosingRequestInterface.php
new file mode 100644
index 0000000..49ad459
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/EntityEnclosingRequestInterface.php
@@ -0,0 +1,137 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Http\Exception\RequestException;
+use Guzzle\Http\EntityBodyInterface;
+use Guzzle\Http\QueryString;
+
+/**
+ * HTTP request that sends an entity-body in the request message (POST, PUT)
+ */
+interface EntityEnclosingRequestInterface extends RequestInterface
+{
+    const URL_ENCODED = 'application/x-www-form-urlencoded; charset=utf-8';
+    const MULTIPART = 'multipart/form-data';
+
+    /**
+     * Set the body of the request
+     *
+     * @param string|resource|EntityBodyInterface $body        Body to use in the entity body of the request
+     * @param string                              $contentType Content-Type to set. Leave null to use an existing
+     *                                                         Content-Type or to guess the Content-Type
+     * @return self
+     * @throws RequestException if the protocol is < 1.1 and Content-Length can not be determined
+     */
+    public function setBody($body, $contentType = null);
+
+    /**
+     * Get the body of the request if set
+     *
+     * @return EntityBodyInterface|null
+     */
+    public function getBody();
+
+    /**
+     * Get a POST field from the request
+     *
+     * @param string $field Field to retrieve
+     *
+     * @return mixed|null
+     */
+    public function getPostField($field);
+
+    /**
+     * Get the post fields that will be used in the request
+     *
+     * @return QueryString
+     */
+    public function getPostFields();
+
+    /**
+     * Set a POST field value
+     *
+     * @param string $key   Key to set
+     * @param string $value Value to set
+     *
+     * @return self
+     */
+    public function setPostField($key, $value);
+
+    /**
+     * Add POST fields to use in the request
+     *
+     * @param QueryString|array $fields POST fields
+     *
+     * @return self
+     */
+    public function addPostFields($fields);
+
+    /**
+     * Remove a POST field or file by name
+     *
+     * @param string $field Name of the POST field or file to remove
+     *
+     * @return self
+     */
+    public function removePostField($field);
+
+    /**
+     * Returns an associative array of POST field names to PostFileInterface objects
+     *
+     * @return array
+     */
+    public function getPostFiles();
+
+    /**
+     * Get a POST file from the request
+     *
+     * @param string $fieldName POST fields to retrieve
+     *
+     * @return array|null Returns an array wrapping an array of PostFileInterface objects
+     */
+    public function getPostFile($fieldName);
+
+    /**
+     * Remove a POST file from the request
+     *
+     * @param string $fieldName POST file field name to remove
+     *
+     * @return self
+     */
+    public function removePostFile($fieldName);
+
+    /**
+     * Add a POST file to the upload
+     *
+     * @param string $field       POST field to use (e.g. file). Used to reference content from the server.
+     * @param string $filename    Full path to the file. Do not include the @ symbol.
+     * @param string $contentType Optional Content-Type to add to the Content-Disposition.
+     *                            Default behavior is to guess. Set to false to not specify.
+     * @param string $postname    The name of the file, when posted. (e.g. rename the file)
+     * @return self
+     */
+    public function addPostFile($field, $filename = null, $contentType = null, $postname = null);
+
+    /**
+     * Add POST files to use in the upload
+     *
+     * @param array $files An array of POST fields => filenames where filename can be a string or PostFileInterface
+     *
+     * @return self
+     */
+    public function addPostFiles(array $files);
+
+    /**
+     * Configure how redirects are handled for the request
+     *
+     * @param bool $strict       Set to true to follow strict RFC compliance when redirecting POST requests. Most
+     *                           browsers with follow a 301-302 redirect for a POST request with a GET request. This is
+     *                           the default behavior of Guzzle. Enable strict redirects to redirect these responses
+     *                           with a POST rather than a GET request.
+     * @param int  $maxRedirects Specify the maximum number of allowed redirects. Set to 0 to disable redirects.
+     *
+     * @return self
+     */
+    public function configureRedirects($strict = false, $maxRedirects = 5);
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/Header.php b/core/vendor/guzzle/http/Guzzle/Http/Message/Header.php
new file mode 100644
index 0000000..50597b2
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/Header.php
@@ -0,0 +1,182 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Common\Version;
+use Guzzle\Http\Message\Header\HeaderInterface;
+
+/**
+ * Represents a header and all of the values stored by that header
+ */
+class Header implements HeaderInterface
+{
+    protected $values = array();
+    protected $header;
+    protected $glue;
+
+    /**
+     * @param string       $header Name of the header
+     * @param array|string $values Values of the header as an array or a scalar
+     * @param string       $glue   Glue used to combine multiple values into a string
+     */
+    public function __construct($header, $values = array(), $glue = ',')
+    {
+        $this->header = trim($header);
+        $this->glue = $glue;
+
+        foreach ((array) $values as $value) {
+            foreach ((array) $value as $v) {
+                $this->values[] = $v;
+            }
+        }
+    }
+
+    public function __toString()
+    {
+        return implode($this->glue . ' ', $this->toArray());
+    }
+
+    public function add($value)
+    {
+        $this->values[] = $value;
+
+        return $this;
+    }
+
+    public function getName()
+    {
+        return $this->header;
+    }
+
+    public function setName($name)
+    {
+        $this->header = $name;
+
+        return $this;
+    }
+
+    public function setGlue($glue)
+    {
+        $this->glue = $glue;
+
+        return $this;
+    }
+
+    public function getGlue()
+    {
+        return $this->glue;
+    }
+
+    /**
+     * Normalize the header to be a single header with an array of values.
+     *
+     * If any values of the header contains the glue string value (e.g. ","), then the value will be exploded into
+     * multiple entries in the header.
+     *
+     * @return self
+     */
+    public function normalize()
+    {
+        $values = $this->toArray();
+
+        for ($i = 0, $total = count($values); $i < $total; $i++) {
+            if (strpos($values[$i], $this->glue) !== false) {
+                // Explode on glue when the glue is not inside of a comma
+                foreach (preg_split('/' . preg_quote($this->glue) . '(?=([^"]*"[^"]*")*[^"]*$)/', $values[$i]) as $v) {
+                    $values[] = trim($v);
+                }
+                unset($values[$i]);
+            }
+        }
+
+        $this->values = array_values($values);
+
+        return $this;
+    }
+
+    public function hasValue($searchValue)
+    {
+        return in_array($searchValue, $this->toArray());
+    }
+
+    public function removeValue($searchValue)
+    {
+        $this->values = array_values(array_filter($this->values, function ($value) use ($searchValue) {
+            return $value != $searchValue;
+        }));
+
+        return $this;
+    }
+
+    public function toArray()
+    {
+        return $this->values;
+    }
+
+    public function count()
+    {
+        return count($this->toArray());
+    }
+
+    public function getIterator()
+    {
+        return new \ArrayIterator($this->toArray());
+    }
+
+    public function parseParams()
+    {
+        $params = $matches = array();
+        $callback = array($this, 'trimHeader');
+
+        // Normalize the header into a single array and iterate over all values
+        foreach ($this->normalize()->toArray() as $val) {
+            $part = array();
+            foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
+                if (!preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {
+                    continue;
+                }
+                $pieces = array_map($callback, $matches[0]);
+                $part[$pieces[0]] = isset($pieces[1]) ? $pieces[1] : '';
+            }
+            if ($part) {
+                $params[] = $part;
+            }
+        }
+
+        return $params;
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function hasExactHeader($header)
+    {
+        Version::warn(__METHOD__ . ' is deprecated');
+        return $this->header == $header;
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function raw()
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use toArray()');
+        return $this->toArray();
+    }
+
+    /**
+     * Trim a header by removing excess spaces and wrapping quotes
+     *
+     * @param $str
+     *
+     * @return string
+     */
+    protected function trimHeader($str)
+    {
+        static $trimmed = "\"'  \n\t";
+
+        return trim($str, $trimmed);
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/Header/CacheControl.php b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/CacheControl.php
new file mode 100644
index 0000000..77789e5
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/CacheControl.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace Guzzle\Http\Message\Header;
+
+use Guzzle\Http\Message\Header;
+
+/**
+ * Provides helpful functionality for Cache-Control headers
+ */
+class CacheControl extends Header
+{
+    /** @var array */
+    protected $directives;
+
+    public function add($value)
+    {
+        parent::add($value);
+        $this->directives = null;
+    }
+
+    public function removeValue($searchValue)
+    {
+        parent::removeValue($searchValue);
+        $this->directives = null;
+    }
+
+    /**
+     * Check if a specific cache control directive exists
+     *
+     * @param string $param Directive to retrieve
+     *
+     * @return bool
+     */
+    public function hasDirective($param)
+    {
+        $directives = $this->getDirectives();
+
+        return isset($directives[$param]);
+    }
+
+    /**
+     * Get a specific cache control directive
+     *
+     * @param string $param Directive to retrieve
+     *
+     * @return string|bool|null
+     */
+    public function getDirective($param)
+    {
+        $directives = $this->getDirectives();
+
+        return isset($directives[$param]) ? $directives[$param] : null;
+    }
+
+    /**
+     * Add a cache control directive
+     *
+     * @param string $param Directive to add
+     * @param string $value Value to set
+     *
+     * @return self
+     */
+    public function addDirective($param, $value)
+    {
+        $directives = $this->getDirectives();
+        $directives[$param] = $value;
+        $this->updateFromDirectives($directives);
+
+        return $this;
+    }
+
+    /**
+     * Remove a cache control directive by name
+     *
+     * @param string $param Directive to remove
+     *
+     * @return self
+     */
+    public function removeDirective($param)
+    {
+        $directives = $this->getDirectives();
+        unset($directives[$param]);
+        $this->updateFromDirectives($directives);
+
+        return $this;
+    }
+
+    /**
+     * Get an associative array of cache control directives
+     *
+     * @return array
+     */
+    public function getDirectives()
+    {
+        if ($this->directives === null) {
+            $this->directives = array();
+            foreach ($this->parseParams() as $collection) {
+                foreach ($collection as $key => $value) {
+                    $this->directives[$key] = $value === '' ? true : $value;
+                }
+            }
+        }
+
+        return $this->directives;
+    }
+
+    /**
+     * Updates the header value based on the parsed directives
+     *
+     * @param array $directives Array of cache control directives
+     */
+    protected function updateFromDirectives(array $directives)
+    {
+        $this->directives = $directives;
+        $this->values = array();
+
+        foreach ($directives as $key => $value) {
+            $this->values[] = $value === true ? $key : "{$key}={$value}";
+        }
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderCollection.php b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderCollection.php
new file mode 100644
index 0000000..8c7f6ae
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderCollection.php
@@ -0,0 +1,108 @@
+<?php
+
+namespace Guzzle\Http\Message\Header;
+
+use Guzzle\Common\ToArrayInterface;
+
+/**
+ * Provides a case-insensitive collection of headers
+ */
+class HeaderCollection implements \IteratorAggregate, \Countable, \ArrayAccess, ToArrayInterface
+{
+    /** @var array */
+    protected $headers;
+
+    public function __construct($headers = array())
+    {
+        $this->headers = $headers;
+    }
+
+    public function __clone()
+    {
+        foreach ($this->headers as &$header) {
+            $header = clone $header;
+        }
+    }
+
+    /**
+     * Clears the header collection
+     */
+    public function clear()
+    {
+        $this->headers = array();
+    }
+
+    /**
+     * Set a header on the collection
+     *
+     * @param HeaderInterface $header Header to add
+     *
+     * @return self
+     */
+    public function add(HeaderInterface $header)
+    {
+        $this->headers[strtolower($header->getName())] = $header;
+
+        return $this;
+    }
+
+    /**
+     * Get an array of header objects
+     *
+     * @return array
+     */
+    public function getAll()
+    {
+        return $this->headers;
+    }
+
+    /**
+     * Alias of offsetGet
+     */
+    public function get($key)
+    {
+        return $this->offsetGet($key);
+    }
+
+    public function count()
+    {
+        return count($this->headers);
+    }
+
+    public function offsetExists($offset)
+    {
+        return isset($this->headers[strtolower($offset)]);
+    }
+
+    public function offsetGet($offset)
+    {
+        $l = strtolower($offset);
+
+        return isset($this->headers[$l]) ? $this->headers[$l] : null;
+    }
+
+    public function offsetSet($offset, $value)
+    {
+        $this->add($value);
+    }
+
+    public function offsetUnset($offset)
+    {
+        unset($this->headers[strtolower($offset)]);
+    }
+
+    public function getIterator()
+    {
+        return new \ArrayIterator($this->headers);
+    }
+
+    public function toArray()
+    {
+        $result = array();
+        foreach ($this->headers as $header) {
+            $result[$header->getName()] = $header->toArray();
+        }
+
+        return $result;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderFactory.php b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderFactory.php
new file mode 100644
index 0000000..0273be5
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderFactory.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Guzzle\Http\Message\Header;
+
+use Guzzle\Http\Message\Header;
+
+/**
+ * Default header factory implementation
+ */
+class HeaderFactory implements HeaderFactoryInterface
+{
+    /** @var array */
+    protected $mapping = array(
+        'cache-control' => 'Guzzle\Http\Message\Header\CacheControl',
+        'link'          => 'Guzzle\Http\Message\Header\Link',
+    );
+
+    public function createHeader($header, $value = null)
+    {
+        $lowercase = strtolower($header);
+
+        return isset($this->mapping[$lowercase])
+            ? new $this->mapping[$lowercase]($header, $value)
+            : new Header($header, $value);
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderFactoryInterface.php b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderFactoryInterface.php
new file mode 100644
index 0000000..9457cf6
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderFactoryInterface.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Guzzle\Http\Message\Header;
+
+/**
+ * Interface for creating headers
+ */
+interface HeaderFactoryInterface
+{
+    /**
+     * Create a header from a header name and a single value
+     *
+     * @param string $header Name of the header to create
+     * @param string $value  Value to set on the header
+     *
+     * @return HeaderInterface
+     */
+    public function createHeader($header, $value = null);
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderInterface.php b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderInterface.php
new file mode 100644
index 0000000..adcc78e
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/HeaderInterface.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Guzzle\Http\Message\Header;
+
+use Guzzle\Common\ToArrayInterface;
+
+interface HeaderInterface extends ToArrayInterface, \Countable, \IteratorAggregate
+{
+    /**
+     * Convert the header to a string
+     *
+     * @return string
+     */
+    public function __toString();
+
+    /**
+     * Add a value to the list of header values
+     *
+     * @param string $value Value to add to the header
+     *
+     * @return self
+     */
+    public function add($value);
+
+    /**
+     * Get the name of the header
+     *
+     * @return string
+     */
+    public function getName();
+
+    /**
+     * Change the name of the header
+     *
+     * @param string $name Name to change to
+     *
+     * @return self
+     */
+    public function setName($name);
+
+    /**
+     * Change the glue used to implode the values
+     *
+     * @param string $glue Glue used to implode multiple values
+     *
+     * @return self
+     */
+    public function setGlue($glue);
+
+    /**
+     * Get the glue used to implode multiple values into a string
+     *
+     * @return string
+     */
+    public function getGlue();
+
+    /**
+     * Check if the collection of headers has a particular value
+     *
+     * @param string $searchValue Value to search for
+     *
+     * @return bool
+     */
+    public function hasValue($searchValue);
+
+    /**
+     * Remove a specific value from the header
+     *
+     * @param string $searchValue Value to remove
+     *
+     * @return self
+     */
+    public function removeValue($searchValue);
+
+    /**
+     * Parse a header containing ";" separated data into an array of associative arrays representing the header
+     * key value pair data of the header. When a parameter does not contain a value, but just contains a key, this
+     * function will inject a key with a '' string value.
+     *
+     * @return array
+     */
+    public function parseParams();
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/Header/Link.php b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/Link.php
new file mode 100644
index 0000000..a9fb961
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/Header/Link.php
@@ -0,0 +1,93 @@
+<?php
+
+namespace Guzzle\Http\Message\Header;
+
+use Guzzle\Http\Message\Header;
+
+/**
+ * Provides helpful functionality for link headers
+ */
+class Link extends Header
+{
+    /**
+     * Add a link to the header
+     *
+     * @param string $url    Link URL
+     * @param string $rel    Link rel
+     * @param array  $params Other link parameters
+     *
+     * @return self
+     */
+    public function addLink($url, $rel, array $params = array())
+    {
+        $values = array("<{$url}>", "rel=\"{$rel}\"");
+
+        foreach ($params as $k => $v) {
+            $values[] = "{$k}=\"{$v}\"";
+        }
+
+        return $this->add(implode('; ', $values));
+    }
+
+    /**
+     * Check if a specific link exists for a given rel attribute
+     *
+     * @param string $rel rel value
+     *
+     * @return bool
+     */
+    public function hasLink($rel)
+    {
+        return $this->getLink($rel) !== null;
+    }
+
+    /**
+     * Get a specific link for a given rel attribute
+     *
+     * @param string $rel Rel value
+     *
+     * @return array|null
+     */
+    public function getLink($rel)
+    {
+        foreach ($this->getLinks() as $link) {
+            if (isset($link['rel']) && $link['rel'] == $rel) {
+                return $link;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Get an associative array of links
+     *
+     * For example:
+     * Link: <http:/.../front.jpeg>; rel=front; type="image/jpeg", <http://.../back.jpeg>; rel=back; type="image/jpeg"
+     *
+     * <code>
+     * var_export($response->getLinks());
+     * array(
+     *     array(
+     *         'url' => 'http:/.../front.jpeg',
+     *         'rel' => 'back',
+     *         'type' => 'image/jpeg',
+     *     )
+     * )
+     * </code>
+     *
+     * @return array
+     */
+    public function getLinks()
+    {
+        $links = $this->parseParams();
+
+        foreach ($links as &$link) {
+            $key = key($link);
+            unset($link[$key]);
+            $link['url'] = trim($key, '<> ');
+        }
+
+        return $links;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/MessageInterface.php b/core/vendor/guzzle/http/Guzzle/Http/Message/MessageInterface.php
new file mode 100644
index 0000000..62bcd43
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/MessageInterface.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+/**
+ * Request and response message interface
+ */
+interface MessageInterface
+{
+    /**
+     * Get application and plugin specific parameters set on the message.
+     *
+     * @return \Guzzle\Common\Collection
+     */
+    public function getParams();
+
+    /**
+     * Add a header to an existing collection of headers.
+     *
+     * @param string $header Header name to add
+     * @param string $value  Value of the header
+     *
+     * @return self
+     */
+    public function addHeader($header, $value);
+
+    /**
+     * Add and merge in an array of HTTP headers.
+     *
+     * @param array $headers Associative array of header data.
+     *
+     * @return self
+     */
+    public function addHeaders(array $headers);
+
+    /**
+     * Retrieve an HTTP header by name. Performs a case-insensitive search of all headers.
+     *
+     * @param string $header Header to retrieve.
+     *
+     * @return Header|null
+     */
+    public function getHeader($header);
+
+    /**
+     * Get all headers as a collection
+     *
+     * @return \Guzzle\Http\Message\Header\HeaderCollection
+     */
+    public function getHeaders();
+
+    /**
+     * Check if the specified header is present.
+     *
+     * @param string $header The header to check.
+     *
+     * @return bool
+     */
+    public function hasHeader($header);
+
+    /**
+     * Remove a specific HTTP header.
+     *
+     * @param string $header HTTP header to remove.
+     *
+     * @return self
+     */
+    public function removeHeader($header);
+
+    /**
+     * Set an HTTP header and overwrite any existing value for the header
+     *
+     * @param string $header Name of the header to set.
+     * @param mixed  $value  Value to set.
+     *
+     * @return self
+     */
+    public function setHeader($header, $value);
+
+    /**
+     * Overwrite all HTTP headers with the supplied array of headers
+     *
+     * @param array $headers Associative array of header data.
+     *
+     * @return self
+     */
+    public function setHeaders(array $headers);
+
+    /**
+     * Get an array of message header lines (e.g. ["Host: example.com", ...])
+     *
+     * @return array
+     */
+    public function getHeaderLines();
+
+    /**
+     * Get the raw message headers as a string
+     *
+     * @return string
+     */
+    public function getRawHeaders();
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/PostFile.php b/core/vendor/guzzle/http/Guzzle/Http/Message/PostFile.php
new file mode 100644
index 0000000..141e66d
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/PostFile.php
@@ -0,0 +1,124 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Common\Version;
+use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Http\Mimetypes;
+
+/**
+ * POST file upload
+ */
+class PostFile implements PostFileInterface
+{
+    protected $fieldName;
+    protected $contentType;
+    protected $filename;
+    protected $postname;
+
+    /**
+     * @param string $fieldName   Name of the field
+     * @param string $filename    Local path to the file
+     * @param string $postname    Remote post file name
+     * @param string $contentType Content-Type of the upload
+     */
+    public function __construct($fieldName, $filename, $contentType = null, $postname = null)
+    {
+        $this->fieldName = $fieldName;
+        $this->setFilename($filename);
+        $this->postname = $postname ? $postname : basename($filename);
+        $this->contentType = $contentType ?: $this->guessContentType();
+    }
+
+    public function setFieldName($name)
+    {
+        $this->fieldName = $name;
+
+        return $this;
+    }
+
+    public function getFieldName()
+    {
+        return $this->fieldName;
+    }
+
+    public function setFilename($filename)
+    {
+        // Remove leading @ symbol
+        if (strpos($filename, '@') === 0) {
+            $filename = substr($filename, 1);
+        }
+
+        if (!is_readable($filename)) {
+            throw new InvalidArgumentException("Unable to open {$filename} for reading");
+        }
+
+        $this->filename = $filename;
+
+        return $this;
+    }
+
+    public function setPostname($postname)
+    {
+        $this->postname = $postname;
+
+        return $this;
+    }
+
+    public function getFilename()
+    {
+        return $this->filename;
+    }
+
+    public function getPostname()
+    {
+        return $this->postname;
+    }
+
+    public function setContentType($type)
+    {
+        $this->contentType = $type;
+
+        return $this;
+    }
+
+    public function getContentType()
+    {
+        return $this->contentType;
+    }
+
+    public function getCurlValue()
+    {
+        // PHP 5.5 introduced a CurlFile object that deprecates the old @filename syntax
+        // See: https://wiki.php.net/rfc/curl-file-upload
+        if (function_exists('curl_file_create')) {
+            return curl_file_create($this->filename, $this->contentType, $this->postname);
+        }
+
+        // Use the old style if using an older version of PHP
+        $value = "@{$this->filename};filename=" . $this->postname;
+        if ($this->contentType) {
+            $value .= ';type=' . $this->contentType;
+        }
+
+        return $value;
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function getCurlString()
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use getCurlValue()');
+        return $this->getCurlValue();
+    }
+
+    /**
+     * Determine the Content-Type of the file
+     */
+    protected function guessContentType()
+    {
+        return Mimetypes::getInstance()->fromFilename($this->filename) ?: 'application/octet-stream';
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/PostFileInterface.php b/core/vendor/guzzle/http/Guzzle/Http/Message/PostFileInterface.php
new file mode 100644
index 0000000..7f0779d
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/PostFileInterface.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Common\Exception\InvalidArgumentException;
+
+/**
+ * POST file upload
+ */
+interface PostFileInterface
+{
+    /**
+     * Set the name of the field
+     *
+     * @param string $name Field name
+     *
+     * @return self
+     */
+    public function setFieldName($name);
+
+    /**
+     * Get the name of the field
+     *
+     * @return string
+     */
+    public function getFieldName();
+
+    /**
+     * Set the path to the file
+     *
+     * @param string $path Full path to the file
+     *
+     * @return self
+     * @throws InvalidArgumentException if the file cannot be read
+     */
+    public function setFilename($path);
+
+    /**
+     * Set the post name of the file
+     *
+     * @param string $name The new name of the file
+     *
+     * @return self
+     */
+    public function setPostname($name);
+
+    /**
+     * Get the full path to the file
+     *
+     * @return string
+     */
+    public function getFilename();
+
+    /**
+     * Get the post name of the file
+     *
+     * @return string
+     */
+    public function getPostname();
+
+    /**
+     * Set the Content-Type of the file
+     *
+     * @param string $type Content type
+     *
+     * @return self
+     */
+    public function setContentType($type);
+
+    /**
+     * Get the Content-Type of the file
+     *
+     * @return string
+     */
+    public function getContentType();
+
+    /**
+     * Get a cURL ready string or CurlFile object for the upload
+     *
+     * @return string
+     */
+    public function getCurlValue();
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/Request.php b/core/vendor/guzzle/http/Guzzle/Http/Message/Request.php
new file mode 100644
index 0000000..f218cd5
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/Request.php
@@ -0,0 +1,638 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Common\Version;
+use Guzzle\Common\Event;
+use Guzzle\Common\Collection;
+use Guzzle\Common\Exception\RuntimeException;
+use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Http\Exception\RequestException;
+use Guzzle\Http\Exception\BadResponseException;
+use Guzzle\Http\ClientInterface;
+use Guzzle\Http\EntityBody;
+use Guzzle\Http\EntityBodyInterface;
+use Guzzle\Http\Message\Header\HeaderInterface;
+use Guzzle\Http\Url;
+use Guzzle\Parser\ParserRegistry;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * HTTP request class to send requests
+ */
+class Request extends AbstractMessage implements RequestInterface
+{
+    /** @var EventDispatcherInterface */
+    protected $eventDispatcher;
+
+    /** @var Url HTTP Url */
+    protected $url;
+
+    /** @var string HTTP method (GET, PUT, POST, DELETE, HEAD, OPTIONS, TRACE) */
+    protected $method;
+
+    /** @var ClientInterface */
+    protected $client;
+
+    /** @var Response Response of the request */
+    protected $response;
+
+    /** @var EntityBodyInterface Response body */
+    protected $responseBody;
+
+    /** @var string State of the request object */
+    protected $state;
+
+    /** @var string Authentication username */
+    protected $username;
+
+    /** @var string Auth password */
+    protected $password;
+
+    /** @var Collection cURL specific transfer options */
+    protected $curlOptions;
+
+    /** @var bool */
+    protected $isRedirect = false;
+
+    public static function getAllEvents()
+    {
+        return array(
+            // Called when receiving or uploading data through cURL
+            'curl.callback.read', 'curl.callback.write', 'curl.callback.progress',
+            // Cloning a request
+            'request.clone',
+            // About to send the request, sent request, completed transaction
+            'request.before_send', 'request.sent', 'request.complete',
+            // A request received a successful response
+            'request.success',
+            // A request received an unsuccessful response
+            'request.error',
+            // An exception is being thrown because of an unsuccessful response
+            'request.exception',
+            // Received response status line
+            'request.receive.status_line'
+        );
+    }
+
+    /**
+     * @param string           $method  HTTP method
+     * @param string|Url       $url     HTTP URL to connect to. The URI scheme, host header, and URI are parsed from the
+     *                                  full URL. If query string parameters are present they will be parsed as well.
+     * @param array|Collection $headers HTTP headers
+     */
+    public function __construct($method, $url, $headers = array())
+    {
+        parent::__construct();
+        $this->method = strtoupper($method);
+        $this->curlOptions = new Collection();
+        $this->setUrl($url);
+
+        if ($headers) {
+            // Special handling for multi-value headers
+            foreach ($headers as $key => $value) {
+                // Deal with collisions with Host and Authorization
+                if ($key == 'host' || $key == 'Host') {
+                    $this->setHeader($key, $value);
+                } elseif ($value instanceof HeaderInterface) {
+                    $this->addHeader($key, $value);
+                } else {
+                    foreach ((array) $value as $v) {
+                        $this->addHeader($key, $v);
+                    }
+                }
+            }
+        }
+
+        $this->setState(self::STATE_NEW);
+    }
+
+    public function __clone()
+    {
+        if ($this->eventDispatcher) {
+            $this->eventDispatcher = clone $this->eventDispatcher;
+        }
+        $this->curlOptions = clone $this->curlOptions;
+        $this->params = clone $this->params;
+        $this->url = clone $this->url;
+        $this->response = $this->responseBody = null;
+        $this->headers = clone $this->headers;
+
+        $this->setState(RequestInterface::STATE_NEW);
+        $this->dispatch('request.clone', array('request' => $this));
+    }
+
+    /**
+     * Get the HTTP request as a string
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->getRawHeaders() . "\r\n\r\n";
+    }
+
+    /**
+     * Default method that will throw exceptions if an unsuccessful response is received.
+     *
+     * @param Event $event Received
+     * @throws BadResponseException if the response is not successful
+     */
+    public static function onRequestError(Event $event)
+    {
+        $e = BadResponseException::factory($event['request'], $event['response']);
+        $event['request']->setState(self::STATE_ERROR, array('exception' => $e) + $event->toArray());
+        throw $e;
+    }
+
+    public function setClient(ClientInterface $client)
+    {
+        $this->client = $client;
+
+        return $this;
+    }
+
+    public function getClient()
+    {
+        return $this->client;
+    }
+
+    public function getRawHeaders()
+    {
+        $protocolVersion = $this->protocolVersion ?: '1.1';
+
+        return trim($this->method . ' ' . $this->getResource()) . ' '
+            . strtoupper(str_replace('https', 'http', $this->url->getScheme()))
+            . '/' . $protocolVersion . "\r\n" . implode("\r\n", $this->getHeaderLines());
+    }
+
+    public function setUrl($url)
+    {
+        if ($url instanceof Url) {
+            $this->url = $url;
+        } else {
+            $this->url = Url::factory($url);
+        }
+
+        // Update the port and host header
+        $this->setPort($this->url->getPort());
+
+        if ($this->url->getUsername() || $this->url->getPassword()) {
+            $this->setAuth($this->url->getUsername(), $this->url->getPassword());
+            // Remove the auth info from the URL
+            $this->url->setUsername(null);
+            $this->url->setPassword(null);
+        }
+
+        return $this;
+    }
+
+    public function send()
+    {
+        if (!$this->client) {
+            throw new RuntimeException('A client must be set on the request');
+        }
+
+        return $this->client->send($this);
+    }
+
+    public function getResponse()
+    {
+        return $this->response;
+    }
+
+    public function getQuery($asString = false)
+    {
+        return $asString
+            ? (string) $this->url->getQuery()
+            : $this->url->getQuery();
+    }
+
+    public function getMethod()
+    {
+        return $this->method;
+    }
+
+    public function getScheme()
+    {
+        return $this->url->getScheme();
+    }
+
+    public function setScheme($scheme)
+    {
+        $this->url->setScheme($scheme);
+
+        return $this;
+    }
+
+    public function getHost()
+    {
+        return $this->url->getHost();
+    }
+
+    public function setHost($host)
+    {
+        $this->url->setHost($host);
+        $this->setPort($this->url->getPort());
+
+        return $this;
+    }
+
+    public function getProtocolVersion()
+    {
+        return $this->protocolVersion;
+    }
+
+    public function setProtocolVersion($protocol)
+    {
+        $this->protocolVersion = $protocol;
+
+        return $this;
+    }
+
+    public function getPath()
+    {
+        return '/' . ltrim($this->url->getPath(), '/');
+    }
+
+    public function setPath($path)
+    {
+        $this->url->setPath($path);
+
+        return $this;
+    }
+
+    public function getPort()
+    {
+        return $this->url->getPort();
+    }
+
+    public function setPort($port)
+    {
+        $this->url->setPort($port);
+
+        // Include the port in the Host header if it is not the default port for the scheme of the URL
+        $scheme = $this->url->getScheme();
+        if ($port && (($scheme == 'http' && $port != 80) || ($scheme == 'https' && $port != 443))) {
+            $this->headers['host'] = $this->headerFactory->createHeader('Host', $this->url->getHost() . ':' . $port);
+        } else {
+            $this->headers['host'] = $this->headerFactory->createHeader('Host', $this->url->getHost());
+        }
+
+        return $this;
+    }
+
+    public function getUsername()
+    {
+        return $this->username;
+    }
+
+    public function getPassword()
+    {
+        return $this->password;
+    }
+
+    public function setAuth($user, $password = '', $scheme = CURLAUTH_BASIC)
+    {
+        static $authMap = array(
+            'basic'  => CURLAUTH_BASIC,
+            'digest' => CURLAUTH_DIGEST,
+            'ntlm'   => CURLAUTH_NTLM,
+            'any'    => CURLAUTH_ANY
+        );
+
+        // If we got false or null, disable authentication
+        if (!$user) {
+            $this->password = $this->username = null;
+            $this->removeHeader('Authorization');
+            $this->getCurlOptions()->remove(CURLOPT_HTTPAUTH);
+            return $this;
+        }
+
+        if (!is_numeric($scheme)) {
+            $scheme = strtolower($scheme);
+            if (!isset($authMap[$scheme])) {
+                throw new InvalidArgumentException($scheme . ' is not a valid authentication type');
+            }
+            $scheme = $authMap[$scheme];
+        }
+
+        $this->username = $user;
+        $this->password = $password;
+
+        // Bypass CURL when using basic auth to promote connection reuse
+        if ($scheme == CURLAUTH_BASIC) {
+            $this->getCurlOptions()->remove(CURLOPT_HTTPAUTH);
+            $this->setHeader('Authorization', 'Basic ' . base64_encode($this->username . ':' . $this->password));
+        } else {
+            $this->getCurlOptions()
+                ->set(CURLOPT_HTTPAUTH, $scheme)
+                ->set(CURLOPT_USERPWD, $this->username . ':' . $this->password);
+        }
+
+        return $this;
+    }
+
+    public function getResource()
+    {
+        $resource = $this->getPath();
+        if ($query = (string) $this->url->getQuery()) {
+            $resource .= '?' . $query;
+        }
+
+        return $resource;
+    }
+
+    public function getUrl($asObject = false)
+    {
+        return $asObject ? clone $this->url : (string) $this->url;
+    }
+
+    public function getState()
+    {
+        return $this->state;
+    }
+
+    public function setState($state, array $context = array())
+    {
+        $oldState = $this->state;
+        $this->state = $state;
+
+        switch ($state) {
+            case self::STATE_NEW:
+                $this->response = null;
+                break;
+            case self::STATE_TRANSFER:
+                if ($oldState !== $state) {
+                    // Fix Content-Length and Transfer-Encoding collisions
+                    if ($this->hasHeader('Transfer-Encoding') && $this->hasHeader('Content-Length')) {
+                        $this->removeHeader('Transfer-Encoding');
+                    }
+                    $this->dispatch('request.before_send', array('request' => $this));
+                }
+                break;
+            case self::STATE_COMPLETE:
+                if ($oldState !== $state) {
+                    $this->processResponse($context);
+                    $this->responseBody = null;
+                }
+                break;
+            case self::STATE_ERROR:
+                if (isset($context['exception'])) {
+                    $this->dispatch('request.exception', array(
+                        'request'   => $this,
+                        'response'  => isset($context['response']) ? $context['response'] : $this->response,
+                        'exception' => isset($context['exception']) ? $context['exception'] : null
+                    ));
+                }
+        }
+
+        return $this->state;
+    }
+
+    public function getCurlOptions()
+    {
+        return $this->curlOptions;
+    }
+
+    public function startResponse(Response $response)
+    {
+        $this->state = self::STATE_TRANSFER;
+        $response->setEffectiveUrl((string) $this->getUrl());
+        $this->response = $response;
+
+        return $this;
+    }
+
+    public function setResponse(Response $response, $queued = false)
+    {
+        $response->setEffectiveUrl((string) $this->url);
+
+        if ($queued) {
+            $ed = $this->getEventDispatcher();
+            $ed->addListener('request.before_send', $f = function ($e) use ($response, &$f, $ed) {
+                $e['request']->setResponse($response);
+                $ed->removeListener('request.before_send', $f);
+            }, -9999);
+        } else {
+            $this->response = $response;
+            // If a specific response body is specified, then use it instead of the response's body
+            if ($this->responseBody && !$this->responseBody->getCustomData('default') && !$response->isRedirect()) {
+                $this->getResponseBody()->write((string) $this->response->getBody());
+            } else {
+                $this->responseBody = $this->response->getBody();
+            }
+            $this->setState(self::STATE_COMPLETE);
+        }
+
+        return $this;
+    }
+
+    public function setResponseBody($body)
+    {
+        // Attempt to open a file for writing if a string was passed
+        if (is_string($body)) {
+            // @codeCoverageIgnoreStart
+            if (!($body = fopen($body, 'w+'))) {
+                throw new InvalidArgumentException('Could not open ' . $body . ' for writing');
+            }
+            // @codeCoverageIgnoreEnd
+        }
+
+        $this->responseBody = EntityBody::factory($body);
+
+        return $this;
+    }
+
+    public function getResponseBody()
+    {
+        if ($this->responseBody === null) {
+            $this->responseBody = EntityBody::factory()->setCustomData('default', true);
+        }
+
+        return $this->responseBody;
+    }
+
+    /**
+     * Determine if the response body is repeatable (readable + seekable)
+     *
+     * @return bool
+     * @deprecated Use getResponseBody()->isSeekable()
+     * @codeCoverageIgnore
+     */
+    public function isResponseBodyRepeatable()
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use $request->getResponseBody()->isRepeatable()');
+        return !$this->responseBody ? true : $this->responseBody->isRepeatable();
+    }
+
+    public function getCookies()
+    {
+        if ($cookie = $this->getHeader('Cookie')) {
+            $data = ParserRegistry::getInstance()->getParser('cookie')->parseCookie($cookie);
+            return $data['cookies'];
+        }
+
+        return array();
+    }
+
+    public function getCookie($name)
+    {
+        $cookies = $this->getCookies();
+
+        return isset($cookies[$name]) ? $cookies[$name] : null;
+    }
+
+    public function addCookie($name, $value)
+    {
+        if (!$this->hasHeader('Cookie')) {
+            $this->setHeader('Cookie', "{$name}={$value}");
+        } else {
+            $this->getHeader('Cookie')->add("{$name}={$value}");
+        }
+
+        // Always use semicolons to separate multiple cookie headers
+        $this->getHeader('Cookie')->setGlue(';');
+
+        return $this;
+    }
+
+    public function removeCookie($name)
+    {
+        if ($cookie = $this->getHeader('Cookie')) {
+            foreach ($cookie as $cookieValue) {
+                if (strpos($cookieValue, $name . '=') === 0) {
+                    $cookie->removeValue($cookieValue);
+                }
+            }
+        }
+
+        return $this;
+    }
+
+    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
+    {
+        $this->eventDispatcher = $eventDispatcher;
+        $this->eventDispatcher->addListener('request.error', array(__CLASS__, 'onRequestError'), -255);
+
+        return $this;
+    }
+
+    public function getEventDispatcher()
+    {
+        if (!$this->eventDispatcher) {
+            $this->setEventDispatcher(new EventDispatcher());
+        }
+
+        return $this->eventDispatcher;
+    }
+
+    public function dispatch($eventName, array $context = array())
+    {
+        $context['request'] = $this;
+
+        return $this->getEventDispatcher()->dispatch($eventName, new Event($context));
+    }
+
+    public function addSubscriber(EventSubscriberInterface $subscriber)
+    {
+        $this->getEventDispatcher()->addSubscriber($subscriber);
+
+        return $this;
+    }
+
+    /**
+     * Get an array containing the request and response for event notifications
+     *
+     * @return array
+     */
+    protected function getEventArray()
+    {
+        return array(
+            'request'  => $this,
+            'response' => $this->response
+        );
+    }
+
+    /**
+     * Process a received response
+     *
+     * @param array $context Contextual information
+     * @throws RequestException|BadResponseException on unsuccessful responses
+     */
+    protected function processResponse(array $context = array())
+    {
+        if (!$this->response) {
+            // If no response, then processResponse shouldn't have been called
+            $e = new RequestException('Error completing request');
+            $e->setRequest($this);
+            throw $e;
+        }
+
+        $this->state = self::STATE_COMPLETE;
+
+        // A request was sent, but we don't know if we'll send more or if the final response will be successful
+        $this->dispatch('request.sent', $this->getEventArray() + $context);
+
+        // Some response processors will remove the response or reset the state (example: ExponentialBackoffPlugin)
+        if ($this->state == RequestInterface::STATE_COMPLETE) {
+
+            // The request completed, so the HTTP transaction is complete
+            $this->dispatch('request.complete', $this->getEventArray());
+
+            // If the response is bad, allow listeners to modify it or throw exceptions. You can change the response by
+            // modifying the Event object in your listeners or calling setResponse() on the request
+            if ($this->response->isError()) {
+                $event = new Event($this->getEventArray());
+                $this->getEventDispatcher()->dispatch('request.error', $event);
+                // Allow events of request.error to quietly change the response
+                if ($event['response'] !== $this->response) {
+                    $this->response = $event['response'];
+                }
+            }
+
+            // If a successful response was received, dispatch an event
+            if ($this->response->isSuccessful()) {
+                $this->dispatch('request.success', $this->getEventArray());
+            }
+        }
+    }
+
+    /**
+     * @deprecated Use Guzzle\Plugin\Cache\DefaultCanCacheStrategy
+     * @codeCoverageIgnore
+     */
+    public function canCache()
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use Guzzle\Plugin\Cache\DefaultCanCacheStrategy.');
+        if (class_exists('Guzzle\Plugin\Cache\DefaultCanCacheStrategy')) {
+            $canCache = new \Guzzle\Plugin\Cache\DefaultCanCacheStrategy();
+            return $canCache->canCacheRequest($this);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @deprecated Use the history plugin (not emitting a warning as this is built-into the RedirectPlugin for now)
+     * @codeCoverageIgnore
+     */
+    public function setIsRedirect($isRedirect)
+    {
+        $this->isRedirect = $isRedirect;
+
+        return $this;
+    }
+
+    /**
+     * @deprecated Use the history plugin
+     * @codeCoverageIgnore
+     */
+    public function isRedirect()
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use the HistoryPlugin to track this.');
+        return $this->isRedirect;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/RequestFactory.php b/core/vendor/guzzle/http/Guzzle/Http/Message/RequestFactory.php
new file mode 100644
index 0000000..ba00a76
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/RequestFactory.php
@@ -0,0 +1,359 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Common\Collection;
+use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Http\RedirectPlugin;
+use Guzzle\Http\Url;
+use Guzzle\Parser\ParserRegistry;
+
+/**
+ * Default HTTP request factory used to create the default {@see Request} and {@see EntityEnclosingRequest} objects.
+ */
+class RequestFactory implements RequestFactoryInterface
+{
+    /** @var RequestFactory Singleton instance of the default request factory */
+    protected static $instance;
+
+    /** @var array Hash of methods available to the class (provides fast isset() lookups) */
+    protected $methods;
+
+    /** @var string Class to instantiate for requests with no body */
+    protected $requestClass = 'Guzzle\\Http\\Message\\Request';
+
+    /** @var string Class to instantiate for requests with a body */
+    protected $entityEnclosingRequestClass = 'Guzzle\\Http\\Message\\EntityEnclosingRequest';
+
+    /**
+     * Get a cached instance of the default request factory
+     *
+     * @return RequestFactory
+     */
+    public static function getInstance()
+    {
+        // @codeCoverageIgnoreStart
+        if (!static::$instance) {
+            static::$instance = new static();
+        }
+        // @codeCoverageIgnoreEnd
+
+        return static::$instance;
+    }
+
+    public function __construct()
+    {
+        $this->methods = array_flip(get_class_methods(__CLASS__));
+    }
+
+    public function fromMessage($message)
+    {
+        $parsed = ParserRegistry::getInstance()->getParser('message')->parseRequest($message);
+
+        if (!$parsed) {
+            return false;
+        }
+
+        $request = $this->fromParts($parsed['method'], $parsed['request_url'],
+            $parsed['headers'], $parsed['body'], $parsed['protocol'],
+            $parsed['version']);
+
+        // EntityEnclosingRequest adds an "Expect: 100-Continue" header when using a raw request body for PUT or POST
+        // requests. This factory method should accurately reflect the message, so here we are removing the Expect
+        // header if one was not supplied in the message.
+        if (!isset($parsed['headers']['Expect']) && !isset($parsed['headers']['expect'])) {
+            $request->removeHeader('Expect');
+        }
+
+        return $request;
+    }
+
+    public function fromParts(
+        $method,
+        array $urlParts,
+        $headers = null,
+        $body = null,
+        $protocol = 'HTTP',
+        $protocolVersion = '1.1'
+    ) {
+        return $this->create($method, Url::buildUrl($urlParts), $headers, $body)
+                    ->setProtocolVersion($protocolVersion);
+    }
+
+    public function create($method, $url, $headers = null, $body = null, array $options = array())
+    {
+        $method = strtoupper($method);
+
+        if ($method == 'GET' || $method == 'HEAD' || $method == 'TRACE') {
+            // Handle non-entity-enclosing request methods
+            $request = new $this->requestClass($method, $url, $headers);
+            if ($body) {
+                // The body is where the response body will be stored
+                $type = gettype($body);
+                if ($type == 'string' || $type == 'resource' || $type == 'object') {
+                    $request->setResponseBody($body);
+                }
+            }
+        } else {
+            // Create an entity enclosing request by default
+            $request = new $this->entityEnclosingRequestClass($method, $url, $headers);
+            if ($body || $body === '0') {
+                // Add POST fields and files to an entity enclosing request if an array is used
+                if (is_array($body) || $body instanceof Collection) {
+                    // Normalize PHP style cURL uploads with a leading '@' symbol
+                    foreach ($body as $key => $value) {
+                        if (is_string($value) && substr($value, 0, 1) == '@') {
+                            $request->addPostFile($key, $value);
+                            unset($body[$key]);
+                        }
+                    }
+                    // Add the fields if they are still present and not all files
+                    $request->addPostFields($body);
+                } else {
+                    // Add a raw entity body body to the request
+                    $request->setBody($body, (string) $request->getHeader('Content-Type'));
+                    if ((string) $request->getHeader('Transfer-Encoding') == 'chunked') {
+                        $request->removeHeader('Content-Length');
+                    }
+                }
+            }
+        }
+
+        if ($options) {
+            $this->applyOptions($request, $options);
+        }
+
+        return $request;
+    }
+
+    /**
+     * Clone a request while changing the method. Emulates the behavior of
+     * {@see Guzzle\Http\Message\Request::clone}, but can change the HTTP method.
+     *
+     * @param RequestInterface $request Request to clone
+     * @param string           $method  Method to set
+     *
+     * @return RequestInterface
+     */
+    public function cloneRequestWithMethod(RequestInterface $request, $method)
+    {
+        // Create the request with the same client if possible
+        if ($request->getClient()) {
+            $cloned = $request->getClient()->createRequest($method, $request->getUrl(), $request->getHeaders());
+        } else {
+            $cloned = $this->create($method, $request->getUrl(), $request->getHeaders());
+        }
+
+        $cloned->getCurlOptions()->replace($request->getCurlOptions()->toArray());
+        $cloned->setEventDispatcher(clone $request->getEventDispatcher());
+        // Ensure that that the Content-Length header is not copied if changing to GET or HEAD
+        if (!($cloned instanceof EntityEnclosingRequestInterface)) {
+            $cloned->removeHeader('Content-Length');
+        } elseif ($request instanceof EntityEnclosingRequestInterface) {
+            $cloned->setBody($request->getBody());
+        }
+        $cloned->getParams()->replace($request->getParams()->toArray());
+        $cloned->dispatch('request.clone', array('request' => $cloned));
+
+        return $cloned;
+    }
+
+    public function applyOptions(RequestInterface $request, array $options = array(), $flags = self::OPTIONS_NONE)
+    {
+        // Iterate over each key value pair and attempt to apply a config using function visitors
+        foreach ($options as $key => $value) {
+            $method = "visit_{$key}";
+            if (isset($this->methods[$method])) {
+                $this->{$method}($request, $value, $flags);
+            }
+        }
+    }
+
+    protected function visit_headers(RequestInterface $request, $value, $flags)
+    {
+        if (!is_array($value)) {
+            throw new InvalidArgumentException('headers value must be an array');
+        }
+
+        if ($flags & self::OPTIONS_AS_DEFAULTS) {
+            // Merge headers in but do not overwrite existing values
+            foreach ($value as $key => $header) {
+                if (!$request->hasHeader($key)) {
+                    $request->setHeader($key, $header);
+                }
+            }
+        } else {
+            $request->addHeaders($value);
+        }
+    }
+
+    protected function visit_body(RequestInterface $request, $value, $flags)
+    {
+        if ($request instanceof EntityEnclosingRequestInterface) {
+            $request->setBody($value);
+        } else {
+            throw new InvalidArgumentException('Attempting to set a body on a non-entity-enclosing request');
+        }
+    }
+
+    protected function visit_allow_redirects(RequestInterface $request, $value, $flags)
+    {
+        if ($value === false) {
+            $request->getParams()->set(RedirectPlugin::DISABLE, true);
+        }
+    }
+
+    protected function visit_auth(RequestInterface $request, $value, $flags)
+    {
+        if (!is_array($value)) {
+            throw new InvalidArgumentException('auth value must be an array');
+        }
+
+        $request->setAuth($value[0], isset($value[1]) ? $value[1] : null, isset($value[2]) ? $value[2] : 'basic');
+    }
+
+    protected function visit_query(RequestInterface $request, $value, $flags)
+    {
+        if (!is_array($value)) {
+            throw new InvalidArgumentException('query value must be an array');
+        }
+
+        if ($flags & self::OPTIONS_AS_DEFAULTS) {
+            // Merge query string values in but do not overwrite existing values
+            $query = $request->getQuery();
+            $query->overwriteWith(array_diff_key($value, $query->toArray()));
+        } else {
+            $request->getQuery()->overwriteWith($value);
+        }
+    }
+
+    protected function visit_cookies(RequestInterface $request, $value, $flags)
+    {
+        if (!is_array($value)) {
+            throw new InvalidArgumentException('cookies value must be an array');
+        }
+
+        foreach ($value as $name => $v) {
+            $request->addCookie($name, $v);
+        }
+    }
+
+    protected function visit_events(RequestInterface $request, $value, $flags)
+    {
+        if (!is_array($value)) {
+            throw new InvalidArgumentException('events value must be an array');
+        }
+
+        foreach ($value as $name => $method) {
+            if (is_array($method)) {
+                $request->getEventDispatcher()->addListener($name, $method[0], $method[1]);
+            } else {
+                $request->getEventDispatcher()->addListener($name, $method);
+            }
+        }
+    }
+
+    protected function visit_plugins(RequestInterface $request, $value, $flags)
+    {
+        if (!is_array($value)) {
+            throw new InvalidArgumentException('plugins value must be an array');
+        }
+
+        foreach ($value as $plugin) {
+            $request->addSubscriber($plugin);
+        }
+    }
+
+    protected function visit_exceptions(RequestInterface $request, $value, $flags)
+    {
+        if ($value === false || $value === 0) {
+            $dispatcher = $request->getEventDispatcher();
+            foreach ($dispatcher->getListeners('request.error') as $listener) {
+                if (is_array($listener) && $listener[0] == 'Guzzle\Http\Message\Request' && $listener[1] = 'onRequestError') {
+                    $dispatcher->removeListener('request.error', $listener);
+                    break;
+                }
+            }
+        }
+    }
+
+    protected function visit_save_to(RequestInterface $request, $value, $flags)
+    {
+        $request->setResponseBody($value);
+    }
+
+    protected function visit_params(RequestInterface $request, $value, $flags)
+    {
+        if (!is_array($value)) {
+            throw new InvalidArgumentException('params value must be an array');
+        }
+
+        $request->getParams()->overwriteWith($value);
+    }
+
+    protected function visit_timeout(RequestInterface $request, $value, $flags)
+    {
+        if (defined('CURLOPT_TIMEOUT_MS')) {
+            $request->getCurlOptions()->set(CURLOPT_TIMEOUT_MS, $value * 1000);
+        } else {
+            $request->getCurlOptions()->set(CURLOPT_TIMEOUT, $value);
+        }
+    }
+
+    protected function visit_connect_timeout(RequestInterface $request, $value, $flags)
+    {
+        if (defined('CURLOPT_CONNECTTIMEOUT_MS')) {
+            $request->getCurlOptions()->set(CURLOPT_CONNECTTIMEOUT_MS, $value * 1000);
+        } else {
+            $request->getCurlOptions()->set(CURLOPT_CONNECTTIMEOUT, $value);
+        }
+    }
+
+    protected function visit_debug(RequestInterface $request, $value, $flags)
+    {
+        if ($value) {
+            $request->getCurlOptions()->set(CURLOPT_VERBOSE, true);
+        }
+    }
+
+    protected function visit_verify(RequestInterface $request, $value, $flags)
+    {
+        $curl = $request->getCurlOptions();
+        if ($value === true || is_string($value)) {
+            $curl[CURLOPT_SSL_VERIFYHOST] = 2;
+            $curl[CURLOPT_SSL_VERIFYPEER] = true;
+            if ($value !== true) {
+                $curl[CURLOPT_CAINFO] = $value;
+            }
+        } elseif ($value === false) {
+            unset($curl[CURLOPT_CAINFO]);
+            $curl[CURLOPT_SSL_VERIFYHOST] = 0;
+            $curl[CURLOPT_SSL_VERIFYPEER] = false;
+        }
+    }
+
+    protected function visit_proxy(RequestInterface $request, $value, $flags)
+    {
+        $request->getCurlOptions()->set(CURLOPT_PROXY, $value, $flags);
+    }
+
+    protected function visit_cert(RequestInterface $request, $value, $flags)
+    {
+        if (is_array($value)) {
+            $request->getCurlOptions()->set(CURLOPT_SSLCERT, $value[0]);
+            $request->getCurlOptions()->set(CURLOPT_SSLCERTPASSWD, $value[1]);
+        } else {
+            $request->getCurlOptions()->set(CURLOPT_SSLCERT, $value);
+        }
+    }
+
+    protected function visit_ssl_key(RequestInterface $request, $value, $flags)
+    {
+        if (is_array($value)) {
+            $request->getCurlOptions()->set(CURLOPT_SSLKEY, $value[0]);
+            $request->getCurlOptions()->set(CURLOPT_SSLKEYPASSWD, $value[1]);
+        } else {
+            $request->getCurlOptions()->set(CURLOPT_SSLKEY, $value);
+        }
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/RequestFactoryInterface.php b/core/vendor/guzzle/http/Guzzle/Http/Message/RequestFactoryInterface.php
new file mode 100644
index 0000000..6088f10
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/RequestFactoryInterface.php
@@ -0,0 +1,105 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Common\Collection;
+use Guzzle\Http\EntityBodyInterface;
+use Guzzle\Http\Url;
+
+/**
+ * Request factory used to create HTTP requests
+ */
+interface RequestFactoryInterface
+{
+    const OPTIONS_NONE = 0;
+    const OPTIONS_AS_DEFAULTS = 1;
+
+    /**
+     * Create a new request based on an HTTP message
+     *
+     * @param string $message HTTP message as a string
+     *
+     * @return RequestInterface
+     */
+    public function fromMessage($message);
+
+    /**
+     * Create a request from URL parts as returned from parse_url()
+     *
+     * @param string $method HTTP method (GET, POST, PUT, HEAD, DELETE, etc)
+     *
+     * @param array $urlParts URL parts containing the same keys as parse_url()
+     *     - scheme: e.g. http
+     *     - host:   e.g. www.guzzle-project.com
+     *     - port:   e.g. 80
+     *     - user:   e.g. michael
+     *     - pass:   e.g. rocks
+     *     - path:   e.g. / OR /index.html
+     *     - query:  after the question mark ?
+     * @param array|Collection                          $headers         HTTP headers
+     * @param string|resource|array|EntityBodyInterface $body            Body to send in the request
+     * @param string                                    $protocol        Protocol (HTTP, SPYDY, etc)
+     * @param string                                    $protocolVersion 1.0, 1.1, etc
+     *
+     * @return RequestInterface
+     */
+    public function fromParts(
+        $method,
+        array $urlParts,
+        $headers = null,
+        $body = null,
+        $protocol = 'HTTP',
+        $protocolVersion = '1.1'
+    );
+
+    /**
+     * Create a new request based on the HTTP method
+     *
+     * @param string                                    $method  HTTP method (GET, POST, PUT, PATCH, HEAD, DELETE, ...)
+     * @param string|Url                                $url     HTTP URL to connect to
+     * @param array|Collection                          $headers HTTP headers
+     * @param string|resource|array|EntityBodyInterface $body    Body to send in the request
+     * @param array                                     $options Array of options to apply to the request
+     *
+     * @return RequestInterface
+     */
+    public function create($method, $url, $headers = null, $body = null, array $options = array());
+
+    /**
+     * Apply an associative array of options to the request
+     *
+     * @param RequestInterface $request Request to update
+     * @param array            $options Options to use with the request. Available options are:
+     *        "headers": Associative array of headers
+     *        "query": Associative array of query string values to add to the request
+     *        "body": Body of a request, including an EntityBody, string, or array when sending POST requests.
+     *        "auth": Array of HTTP authentication parameters to use with the request. The array must contain the
+     *            username in index [0], the password in index [2], and can optionally contain the authentication type
+     *            in index [3]. The authentication types are: "Basic", "Digest", "NTLM", "Any" (defaults to "Basic").
+     *        "cookies": Associative array of cookies
+     *        "allow_redirects": Set to false to disable redirects
+     *        "save_to": String, fopen resource, or EntityBody object used to store the body of the response
+     *        "events": Associative array mapping event names to a closure or array of (priority, closure)
+     *        "plugins": Array of plugins to add to the request
+     *        "exceptions": Set to false to disable throwing exceptions on an HTTP level error (e.g. 404, 500, etc)
+     *        "params": Set custom request data parameters on a request. (Note: these are not query string parameters)
+     *        "timeout": Float describing the timeout of the request in seconds
+     *        "connect_timeout": Float describing the number of seconds to wait while trying to connect. Use 0 to wait
+     *            indefinitely.
+     *        "verify": Set to true to enable SSL cert validation (the default), false to disable, or supply the path
+     *            to a CA bundle to enable verification using a custom certificate.
+     *        "cert": Set to a string to specify the path to a file containing a PEM formatted certificate. If a
+     *            password is required, then set an array containing the path to the PEM file followed by the the
+     *            password required for the certificate.
+     *        "ssl_key": Specify the path to a file containing a private SSL key in PEM format. If a password is
+     *            required, then set an array containing the path to the SSL key followed by the password required for
+     *            the certificate.
+     *        "proxy": Specify an HTTP proxy (e.g. "http://username:password@192.168.16.1:10")
+     *        "debug": Set to true to display all data sent over the wire
+     * @param int $flags Bitwise flags to apply when applying the options to the request. Defaults to no special
+     *                   options. `1` (OPTIONS_AS_DEFAULTS): When specified, options will only update a request when
+     *                   the value does not already exist on the request. This is only supported by "query" and
+     *                   "headers". Other bitwise options may be added in the future.
+     */
+    public function applyOptions(RequestInterface $request, array $options = array(), $flags = self::OPTIONS_NONE);
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/RequestInterface.php b/core/vendor/guzzle/http/Guzzle/Http/Message/RequestInterface.php
new file mode 100644
index 0000000..2f6b3c8
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/RequestInterface.php
@@ -0,0 +1,318 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Common\Collection;
+use Guzzle\Common\HasDispatcherInterface;
+use Guzzle\Http\Exception\RequestException;
+use Guzzle\Http\ClientInterface;
+use Guzzle\Http\EntityBodyInterface;
+use Guzzle\Http\Url;
+use Guzzle\Http\QueryString;
+
+/**
+ * Generic HTTP request interface
+ */
+interface RequestInterface extends MessageInterface, HasDispatcherInterface
+{
+    const STATE_NEW = 'new';
+    const STATE_COMPLETE = 'complete';
+    const STATE_TRANSFER = 'transfer';
+    const STATE_ERROR = 'error';
+
+    const GET = 'GET';
+    const PUT = 'PUT';
+    const POST = 'POST';
+    const DELETE = 'DELETE';
+    const HEAD = 'HEAD';
+    const CONNECT = 'CONNECT';
+    const OPTIONS = 'OPTIONS';
+    const TRACE = 'TRACE';
+    const PATCH = 'PATCH';
+
+    /**
+     * @return string
+     */
+    public function __toString();
+
+    /**
+     * Send the request
+     *
+     * @return Response
+     * @throws RequestException on a request error
+     */
+    public function send();
+
+    /**
+     * Set the client used to transport the request
+     *
+     * @param ClientInterface $client
+     *
+     * @return self
+     */
+    public function setClient(ClientInterface $client);
+
+    /**
+     * Get the client used to transport the request
+     *
+     * @return ClientInterface $client
+     */
+    public function getClient();
+
+    /**
+     * Set the URL of the request
+     *
+     * @param string $url|Url Full URL to set including query string
+     *
+     * @return self
+     */
+    public function setUrl($url);
+
+    /**
+     * Get the full URL of the request (e.g. 'http://www.guzzle-project.com/')
+     *
+     * @param bool $asObject Set to TRUE to retrieve the URL as a clone of the URL object owned by the request.
+     *
+     * @return string|Url
+     */
+    public function getUrl($asObject = false);
+
+    /**
+     * Get the resource part of the the request, including the path, query string, and fragment
+     *
+     * @return string
+     */
+    public function getResource();
+
+    /**
+     * Get the collection of key value pairs that will be used as the query string in the request
+     *
+     * @return QueryString
+     */
+    public function getQuery();
+
+    /**
+     * Get the HTTP method of the request
+     *
+     * @return string
+     */
+    public function getMethod();
+
+    /**
+     * Get the URI scheme of the request (http, https, ftp, etc)
+     *
+     * @return string
+     */
+    public function getScheme();
+
+    /**
+     * Set the URI scheme of the request (http, https, ftp, etc)
+     *
+     * @param string $scheme Scheme to set
+     *
+     * @return self
+     */
+    public function setScheme($scheme);
+
+    /**
+     * Get the host of the request
+     *
+     * @return string
+     */
+    public function getHost();
+
+    /**
+     * Set the host of the request. Including a port in the host will modify the port of the request.
+     *
+     * @param string $host Host to set (e.g. www.yahoo.com, www.yahoo.com:80)
+     *
+     * @return self
+     */
+    public function setHost($host);
+
+    /**
+     * Get the path of the request (e.g. '/', '/index.html')
+     *
+     * @return string
+     */
+    public function getPath();
+
+    /**
+     * Set the path of the request (e.g. '/', '/index.html')
+     *
+     * @param string|array $path Path to set or array of segments to implode
+     *
+     * @return self
+     */
+    public function setPath($path);
+
+    /**
+     * Get the port that the request will be sent on if it has been set
+     *
+     * @return int|null
+     */
+    public function getPort();
+
+    /**
+     * Set the port that the request will be sent on
+     *
+     * @param int $port Port number to set
+     *
+     * @return self
+     */
+    public function setPort($port);
+
+    /**
+     * Get the username to pass in the URL if set
+     *
+     * @return string|null
+     */
+    public function getUsername();
+
+    /**
+     * Get the password to pass in the URL if set
+     *
+     * @return string|null
+     */
+    public function getPassword();
+
+    /**
+     * Set HTTP authorization parameters
+     *
+     * @param string|bool $user     User name or false disable authentication
+     * @param string      $password Password
+     * @param string      $scheme   Authentication scheme ('Basic', 'Digest', or a CURLAUTH_* constant (deprecated))
+     *
+     * @return self
+     * @link http://www.ietf.org/rfc/rfc2617.txt
+     * @link http://php.net/manual/en/function.curl-setopt.php See the available options for CURLOPT_HTTPAUTH
+     * @throws RequestException
+     */
+    public function setAuth($user, $password = '', $scheme = 'Basic');
+
+    /**
+     * Get the HTTP protocol version of the request
+     *
+     * @return string
+     */
+    public function getProtocolVersion();
+
+    /**
+     * Set the HTTP protocol version of the request (e.g. 1.1 or 1.0)
+     *
+     * @param string $protocol HTTP protocol version to use with the request
+     *
+     * @return self
+     */
+    public function setProtocolVersion($protocol);
+
+    /**
+     * Get the previously received {@see Response} or NULL if the request has not been sent
+     *
+     * @return Response|null
+     */
+    public function getResponse();
+
+    /**
+     * Manually set a response for the request.
+     *
+     * This method is useful for specifying a mock response for the request or setting the response using a cache.
+     * Manually setting a response will bypass the actual sending of a request.
+     *
+     * @param Response $response Response object to set
+     * @param bool     $queued   Set to TRUE to keep the request in a state of not having been sent, but queue the
+     *                           response for send()
+     *
+     * @return self Returns a reference to the object.
+     */
+    public function setResponse(Response $response, $queued = false);
+
+    /**
+     * The start of a response has been received for a request and the request is still in progress
+     *
+     * @param Response $response Response that has been received so far
+     *
+     * @return self
+     */
+    public function startResponse(Response $response);
+
+    /**
+     * Set the EntityBody that will hold a successful response message's entity body.
+     *
+     * This method should be invoked when you need to send the response's entity body somewhere other than the normal
+     * php://temp buffer. For example, you can send the entity body to a socket, file, or some other custom stream.
+     *
+     * @param EntityBodyInterface|string|resource $body Response body object. Pass a string to attempt to store the
+     *                                                  response body in a local file.
+     * @return Request
+     */
+    public function setResponseBody($body);
+
+    /**
+     * Get the EntityBody that will hold the resulting response message's entity body. This response body will only
+     * be used for successful responses. Intermediate responses (e.g. redirects) will not use the targeted response
+     * body.
+     *
+     * @return EntityBodyInterface
+     */
+    public function getResponseBody();
+
+    /**
+     * Get the state of the request. One of 'complete', 'transfer', 'new', 'error'
+     *
+     * @return string
+     */
+    public function getState();
+
+    /**
+     * Set the state of the request
+     *
+     * @param string $state   State of the request ('complete', 'transfer', 'new', 'error')
+     * @param array  $context Contextual information about the state change
+     *
+     * @return string Returns the current state of the request (which may have changed due to events being fired)
+     */
+    public function setState($state, array $context = array());
+
+    /**
+     * Get the cURL options that will be applied when the cURL handle is created
+     *
+     * @return Collection
+     */
+    public function getCurlOptions();
+
+    /**
+     * Get an array of Cookies
+     *
+     * @return array
+     */
+    public function getCookies();
+
+    /**
+     * Get a cookie value by name
+     *
+     * @param string $name Cookie to retrieve
+     *
+     * @return null|string
+     */
+    public function getCookie($name);
+
+    /**
+     * Add a Cookie value by name to the Cookie header
+     *
+     * @param string $name  Name of the cookie to add
+     * @param string $value Value to set
+     *
+     * @return self
+     */
+    public function addCookie($name, $value);
+
+    /**
+     * Remove a specific cookie value by name
+     *
+     * @param string $name Cookie to remove by name
+     *
+     * @return self
+     */
+    public function removeCookie($name);
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Message/Response.php b/core/vendor/guzzle/http/Guzzle/Http/Message/Response.php
new file mode 100644
index 0000000..153e2dd
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Message/Response.php
@@ -0,0 +1,968 @@
+<?php
+
+namespace Guzzle\Http\Message;
+
+use Guzzle\Common\Version;
+use Guzzle\Common\ToArrayInterface;
+use Guzzle\Common\Exception\RuntimeException;
+use Guzzle\Http\EntityBodyInterface;
+use Guzzle\Http\EntityBody;
+use Guzzle\Http\Exception\BadResponseException;
+use Guzzle\Http\RedirectPlugin;
+use Guzzle\Parser\ParserRegistry;
+
+/**
+ * Guzzle HTTP response object
+ */
+class Response extends AbstractMessage implements \Serializable
+{
+    /**
+     * @var array Array of reason phrases and their corresponding status codes
+     */
+    private static $statusTexts = array(
+        100 => 'Continue',
+        101 => 'Switching Protocols',
+        102 => 'Processing',
+        200 => 'OK',
+        201 => 'Created',
+        202 => 'Accepted',
+        203 => 'Non-Authoritative Information',
+        204 => 'No Content',
+        205 => 'Reset Content',
+        206 => 'Partial Content',
+        207 => 'Multi-Status',
+        208 => 'Already Reported',
+        226 => 'IM Used',
+        300 => 'Multiple Choices',
+        301 => 'Moved Permanently',
+        302 => 'Found',
+        303 => 'See Other',
+        304 => 'Not Modified',
+        305 => 'Use Proxy',
+        307 => 'Temporary Redirect',
+        308 => 'Permanent Redirect',
+        400 => 'Bad Request',
+        401 => 'Unauthorized',
+        402 => 'Payment Required',
+        403 => 'Forbidden',
+        404 => 'Not Found',
+        405 => 'Method Not Allowed',
+        406 => 'Not Acceptable',
+        407 => 'Proxy Authentication Required',
+        408 => 'Request Timeout',
+        409 => 'Conflict',
+        410 => 'Gone',
+        411 => 'Length Required',
+        412 => 'Precondition Failed',
+        413 => 'Request Entity Too Large',
+        414 => 'Request-URI Too Long',
+        415 => 'Unsupported Media Type',
+        416 => 'Requested Range Not Satisfiable',
+        417 => 'Expectation Failed',
+        422 => 'Unprocessable Entity',
+        423 => 'Locked',
+        424 => 'Failed Dependency',
+        425 => 'Reserved for WebDAV advanced collections expired proposal',
+        426 => 'Upgrade required',
+        428 => 'Precondition Required',
+        429 => 'Too Many Requests',
+        431 => 'Request Header Fields Too Large',
+        500 => 'Internal Server Error',
+        501 => 'Not Implemented',
+        502 => 'Bad Gateway',
+        503 => 'Service Unavailable',
+        504 => 'Gateway Timeout',
+        505 => 'HTTP Version Not Supported',
+        506 => 'Variant Also Negotiates (Experimental)',
+        507 => 'Insufficient Storage',
+        508 => 'Loop Detected',
+        510 => 'Not Extended',
+        511 => 'Network Authentication Required',
+    );
+
+    /** @var EntityBodyInterface The response body */
+    protected $body;
+
+    /** @var string The reason phrase of the response (human readable code) */
+    protected $reasonPhrase;
+
+    /** @var string The status code of the response */
+    protected $statusCode;
+
+    /** @var array Information about the request */
+    protected $info = array();
+
+    /** @var string The effective URL that returned this response */
+    protected $effectiveUrl;
+
+    /** @var array Cacheable response codes (see RFC 2616:13.4) */
+    protected static $cacheResponseCodes = array(200, 203, 206, 300, 301, 410);
+
+    /**
+     * Create a new Response based on a raw response message
+     *
+     * @param string $message Response message
+     *
+     * @return self|bool Returns false on error
+     */
+    public static function fromMessage($message)
+    {
+        $data = ParserRegistry::getInstance()->getParser('message')->parseResponse($message);
+        if (!$data) {
+            return false;
+        }
+
+        $response = new static($data['code'], $data['headers'], $data['body']);
+        $response->setProtocol($data['protocol'], $data['version'])
+                 ->setStatus($data['code'], $data['reason_phrase']);
+
+        // Set the appropriate Content-Length if the one set is inaccurate (e.g. setting to X)
+        $contentLength = (string) $response->getHeader('Content-Length');
+        $actualLength = strlen($data['body']);
+        if (strlen($data['body']) > 0 && $contentLength != $actualLength) {
+            $response->setHeader('Content-Length', $actualLength);
+        }
+
+        return $response;
+    }
+
+    /**
+     * Construct the response
+     *
+     * @param string                              $statusCode The response status code (e.g. 200, 404, etc)
+     * @param ToArrayInterface|array              $headers    The response headers
+     * @param string|resource|EntityBodyInterface $body       The body of the response
+     *
+     * @throws BadResponseException if an invalid response code is given
+     */
+    public function __construct($statusCode, $headers = null, $body = null)
+    {
+        parent::__construct();
+        $this->setStatus($statusCode);
+        $this->body = EntityBody::factory($body !== null ? $body : '');
+
+        if ($headers) {
+            if (is_array($headers)) {
+                $this->setHeaders($headers);
+            } elseif ($headers instanceof ToArrayInterface) {
+                $this->setHeaders($headers->toArray());
+            } else {
+                throw new BadResponseException('Invalid headers argument received');
+            }
+        }
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->getMessage();
+    }
+
+    public function serialize()
+    {
+        return json_encode(array(
+            'status'  => $this->statusCode,
+            'body'    => (string) $this->body,
+            'headers' => $this->headers->toArray()
+        ));
+    }
+
+    public function unserialize($serialize)
+    {
+        $data = json_decode($serialize, true);
+        $this->__construct($data['status'], $data['headers'], $data['body']);
+    }
+
+    /**
+     * Get the response entity body
+     *
+     * @param bool $asString Set to TRUE to return a string of the body rather than a full body object
+     *
+     * @return EntityBodyInterface|string
+     */
+    public function getBody($asString = false)
+    {
+        return $asString ? (string) $this->body : $this->body;
+    }
+
+    /**
+     * Set the response entity body
+     *
+     * @param EntityBodyInterface|string $body Body to set
+     *
+     * @return self
+     */
+    public function setBody($body)
+    {
+        $this->body = EntityBody::factory($body);
+
+        return $this;
+    }
+
+    /**
+     * Set the protocol and protocol version of the response
+     *
+     * @param string $protocol Response protocol
+     * @param string $version  Protocol version
+     *
+     * @return self
+     */
+    public function setProtocol($protocol, $version)
+    {
+        $this->protocol = $protocol;
+        $this->protocolVersion = $version;
+
+        return $this;
+    }
+
+    /**
+     * Get the protocol used for the response (e.g. HTTP)
+     *
+     * @return string
+     */
+    public function getProtocol()
+    {
+        return $this->protocol;
+    }
+
+    /**
+     * Get the HTTP protocol version
+     *
+     * @return string
+     */
+    public function getProtocolVersion()
+    {
+        return $this->protocolVersion;
+    }
+
+    /**
+     * Get a cURL transfer information
+     *
+     * @param string $key A single statistic to check
+     *
+     * @return array|string|null Returns all stats if no key is set, a single stat if a key is set, or null if a key
+     *                           is set and not found
+     * @link http://www.php.net/manual/en/function.curl-getinfo.php
+     */
+    public function getInfo($key = null)
+    {
+        if ($key === null) {
+            return $this->info;
+        } elseif (array_key_exists($key, $this->info)) {
+            return $this->info[$key];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Set the transfer information
+     *
+     * @param array $info Array of cURL transfer stats
+     *
+     * @return self
+     */
+    public function setInfo(array $info)
+    {
+        $this->info = $info;
+
+        return $this;
+    }
+
+    /**
+     * Set the response status
+     *
+     * @param int    $statusCode   Response status code to set
+     * @param string $reasonPhrase Response reason phrase
+     *
+     * @return self
+     * @throws BadResponseException when an invalid response code is received
+     */
+    public function setStatus($statusCode, $reasonPhrase = '')
+    {
+        $this->statusCode = (int) $statusCode;
+
+        if (!$reasonPhrase && isset(self::$statusTexts[$this->statusCode])) {
+            $this->reasonPhrase = self::$statusTexts[$this->statusCode];
+        } else {
+            $this->reasonPhrase = $reasonPhrase;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get the response status code
+     *
+     * @return integer
+     */
+    public function getStatusCode()
+    {
+        return $this->statusCode;
+    }
+
+    /**
+     * Get the entire response as a string
+     *
+     * @return string
+     */
+    public function getMessage()
+    {
+        $message = $this->getRawHeaders();
+
+        // Only include the body in the message if the size is < 2MB
+        $size = $this->body->getSize();
+        if ($size < 2097152) {
+            $message .= (string) $this->body;
+        }
+
+        return $message;
+    }
+
+    /**
+     * Get the the raw message headers as a string
+     *
+     * @return string
+     */
+    public function getRawHeaders()
+    {
+        $headers = 'HTTP/1.1 ' . $this->statusCode . ' ' . $this->reasonPhrase . "\r\n";
+        $lines = $this->getHeaderLines();
+        if (!empty($lines)) {
+            $headers .= implode("\r\n", $lines) . "\r\n";
+        }
+
+        return $headers . "\r\n";
+    }
+
+    /**
+     * Get the response reason phrase- a human readable version of the numeric
+     * status code
+     *
+     * @return string
+     */
+    public function getReasonPhrase()
+    {
+        return $this->reasonPhrase;
+    }
+
+    /**
+     * Get the Accept-Ranges HTTP header
+     *
+     * @return string Returns what partial content range types this server supports.
+     */
+    public function getAcceptRanges()
+    {
+        return (string) $this->getHeader('Accept-Ranges');
+    }
+
+    /**
+     * Calculate the age of the response
+     *
+     * @return integer
+     */
+    public function calculateAge()
+    {
+        $age = $this->getHeader('Age');
+
+        if ($age === null && $this->getDate()) {
+            $age = time() - strtotime($this->getDate());
+        }
+
+        return $age === null ? null : (int) (string) $age;
+    }
+
+    /**
+     * Get the Age HTTP header
+     *
+     * @return integer|null Returns the age the object has been in a proxy cache in seconds.
+     */
+    public function getAge()
+    {
+        return (string) $this->getHeader('Age');
+    }
+
+    /**
+     * Get the Allow HTTP header
+     *
+     * @return string|null Returns valid actions for a specified resource. To be used for a 405 Method not allowed.
+     */
+    public function getAllow()
+    {
+        return (string) $this->getHeader('Allow');
+    }
+
+    /**
+     * Check if an HTTP method is allowed by checking the Allow response header
+     *
+     * @param string $method Method to check
+     *
+     * @return bool
+     */
+    public function isMethodAllowed($method)
+    {
+        $allow = $this->getHeader('Allow');
+        if ($allow) {
+            foreach (explode(',', $allow) as $allowable) {
+                if (!strcasecmp(trim($allowable), $method)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Get the Cache-Control HTTP header
+     *
+     * @return string
+     */
+    public function getCacheControl()
+    {
+        return (string) $this->getHeader('Cache-Control');
+    }
+
+    /**
+     * Get the Connection HTTP header
+     *
+     * @return string
+     */
+    public function getConnection()
+    {
+        return (string) $this->getHeader('Connection');
+    }
+
+    /**
+     * Get the Content-Encoding HTTP header
+     *
+     * @return string|null
+     */
+    public function getContentEncoding()
+    {
+        return (string) $this->getHeader('Content-Encoding');
+    }
+
+    /**
+     * Get the Content-Language HTTP header
+     *
+     * @return string|null Returns the language the content is in.
+     */
+    public function getContentLanguage()
+    {
+        return (string) $this->getHeader('Content-Language');
+    }
+
+    /**
+     * Get the Content-Length HTTP header
+     *
+     * @return integer Returns the length of the response body in bytes
+     */
+    public function getContentLength()
+    {
+        return (int) (string) $this->getHeader('Content-Length');
+    }
+
+    /**
+     * Get the Content-Location HTTP header
+     *
+     * @return string|null Returns an alternate location for the returned data (e.g /index.htm)
+     */
+    public function getContentLocation()
+    {
+        return (string) $this->getHeader('Content-Location');
+    }
+
+    /**
+     * Get the Content-Disposition HTTP header
+     *
+     * @return string|null Returns the Content-Disposition header
+     */
+    public function getContentDisposition()
+    {
+        return (string) $this->getHeader('Content-Disposition');
+    }
+
+    /**
+     * Get the Content-MD5 HTTP header
+     *
+     * @return string|null Returns a Base64-encoded binary MD5 sum of the content of the response.
+     */
+    public function getContentMd5()
+    {
+        return (string) $this->getHeader('Content-MD5');
+    }
+
+    /**
+     * Get the Content-Range HTTP header
+     *
+     * @return string Returns where in a full body message this partial message belongs (e.g. bytes 21010-47021/47022).
+     */
+    public function getContentRange()
+    {
+        return (string) $this->getHeader('Content-Range');
+    }
+
+    /**
+     * Get the Content-Type HTTP header
+     *
+     * @return string Returns the mime type of this content.
+     */
+    public function getContentType()
+    {
+        return (string) $this->getHeader('Content-Type');
+    }
+
+    /**
+     * Checks if the Content-Type is of a certain type.  This is useful if the
+     * Content-Type header contains charset information and you need to know if
+     * the Content-Type matches a particular type.
+     *
+     * @param string $type Content type to check against
+     *
+     * @return bool
+     */
+    public function isContentType($type)
+    {
+        return stripos($this->getHeader('Content-Type'), $type) !== false;
+    }
+
+    /**
+     * Get the Date HTTP header
+     *
+     * @return string|null Returns the date and time that the message was sent.
+     */
+    public function getDate()
+    {
+        return (string) $this->getHeader('Date');
+    }
+
+    /**
+     * Get the ETag HTTP header
+     *
+     * @return string|null Returns an identifier for a specific version of a resource, often a Message digest.
+     */
+    public function getEtag()
+    {
+        return (string) $this->getHeader('ETag');
+    }
+
+    /**
+     * Get the Expires HTTP header
+     *
+     * @return string|null Returns the date/time after which the response is considered stale.
+     */
+    public function getExpires()
+    {
+        return (string) $this->getHeader('Expires');
+    }
+
+    /**
+     * Get the Last-Modified HTTP header
+     *
+     * @return string|null Returns the last modified date for the requested object, in RFC 2822 format
+     *                     (e.g. Tue, 15 Nov 1994 12:45:26 GMT)
+     */
+    public function getLastModified()
+    {
+        return (string) $this->getHeader('Last-Modified');
+    }
+
+    /**
+     * Get the Location HTTP header
+     *
+     * @return string|null Used in redirection, or when a new resource has been created.
+     */
+    public function getLocation()
+    {
+        return (string) $this->getHeader('Location');
+    }
+
+    /**
+     * Get the Pragma HTTP header
+     *
+     * @return Header|null Returns the implementation-specific headers that may have various effects anywhere along
+     *                     the request-response chain.
+     */
+    public function getPragma()
+    {
+        return (string) $this->getHeader('Pragma');
+    }
+
+    /**
+     * Get the Proxy-Authenticate HTTP header
+     *
+     * @return string|null Authentication to access the proxy (e.g. Basic)
+     */
+    public function getProxyAuthenticate()
+    {
+        return (string) $this->getHeader('Proxy-Authenticate');
+    }
+
+    /**
+     * Get the Retry-After HTTP header
+     *
+     * @return int|null If an entity is temporarily unavailable, this instructs the client to try again after a
+     *                  specified period of time.
+     */
+    public function getRetryAfter()
+    {
+        return (string) $this->getHeader('Retry-After');
+    }
+
+    /**
+     * Get the Server HTTP header
+     *
+     * @return string|null A name for the server
+     */
+    public function getServer()
+    {
+        return (string)  $this->getHeader('Server');
+    }
+
+    /**
+     * Get the Set-Cookie HTTP header
+     *
+     * @return string|null An HTTP cookie.
+     */
+    public function getSetCookie()
+    {
+        return (string) $this->getHeader('Set-Cookie');
+    }
+
+    /**
+     * Get the Trailer HTTP header
+     *
+     * @return string|null The Trailer general field value indicates that the given set of header fields is present in
+     *                     the trailer of a message encoded with chunked transfer-coding.
+     */
+    public function getTrailer()
+    {
+        return (string) $this->getHeader('Trailer');
+    }
+
+    /**
+     * Get the Transfer-Encoding HTTP header
+     *
+     * @return string|null The form of encoding used to safely transfer the entity to the user
+     */
+    public function getTransferEncoding()
+    {
+        return (string) $this->getHeader('Transfer-Encoding');
+    }
+
+    /**
+     * Get the Vary HTTP header
+     *
+     * @return string|null Tells downstream proxies how to match future request headers to decide whether the cached
+     *                     response can be used rather than requesting a fresh one from the origin server.
+     */
+    public function getVary()
+    {
+        return (string) $this->getHeader('Vary');
+    }
+
+    /**
+     * Get the Via HTTP header
+     *
+     * @return string|null Informs the client of proxies through which the response was sent.
+     */
+    public function getVia()
+    {
+        return (string) $this->getHeader('Via');
+    }
+
+    /**
+     * Get the Warning HTTP header
+     *
+     * @return string|null A general warning about possible problems with the entity body
+     */
+    public function getWarning()
+    {
+        return (string) $this->getHeader('Warning');
+    }
+
+    /**
+     * Get the WWW-Authenticate HTTP header
+     *
+     * @return string|null Indicates the authentication scheme that should be used to access the requested entity
+     */
+    public function getWwwAuthenticate()
+    {
+        return (string) $this->getHeader('WWW-Authenticate');
+    }
+
+    /**
+     * Checks if HTTP Status code is a Client Error (4xx)
+     *
+     * @return bool
+     */
+    public function isClientError()
+    {
+        return $this->statusCode >= 400 && $this->statusCode < 500;
+    }
+
+    /**
+     * Checks if HTTP Status code is Server OR Client Error (4xx or 5xx)
+     *
+     * @return boolean
+     */
+    public function isError()
+    {
+        return $this->isClientError() || $this->isServerError();
+    }
+
+    /**
+     * Checks if HTTP Status code is Information (1xx)
+     *
+     * @return bool
+     */
+    public function isInformational()
+    {
+        return $this->statusCode < 200;
+    }
+
+    /**
+     * Checks if HTTP Status code is a Redirect (3xx)
+     *
+     * @return bool
+     */
+    public function isRedirect()
+    {
+        return $this->statusCode >= 300 && $this->statusCode < 400;
+    }
+
+    /**
+     * Checks if HTTP Status code is Server Error (5xx)
+     *
+     * @return bool
+     */
+    public function isServerError()
+    {
+        return $this->statusCode >= 500 && $this->statusCode < 600;
+    }
+
+    /**
+     * Checks if HTTP Status code is Successful (2xx | 304)
+     *
+     * @return bool
+     */
+    public function isSuccessful()
+    {
+        return ($this->statusCode >= 200 && $this->statusCode < 300) || $this->statusCode == 304;
+    }
+
+    /**
+     * Check if the response can be cached based on the response headers
+     *
+     * @return bool Returns TRUE if the response can be cached or false if not
+     */
+    public function canCache()
+    {
+        // Check if the response is cacheable based on the code
+        if (!in_array((int) $this->getStatusCode(), self::$cacheResponseCodes)) {
+            return false;
+        }
+
+        // Make sure a valid body was returned and can be cached
+        if ((!$this->getBody()->isReadable() || !$this->getBody()->isSeekable())
+            && ($this->getContentLength() > 0 || $this->getTransferEncoding() == 'chunked')) {
+            return false;
+        }
+
+        // Never cache no-store resources (this is a private cache, so private
+        // can be cached)
+        if ($this->getHeader('Cache-Control') && $this->getHeader('Cache-Control')->hasDirective('no-store')) {
+            return false;
+        }
+
+        return $this->isFresh() || $this->getFreshness() === null || $this->canValidate();
+    }
+
+    /**
+     * Gets the number of seconds from the current time in which this response is still considered fresh
+     *
+     * @return int|null Returns the number of seconds
+     */
+    public function getMaxAge()
+    {
+        if ($header = $this->getHeader('Cache-Control')) {
+            // s-max-age, then max-age, then Expires
+            if ($age = $header->getDirective('s-maxage')) {
+                return $age;
+            }
+            if ($age = $header->getDirective('max-age')) {
+                return $age;
+            }
+        }
+
+        if ($this->getHeader('Expires')) {
+            return strtotime($this->getExpires()) - time();
+        }
+
+        return null;
+    }
+
+    /**
+     * Check if the response is considered fresh.
+     *
+     * A response is considered fresh when its age is less than or equal to the freshness lifetime (maximum age) of the
+     * response.
+     *
+     * @return bool|null
+     */
+    public function isFresh()
+    {
+        $fresh = $this->getFreshness();
+
+        return $fresh === null ? null : $fresh >= 0;
+    }
+
+    /**
+     * Check if the response can be validated against the origin server using a conditional GET request.
+     *
+     * @return bool
+     */
+    public function canValidate()
+    {
+        return $this->getEtag() || $this->getLastModified();
+    }
+
+    /**
+     * Get the freshness of the response by returning the difference of the maximum lifetime of the response and the
+     * age of the response (max-age - age).
+     *
+     * Freshness values less than 0 mean that the response is no longer fresh and is ABS(freshness) seconds expired.
+     * Freshness values of greater than zero is the number of seconds until the response is no longer fresh. A NULL
+     * result means that no freshness information is available.
+     *
+     * @return int
+     */
+    public function getFreshness()
+    {
+        $maxAge = $this->getMaxAge();
+        $age = $this->calculateAge();
+
+        return $maxAge && $age ? ($maxAge - $age) : null;
+    }
+
+    /**
+     * Parse the JSON response body and return an array
+     *
+     * @return array|string|int|bool|float
+     * @throws RuntimeException if the response body is not in JSON format
+     */
+    public function json()
+    {
+        $data = json_decode((string) $this->body, true);
+        if (JSON_ERROR_NONE !== json_last_error()) {
+            throw new RuntimeException('Unable to parse response body into JSON: ' . json_last_error());
+        }
+
+        return $data === null ? array() : $data;
+    }
+
+    /**
+     * Parse the XML response body and return a \SimpleXMLElement.
+     *
+     * In order to prevent XXE attacks, this method disables loading external
+     * entities. If you rely on external entities, then you must parse the
+     * XML response manually by accessing the response body directly.
+     *
+     * @return \SimpleXMLElement
+     * @throws RuntimeException if the response body is not in XML format
+     * @link http://websec.io/2012/08/27/Preventing-XXE-in-PHP.html
+     */
+    public function xml()
+    {
+        $errorMessage = null;
+        $internalErrors = libxml_use_internal_errors(true);
+        $disableEntities = libxml_disable_entity_loader(true);
+        libxml_clear_errors();
+
+        try {
+            $xml = new \SimpleXMLElement((string) $this->body ?: '<root />', LIBXML_NONET);
+            if ($error = libxml_get_last_error()) {
+                $errorMessage = $error->message;
+            }
+        } catch (\Exception $e) {
+            $errorMessage = $e->getMessage();
+        }
+
+        libxml_clear_errors();
+        libxml_use_internal_errors($internalErrors);
+        libxml_disable_entity_loader($disableEntities);
+
+        if ($errorMessage) {
+            throw new RuntimeException('Unable to parse response body into XML: ' . $errorMessage);
+        }
+
+        return $xml;
+    }
+
+    /**
+     * Get the redirect count of this response
+     *
+     * @return int
+     */
+    public function getRedirectCount()
+    {
+        return (int) $this->params->get(RedirectPlugin::REDIRECT_COUNT);
+    }
+
+    /**
+     * Set the effective URL that resulted in this response (e.g. the last redirect URL)
+     *
+     * @param string $url The effective URL
+     *
+     * @return self
+     */
+    public function setEffectiveUrl($url)
+    {
+        $this->effectiveUrl = $url;
+
+        return $this;
+    }
+
+    /**
+     * Get the effective URL that resulted in this response (e.g. the last redirect URL)
+     *
+     * @return string
+     */
+    public function getEffectiveUrl()
+    {
+        return $this->effectiveUrl;
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function getPreviousResponse()
+    {
+        Version::warn(__METHOD__ . ' is deprecated. Use the HistoryPlugin.');
+        return null;
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function setRequest($request)
+    {
+        Version::warn(__METHOD__ . ' is deprecated');
+        return $this;
+    }
+
+    /**
+     * @deprecated
+     * @codeCoverageIgnore
+     */
+    public function getRequest()
+    {
+        Version::warn(__METHOD__ . ' is deprecated');
+        return null;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Mimetypes.php b/core/vendor/guzzle/http/Guzzle/Http/Mimetypes.php
new file mode 100644
index 0000000..d71586a
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Mimetypes.php
@@ -0,0 +1,962 @@
+<?php
+
+namespace Guzzle\Http;
+
+/**
+ * Provides mappings of file extensions to mimetypes
+ * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
+ */
+class Mimetypes
+{
+    /** @var self */
+    protected static $instance;
+
+    /** @var array Mapping of extension to mimetype */
+    protected $mimetypes = array(
+        '3dml' => 'text/vnd.in3d.3dml',
+        '3g2' => 'video/3gpp2',
+        '3gp' => 'video/3gpp',
+        '7z' => 'application/x-7z-compressed',
+        'aab' => 'application/x-authorware-bin',
+        'aac' => 'audio/x-aac',
+        'aam' => 'application/x-authorware-map',
+        'aas' => 'application/x-authorware-seg',
+        'abw' => 'application/x-abiword',
+        'ac' => 'application/pkix-attr-cert',
+        'acc' => 'application/vnd.americandynamics.acc',
+        'ace' => 'application/x-ace-compressed',
+        'acu' => 'application/vnd.acucobol',
+        'acutc' => 'application/vnd.acucorp',
+        'adp' => 'audio/adpcm',
+        'aep' => 'application/vnd.audiograph',
+        'afm' => 'application/x-font-type1',
+        'afp' => 'application/vnd.ibm.modcap',
+        'ahead' => 'application/vnd.ahead.space',
+        'ai' => 'application/postscript',
+        'aif' => 'audio/x-aiff',
+        'aifc' => 'audio/x-aiff',
+        'aiff' => 'audio/x-aiff',
+        'air' => 'application/vnd.adobe.air-application-installer-package+zip',
+        'ait' => 'application/vnd.dvb.ait',
+        'ami' => 'application/vnd.amiga.ami',
+        'apk' => 'application/vnd.android.package-archive',
+        'application' => 'application/x-ms-application',
+        'apr' => 'application/vnd.lotus-approach',
+        'asa' => 'text/plain',
+        'asax' => 'application/octet-stream',
+        'asc' => 'application/pgp-signature',
+        'ascx' => 'text/plain',
+        'asf' => 'video/x-ms-asf',
+        'ashx' => 'text/plain',
+        'asm' => 'text/x-asm',
+        'asmx' => 'text/plain',
+        'aso' => 'application/vnd.accpac.simply.aso',
+        'asp' => 'text/plain',
+        'aspx' => 'text/plain',
+        'asx' => 'video/x-ms-asf',
+        'atc' => 'application/vnd.acucorp',
+        'atom' => 'application/atom+xml',
+        'atomcat' => 'application/atomcat+xml',
+        'atomsvc' => 'application/atomsvc+xml',
+        'atx' => 'application/vnd.antix.game-component',
+        'au' => 'audio/basic',
+        'avi' => 'video/x-msvideo',
+        'aw' => 'application/applixware',
+        'axd' => 'text/plain',
+        'azf' => 'application/vnd.airzip.filesecure.azf',
+        'azs' => 'application/vnd.airzip.filesecure.azs',
+        'azw' => 'application/vnd.amazon.ebook',
+        'bat' => 'application/x-msdownload',
+        'bcpio' => 'application/x-bcpio',
+        'bdf' => 'application/x-font-bdf',
+        'bdm' => 'application/vnd.syncml.dm+wbxml',
+        'bed' => 'application/vnd.realvnc.bed',
+        'bh2' => 'application/vnd.fujitsu.oasysprs',
+        'bin' => 'application/octet-stream',
+        'bmi' => 'application/vnd.bmi',
+        'bmp' => 'image/bmp',
+        'book' => 'application/vnd.framemaker',
+        'box' => 'application/vnd.previewsystems.box',
+        'boz' => 'application/x-bzip2',
+        'bpk' => 'application/octet-stream',
+        'btif' => 'image/prs.btif',
+        'bz' => 'application/x-bzip',
+        'bz2' => 'application/x-bzip2',
+        'c' => 'text/x-c',
+        'c11amc' => 'application/vnd.cluetrust.cartomobile-config',
+        'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg',
+        'c4d' => 'application/vnd.clonk.c4group',
+        'c4f' => 'application/vnd.clonk.c4group',
+        'c4g' => 'application/vnd.clonk.c4group',
+        'c4p' => 'application/vnd.clonk.c4group',
+        'c4u' => 'application/vnd.clonk.c4group',
+        'cab' => 'application/vnd.ms-cab-compressed',
+        'car' => 'application/vnd.curl.car',
+        'cat' => 'application/vnd.ms-pki.seccat',
+        'cc' => 'text/x-c',
+        'cct' => 'application/x-director',
+        'ccxml' => 'application/ccxml+xml',
+        'cdbcmsg' => 'application/vnd.contact.cmsg',
+        'cdf' => 'application/x-netcdf',
+        'cdkey' => 'application/vnd.mediastation.cdkey',
+        'cdmia' => 'application/cdmi-capability',
+        'cdmic' => 'application/cdmi-container',
+        'cdmid' => 'application/cdmi-domain',
+        'cdmio' => 'application/cdmi-object',
+        'cdmiq' => 'application/cdmi-queue',
+        'cdx' => 'chemical/x-cdx',
+        'cdxml' => 'application/vnd.chemdraw+xml',
+        'cdy' => 'application/vnd.cinderella',
+        'cer' => 'application/pkix-cert',
+        'cfc' => 'application/x-coldfusion',
+        'cfm' => 'application/x-coldfusion',
+        'cgm' => 'image/cgm',
+        'chat' => 'application/x-chat',
+        'chm' => 'application/vnd.ms-htmlhelp',
+        'chrt' => 'application/vnd.kde.kchart',
+        'cif' => 'chemical/x-cif',
+        'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
+        'cil' => 'application/vnd.ms-artgalry',
+        'cla' => 'application/vnd.claymore',
+        'class' => 'application/java-vm',
+        'clkk' => 'application/vnd.crick.clicker.keyboard',
+        'clkp' => 'application/vnd.crick.clicker.palette',
+        'clkt' => 'application/vnd.crick.clicker.template',
+        'clkw' => 'application/vnd.crick.clicker.wordbank',
+        'clkx' => 'application/vnd.crick.clicker',
+        'clp' => 'application/x-msclip',
+        'cmc' => 'application/vnd.cosmocaller',
+        'cmdf' => 'chemical/x-cmdf',
+        'cml' => 'chemical/x-cml',
+        'cmp' => 'application/vnd.yellowriver-custom-menu',
+        'cmx' => 'image/x-cmx',
+        'cod' => 'application/vnd.rim.cod',
+        'com' => 'application/x-msdownload',
+        'conf' => 'text/plain',
+        'cpio' => 'application/x-cpio',
+        'cpp' => 'text/x-c',
+        'cpt' => 'application/mac-compactpro',
+        'crd' => 'application/x-mscardfile',
+        'crl' => 'application/pkix-crl',
+        'crt' => 'application/x-x509-ca-cert',
+        'cryptonote' => 'application/vnd.rig.cryptonote',
+        'cs' => 'text/plain',
+        'csh' => 'application/x-csh',
+        'csml' => 'chemical/x-csml',
+        'csp' => 'application/vnd.commonspace',
+        'css' => 'text/css',
+        'cst' => 'application/x-director',
+        'csv' => 'text/csv',
+        'cu' => 'application/cu-seeme',
+        'curl' => 'text/vnd.curl',
+        'cww' => 'application/prs.cww',
+        'cxt' => 'application/x-director',
+        'cxx' => 'text/x-c',
+        'dae' => 'model/vnd.collada+xml',
+        'daf' => 'application/vnd.mobius.daf',
+        'dataless' => 'application/vnd.fdsn.seed',
+        'davmount' => 'application/davmount+xml',
+        'dcr' => 'application/x-director',
+        'dcurl' => 'text/vnd.curl.dcurl',
+        'dd2' => 'application/vnd.oma.dd2+xml',
+        'ddd' => 'application/vnd.fujixerox.ddd',
+        'deb' => 'application/x-debian-package',
+        'def' => 'text/plain',
+        'deploy' => 'application/octet-stream',
+        'der' => 'application/x-x509-ca-cert',
+        'dfac' => 'application/vnd.dreamfactory',
+        'dic' => 'text/x-c',
+        'dir' => 'application/x-director',
+        'dis' => 'application/vnd.mobius.dis',
+        'dist' => 'application/octet-stream',
+        'distz' => 'application/octet-stream',
+        'djv' => 'image/vnd.djvu',
+        'djvu' => 'image/vnd.djvu',
+        'dll' => 'application/x-msdownload',
+        'dmg' => 'application/octet-stream',
+        'dms' => 'application/octet-stream',
+        'dna' => 'application/vnd.dna',
+        'doc' => 'application/msword',
+        'docm' => 'application/vnd.ms-word.document.macroenabled.12',
+        'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+        'dot' => 'application/msword',
+        'dotm' => 'application/vnd.ms-word.template.macroenabled.12',
+        'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+        'dp' => 'application/vnd.osgi.dp',
+        'dpg' => 'application/vnd.dpgraph',
+        'dra' => 'audio/vnd.dra',
+        'dsc' => 'text/prs.lines.tag',
+        'dssc' => 'application/dssc+der',
+        'dtb' => 'application/x-dtbook+xml',
+        'dtd' => 'application/xml-dtd',
+        'dts' => 'audio/vnd.dts',
+        'dtshd' => 'audio/vnd.dts.hd',
+        'dump' => 'application/octet-stream',
+        'dvi' => 'application/x-dvi',
+        'dwf' => 'model/vnd.dwf',
+        'dwg' => 'image/vnd.dwg',
+        'dxf' => 'image/vnd.dxf',
+        'dxp' => 'application/vnd.spotfire.dxp',
+        'dxr' => 'application/x-director',
+        'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
+        'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
+        'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
+        'ecma' => 'application/ecmascript',
+        'edm' => 'application/vnd.novadigm.edm',
+        'edx' => 'application/vnd.novadigm.edx',
+        'efif' => 'application/vnd.picsel',
+        'ei6' => 'application/vnd.pg.osasli',
+        'elc' => 'application/octet-stream',
+        'eml' => 'message/rfc822',
+        'emma' => 'application/emma+xml',
+        'eol' => 'audio/vnd.digital-winds',
+        'eot' => 'application/vnd.ms-fontobject',
+        'eps' => 'application/postscript',
+        'epub' => 'application/epub+zip',
+        'es3' => 'application/vnd.eszigno3+xml',
+        'esf' => 'application/vnd.epson.esf',
+        'et3' => 'application/vnd.eszigno3+xml',
+        'etx' => 'text/x-setext',
+        'exe' => 'application/x-msdownload',
+        'exi' => 'application/exi',
+        'ext' => 'application/vnd.novadigm.ext',
+        'ez' => 'application/andrew-inset',
+        'ez2' => 'application/vnd.ezpix-album',
+        'ez3' => 'application/vnd.ezpix-package',
+        'f' => 'text/x-fortran',
+        'f4v' => 'video/x-f4v',
+        'f77' => 'text/x-fortran',
+        'f90' => 'text/x-fortran',
+        'fbs' => 'image/vnd.fastbidsheet',
+        'fcs' => 'application/vnd.isac.fcs',
+        'fdf' => 'application/vnd.fdf',
+        'fe_launch' => 'application/vnd.denovo.fcselayout-link',
+        'fg5' => 'application/vnd.fujitsu.oasysgp',
+        'fgd' => 'application/x-director',
+        'fh' => 'image/x-freehand',
+        'fh4' => 'image/x-freehand',
+        'fh5' => 'image/x-freehand',
+        'fh7' => 'image/x-freehand',
+        'fhc' => 'image/x-freehand',
+        'fig' => 'application/x-xfig',
+        'fli' => 'video/x-fli',
+        'flo' => 'application/vnd.micrografx.flo',
+        'flv' => 'video/x-flv',
+        'flw' => 'application/vnd.kde.kivio',
+        'flx' => 'text/vnd.fmi.flexstor',
+        'fly' => 'text/vnd.fly',
+        'fm' => 'application/vnd.framemaker',
+        'fnc' => 'application/vnd.frogans.fnc',
+        'for' => 'text/x-fortran',
+        'fpx' => 'image/vnd.fpx',
+        'frame' => 'application/vnd.framemaker',
+        'fsc' => 'application/vnd.fsc.weblaunch',
+        'fst' => 'image/vnd.fst',
+        'ftc' => 'application/vnd.fluxtime.clip',
+        'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
+        'fvt' => 'video/vnd.fvt',
+        'fxp' => 'application/vnd.adobe.fxp',
+        'fxpl' => 'application/vnd.adobe.fxp',
+        'fzs' => 'application/vnd.fuzzysheet',
+        'g2w' => 'application/vnd.geoplan',
+        'g3' => 'image/g3fax',
+        'g3w' => 'application/vnd.geospace',
+        'gac' => 'application/vnd.groove-account',
+        'gdl' => 'model/vnd.gdl',
+        'geo' => 'application/vnd.dynageo',
+        'gex' => 'application/vnd.geometry-explorer',
+        'ggb' => 'application/vnd.geogebra.file',
+        'ggt' => 'application/vnd.geogebra.tool',
+        'ghf' => 'application/vnd.groove-help',
+        'gif' => 'image/gif',
+        'gim' => 'application/vnd.groove-identity-message',
+        'gmx' => 'application/vnd.gmx',
+        'gnumeric' => 'application/x-gnumeric',
+        'gph' => 'application/vnd.flographit',
+        'gqf' => 'application/vnd.grafeq',
+        'gqs' => 'application/vnd.grafeq',
+        'gram' => 'application/srgs',
+        'gre' => 'application/vnd.geometry-explorer',
+        'grv' => 'application/vnd.groove-injector',
+        'grxml' => 'application/srgs+xml',
+        'gsf' => 'application/x-font-ghostscript',
+        'gtar' => 'application/x-gtar',
+        'gtm' => 'application/vnd.groove-tool-message',
+        'gtw' => 'model/vnd.gtw',
+        'gv' => 'text/vnd.graphviz',
+        'gxt' => 'application/vnd.geonext',
+        'h' => 'text/x-c',
+        'h261' => 'video/h261',
+        'h263' => 'video/h263',
+        'h264' => 'video/h264',
+        'hal' => 'application/vnd.hal+xml',
+        'hbci' => 'application/vnd.hbci',
+        'hdf' => 'application/x-hdf',
+        'hh' => 'text/x-c',
+        'hlp' => 'application/winhlp',
+        'hpgl' => 'application/vnd.hp-hpgl',
+        'hpid' => 'application/vnd.hp-hpid',
+        'hps' => 'application/vnd.hp-hps',
+        'hqx' => 'application/mac-binhex40',
+        'hta' => 'application/octet-stream',
+        'htc' => 'text/html',
+        'htke' => 'application/vnd.kenameaapp',
+        'htm' => 'text/html',
+        'html' => 'text/html',
+        'hvd' => 'application/vnd.yamaha.hv-dic',
+        'hvp' => 'application/vnd.yamaha.hv-voice',
+        'hvs' => 'application/vnd.yamaha.hv-script',
+        'i2g' => 'application/vnd.intergeo',
+        'icc' => 'application/vnd.iccprofile',
+        'ice' => 'x-conference/x-cooltalk',
+        'icm' => 'application/vnd.iccprofile',
+        'ico' => 'image/x-icon',
+        'ics' => 'text/calendar',
+        'ief' => 'image/ief',
+        'ifb' => 'text/calendar',
+        'ifm' => 'application/vnd.shana.informed.formdata',
+        'iges' => 'model/iges',
+        'igl' => 'application/vnd.igloader',
+        'igm' => 'application/vnd.insors.igm',
+        'igs' => 'model/iges',
+        'igx' => 'application/vnd.micrografx.igx',
+        'iif' => 'application/vnd.shana.informed.interchange',
+        'imp' => 'application/vnd.accpac.simply.imp',
+        'ims' => 'application/vnd.ms-ims',
+        'in' => 'text/plain',
+        'ini' => 'text/plain',
+        'ipfix' => 'application/ipfix',
+        'ipk' => 'application/vnd.shana.informed.package',
+        'irm' => 'application/vnd.ibm.rights-management',
+        'irp' => 'application/vnd.irepository.package+xml',
+        'iso' => 'application/octet-stream',
+        'itp' => 'application/vnd.shana.informed.formtemplate',
+        'ivp' => 'application/vnd.immervision-ivp',
+        'ivu' => 'application/vnd.immervision-ivu',
+        'jad' => 'text/vnd.sun.j2me.app-descriptor',
+        'jam' => 'application/vnd.jam',
+        'jar' => 'application/java-archive',
+        'java' => 'text/x-java-source',
+        'jisp' => 'application/vnd.jisp',
+        'jlt' => 'application/vnd.hp-jlyt',
+        'jnlp' => 'application/x-java-jnlp-file',
+        'joda' => 'application/vnd.joost.joda-archive',
+        'jpe' => 'image/jpeg',
+        'jpeg' => 'image/jpeg',
+        'jpg' => 'image/jpeg',
+        'jpgm' => 'video/jpm',
+        'jpgv' => 'video/jpeg',
+        'jpm' => 'video/jpm',
+        'js' => 'text/javascript',
+        'json' => 'application/json',
+        'kar' => 'audio/midi',
+        'karbon' => 'application/vnd.kde.karbon',
+        'kfo' => 'application/vnd.kde.kformula',
+        'kia' => 'application/vnd.kidspiration',
+        'kml' => 'application/vnd.google-earth.kml+xml',
+        'kmz' => 'application/vnd.google-earth.kmz',
+        'kne' => 'application/vnd.kinar',
+        'knp' => 'application/vnd.kinar',
+        'kon' => 'application/vnd.kde.kontour',
+        'kpr' => 'application/vnd.kde.kpresenter',
+        'kpt' => 'application/vnd.kde.kpresenter',
+        'ksp' => 'application/vnd.kde.kspread',
+        'ktr' => 'application/vnd.kahootz',
+        'ktx' => 'image/ktx',
+        'ktz' => 'application/vnd.kahootz',
+        'kwd' => 'application/vnd.kde.kword',
+        'kwt' => 'application/vnd.kde.kword',
+        'lasxml' => 'application/vnd.las.las+xml',
+        'latex' => 'application/x-latex',
+        'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
+        'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
+        'les' => 'application/vnd.hhe.lesson-player',
+        'lha' => 'application/octet-stream',
+        'link66' => 'application/vnd.route66.link66+xml',
+        'list' => 'text/plain',
+        'list3820' => 'application/vnd.ibm.modcap',
+        'listafp' => 'application/vnd.ibm.modcap',
+        'log' => 'text/plain',
+        'lostxml' => 'application/lost+xml',
+        'lrf' => 'application/octet-stream',
+        'lrm' => 'application/vnd.ms-lrm',
+        'ltf' => 'application/vnd.frogans.ltf',
+        'lvp' => 'audio/vnd.lucent.voice',
+        'lwp' => 'application/vnd.lotus-wordpro',
+        'lzh' => 'application/octet-stream',
+        'm13' => 'application/x-msmediaview',
+        'm14' => 'application/x-msmediaview',
+        'm1v' => 'video/mpeg',
+        'm21' => 'application/mp21',
+        'm2a' => 'audio/mpeg',
+        'm2v' => 'video/mpeg',
+        'm3a' => 'audio/mpeg',
+        'm3u' => 'audio/x-mpegurl',
+        'm3u8' => 'application/vnd.apple.mpegurl',
+        'm4a' => 'audio/mp4',
+        'm4u' => 'video/vnd.mpegurl',
+        'm4v' => 'video/mp4',
+        'ma' => 'application/mathematica',
+        'mads' => 'application/mads+xml',
+        'mag' => 'application/vnd.ecowin.chart',
+        'maker' => 'application/vnd.framemaker',
+        'man' => 'text/troff',
+        'mathml' => 'application/mathml+xml',
+        'mb' => 'application/mathematica',
+        'mbk' => 'application/vnd.mobius.mbk',
+        'mbox' => 'application/mbox',
+        'mc1' => 'application/vnd.medcalcdata',
+        'mcd' => 'application/vnd.mcd',
+        'mcurl' => 'text/vnd.curl.mcurl',
+        'mdb' => 'application/x-msaccess',
+        'mdi' => 'image/vnd.ms-modi',
+        'me' => 'text/troff',
+        'mesh' => 'model/mesh',
+        'meta4' => 'application/metalink4+xml',
+        'mets' => 'application/mets+xml',
+        'mfm' => 'application/vnd.mfmp',
+        'mgp' => 'application/vnd.osgeo.mapguide.package',
+        'mgz' => 'application/vnd.proteus.magazine',
+        'mid' => 'audio/midi',
+        'midi' => 'audio/midi',
+        'mif' => 'application/vnd.mif',
+        'mime' => 'message/rfc822',
+        'mj2' => 'video/mj2',
+        'mjp2' => 'video/mj2',
+        'mlp' => 'application/vnd.dolby.mlp',
+        'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
+        'mmf' => 'application/vnd.smaf',
+        'mmr' => 'image/vnd.fujixerox.edmics-mmr',
+        'mny' => 'application/x-msmoney',
+        'mobi' => 'application/x-mobipocket-ebook',
+        'mods' => 'application/mods+xml',
+        'mov' => 'video/quicktime',
+        'movie' => 'video/x-sgi-movie',
+        'mp2' => 'audio/mpeg',
+        'mp21' => 'application/mp21',
+        'mp2a' => 'audio/mpeg',
+        'mp3' => 'audio/mpeg',
+        'mp4' => 'video/mp4',
+        'mp4a' => 'audio/mp4',
+        'mp4s' => 'application/mp4',
+        'mp4v' => 'video/mp4',
+        'mpc' => 'application/vnd.mophun.certificate',
+        'mpe' => 'video/mpeg',
+        'mpeg' => 'video/mpeg',
+        'mpg' => 'video/mpeg',
+        'mpg4' => 'video/mp4',
+        'mpga' => 'audio/mpeg',
+        'mpkg' => 'application/vnd.apple.installer+xml',
+        'mpm' => 'application/vnd.blueice.multipass',
+        'mpn' => 'application/vnd.mophun.application',
+        'mpp' => 'application/vnd.ms-project',
+        'mpt' => 'application/vnd.ms-project',
+        'mpy' => 'application/vnd.ibm.minipay',
+        'mqy' => 'application/vnd.mobius.mqy',
+        'mrc' => 'application/marc',
+        'mrcx' => 'application/marcxml+xml',
+        'ms' => 'text/troff',
+        'mscml' => 'application/mediaservercontrol+xml',
+        'mseed' => 'application/vnd.fdsn.mseed',
+        'mseq' => 'application/vnd.mseq',
+        'msf' => 'application/vnd.epson.msf',
+        'msh' => 'model/mesh',
+        'msi' => 'application/x-msdownload',
+        'msl' => 'application/vnd.mobius.msl',
+        'msty' => 'application/vnd.muvee.style',
+        'mts' => 'model/vnd.mts',
+        'mus' => 'application/vnd.musician',
+        'musicxml' => 'application/vnd.recordare.musicxml+xml',
+        'mvb' => 'application/x-msmediaview',
+        'mwf' => 'application/vnd.mfer',
+        'mxf' => 'application/mxf',
+        'mxl' => 'application/vnd.recordare.musicxml',
+        'mxml' => 'application/xv+xml',
+        'mxs' => 'application/vnd.triscape.mxs',
+        'mxu' => 'video/vnd.mpegurl',
+        'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
+        'n3' => 'text/n3',
+        'nb' => 'application/mathematica',
+        'nbp' => 'application/vnd.wolfram.player',
+        'nc' => 'application/x-netcdf',
+        'ncx' => 'application/x-dtbncx+xml',
+        'ngdat' => 'application/vnd.nokia.n-gage.data',
+        'nlu' => 'application/vnd.neurolanguage.nlu',
+        'nml' => 'application/vnd.enliven',
+        'nnd' => 'application/vnd.noblenet-directory',
+        'nns' => 'application/vnd.noblenet-sealer',
+        'nnw' => 'application/vnd.noblenet-web',
+        'npx' => 'image/vnd.net-fpx',
+        'nsf' => 'application/vnd.lotus-notes',
+        'oa2' => 'application/vnd.fujitsu.oasys2',
+        'oa3' => 'application/vnd.fujitsu.oasys3',
+        'oas' => 'application/vnd.fujitsu.oasys',
+        'obd' => 'application/x-msbinder',
+        'oda' => 'application/oda',
+        'odb' => 'application/vnd.oasis.opendocument.database',
+        'odc' => 'application/vnd.oasis.opendocument.chart',
+        'odf' => 'application/vnd.oasis.opendocument.formula',
+        'odft' => 'application/vnd.oasis.opendocument.formula-template',
+        'odg' => 'application/vnd.oasis.opendocument.graphics',
+        'odi' => 'application/vnd.oasis.opendocument.image',
+        'odm' => 'application/vnd.oasis.opendocument.text-master',
+        'odp' => 'application/vnd.oasis.opendocument.presentation',
+        'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+        'odt' => 'application/vnd.oasis.opendocument.text',
+        'oga' => 'audio/ogg',
+        'ogg' => 'audio/ogg',
+        'ogv' => 'video/ogg',
+        'ogx' => 'application/ogg',
+        'onepkg' => 'application/onenote',
+        'onetmp' => 'application/onenote',
+        'onetoc' => 'application/onenote',
+        'onetoc2' => 'application/onenote',
+        'opf' => 'application/oebps-package+xml',
+        'oprc' => 'application/vnd.palm',
+        'org' => 'application/vnd.lotus-organizer',
+        'osf' => 'application/vnd.yamaha.openscoreformat',
+        'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
+        'otc' => 'application/vnd.oasis.opendocument.chart-template',
+        'otf' => 'application/x-font-otf',
+        'otg' => 'application/vnd.oasis.opendocument.graphics-template',
+        'oth' => 'application/vnd.oasis.opendocument.text-web',
+        'oti' => 'application/vnd.oasis.opendocument.image-template',
+        'otp' => 'application/vnd.oasis.opendocument.presentation-template',
+        'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
+        'ott' => 'application/vnd.oasis.opendocument.text-template',
+        'oxt' => 'application/vnd.openofficeorg.extension',
+        'p' => 'text/x-pascal',
+        'p10' => 'application/pkcs10',
+        'p12' => 'application/x-pkcs12',
+        'p7b' => 'application/x-pkcs7-certificates',
+        'p7c' => 'application/pkcs7-mime',
+        'p7m' => 'application/pkcs7-mime',
+        'p7r' => 'application/x-pkcs7-certreqresp',
+        'p7s' => 'application/pkcs7-signature',
+        'p8' => 'application/pkcs8',
+        'pas' => 'text/x-pascal',
+        'paw' => 'application/vnd.pawaafile',
+        'pbd' => 'application/vnd.powerbuilder6',
+        'pbm' => 'image/x-portable-bitmap',
+        'pcf' => 'application/x-font-pcf',
+        'pcl' => 'application/vnd.hp-pcl',
+        'pclxl' => 'application/vnd.hp-pclxl',
+        'pct' => 'image/x-pict',
+        'pcurl' => 'application/vnd.curl.pcurl',
+        'pcx' => 'image/x-pcx',
+        'pdb' => 'application/vnd.palm',
+        'pdf' => 'application/pdf',
+        'pfa' => 'application/x-font-type1',
+        'pfb' => 'application/x-font-type1',
+        'pfm' => 'application/x-font-type1',
+        'pfr' => 'application/font-tdpfr',
+        'pfx' => 'application/x-pkcs12',
+        'pgm' => 'image/x-portable-graymap',
+        'pgn' => 'application/x-chess-pgn',
+        'pgp' => 'application/pgp-encrypted',
+        'php' => 'text/x-php',
+        'phps' => 'application/x-httpd-phps',
+        'pic' => 'image/x-pict',
+        'pkg' => 'application/octet-stream',
+        'pki' => 'application/pkixcmp',
+        'pkipath' => 'application/pkix-pkipath',
+        'plb' => 'application/vnd.3gpp.pic-bw-large',
+        'plc' => 'application/vnd.mobius.plc',
+        'plf' => 'application/vnd.pocketlearn',
+        'pls' => 'application/pls+xml',
+        'pml' => 'application/vnd.ctc-posml',
+        'png' => 'image/png',
+        'pnm' => 'image/x-portable-anymap',
+        'portpkg' => 'application/vnd.macports.portpkg',
+        'pot' => 'application/vnd.ms-powerpoint',
+        'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12',
+        'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+        'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12',
+        'ppd' => 'application/vnd.cups-ppd',
+        'ppm' => 'image/x-portable-pixmap',
+        'pps' => 'application/vnd.ms-powerpoint',
+        'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
+        'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+        'ppt' => 'application/vnd.ms-powerpoint',
+        'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
+        'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+        'pqa' => 'application/vnd.palm',
+        'prc' => 'application/x-mobipocket-ebook',
+        'pre' => 'application/vnd.lotus-freelance',
+        'prf' => 'application/pics-rules',
+        'ps' => 'application/postscript',
+        'psb' => 'application/vnd.3gpp.pic-bw-small',
+        'psd' => 'image/vnd.adobe.photoshop',
+        'psf' => 'application/x-font-linux-psf',
+        'pskcxml' => 'application/pskc+xml',
+        'ptid' => 'application/vnd.pvi.ptid1',
+        'pub' => 'application/x-mspublisher',
+        'pvb' => 'application/vnd.3gpp.pic-bw-var',
+        'pwn' => 'application/vnd.3m.post-it-notes',
+        'pya' => 'audio/vnd.ms-playready.media.pya',
+        'pyv' => 'video/vnd.ms-playready.media.pyv',
+        'qam' => 'application/vnd.epson.quickanime',
+        'qbo' => 'application/vnd.intu.qbo',
+        'qfx' => 'application/vnd.intu.qfx',
+        'qps' => 'application/vnd.publishare-delta-tree',
+        'qt' => 'video/quicktime',
+        'qwd' => 'application/vnd.quark.quarkxpress',
+        'qwt' => 'application/vnd.quark.quarkxpress',
+        'qxb' => 'application/vnd.quark.quarkxpress',
+        'qxd' => 'application/vnd.quark.quarkxpress',
+        'qxl' => 'application/vnd.quark.quarkxpress',
+        'qxt' => 'application/vnd.quark.quarkxpress',
+        'ra' => 'audio/x-pn-realaudio',
+        'ram' => 'audio/x-pn-realaudio',
+        'rar' => 'application/x-rar-compressed',
+        'ras' => 'image/x-cmu-raster',
+        'rb' => 'text/plain',
+        'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
+        'rdf' => 'application/rdf+xml',
+        'rdz' => 'application/vnd.data-vision.rdz',
+        'rep' => 'application/vnd.businessobjects',
+        'res' => 'application/x-dtbresource+xml',
+        'resx' => 'text/xml',
+        'rgb' => 'image/x-rgb',
+        'rif' => 'application/reginfo+xml',
+        'rip' => 'audio/vnd.rip',
+        'rl' => 'application/resource-lists+xml',
+        'rlc' => 'image/vnd.fujixerox.edmics-rlc',
+        'rld' => 'application/resource-lists-diff+xml',
+        'rm' => 'application/vnd.rn-realmedia',
+        'rmi' => 'audio/midi',
+        'rmp' => 'audio/x-pn-realaudio-plugin',
+        'rms' => 'application/vnd.jcp.javame.midlet-rms',
+        'rnc' => 'application/relax-ng-compact-syntax',
+        'roff' => 'text/troff',
+        'rp9' => 'application/vnd.cloanto.rp9',
+        'rpss' => 'application/vnd.nokia.radio-presets',
+        'rpst' => 'application/vnd.nokia.radio-preset',
+        'rq' => 'application/sparql-query',
+        'rs' => 'application/rls-services+xml',
+        'rsd' => 'application/rsd+xml',
+        'rss' => 'application/rss+xml',
+        'rtf' => 'application/rtf',
+        'rtx' => 'text/richtext',
+        's' => 'text/x-asm',
+        'saf' => 'application/vnd.yamaha.smaf-audio',
+        'sbml' => 'application/sbml+xml',
+        'sc' => 'application/vnd.ibm.secure-container',
+        'scd' => 'application/x-msschedule',
+        'scm' => 'application/vnd.lotus-screencam',
+        'scq' => 'application/scvp-cv-request',
+        'scs' => 'application/scvp-cv-response',
+        'scurl' => 'text/vnd.curl.scurl',
+        'sda' => 'application/vnd.stardivision.draw',
+        'sdc' => 'application/vnd.stardivision.calc',
+        'sdd' => 'application/vnd.stardivision.impress',
+        'sdkd' => 'application/vnd.solent.sdkm+xml',
+        'sdkm' => 'application/vnd.solent.sdkm+xml',
+        'sdp' => 'application/sdp',
+        'sdw' => 'application/vnd.stardivision.writer',
+        'see' => 'application/vnd.seemail',
+        'seed' => 'application/vnd.fdsn.seed',
+        'sema' => 'application/vnd.sema',
+        'semd' => 'application/vnd.semd',
+        'semf' => 'application/vnd.semf',
+        'ser' => 'application/java-serialized-object',
+        'setpay' => 'application/set-payment-initiation',
+        'setreg' => 'application/set-registration-initiation',
+        'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
+        'sfs' => 'application/vnd.spotfire.sfs',
+        'sgl' => 'application/vnd.stardivision.writer-global',
+        'sgm' => 'text/sgml',
+        'sgml' => 'text/sgml',
+        'sh' => 'application/x-sh',
+        'shar' => 'application/x-shar',
+        'shf' => 'application/shf+xml',
+        'sig' => 'application/pgp-signature',
+        'silo' => 'model/mesh',
+        'sis' => 'application/vnd.symbian.install',
+        'sisx' => 'application/vnd.symbian.install',
+        'sit' => 'application/x-stuffit',
+        'sitx' => 'application/x-stuffitx',
+        'skd' => 'application/vnd.koan',
+        'skm' => 'application/vnd.koan',
+        'skp' => 'application/vnd.koan',
+        'skt' => 'application/vnd.koan',
+        'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
+        'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
+        'slt' => 'application/vnd.epson.salt',
+        'sm' => 'application/vnd.stepmania.stepchart',
+        'smf' => 'application/vnd.stardivision.math',
+        'smi' => 'application/smil+xml',
+        'smil' => 'application/smil+xml',
+        'snd' => 'audio/basic',
+        'snf' => 'application/x-font-snf',
+        'so' => 'application/octet-stream',
+        'spc' => 'application/x-pkcs7-certificates',
+        'spf' => 'application/vnd.yamaha.smaf-phrase',
+        'spl' => 'application/x-futuresplash',
+        'spot' => 'text/vnd.in3d.spot',
+        'spp' => 'application/scvp-vp-response',
+        'spq' => 'application/scvp-vp-request',
+        'spx' => 'audio/ogg',
+        'src' => 'application/x-wais-source',
+        'sru' => 'application/sru+xml',
+        'srx' => 'application/sparql-results+xml',
+        'sse' => 'application/vnd.kodak-descriptor',
+        'ssf' => 'application/vnd.epson.ssf',
+        'ssml' => 'application/ssml+xml',
+        'st' => 'application/vnd.sailingtracker.track',
+        'stc' => 'application/vnd.sun.xml.calc.template',
+        'std' => 'application/vnd.sun.xml.draw.template',
+        'stf' => 'application/vnd.wt.stf',
+        'sti' => 'application/vnd.sun.xml.impress.template',
+        'stk' => 'application/hyperstudio',
+        'stl' => 'application/vnd.ms-pki.stl',
+        'str' => 'application/vnd.pg.format',
+        'stw' => 'application/vnd.sun.xml.writer.template',
+        'sub' => 'image/vnd.dvb.subtitle',
+        'sus' => 'application/vnd.sus-calendar',
+        'susp' => 'application/vnd.sus-calendar',
+        'sv4cpio' => 'application/x-sv4cpio',
+        'sv4crc' => 'application/x-sv4crc',
+        'svc' => 'application/vnd.dvb.service',
+        'svd' => 'application/vnd.svd',
+        'svg' => 'image/svg+xml',
+        'svgz' => 'image/svg+xml',
+        'swa' => 'application/x-director',
+        'swf' => 'application/x-shockwave-flash',
+        'swi' => 'application/vnd.aristanetworks.swi',
+        'sxc' => 'application/vnd.sun.xml.calc',
+        'sxd' => 'application/vnd.sun.xml.draw',
+        'sxg' => 'application/vnd.sun.xml.writer.global',
+        'sxi' => 'application/vnd.sun.xml.impress',
+        'sxm' => 'application/vnd.sun.xml.math',
+        'sxw' => 'application/vnd.sun.xml.writer',
+        't' => 'text/troff',
+        'tao' => 'application/vnd.tao.intent-module-archive',
+        'tar' => 'application/x-tar',
+        'tcap' => 'application/vnd.3gpp2.tcap',
+        'tcl' => 'application/x-tcl',
+        'teacher' => 'application/vnd.smart.teacher',
+        'tei' => 'application/tei+xml',
+        'teicorpus' => 'application/tei+xml',
+        'tex' => 'application/x-tex',
+        'texi' => 'application/x-texinfo',
+        'texinfo' => 'application/x-texinfo',
+        'text' => 'text/plain',
+        'tfi' => 'application/thraud+xml',
+        'tfm' => 'application/x-tex-tfm',
+        'thmx' => 'application/vnd.ms-officetheme',
+        'tif' => 'image/tiff',
+        'tiff' => 'image/tiff',
+        'tmo' => 'application/vnd.tmobile-livetv',
+        'torrent' => 'application/x-bittorrent',
+        'tpl' => 'application/vnd.groove-tool-template',
+        'tpt' => 'application/vnd.trid.tpt',
+        'tr' => 'text/troff',
+        'tra' => 'application/vnd.trueapp',
+        'trm' => 'application/x-msterminal',
+        'tsd' => 'application/timestamped-data',
+        'tsv' => 'text/tab-separated-values',
+        'ttc' => 'application/x-font-ttf',
+        'ttf' => 'application/x-font-ttf',
+        'ttl' => 'text/turtle',
+        'twd' => 'application/vnd.simtech-mindmapper',
+        'twds' => 'application/vnd.simtech-mindmapper',
+        'txd' => 'application/vnd.genomatix.tuxedo',
+        'txf' => 'application/vnd.mobius.txf',
+        'txt' => 'text/plain',
+        'u32' => 'application/x-authorware-bin',
+        'udeb' => 'application/x-debian-package',
+        'ufd' => 'application/vnd.ufdl',
+        'ufdl' => 'application/vnd.ufdl',
+        'umj' => 'application/vnd.umajin',
+        'unityweb' => 'application/vnd.unity',
+        'uoml' => 'application/vnd.uoml+xml',
+        'uri' => 'text/uri-list',
+        'uris' => 'text/uri-list',
+        'urls' => 'text/uri-list',
+        'ustar' => 'application/x-ustar',
+        'utz' => 'application/vnd.uiq.theme',
+        'uu' => 'text/x-uuencode',
+        'uva' => 'audio/vnd.dece.audio',
+        'uvd' => 'application/vnd.dece.data',
+        'uvf' => 'application/vnd.dece.data',
+        'uvg' => 'image/vnd.dece.graphic',
+        'uvh' => 'video/vnd.dece.hd',
+        'uvi' => 'image/vnd.dece.graphic',
+        'uvm' => 'video/vnd.dece.mobile',
+        'uvp' => 'video/vnd.dece.pd',
+        'uvs' => 'video/vnd.dece.sd',
+        'uvt' => 'application/vnd.dece.ttml+xml',
+        'uvu' => 'video/vnd.uvvu.mp4',
+        'uvv' => 'video/vnd.dece.video',
+        'uvva' => 'audio/vnd.dece.audio',
+        'uvvd' => 'application/vnd.dece.data',
+        'uvvf' => 'application/vnd.dece.data',
+        'uvvg' => 'image/vnd.dece.graphic',
+        'uvvh' => 'video/vnd.dece.hd',
+        'uvvi' => 'image/vnd.dece.graphic',
+        'uvvm' => 'video/vnd.dece.mobile',
+        'uvvp' => 'video/vnd.dece.pd',
+        'uvvs' => 'video/vnd.dece.sd',
+        'uvvt' => 'application/vnd.dece.ttml+xml',
+        'uvvu' => 'video/vnd.uvvu.mp4',
+        'uvvv' => 'video/vnd.dece.video',
+        'uvvx' => 'application/vnd.dece.unspecified',
+        'uvx' => 'application/vnd.dece.unspecified',
+        'vcd' => 'application/x-cdlink',
+        'vcf' => 'text/x-vcard',
+        'vcg' => 'application/vnd.groove-vcard',
+        'vcs' => 'text/x-vcalendar',
+        'vcx' => 'application/vnd.vcx',
+        'vis' => 'application/vnd.visionary',
+        'viv' => 'video/vnd.vivo',
+        'vor' => 'application/vnd.stardivision.writer',
+        'vox' => 'application/x-authorware-bin',
+        'vrml' => 'model/vrml',
+        'vsd' => 'application/vnd.visio',
+        'vsf' => 'application/vnd.vsf',
+        'vss' => 'application/vnd.visio',
+        'vst' => 'application/vnd.visio',
+        'vsw' => 'application/vnd.visio',
+        'vtu' => 'model/vnd.vtu',
+        'vxml' => 'application/voicexml+xml',
+        'w3d' => 'application/x-director',
+        'wad' => 'application/x-doom',
+        'wav' => 'audio/x-wav',
+        'wax' => 'audio/x-ms-wax',
+        'wbmp' => 'image/vnd.wap.wbmp',
+        'wbs' => 'application/vnd.criticaltools.wbs+xml',
+        'wbxml' => 'application/vnd.wap.wbxml',
+        'wcm' => 'application/vnd.ms-works',
+        'wdb' => 'application/vnd.ms-works',
+        'weba' => 'audio/webm',
+        'webm' => 'video/webm',
+        'webp' => 'image/webp',
+        'wg' => 'application/vnd.pmi.widget',
+        'wgt' => 'application/widget',
+        'wks' => 'application/vnd.ms-works',
+        'wm' => 'video/x-ms-wm',
+        'wma' => 'audio/x-ms-wma',
+        'wmd' => 'application/x-ms-wmd',
+        'wmf' => 'application/x-msmetafile',
+        'wml' => 'text/vnd.wap.wml',
+        'wmlc' => 'application/vnd.wap.wmlc',
+        'wmls' => 'text/vnd.wap.wmlscript',
+        'wmlsc' => 'application/vnd.wap.wmlscriptc',
+        'wmv' => 'video/x-ms-wmv',
+        'wmx' => 'video/x-ms-wmx',
+        'wmz' => 'application/x-ms-wmz',
+        'woff' => 'application/x-font-woff',
+        'wpd' => 'application/vnd.wordperfect',
+        'wpl' => 'application/vnd.ms-wpl',
+        'wps' => 'application/vnd.ms-works',
+        'wqd' => 'application/vnd.wqd',
+        'wri' => 'application/x-mswrite',
+        'wrl' => 'model/vrml',
+        'wsdl' => 'application/wsdl+xml',
+        'wspolicy' => 'application/wspolicy+xml',
+        'wtb' => 'application/vnd.webturbo',
+        'wvx' => 'video/x-ms-wvx',
+        'x32' => 'application/x-authorware-bin',
+        'x3d' => 'application/vnd.hzn-3d-crossword',
+        'xap' => 'application/x-silverlight-app',
+        'xar' => 'application/vnd.xara',
+        'xbap' => 'application/x-ms-xbap',
+        'xbd' => 'application/vnd.fujixerox.docuworks.binder',
+        'xbm' => 'image/x-xbitmap',
+        'xdf' => 'application/xcap-diff+xml',
+        'xdm' => 'application/vnd.syncml.dm+xml',
+        'xdp' => 'application/vnd.adobe.xdp+xml',
+        'xdssc' => 'application/dssc+xml',
+        'xdw' => 'application/vnd.fujixerox.docuworks',
+        'xenc' => 'application/xenc+xml',
+        'xer' => 'application/patch-ops-error+xml',
+        'xfdf' => 'application/vnd.adobe.xfdf',
+        'xfdl' => 'application/vnd.xfdl',
+        'xht' => 'application/xhtml+xml',
+        'xhtml' => 'application/xhtml+xml',
+        'xhvml' => 'application/xv+xml',
+        'xif' => 'image/vnd.xiff',
+        'xla' => 'application/vnd.ms-excel',
+        'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12',
+        'xlc' => 'application/vnd.ms-excel',
+        'xlm' => 'application/vnd.ms-excel',
+        'xls' => 'application/vnd.ms-excel',
+        'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
+        'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12',
+        'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+        'xlt' => 'application/vnd.ms-excel',
+        'xltm' => 'application/vnd.ms-excel.template.macroenabled.12',
+        'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+        'xlw' => 'application/vnd.ms-excel',
+        'xml' => 'application/xml',
+        'xo' => 'application/vnd.olpc-sugar',
+        'xop' => 'application/xop+xml',
+        'xpi' => 'application/x-xpinstall',
+        'xpm' => 'image/x-xpixmap',
+        'xpr' => 'application/vnd.is-xpr',
+        'xps' => 'application/vnd.ms-xpsdocument',
+        'xpw' => 'application/vnd.intercon.formnet',
+        'xpx' => 'application/vnd.intercon.formnet',
+        'xsl' => 'application/xml',
+        'xslt' => 'application/xslt+xml',
+        'xsm' => 'application/vnd.syncml+xml',
+        'xspf' => 'application/xspf+xml',
+        'xul' => 'application/vnd.mozilla.xul+xml',
+        'xvm' => 'application/xv+xml',
+        'xvml' => 'application/xv+xml',
+        'xwd' => 'image/x-xwindowdump',
+        'xyz' => 'chemical/x-xyz',
+        'yaml' => 'text/yaml',
+        'yang' => 'application/yang',
+        'yin' => 'application/yin+xml',
+        'yml' => 'text/yaml',
+        'zaz' => 'application/vnd.zzazz.deck+xml',
+        'zip' => 'application/zip',
+        'zir' => 'application/vnd.zul',
+        'zirz' => 'application/vnd.zul',
+        'zmm' => 'application/vnd.handheld-entertainment+xml'
+    );
+
+    /**
+     * Get a singleton instance of the class
+     *
+     * @return self
+     * @codeCoverageIgnore
+     */
+    public static function getInstance()
+    {
+        if (!self::$instance) {
+            self::$instance = new self();
+        }
+
+        return self::$instance;
+    }
+
+    /**
+     * Get a mimetype value from a file extension
+     *
+     * @param string $extension File extension
+     *
+     * @return string|null
+     *
+     */
+    public function fromExtension($extension)
+    {
+        $extension = strtolower($extension);
+
+        return isset($this->mimetypes[$extension]) ? $this->mimetypes[$extension] : null;
+    }
+
+    /**
+     * Get a mimetype from a filename
+     *
+     * @param string $filename Filename to generate a mimetype from
+     *
+     * @return string|null
+     */
+    public function fromFilename($filename)
+    {
+        return $this->fromExtension(pathinfo($filename, PATHINFO_EXTENSION));
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/CommaAggregator.php b/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/CommaAggregator.php
new file mode 100644
index 0000000..4b4e49d
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/CommaAggregator.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Guzzle\Http\QueryAggregator;
+
+use Guzzle\Http\QueryString;
+
+/**
+ * Aggregates nested query string variables using commas
+ */
+class CommaAggregator implements QueryAggregatorInterface
+{
+    public function aggregate($key, $value, QueryString $query)
+    {
+        if ($query->isUrlEncoding()) {
+            return array($query->encodeValue($key) => implode(',', array_map(array($query, 'encodeValue'), $value)));
+        } else {
+            return array($key => implode(',', $value));
+        }
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/DuplicateAggregator.php b/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/DuplicateAggregator.php
new file mode 100644
index 0000000..1bf1730
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/DuplicateAggregator.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Guzzle\Http\QueryAggregator;
+
+use Guzzle\Http\QueryString;
+
+/**
+ * Does not aggregate nested query string values and allows duplicates in the resulting array
+ *
+ * Example: http://test.com?q=1&q=2
+ */
+class DuplicateAggregator implements QueryAggregatorInterface
+{
+    public function aggregate($key, $value, QueryString $query)
+    {
+        if ($query->isUrlEncoding()) {
+            return array($query->encodeValue($key) => array_map(array($query, 'encodeValue'), $value));
+        } else {
+            return array($key => $value);
+        }
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/PhpAggregator.php b/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/PhpAggregator.php
new file mode 100644
index 0000000..133ea2b
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/PhpAggregator.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Guzzle\Http\QueryAggregator;
+
+use Guzzle\Http\QueryString;
+
+/**
+ * Aggregates nested query string variables using PHP style []
+ */
+class PhpAggregator implements QueryAggregatorInterface
+{
+    public function aggregate($key, $value, QueryString $query)
+    {
+        $ret = array();
+
+        foreach ($value as $k => $v) {
+            $k = "{$key}[{$k}]";
+            if (is_array($v)) {
+                $ret = array_merge($ret, self::aggregate($k, $v, $query));
+            } else {
+                $ret[$query->encodeValue($k)] = $query->encodeValue($v);
+            }
+        }
+
+        return $ret;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/QueryAggregatorInterface.php b/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/QueryAggregatorInterface.php
new file mode 100644
index 0000000..72bee62
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/QueryAggregator/QueryAggregatorInterface.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Guzzle\Http\QueryAggregator;
+
+use Guzzle\Http\QueryString;
+
+/**
+ * Interface used for aggregating nested query string variables into a flattened array of key value pairs
+ */
+interface QueryAggregatorInterface
+{
+    /**
+     * Aggregate multi-valued parameters into a flattened associative array
+     *
+     * @param string      $key   The name of the query string parameter
+     * @param array       $value The values of the parameter
+     * @param QueryString $query The query string that is being aggregated
+     *
+     * @return array Returns an array of the combined values
+     */
+    public function aggregate($key, $value, QueryString $query);
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/QueryString.php b/core/vendor/guzzle/http/Guzzle/Http/QueryString.php
new file mode 100644
index 0000000..38a2640
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/QueryString.php
@@ -0,0 +1,297 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Common\Collection;
+use Guzzle\Common\Exception\RuntimeException;
+use Guzzle\Http\QueryAggregator\DuplicateAggregator;
+use Guzzle\Http\QueryAggregator\QueryAggregatorInterface;
+use Guzzle\Http\QueryAggregator\PhpAggregator;
+
+/**
+ * Query string object to handle managing query string parameters and aggregating those parameters together as a string.
+ */
+class QueryString extends Collection
+{
+    /** @var string Used to URL encode with rawurlencode */
+    const RFC_3986 = 'RFC 3986';
+
+    /** @var string Used to encode with urlencode */
+    const FORM_URLENCODED = 'application/x-www-form-urlencoded';
+
+    /** @var string Constant used to create blank query string values (e.g. ?foo) */
+    const BLANK = "_guzzle_blank_";
+
+    /** @var string The query string field separator (e.g. '&') */
+    protected $fieldSeparator = '&';
+
+    /** @var string The query string value separator (e.g. '=') */
+    protected $valueSeparator = '=';
+
+    /** @var bool URL encode fields and values */
+    protected $urlEncode = 'RFC 3986';
+
+    /** @var QueryAggregatorInterface */
+    protected $aggregator;
+
+    /** @var array Cached PHP aggregator */
+    private static $defaultAggregator = null;
+
+    /**
+     * Parse a query string into a QueryString object
+     *
+     * @param string $query Query string to parse
+     *
+     * @return self
+     */
+    public static function fromString($query)
+    {
+        $q = new static();
+        if ($query === '') {
+            return $q;
+        }
+
+        $foundDuplicates = $foundPhpStyle = false;
+
+        foreach (explode('&', $query) as $kvp) {
+            $parts = explode('=', $kvp, 2);
+            $key = rawurldecode($parts[0]);
+            if ($paramIsPhpStyleArray = substr($key, -2) == '[]') {
+                $foundPhpStyle = true;
+                $key = substr($key, 0, -2);
+            }
+            if (isset($parts[1])) {
+                $value = rawurldecode(str_replace('+', '%20', $parts[1]));
+                if (isset($q[$key])) {
+                    $q->add($key, $value);
+                    $foundDuplicates = true;
+                } elseif ($paramIsPhpStyleArray) {
+                    $q[$key] = array($value);
+                } else {
+                    $q[$key] = $value;
+                }
+            } else {
+                // Uses false by default to represent keys with no trailing "=" sign.
+                $q->add($key, false);
+            }
+        }
+
+        // Use the duplicate aggregator if duplicates were found and not using PHP style arrays
+        if ($foundDuplicates && !$foundPhpStyle) {
+            $q->setAggregator(new DuplicateAggregator());
+        }
+
+        return $q;
+    }
+
+    /**
+     * Convert the query string parameters to a query string string
+     *
+     * @return string
+     * @throws RuntimeException
+     */
+    public function __toString()
+    {
+        if (!$this->data) {
+            return '';
+        }
+
+        $queryList = array();
+        foreach ($this->prepareData($this->data) as $name => $value) {
+            $queryList[] = $this->convertKvp($name, $value);
+        }
+
+        return implode($this->fieldSeparator, $queryList);
+    }
+
+    /**
+     * Get the query string field separator
+     *
+     * @return string
+     */
+    public function getFieldSeparator()
+    {
+        return $this->fieldSeparator;
+    }
+
+    /**
+     * Get the query string value separator
+     *
+     * @return string
+     */
+    public function getValueSeparator()
+    {
+        return $this->valueSeparator;
+    }
+
+    /**
+     * Returns the type of URL encoding used by the query string
+     *
+     * One of: false, "RFC 3986", or "application/x-www-form-urlencoded"
+     *
+     * @return bool|string
+     */
+    public function getUrlEncoding()
+    {
+        return $this->urlEncode;
+    }
+
+    /**
+     * Returns true or false if using URL encoding
+     *
+     * @return bool
+     */
+    public function isUrlEncoding()
+    {
+        return $this->urlEncode !== false;
+    }
+
+    /**
+     * Provide a function for combining multi-valued query string parameters into a single or multiple fields
+     *
+     * @param null|QueryAggregatorInterface $aggregator Pass in a QueryAggregatorInterface object to handle converting
+     *                                                  deeply nested query string variables into a flattened array.
+     *                                                  Pass null to use the default PHP style aggregator. For legacy
+     *                                                  reasons, this function accepts a callable that must accepts a
+     *                                                  $key, $value, and query object.
+     * @return self
+     * @see \Guzzle\Http\QueryString::aggregateUsingComma()
+     */
+    public function setAggregator(QueryAggregatorInterface $aggregator = null)
+    {
+        // Use the default aggregator if none was set
+        if (!$aggregator) {
+            if (!self::$defaultAggregator) {
+                self::$defaultAggregator = new PhpAggregator();
+            }
+            $aggregator = self::$defaultAggregator;
+        }
+
+        $this->aggregator = $aggregator;
+
+        return $this;
+    }
+
+    /**
+     * Set whether or not field names and values should be rawurlencoded
+     *
+     * @param bool|string $encode Set to TRUE to use RFC 3986 encoding (rawurlencode), false to disable encoding, or
+     *                            form_urlencoding to use application/x-www-form-urlencoded encoding (urlencode)
+     * @return self
+     */
+    public function useUrlEncoding($encode)
+    {
+        $this->urlEncode = ($encode === true) ? self::RFC_3986 : $encode;
+
+        return $this;
+    }
+
+    /**
+     * Set the query string separator
+     *
+     * @param string $separator The query string separator that will separate fields
+     *
+     * @return self
+     */
+    public function setFieldSeparator($separator)
+    {
+        $this->fieldSeparator = $separator;
+
+        return $this;
+    }
+
+    /**
+     * Set the query string value separator
+     *
+     * @param string $separator The query string separator that will separate values from fields
+     *
+     * @return self
+     */
+    public function setValueSeparator($separator)
+    {
+        $this->valueSeparator = $separator;
+
+        return $this;
+    }
+
+    /**
+     * Returns an array of url encoded field names and values
+     *
+     * @return array
+     */
+    public function urlEncode()
+    {
+        return $this->prepareData($this->data);
+    }
+
+    /**
+     * URL encodes a value based on the url encoding type of the query string object
+     *
+     * @param string $value Value to encode
+     *
+     * @return string
+     */
+    public function encodeValue($value)
+    {
+        if ($this->urlEncode == self::RFC_3986) {
+            return rawurlencode($value);
+        } elseif ($this->urlEncode == self::FORM_URLENCODED) {
+            return urlencode($value);
+        } else {
+            return (string) $value;
+        }
+    }
+
+    /**
+     * Url encode parameter data and convert nested query strings into a flattened hash.
+     *
+     * @param array $data The data to encode
+     *
+     * @return array Returns an array of encoded values and keys
+     */
+    protected function prepareData(array $data)
+    {
+        // If no aggregator is present then set the default
+        if (!$this->aggregator) {
+            $this->setAggregator(null);
+        }
+
+        $temp = array();
+        foreach ($data as $key => $value) {
+            if ($value === false || $value === null) {
+                // False and null will not include the "=". Use an empty string to include the "=".
+                $temp[$this->encodeValue($key)] = $value;
+            } elseif (is_array($value)) {
+                $temp = array_merge($temp, $this->aggregator->aggregate($key, $value, $this));
+            } else {
+                $temp[$this->encodeValue($key)] = $this->encodeValue($value);
+            }
+        }
+
+        return $temp;
+    }
+
+    /**
+     * Converts a key value pair that can contain strings, nulls, false, or arrays
+     * into a single string.
+     *
+     * @param string $name  Name of the field
+     * @param mixed  $value Value of the field
+     * @return string
+     */
+    private function convertKvp($name, $value)
+    {
+        if ($value === self::BLANK || $value === null || $value === false) {
+            return $name;
+        } elseif (!is_array($value)) {
+            return $name . $this->valueSeparator . $value;
+        }
+
+        $result = '';
+        foreach ($value as $v) {
+            $result .= $this->convertKvp($name, $v) . $this->fieldSeparator;
+        }
+
+        return rtrim($result, $this->fieldSeparator);
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/ReadLimitEntityBody.php b/core/vendor/guzzle/http/Guzzle/Http/ReadLimitEntityBody.php
new file mode 100644
index 0000000..a34893a
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/ReadLimitEntityBody.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace Guzzle\Http;
+
+/**
+ * EntityBody decorator used to return only a subset of an entity body
+ */
+class ReadLimitEntityBody extends AbstractEntityBodyDecorator
+{
+    /** @var int Limit the number of bytes that can be read */
+    protected $limit;
+
+    /** @var int Offset to start reading from */
+    protected $offset;
+
+    /**
+     * @param EntityBodyInterface $body   Body to wrap
+     * @param int                 $limit  Total number of bytes to allow to be read from the stream
+     * @param int                 $offset Position to seek to before reading (only works on seekable streams)
+     */
+    public function __construct(EntityBodyInterface $body, $limit, $offset = 0)
+    {
+        parent::__construct($body);
+        $this->setLimit($limit)->setOffset($offset);
+    }
+
+    /**
+     * Returns only a subset of the decorated entity body when cast as a string
+     * {@inheritdoc}
+     */
+    public function __toString()
+    {
+        return substr((string) $this->body, $this->offset, $this->limit) ?: '';
+    }
+
+    public function isConsumed()
+    {
+        return $this->body->isConsumed() ||
+            ($this->body->ftell() >= $this->offset + $this->limit);
+    }
+
+    /**
+     * Returns the Content-Length of the limited subset of data
+     * {@inheritdoc}
+     */
+    public function getContentLength()
+    {
+        $length = $this->body->getContentLength();
+
+        return $length === false
+            ? $this->limit
+            : min($this->limit, min($length, $this->offset + $this->limit) - $this->offset);
+    }
+
+    /**
+     * Allow for a bounded seek on the read limited entity body
+     * {@inheritdoc}
+     */
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        return $whence === SEEK_SET
+            ? $this->body->seek(max($this->offset, min($this->offset + $this->limit, $offset)))
+            : false;
+    }
+
+    /**
+     * Set the offset to start limiting from
+     *
+     * @param int $offset Offset to seek to and begin byte limiting from
+     *
+     * @return self
+     */
+    public function setOffset($offset)
+    {
+        $this->body->seek($offset);
+        $this->offset = $offset;
+
+        return $this;
+    }
+
+    /**
+     * Set the limit of bytes that the decorator allows to be read from the stream
+     *
+     * @param int $limit Total number of bytes to allow to be read from the stream
+     *
+     * @return self
+     */
+    public function setLimit($limit)
+    {
+        $this->limit = $limit;
+
+        return $this;
+    }
+
+    public function read($length)
+    {
+        // Check if the current position is less than the total allowed bytes + original offset
+        $remaining = ($this->offset + $this->limit) - $this->body->ftell();
+        if ($remaining > 0) {
+            // Only return the amount of requested data, ensuring that the byte limit is not exceeded
+            return $this->body->read(min($remaining, $length));
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/RedirectPlugin.php b/core/vendor/guzzle/http/Guzzle/Http/RedirectPlugin.php
new file mode 100644
index 0000000..1a824b8
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/RedirectPlugin.php
@@ -0,0 +1,250 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Common\Event;
+use Guzzle\Http\Exception\BadResponseException;
+use Guzzle\Http\Url;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\RequestFactory;
+use Guzzle\Http\Message\EntityEnclosingRequestInterface;
+use Guzzle\Http\Exception\TooManyRedirectsException;
+use Guzzle\Http\Exception\CouldNotRewindStreamException;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Plugin to implement HTTP redirects. Can redirect like a web browser or using strict RFC 2616 compliance
+ */
+class RedirectPlugin implements EventSubscriberInterface
+{
+    const REDIRECT_COUNT = 'redirect.count';
+    const MAX_REDIRECTS = 'redirect.max';
+    const STRICT_REDIRECTS = 'redirect.strict';
+    const PARENT_REQUEST = 'redirect.parent_request';
+    const DISABLE = 'redirect.disable';
+
+    /**
+     * @var int Default number of redirects allowed when no setting is supplied by a request
+     */
+    protected $defaultMaxRedirects = 5;
+
+    public static function getSubscribedEvents()
+    {
+        return array(
+            'request.sent'        => array('onRequestSent', 100),
+            'request.clone'       => 'cleanupRequest',
+            'request.before_send' => 'cleanupRequest'
+        );
+    }
+
+    /**
+     * Clean up the parameters of a request when it is cloned
+     *
+     * @param Event $event Event emitted
+     */
+    public function cleanupRequest(Event $event)
+    {
+        $params = $event['request']->getParams();
+        unset($params[self::REDIRECT_COUNT]);
+        unset($params[self::PARENT_REQUEST]);
+    }
+
+    /**
+     * Called when a request receives a redirect response
+     *
+     * @param Event $event Event emitted
+     */
+    public function onRequestSent(Event $event)
+    {
+        $response = $event['response'];
+        $request = $event['request'];
+
+        // Only act on redirect requests with Location headers
+        if (!$response || $request->getParams()->get(self::DISABLE)) {
+            return;
+        }
+
+        // Trace the original request based on parameter history
+        $original = $this->getOriginalRequest($request);
+
+        // Terminating condition to set the effective response on the original request
+        if (!$response->isRedirect() || !$response->hasHeader('Location')) {
+            if ($request !== $original) {
+                // This is a terminating redirect response, so set it on the original request
+                $response->getParams()->set(self::REDIRECT_COUNT, $original->getParams()->get(self::REDIRECT_COUNT));
+                $original->setResponse($response);
+                $response->setEffectiveUrl($request->getUrl());
+            }
+            return;
+        }
+
+        $this->sendRedirectRequest($original, $request, $response);
+    }
+
+    /**
+     * Get the original request that initiated a series of redirects
+     *
+     * @param RequestInterface $request Request to get the original request from
+     *
+     * @return RequestInterface
+     */
+    protected function getOriginalRequest(RequestInterface $request)
+    {
+        $original = $request;
+        // The number of redirects is held on the original request, so determine which request that is
+        while ($parent = $original->getParams()->get(self::PARENT_REQUEST)) {
+            $original = $parent;
+        }
+
+        return $original;
+    }
+
+    /**
+     * Create a redirect request for a specific request object
+     *
+     * Takes into account strict RFC compliant redirection (e.g. redirect POST with POST) vs doing what most clients do
+     * (e.g. redirect POST with GET).
+     *
+     * @param RequestInterface $request    Request being redirected
+     * @param RequestInterface $original   Original request
+     * @param int              $statusCode Status code of the redirect
+     * @param string           $location   Location header of the redirect
+     *
+     * @return RequestInterface Returns a new redirect request
+     * @throws CouldNotRewindStreamException If the body needs to be rewound but cannot
+     */
+    protected function createRedirectRequest(
+        RequestInterface $request,
+        $statusCode,
+        $location,
+        RequestInterface $original
+    ) {
+        $redirectRequest = null;
+        $strict = $original->getParams()->get(self::STRICT_REDIRECTS);
+
+        // Switch method to GET for 303 redirects.  301 and 302 redirects also switch to GET unless we are forcing RFC
+        // compliance to emulate what most browsers do.  NOTE: IE only switches methods on 301/302 when coming from a POST.
+        if ($request instanceof EntityEnclosingRequestInterface && ($statusCode == 303 || (!$strict && $statusCode <= 302))) {
+            $redirectRequest = RequestFactory::getInstance()->cloneRequestWithMethod($request, 'GET');
+        } else {
+            $redirectRequest = clone $request;
+        }
+
+        $redirectRequest->setIsRedirect(true);
+        // Always use the same response body when redirecting
+        $redirectRequest->setResponseBody($request->getResponseBody());
+
+        $location = Url::factory($location);
+        // If the location is not absolute, then combine it with the original URL
+        if (!$location->isAbsolute()) {
+            $originalUrl = $redirectRequest->getUrl(true);
+            // Remove query string parameters and just take what is present on the redirect Location header
+            $originalUrl->getQuery()->clear();
+            $location = $originalUrl->combine((string) $location, true);
+        }
+
+        $redirectRequest->setUrl($location);
+
+        // Add the parent request to the request before it sends (make sure it's before the onRequestClone event too)
+        $redirectRequest->getEventDispatcher()->addListener(
+            'request.before_send',
+            $func = function ($e) use (&$func, $request, $redirectRequest) {
+                $redirectRequest->getEventDispatcher()->removeListener('request.before_send', $func);
+                $e['request']->getParams()->set(RedirectPlugin::PARENT_REQUEST, $request);
+            }
+        );
+
+        // Rewind the entity body of the request if needed
+        if ($redirectRequest instanceof EntityEnclosingRequestInterface && $redirectRequest->getBody()) {
+            $body = $redirectRequest->getBody();
+            // Only rewind the body if some of it has been read already, and throw an exception if the rewind fails
+            if ($body->ftell() && !$body->rewind()) {
+                throw new CouldNotRewindStreamException(
+                    'Unable to rewind the non-seekable entity body of the request after redirecting. cURL probably '
+                    . 'sent part of body before the redirect occurred. Try adding acustom rewind function using on the '
+                    . 'entity body of the request using setRewindFunction().'
+                );
+            }
+        }
+
+        return $redirectRequest;
+    }
+
+    /**
+     * Prepare the request for redirection and enforce the maximum number of allowed redirects per client
+     *
+     * @param RequestInterface $original  Original request
+     * @param RequestInterface $request   Request to prepare and validate
+     * @param Response         $response  The current response
+     *
+     * @return RequestInterface
+     */
+    protected function prepareRedirection(RequestInterface $original, RequestInterface $request, Response $response)
+    {
+        $params = $original->getParams();
+        // This is a new redirect, so increment the redirect counter
+        $current = $params[self::REDIRECT_COUNT] + 1;
+        $params[self::REDIRECT_COUNT] = $current;
+        // Use a provided maximum value or default to a max redirect count of 5
+        $max = isset($params[self::MAX_REDIRECTS]) ? $params[self::MAX_REDIRECTS] : $this->defaultMaxRedirects;
+
+        // Throw an exception if the redirect count is exceeded
+        if ($current > $max) {
+            $this->throwTooManyRedirectsException($original, $max);
+            return false;
+        } else {
+            // Create a redirect request based on the redirect rules set on the request
+            return $this->createRedirectRequest(
+                $request,
+                $response->getStatusCode(),
+                trim($response->getLocation()),
+                $original
+            );
+        }
+    }
+
+    /**
+     * Send a redirect request and handle any errors
+     *
+     * @param RequestInterface $original The originating request
+     * @param RequestInterface $request  The current request being redirected
+     * @param Response         $response The response of the current request
+     *
+     * @throws BadResponseException|\Exception
+     */
+    protected function sendRedirectRequest(RequestInterface $original, RequestInterface $request, Response $response)
+    {
+        // Validate and create a redirect request based on the original request and current response
+        if ($redirectRequest = $this->prepareRedirection($original, $request, $response)) {
+            try {
+                $redirectRequest->send();
+            } catch (BadResponseException $e) {
+                $e->getResponse();
+                if (!$e->getResponse()) {
+                    throw $e;
+                }
+            }
+        }
+    }
+
+    /**
+     * Throw a too many redirects exception for a request
+     *
+     * @param RequestInterface $original Request
+     * @param int              $max      Max allowed redirects
+     *
+     * @throws TooManyRedirectsException when too many redirects have been issued
+     */
+    protected function throwTooManyRedirectsException(RequestInterface $original, $max)
+    {
+        $original->getEventDispatcher()->addListener(
+            'request.complete',
+            $func = function ($e) use (&$func, $original, $max) {
+                $original->getEventDispatcher()->removeListener('request.complete', $func);
+                $str = "{$max} redirects were issued for this request:\n" . $e['request']->getRawHeaders();
+                throw new TooManyRedirectsException($str);
+            }
+        );
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Resources/cacert.pem b/core/vendor/guzzle/http/Guzzle/Http/Resources/cacert.pem
new file mode 100644
index 0000000..9794dfb
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Resources/cacert.pem
@@ -0,0 +1,3866 @@
+##
+## ca-bundle.crt -- Bundle of CA Root Certificates
+##
+## Certificate data from Mozilla as of: Tue Apr 22 08:29:31 2014
+##
+## This is a bundle of X.509 certificates of public Certificate Authorities
+## (CA). These were automatically extracted from Mozilla's root certificates
+## file (certdata.txt).  This file can be found in the mozilla source tree:
+## http://mxr.mozilla.org/mozilla-release/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1
+##
+## It contains the certificates in PEM format and therefore
+## can be directly used with curl / libcurl / php_curl, or with
+## an Apache+mod_ssl webserver for SSL client authentication.
+## Just configure this file as the SSLCACertificateFile.
+##
+
+
+GTE CyberTrust Global Root
+==========================
+-----BEGIN CERTIFICATE-----
+MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg
+Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG
+A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz
+MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL
+Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0
+IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u
+sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql
+HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID
+AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW
+M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF
+NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
+-----END CERTIFICATE-----
+
+Thawte Server CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
+DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
+dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE
+AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j
+b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV
+BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u
+c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG
+A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0
+ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl
+/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7
+1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR
+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J
+GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ
+GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc=
+-----END CERTIFICATE-----
+
+Thawte Premium Server CA
+========================
+-----BEGIN CERTIFICATE-----
+MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT
+DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
+dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE
+AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl
+ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT
+AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU
+VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2
+aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ
+cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2
+aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh
+Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/
+qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm
+SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf
+8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t
+UCemDaYj+bvLpgcUQg==
+-----END CERTIFICATE-----
+
+Equifax Secure CA
+=================
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE
+ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
+MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT
+B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB
+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR
+fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW
+8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG
+A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE
+CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG
+A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS
+spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB
+Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961
+zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB
+BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95
+70+sB3c4
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow
+XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz
+IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94
+f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol
+hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA
+TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah
+WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf
+Tqj/ZA1k
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority - G2
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT
+MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
+dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT
+MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
+dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO
+FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71
+lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB
+MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT
+1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD
+Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9
+-----END CERTIFICATE-----
+
+GlobalSign Root CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
+GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
+b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
+BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
+VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
+DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
+THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
+Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
+c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
+gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
+AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
+Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
+j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
+hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
+X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R2
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
+YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
+bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
+aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
+bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
+ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
+s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
+S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
+TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
+ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
+YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
+BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
+9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
+01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
+9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+ValiCert Class 1 VA
+===================
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
+b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
+bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy
+MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
+d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg
+UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
+LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi
+GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm
+DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG
+lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX
+icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP
+Orf1LXLI
+-----END CERTIFICATE-----
+
+ValiCert Class 2 VA
+===================
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
+b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
+bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw
+MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
+d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg
+UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
+LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC
+CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf
+ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ
+SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV
+UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8
+W9ViH0Pd
+-----END CERTIFICATE-----
+
+RSA Root Certificate 1
+======================
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
+b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
+bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw
+MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
+d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg
+UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
+LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td
+3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H
+BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs
+3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF
+V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r
+on+jjBXu
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority - G3
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
+dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
+EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
+cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
+EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
+055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
+ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
+j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
+/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
+xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
+t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
+-----END CERTIFICATE-----
+
+Verisign Class 4 Public Primary Certification Authority - G3
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
+dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS
+tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM
+8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW
+Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX
+Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
+j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt
+mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
+fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd
+RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG
+UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
+-----END CERTIFICATE-----
+
+Entrust.net Secure Server CA
+============================
+-----BEGIN CERTIFICATE-----
+MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV
+BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg
+cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl
+ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG
+A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi
+eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p
+dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ
+aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5
+gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw
+ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw
+CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l
+dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
+bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
+dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw
+NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow
+HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA
+BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN
+Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9
+n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
+-----END CERTIFICATE-----
+
+Entrust.net Premium 2048 Secure Server CA
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
+ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
+bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
+BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
+NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
+d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
+MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
+ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
+Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
+hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
+nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
+VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
+KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
+T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
+J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
+nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+Baltimore CyberTrust Root
+=========================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
+ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
+ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
+SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
+dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
+uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
+UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
+G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
+XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
+l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
+VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
+BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
+cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
+hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
+Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
+RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+Equifax Secure Global eBusiness CA
+==================================
+-----BEGIN CERTIFICATE-----
+MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp
+bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx
+HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds
+b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV
+PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN
+qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn
+hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
+BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs
+MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN
+I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY
+NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
+-----END CERTIFICATE-----
+
+Equifax Secure eBusiness CA 1
+=============================
+-----BEGIN CERTIFICATE-----
+MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB
+LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE
+ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz
+IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ
+1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a
+IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk
+MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW
+Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF
+AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5
+lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+
+KpYrtWKmpj29f5JZzVoqgrI3eQ==
+-----END CERTIFICATE-----
+
+AddTrust Low-Value Services Root
+================================
+-----BEGIN CERTIFICATE-----
+MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU
+cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw
+CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO
+ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6
+54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr
+oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1
+Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui
+GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w
+HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT
+RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw
+HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt
+ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph
+iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
+eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr
+mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj
+ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
+-----END CERTIFICATE-----
+
+AddTrust External Root
+======================
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
+VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
+NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
+cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
+Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
++iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
+Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
+aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
+2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
+7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
+VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
+VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
+IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
+j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
+e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
+G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----
+
+AddTrust Public Services Root
+=============================
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU
+cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ
+BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l
+dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu
+nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i
+d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG
+Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw
+HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G
+A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G
+A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4
+JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL
++YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
+GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9
+Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H
+EufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
+-----END CERTIFICATE-----
+
+AddTrust Qualified Certificates Root
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU
+cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx
+CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ
+IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx
+64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3
+KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o
+L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR
+wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU
+MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE
+BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y
+azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG
+GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
+dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze
+RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB
+iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE=
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
+BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
+b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
+A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
+MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
+MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
+Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
+dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
+A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
+Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
+j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
+rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
+MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
+hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
+Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
+v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
+W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
+tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+RSA Security 2048 v3
+====================
+-----BEGIN CERTIFICATE-----
+MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK
+ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy
+MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb
+BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7
+Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb
+WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH
+KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP
++Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/
+MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E
+FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY
+v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj
+0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj
+VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395
+nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA
+pKnXwiJPZ9d37CAFYd4=
+-----END CERTIFICATE-----
+
+GeoTrust Global CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
+Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
+MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
+LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
+BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
+8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
+T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
+vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
+DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
+zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
+d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
+mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
+XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
+Mw==
+-----END CERTIFICATE-----
+
+GeoTrust Global CA 2
+====================
+-----BEGIN CERTIFICATE-----
+MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw
+MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
+LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/
+NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k
+LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA
+Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b
+HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH
+K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7
+srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh
+ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL
+OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC
+x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF
+H4z1Ir+rzoPz4iIprn2DQKi6bA==
+-----END CERTIFICATE-----
+
+GeoTrust Universal CA
+=====================
+-----BEGIN CERTIFICATE-----
+MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
+MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
+Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
+JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
+RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
+7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
+8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
+qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
+Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
+Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
+KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
+ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
+XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
+hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
+aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
+qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
+oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
+xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
+KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
+DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
+xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
+p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
+P/rmMuGNG2+k5o7Y+SlIis5z/iw=
+-----END CERTIFICATE-----
+
+GeoTrust Universal CA 2
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
+MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
+SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
+DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
+j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
+JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
+QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
+WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
+20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
+ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
+SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
+8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
++/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
+BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
+dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
+4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
+A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
+Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
+pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
+FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
+gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
+X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
+-----END CERTIFICATE-----
+
+America Online Root Certification Authority 1
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG
+A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg
+T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG
+v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z
+DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh
+sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP
+8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z
+o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf
+GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF
+VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft
+3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g
+Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds
+sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7
+-----END CERTIFICATE-----
+
+America Online Root Certification Authority 2
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG
+A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg
+T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en
+fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8
+f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO
+qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN
+RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0
+gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn
+6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid
+FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6
+Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj
+B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op
+aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY
+T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p
++DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg
+JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy
+zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO
+ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh
+1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf
+GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff
+Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP
+cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk=
+-----END CERTIFICATE-----
+
+Visa eCommerce Root
+===================
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
+EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
+QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
+WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
+VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
+bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
+F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
+RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
+TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
+/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
+GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
+MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
+CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
+YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
+zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
+YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
+398znM/jra6O1I7mT1GvFpLgXPYHDw==
+-----END CERTIFICATE-----
+
+Certum Root CA
+==============
+-----BEGIN CERTIFICATE-----
+MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK
+ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla
+Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u
+by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x
+wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL
+kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ
+89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K
+Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P
+NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+
+GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg
+GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/
+0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS
+qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==
+-----END CERTIFICATE-----
+
+Comodo AAA Services root
+========================
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
+MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
+c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
+BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
+C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
+i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
+Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
+Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
+Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
+BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
+cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
+LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
+7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
+8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
+12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+Comodo Secure Services root
+===========================
+-----BEGIN CERTIFICATE-----
+MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw
+MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu
+Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi
+BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP
+9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc
+rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC
+oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V
+p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E
+FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
+gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj
+YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm
+aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm
+4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
+Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL
+DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw
+pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H
+RR3B7Hzs/Sk=
+-----END CERTIFICATE-----
+
+Comodo Trusted Services root
+============================
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw
+MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h
+bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw
+IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7
+3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y
+/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6
+juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS
+ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud
+DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp
+ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl
+cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw
+uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
+pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA
+BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l
+R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O
+9y5Xt5hwXsjEeLBi
+-----END CERTIFICATE-----
+
+QuoVadis Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
+ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
+MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
+cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
+EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
+J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
+F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
+YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
+AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
+PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
+ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
+MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
+YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
+ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
+Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
+Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
+BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
+FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
+tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
+fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
+LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
+gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
+5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
+5nrQNiOKSnQ2+Q==
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 2
+==================
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
+ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
+XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
+lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
+lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
+lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
+66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
+wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
+D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
+BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
+J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
+DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
+a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
+Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
+UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
+VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
+IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
+WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
+f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
+4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
+VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 3
+==================
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
+OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
+DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
+KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
+DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
+BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
+p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
+nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
+MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
+Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
+uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
+BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
+YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
+BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
+VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
+ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
+AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
+qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
+hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
+POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
+Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
+8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
+bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
+g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
+vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
+qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+
+Security Communication Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
+U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
+HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
+U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
+8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
+DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
+5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
+DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
+JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
+0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
+mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
+s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
+6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
+FL39vmwLAw==
+-----END CERTIFICATE-----
+
+Sonera Class 2 Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
+U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
+NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
+IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
+/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
+dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
+f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
+tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
+nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
+XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
+0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
+cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
+Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
+EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
+llpwrN9M
+-----END CERTIFICATE-----
+
+Staat der Nederlanden Root CA
+=============================
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE
+ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w
+HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh
+bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt
+vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P
+jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca
+C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth
+vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6
+22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV
+HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v
+dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN
+BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR
+EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw
+MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y
+nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR
+iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw==
+-----END CERTIFICATE-----
+
+TDC Internet Root CA
+====================
+-----BEGIN CERTIFICATE-----
+MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE
+ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx
+NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu
+ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j
+xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL
+znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc
+5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6
+otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI
+AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM
+VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM
+MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC
+AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe
+UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G
+CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m
+gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+
+2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb
+O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU
+Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l
+-----END CERTIFICATE-----
+
+UTN DATACorp SGC Root CA
+========================
+-----BEGIN CERTIFICATE-----
+MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE
+BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
+IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ
+BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa
+MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w
+HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy
+dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys
+raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo
+wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA
+9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv
+33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud
+DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9
+BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD
+LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3
+DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft
+Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0
+I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx
+EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP
+DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI
+-----END CERTIFICATE-----
+
+UTN USERFirst Hardware Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE
+BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
+IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd
+BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx
+OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0
+eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz
+ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI
+wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd
+tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8
+i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf
+Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw
+gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF
+lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF
+UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF
+BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
+//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW
+XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2
+lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn
+iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67
+nfhmqA==
+-----END CERTIFICATE-----
+
+Camerfirma Chambers of Commerce Root
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
+QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
+ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx
+NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp
+cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn
+MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC
+AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU
+xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH
+NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW
+DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV
+d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud
+EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v
+cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P
+AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh
+bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD
+VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
+aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi
+fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD
+L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN
+UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n
+ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1
+erfutGWaIZDgqtCYvDi1czyL+Nw=
+-----END CERTIFICATE-----
+
+Camerfirma Global Chambersign Root
+==================================
+-----BEGIN CERTIFICATE-----
+MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
+QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
+ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx
+NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
+YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg
+MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw
+ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J
+1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O
+by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl
+6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c
+8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/
+BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j
+aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B
+Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj
+aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y
+ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
+bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA
+PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y
+gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ
+PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4
+IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes
+t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
+-----END CERTIFICATE-----
+
+NetLock Notary (Class A) Root
+=============================
+-----BEGIN CERTIFICATE-----
+MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI
+EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6
+dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j
+ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX
+DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH
+EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD
+VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz
+cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM
+D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ
+z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC
+/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7
+tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6
+4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG
+A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC
+Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv
+bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu
+IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn
+LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0
+ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz
+IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh
+IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu
+b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh
+bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg
+Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp
+bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5
+ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP
+ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB
+CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr
+KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM
+8CgHrTwXZoi1/baI
+-----END CERTIFICATE-----
+
+NetLock Business (Class B) Root
+===============================
+-----BEGIN CERTIFICATE-----
+MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT
+CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV
+BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg
+VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD
+VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv
+bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg
+VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S
+o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr
+1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV
+HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ
+RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh
+dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0
+ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv
+c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg
+YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh
+c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz
+Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA
+bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl
+IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2
+YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj
+cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM
+43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR
+stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI
+-----END CERTIFICATE-----
+
+NetLock Express (Class C) Root
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT
+CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV
+BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD
+KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ
+BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6
+dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j
+ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB
+jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z
+W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63
+euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw
+DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN
+RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn
+YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB
+IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i
+aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0
+ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs
+ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo
+dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y
+emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k
+IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ
+UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg
+YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2
+xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW
+gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A==
+-----END CERTIFICATE-----
+
+XRamp Global CA Root
+====================
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
+BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
+dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
+HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
+U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
+IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
+foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
+zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
+AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
+xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
+oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
+AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
+/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
+nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
+8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
+
+Go Daddy Class 2 CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
+VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
+A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
+RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
+ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
+2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
+qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
+YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
+vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
+BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
+atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
+MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
+PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
+I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
+Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
+vZ8=
+-----END CERTIFICATE-----
+
+Starfield Class 2 CA
+====================
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
+U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
+MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
+A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
+SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
+bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
+JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
+epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
+F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
+MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
+hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
+bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
+QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
+afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
+PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
+KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
+QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+StartCom Certification Authority
+================================
+-----BEGIN CERTIFICATE-----
+MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
+U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
+ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
+NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
+LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
+U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
+o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
+Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
+eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
+2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
+6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
+osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
+untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
+UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
+37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0
+Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj
+YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH
+AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw
+Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg
+U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5
+LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh
+cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT
+dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC
+AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh
+3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm
+vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk
+fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3
+fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ
+EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
+yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl
+1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/
+lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro
+g14=
+-----END CERTIFICATE-----
+
+Taiwan GRCA
+===========
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
+EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
+DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
+dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
+w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
+BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
+1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
+htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
+J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
+Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
+B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
+O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
+lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
+HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
+09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
+TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
+Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
+Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
+D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
+DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
+Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
+7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
+CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
++fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
+-----END CERTIFICATE-----
+
+Swisscom Root CA 1
+==================
+-----BEGIN CERTIFICATE-----
+MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG
+EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
+dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4
+MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
+aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC
+IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM
+MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF
+NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe
+AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC
+b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn
+7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN
+cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp
+WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5
+haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY
+MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
+HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j
+BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9
+MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn
+jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ
+MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H
+VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl
+vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl
+OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3
+1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq
+nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy
+x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW
+NY6E0F/6MBr1mmz0DlP5OlvRHA==
+-----END CERTIFICATE-----
+
+DigiCert Assured ID Root CA
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
+IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
+MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
+ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
+9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
+UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
+/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
+oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
+GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
+66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
+hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
+EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
+SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
+8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+DigiCert Global Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
+HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
+MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
+dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
+TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
+BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
+4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
+7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
+o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
+8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
+BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
+EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
+tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
+UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+DigiCert High Assurance EV Root CA
+==================================
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
+KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
+MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
+MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
+Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
+Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
+OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
+MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
+NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
+h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
+Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
+JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
+V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
+myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
+mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
+-----END CERTIFICATE-----
+
+Certplus Class 2 Primary CA
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
+BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
+OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
+dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
+5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
+Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
+YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
+e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
+CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
+YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
+L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
+P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
+TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
+7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
+//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
+l7+ijrRU
+-----END CERTIFICATE-----
+
+DST Root CA X3
+==============
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
+ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
+DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
+cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
+rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
+UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
+xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
+utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
+MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
+dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
+GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
+RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
+fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
+
+DST ACES CA X6
+==============
+-----BEGIN CERTIFICATE-----
+MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT
+MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha
+MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE
+CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI
+DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa
+pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow
+GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy
+MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu
+Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy
+dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU
+CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2
+5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t
+Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
+nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs
+vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3
+oKfN5XozNmr6mis=
+-----END CERTIFICATE-----
+
+TURKTRUST Certificate Services Provider Root 1
+==============================================
+-----BEGIN CERTIFICATE-----
+MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP
+MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0
+acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx
+MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg
+U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB
+TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC
+aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX
+yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i
+Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ
+8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4
+W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME
+BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46
+sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE
+q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy
+B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY
+nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H
+-----END CERTIFICATE-----
+
+TURKTRUST Certificate Services Provider Root 2
+==============================================
+-----BEGIN CERTIFICATE-----
+MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
+MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
+QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN
+MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr
+dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G
+A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls
+acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe
+LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI
+x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g
+QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr
+5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB
+AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt
+Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4
+Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+
+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P
+9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5
+UrbnBEI=
+-----END CERTIFICATE-----
+
+SwissSign Gold CA - G2
+======================
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
+EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
+MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
+c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
+t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
+jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
+vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
+ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
+AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
+jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
+peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
+7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
+GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
+OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
+5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
+44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
+Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
+Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
+mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
+vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
+KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
+NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
+viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+
+SwissSign Silver CA - G2
+========================
+-----BEGIN CERTIFICATE-----
+MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
+BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
+DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
+aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
+N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
+6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
+MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
+qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
+FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
+ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
+celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
+CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
+tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
+cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
+4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
+kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
+3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
+/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
+DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
+e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
+WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
+DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
+DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority
+========================================
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
+CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
+cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
+b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
+nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
+RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
+tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
+hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
+Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
+NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
+Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
+1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
+-----END CERTIFICATE-----
+
+thawte Primary Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
+BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
+aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
+MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
+SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
+KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
+FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
+oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
+1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
+q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
+aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
+afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
+AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
+uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
+xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
+jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
+z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
+-----END CERTIFICATE-----
+
+VeriSign Class 3 Public Primary Certification Authority - G5
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
+BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
+ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
+IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
+biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
+dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
+j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
+Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
+Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
+fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
+BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
+Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
+SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
+KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
+Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
+ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+
+SecureTrust CA
+==============
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
+dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
+BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
+OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
+DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
+GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
+01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
+ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
+aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
+KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
+SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
+mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
+nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+Secure Global CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
+bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
+MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
+Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
+YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
+bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
+8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
+HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
+0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
+oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
+MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
+CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
+3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+
+COMODO Certification Authority
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
+BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
+A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
+MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
+T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
+xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
+4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
+1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
+rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
+b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
+AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
+OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
+IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
+-----END CERTIFICATE-----
+
+Network Solutions Certificate Authority
+=======================================
+-----BEGIN CERTIFICATE-----
+MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
+EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
+IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
+MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
+MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
+jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
+aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
+crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
+/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
+AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
+bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
+A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
+4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
+GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
+wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
+ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
+-----END CERTIFICATE-----
+
+WellsSecure Public Root Certificate Authority
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM
+F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw
+NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN
+MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl
+bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD
+VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1
+iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13
+i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8
+bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB
+K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB
+AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu
+cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm
+lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB
+i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww
+GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg
+Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI
+K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0
+bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj
+qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es
+E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ
+tylv2G0xffX8oRAHh84vWdw+WNs=
+-----END CERTIFICATE-----
+
+COMODO ECC Certification Authority
+==================================
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
+R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
+ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
+GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
+b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
+4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
+wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
+FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
+U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+IGC/A
+=====
+-----BEGIN CERTIFICATE-----
+MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD
+VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE
+Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy
+MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI
+EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT
+STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2
+TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW
+So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy
+HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd
+frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ
+tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB
+egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC
+iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK
+q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q
+MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg
+Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI
+lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF
+0mBWWg==
+-----END CERTIFICATE-----
+
+Security Communication EV RootCA1
+=================================
+-----BEGIN CERTIFICATE-----
+MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
+U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh
+dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE
+BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl
+Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO
+/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX
+WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z
+ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4
+bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK
+9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
+SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm
+iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG
+Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW
+mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW
+T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
+-----END CERTIFICATE-----
+
+OISTE WISeKey Global Root GA CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
+BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
+A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
+bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
+VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
+IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
+IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
+Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
+Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
+d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
+/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
+LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
+KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
+MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
++vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
+hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
+okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
+-----END CERTIFICATE-----
+
+Microsec e-Szigno Root CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE
+BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL
+EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0
+MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz
+dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT
+GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG
+d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N
+oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc
+QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ
+PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb
+MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG
+IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD
+VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3
+LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A
+dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn
+AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA
+4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg
+AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA
+egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6
+Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO
+PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv
+c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h
+cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw
+IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT
+WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV
+MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER
+MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp
+Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal
+HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT
+nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE
+aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a
+86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK
+yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB
+S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU=
+-----END CERTIFICATE-----
+
+Certigna
+========
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
+EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
+MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
+Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
+XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
+GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
+ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
+DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
+Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
+tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
+BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
+SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
+hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
+PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
+1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+
+AC Ra\xC3\xADz Certic\xC3\xA1mara S.A.
+======================================
+-----BEGIN CERTIFICATE-----
+MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNVBAYT
+AkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERpZ2l0YWwg
+LSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4w
+HhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+
+U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJh
+IFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeGqentLhM0R7LQcNzJPNCN
+yu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzLfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU
+2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU3
+4ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP
+2yYe68yQ54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm
+8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhf
+HjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCa
+Mh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK
+5lw1omdMEWux+IBkAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1b
+czwmPS9KvqfJpxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0g
+ADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF
+BQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2Ug
+cHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEf
+AygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuX
+EpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/Jre7Ir5v
+/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dpezy4ydV/NgIlqmjCMRW3
+MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI8ck1fj+404HGIGQatlDCIaR4
+3NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wk
+eZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f
+/RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5h
+RqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecU
+Iw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ==
+-----END CERTIFICATE-----
+
+TC TrustCenter Class 2 CA II
+============================
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy
+IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw
+MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1
+c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE
+AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw
+IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2
+xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ
+Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u
+SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB
+7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90
+Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU
+cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i
+SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
+TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G
+dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ
+KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj
+TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP
+JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk
+vQ==
+-----END CERTIFICATE-----
+
+TC TrustCenter Class 3 CA II
+============================
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy
+IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw
+MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1
+c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE
+AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W
+yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo
+6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ
+uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk
+2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB
+7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90
+Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU
+cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i
+SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
+TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE
+O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8
+yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9
+IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal
+092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc
+5A==
+-----END CERTIFICATE-----
+
+TC TrustCenter Universal CA I
+=============================
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy
+IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN
+MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg
+VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw
+JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC
+qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv
+xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw
+ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O
+gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j
+BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG
+1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy
+vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3
+ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT
+ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a
+7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY
+-----END CERTIFICATE-----
+
+Deutsche Telekom Root CA 2
+==========================
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
+RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
+A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
+MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
+A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
+b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
+bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
+KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
+AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
+Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
+jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
+HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
+E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
+zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
+rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
+dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
+Cm26OWMohpLzGITY+9HPBVZkVw==
+-----END CERTIFICATE-----
+
+ComSign Secured CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE
+AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w
+NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD
+QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs
+49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH
+7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB
+kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1
+9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw
+AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t
+U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA
+j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC
+AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a
+BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp
+FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP
+51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz
+OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw==
+-----END CERTIFICATE-----
+
+Cybertrust Global Root
+======================
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
+ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
+MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
+ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
+0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
+AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
+89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
+8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
+MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
+A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
+lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
+5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
+hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
+X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
+
+ePKI Root Certification Authority
+=================================
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
+EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
+Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
+MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
+MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
+IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
+lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
+qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
+12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
+WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
+lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
+vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
+Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
+MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
+1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
+KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
+xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
+NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
+GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
+xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
+gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
+sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
+BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3
+=============================================================================================================================
+-----BEGIN CERTIFICATE-----
+MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH
+DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q
+aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry
+b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV
+BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg
+S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4
+MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl
+IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF
+n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl
+IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft
+dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl
+cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO
+Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1
+xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR
+6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
+hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd
+BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4
+N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT
+y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh
+LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M
+dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI=
+-----END CERTIFICATE-----
+
+Buypass Class 2 CA 1
+====================
+-----BEGIN CERTIFICATE-----
+MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2
+MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh
+c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M
+cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83
+0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4
+0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R
+uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P
+AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV
+1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt
+7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2
+fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w
+wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho
+-----END CERTIFICATE-----
+
+Buypass Class 3 CA 1
+====================
+-----BEGIN CERTIFICATE-----
+MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1
+MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh
+c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx
+ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0
+n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia
+AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c
+1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P
+AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7
+pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA
+EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5
+htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj
+el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915
+-----END CERTIFICATE-----
+
+EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1
+==========================================================================
+-----BEGIN CERTIFICATE-----
+MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VCRyBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQKDC5FQkcg
+QmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAe
+Fw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25p
+ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2lt
+IFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h4fuXd7hxlugTlkaDT7by
+X3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAktiHq6yOU/im/+4mRDGSaBUorzAzu8T2b
+gmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfr
+eYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZ
+TqNGFav4c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGy
+Y5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1Zn
+uqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJI
+qkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vm
+ExH8nYQKE3vwO9D8owrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0
+Nokb+Clsi7n2l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
+/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wW
+Z5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t
+FcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgm
+zJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64k
+XPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqT
+bCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJnxk1Gj7sU
+RT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4QDgZxGhBM/nV+/x5XOULK
+1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt
+2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQ
+Y9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9
+AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT
+-----END CERTIFICATE-----
+
+certSIGN ROOT CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
+VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
+Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
+CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
+JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
+rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
+ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
+0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
+AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
+Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
+AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
+SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
+x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
+vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
+TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+CNNIC ROOT
+==========
+-----BEGIN CERTIFICATE-----
+MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE
+ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw
+OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD
+o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz
+VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT
+VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or
+czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK
+y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC
+wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S
+lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5
+Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM
+O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8
+BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2
+G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m
+mxE=
+-----END CERTIFICATE-----
+
+ApplicationCA - Japanese Government
+===================================
+-----BEGIN CERTIFICATE-----
+MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT
+SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw
+MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl
+cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4
+fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN
+wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE
+jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu
+nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU
+WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV
+BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD
+vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs
+o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g
+/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD
+io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW
+dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL
+rosot4LKGAfmt1t06SAZf7IbiVQ=
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority - G3
+=============================================
+-----BEGIN CERTIFICATE-----
+MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
+BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
+IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
+NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
+YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
+LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
+K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
+c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
+IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
+dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
+2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
+cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
+Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
+AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
+t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
+-----END CERTIFICATE-----
+
+thawte Primary Root CA - G2
+===========================
+-----BEGIN CERTIFICATE-----
+MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
+VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
+IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
+Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
+MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
+b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
+IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
+LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
+8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
+mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
+G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
+rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
+-----END CERTIFICATE-----
+
+thawte Primary Root CA - G3
+===========================
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
+BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
+aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
+ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
+d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
+VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
+A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
+P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
++BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
+7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
+vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
+KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
+A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
+t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
+8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
+er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority - G2
+=============================================
+-----BEGIN CERTIFICATE-----
+MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
+Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
+OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
+MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
+b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
+BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
+KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
+EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
+ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
+npaqBA+K
+-----END CERTIFICATE-----
+
+VeriSign Universal Root Certification Authority
+===============================================
+-----BEGIN CERTIFICATE-----
+MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
+BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
+ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
+IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
+IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
+1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
+MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
+9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
+AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
+tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
+CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
+a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
+DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
+Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
+Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
+P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
+wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
+mJO37M2CYfE45k+XmCpajQ==
+-----END CERTIFICATE-----
+
+VeriSign Class 3 Public Primary Certification Authority - G4
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
+VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
+b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
+ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
+cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
+b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
+Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
+rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
+HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
+Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
+A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
+AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
+-----END CERTIFICATE-----
+
+NetLock Arany (Class Gold) FÅ‘tanÃºsÃ­tvÃ¡ny
+============================================
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
+A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
+dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
+cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
+MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
+ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
+biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
+c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
+0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
+/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
+H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
+fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
+neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
+qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
+YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
+NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
+dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+Staat der Nederlanden Root CA - G2
+==================================
+-----BEGIN CERTIFICATE-----
+MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
+CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
+TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
+ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
+5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
+vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
+CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
+e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
+OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
+CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
+48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
+trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
+qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
+AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
+ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
+A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
++51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
+f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
+kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
+CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
+URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
+CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
+oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
+IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
+66+KAQ==
+-----END CERTIFICATE-----
+
+CA Disig
+========
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK
+QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw
+MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz
+bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm
+GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD
+Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo
+hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt
+ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w
+gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P
+AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz
+aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff
+ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa
+BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t
+WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3
+mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/
+CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K
+ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA
+4Z7CRneC9VkGjCFMhwnN5ag=
+-----END CERTIFICATE-----
+
+Juur-SK
+=======
+-----BEGIN CERTIFICATE-----
+MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA
+c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw
+DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG
+SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy
+aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf
+TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC
++Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw
+UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa
+Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF
+MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD
+HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh
+AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA
+cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr
+AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw
+cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE
+FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G
+A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo
+ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL
+abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678
+IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh
+Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2
+yyqcjg==
+-----END CERTIFICATE-----
+
+Hongkong Post Root CA 1
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
+DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
+NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
+IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
+ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
+auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
+qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
+V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
+HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
+h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
+l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
+IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
+T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
+c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
+-----END CERTIFICATE-----
+
+SecureSign RootCA11
+===================
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
+SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
+b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
+KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
+cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
+TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
+wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
+g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
+O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
+bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
+t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
+OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
+bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
+Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
+y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
+lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
+-----END CERTIFICATE-----
+
+ACEDICOM Root
+=============
+-----BEGIN CERTIFICATE-----
+MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD
+T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4
+MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG
+A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk
+WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD
+YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew
+MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb
+m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk
+HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT
+xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2
+3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9
+2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq
+TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz
+4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU
+9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
+bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg
+aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP
+eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk
+zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1
+ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI
+KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq
+nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE
+I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp
+MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o
+tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA==
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow
+XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz
+IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94
+f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol
+hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky
+CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX
+bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/
+D/xwzoiQ
+-----END CERTIFICATE-----
+
+Microsec e-Szigno Root CA 2009
+==============================
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
+MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
+c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
+BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
+U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
+fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
+0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
+pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
+1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
+AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
+QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
+FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
+lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
+I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
+yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
+LXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi
+===================================================
+-----BEGIN CERTIFICATE-----
+MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
+EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz
+ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3
+MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0
+cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u
+aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY
+8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y
+jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI
+JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk
+9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD
+AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG
+SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d
+F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq
+D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4
+Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq
+fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R3
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
+YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
+bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
+aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
+bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
+iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
+0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
+rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
+OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
+xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
+FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
+lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
+EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
+bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
+YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
+kpeDMdmztcpHWD9f
+-----END CERTIFICATE-----
+
+Autoridad de Certificacion Firmaprofesional CIF A62634068
+=========================================================
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
+BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
+MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
+QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
+NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
+Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
+B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
+7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
+ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
+plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
+MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
+LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
+bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
+vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
+EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
+DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
+cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
+bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
+ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
+51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
+R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
+T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
+Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
+osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
+crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
+saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
+KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
+6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
+-----END CERTIFICATE-----
+
+Izenpe.com
+==========
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
+EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
+MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
+QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
+03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
+ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
+PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
+OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
+F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
+0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
+leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
+AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
+SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
+NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
+Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
+kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
+hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
+g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
+aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
+nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
+ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
+Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
+WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+Chambers of Commerce Root - 2008
+================================
+-----BEGIN CERTIFICATE-----
+MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
+MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
+bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
+QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
+Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
+ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
+EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
+cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
+XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
+h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
+ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
+NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
+D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
+lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
+0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
+ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
+EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
+G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
+BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
+bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
+bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
+CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
+AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
+wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
+3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
+RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
+M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
+YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
+9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
+zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
+nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
+OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
+-----END CERTIFICATE-----
+
+Global Chambersign Root - 2008
+==============================
+-----BEGIN CERTIFICATE-----
+MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
+MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
+bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
+QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
+NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
+Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
+QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
+aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
+VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
+XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
+ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
+/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
+TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
+H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
+Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
+HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
+wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
+AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
+BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
+BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
+aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
+aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
+1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
+dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
+/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
+ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
+dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
+9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
+foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
+qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
+P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
+c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
+09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
+-----END CERTIFICATE-----
+
+Go Daddy Root Certificate Authority - G2
+========================================
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
+MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
+A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
+9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
+fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
+NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
+BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
+vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
+5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
+N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+Starfield Root Certificate Authority - G2
+=========================================
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
+b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
+eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
+DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
+VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
+dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
+W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
+bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
+N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
+ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
+JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
+TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
+4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
+F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
+c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+Starfield Services Root Certificate Authority - G2
+==================================================
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
+b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
+IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
+BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
+dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
+Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
+h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
+hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
+LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
+rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
+SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
+E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
+xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
+YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
+-----END CERTIFICATE-----
+
+AffirmTrust Commercial
+======================
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
+MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
+bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
+DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
+C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
+BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
+MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
+HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
+hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
+qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
+0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
+sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+AffirmTrust Networking
+======================
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
+MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
+bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
+Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
+dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
+/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
+h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
+HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
+UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
+12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
+WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
+/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+AffirmTrust Premium
+===================
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
+OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
+dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
+BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
+5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
+GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
+p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
+S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
+6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
+/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
+MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
+6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
+L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
+BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
+IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
+g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
+zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+AffirmTrust Premium ECC
+=======================
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
+BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
+MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
+cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
+N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
+BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
+BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
+57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
+eQ==
+-----END CERTIFICATE-----
+
+Certum Trusted Network CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
+ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
+MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
+ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
+l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
+J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
+fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
+cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
+Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
+DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
+jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
+mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
+Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+Certinomis - AutoritÃ© Racine
+=============================
+-----BEGIN CERTIFICATE-----
+MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
+Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg
+LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG
+A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw
+JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa
+wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly
+Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw
+2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N
+jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q
+c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC
+lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb
+xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g
+530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna
+4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ
+KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x
+WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva
+R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40
+nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B
+CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv
+JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE
+qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b
+WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE
+wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/
+vgt2Fl43N+bYdJeimUV5
+-----END CERTIFICATE-----
+
+Root CA Generalitat Valenciana
+==============================
+-----BEGIN CERTIFICATE-----
+MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE
+ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290
+IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3
+WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE
+CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2
+F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B
+ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ
+D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte
+JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB
+AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n
+dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB
+ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl
+AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA
+YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy
+AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA
+aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt
+AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA
+YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu
+AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA
+OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0
+dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV
+BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G
+A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S
+b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh
+TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz
+Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63
+NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH
+iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt
++GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM=
+-----END CERTIFICATE-----
+
+A-Trust-nQual-03
+================
+-----BEGIN CERTIFICATE-----
+MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE
+Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy
+a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R
+dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw
+RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0
+ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1
+c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA
+zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n
+yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE
+SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4
+iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V
+cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV
+eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40
+ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr
+sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd
+JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS
+mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6
+ahq97BvIxYSazQ==
+-----END CERTIFICATE-----
+
+TWCA Root Certification Authority
+=================================
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
+VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
+EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
+IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
+QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
+oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
+4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
+y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
+9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
+mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
+QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
+T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
+Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+Security Communication RootCA2
+==============================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
+U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
+dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
+SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
+aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
+3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
+spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
+EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
+QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
+CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
+u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
+3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
+tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
+mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+EC-ACC
+======
+-----BEGIN CERTIFICATE-----
+MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
+BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
+ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
+VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
+CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
+BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
+MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
+SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
+Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
+cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
+w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
+ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
+HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
+E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
+0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
+VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
+Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
+dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
+lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
+Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
+l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
+E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
+5EI=
+-----END CERTIFICATE-----
+
+Hellenic Academic and Research Institutions RootCA 2011
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
+O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
+aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
+IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
+AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
+IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
+IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
+1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
+71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
+8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
+3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
+MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
+MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
+b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
+XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
+TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
+/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
+7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
+-----END CERTIFICATE-----
+
+Actalis Authentication Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
+BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
+AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
+MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
+IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
+wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
+by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
+zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
+YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
+oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
+EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
+hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
+EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
+jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
+iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
+WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
+JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
+K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
+Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
+4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
+2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
+lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
+OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
+vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+
+Trustis FPS Root CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
+EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
+IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
+BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
+RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
+H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
+cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
+o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
+AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
+BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
+GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
+yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
+8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
+l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
+iB6XzCGcKQENZetX2fNXlrtIzYE=
+-----END CERTIFICATE-----
+
+StartCom Certification Authority
+================================
+-----BEGIN CERTIFICATE-----
+MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
+U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
+ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
+NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
+LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
+U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
+o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
+Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
+eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
+2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
+6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
+osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
+untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
+UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
+37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ
+Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0
+dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu
+c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv
+bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0
+aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
+L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG
+cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5
+fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm
+N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN
+Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T
+tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX
+e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA
+2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs
+HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
+JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib
+D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8=
+-----END CERTIFICATE-----
+
+StartCom Certification Authority G2
+===================================
+-----BEGIN CERTIFICATE-----
+MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
+U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE
+ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O
+o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG
+4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi
+Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul
+Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs
+O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H
+vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L
+nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS
+FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa
+z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ
+KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
+2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk
+J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+
+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG
+/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc
+nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld
+blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc
+l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm
+7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm
+obp573PYtlNXLfbQ4ddI
+-----END CERTIFICATE-----
+
+Buypass Class 2 Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
+DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
+eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
+g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
+9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
+/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
+CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
+awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
+zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
+Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
+Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
+M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
+AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
+osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
+aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
+DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
+LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
+oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
+wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
+CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
+rJgWVqA=
+-----END CERTIFICATE-----
+
+Buypass Class 3 Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
+DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
+eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
+sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
+5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
+7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
+ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
+2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
+/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
+RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
+Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
+j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
+AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
+uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
+Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
+ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
+KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
+6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
+UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
+eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
+Cp/HuZc=
+-----END CERTIFICATE-----
+
+T-TeleSec GlobalRoot Class 3
+============================
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
+IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
+cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
+MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
+dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
+ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
+9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
+NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
+iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
+0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
+AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
+fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
+ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
+P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
+-----END CERTIFICATE-----
+
+EE Certification Centre Root CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
+EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
+dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
+MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
+UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
+ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
+TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
+rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
+93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
+P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
+MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
+BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
+xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
+lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
+uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
+3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
+dcGWxZ0=
+-----END CERTIFICATE-----
+
+TURKTRUST Certificate Services Provider Root 2007
+=================================================
+-----BEGIN CERTIFICATE-----
+MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
+MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
+QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X
+DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl
+a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN
+BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
+bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N
+YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv
+KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya
+KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT
+rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC
+AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s
+Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I
+aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO
+Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb
+BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK
+poRq0Tl9
+-----END CERTIFICATE-----
+
+D-TRUST Root Class 3 CA 2 2009
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
+DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
+Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
+LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
+ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
+BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
+KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
+p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
+AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
+4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
+eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
+MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
+PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
+OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
+2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
+dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
+X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
+-----END CERTIFICATE-----
+
+D-TRUST Root Class 3 CA 2 EV 2009
+=================================
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
+DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
+OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
+DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
+OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
+egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
+zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
+7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
+sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
+11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
+cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
+ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
+MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
+b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
+c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
+PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
+ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
+NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
+w9y4AyHqnxbxLFS1
+-----END CERTIFICATE-----
+
+PSCProcert
+==========
+-----BEGIN CERTIFICATE-----
+MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk
+ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ
+MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz
+dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl
+cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw
+IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw
+MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w
+DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD
+ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp
+Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC
+wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA
+3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh
+RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO
+EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2
+0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH
+0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU
+td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw
+Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp
+r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/
+AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz
+Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId
+xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp
+ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH
+EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h
+Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k
+ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG
+9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG
+MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG
+LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52
+ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy
+YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v
+Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o
+dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq
+T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN
+g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q
+uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1
+n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn
+FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo
+5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq
+3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5
+poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y
+eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km
+-----END CERTIFICATE-----
+
+China Internet Network Information Center EV Certificates Root
+==============================================================
+-----BEGIN CERTIFICATE-----
+MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xMjAwBgNV
+BAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyMUcwRQYDVQQDDD5D
+aGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMg
+Um9vdDAeFw0xMDA4MzEwNzExMjVaFw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAG
+A1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMM
+PkNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRl
+cyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z7r07eKpkQ0H1UN+U8i6y
+jUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV
+98YPjUesWgbdYavi7NifFy2cyjw1l1VxzUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2H
+klY0bBoQCxfVWhyXWIQ8hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23
+KzhmBsUs4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54ugQEC
+7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oYNJKiyoOCWTAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUfHJLOcfA22KlT5uqGDSSosqD
+glkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd5
+0XPFtQO3WKwMVC/GVhMPMdoG52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM
+7+czV0I664zBechNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws
+ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrIzo9uoV1/A3U0
+5K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATywy39FCqQmbkHzJ8=
+-----END CERTIFICATE-----
+
+Swisscom Root CA 2
+==================
+-----BEGIN CERTIFICATE-----
+MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQG
+EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
+dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2
+MjUwNzM4MTRaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
+aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIIC
+IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvErjw0DzpPM
+LgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r0rk0X2s682Q2zsKwzxNo
+ysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJ
+wDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVPACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpH
+Wrumnf2U5NGKpV+GY3aFy6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1a
+SgJA/MTAtukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL6yxS
+NLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0uPoTXGiTOmekl9Ab
+mbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrALacywlKinh/LTSlDcX3KwFnUey7QY
+Ypqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velhk6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3
+qPyZ7iVNTA6z00yPhOgpD/0QVAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
+HQYDVR0hBBYwFDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O
+BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqhb97iEoHF8Twu
+MA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4RfbgZPnm3qKhyN2abGu2sEzsO
+v2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ
+82YqZh6NM4OKb3xuqFp1mrjX2lhIREeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLz
+o9v/tdhZsnPdTSpxsrpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcs
+a0vvaGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciATwoCqISxx
+OQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99nBjx8Oto0QuFmtEYE3saW
+mA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5Wt6NlUe07qxS/TFED6F+KBZvuim6c779o
++sjaC+NCydAXFJy3SuCvkychVSa1ZC+N8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TC
+rvJcwhbtkj6EPnNgiLx29CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX
+5OfNeOI5wSsSnqaeG8XmDtkx2Q==
+-----END CERTIFICATE-----
+
+Swisscom Root EV CA 2
+=====================
+-----BEGIN CERTIFICATE-----
+MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UE
+BhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdpdGFsIENlcnRpZmljYXRlIFNl
+cnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcN
+MzEwNjI1MDg0NTA4WjBnMQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsT
+HERpZ2l0YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYg
+Q0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7BxUglgRCgz
+o3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD1ycfMQ4jFrclyxy0uYAy
+Xhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPHoCE2G3pXKSinLr9xJZDzRINpUKTk4Rti
+GZQJo/PDvO/0vezbE53PnUgJUmfANykRHvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8Li
+qG12W0OfvrSdsyaGOx9/5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaH
+Za0zKcQvidm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHLOdAG
+alNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaCNYGu+HuB5ur+rPQa
+m3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f46Fq9mDU5zXNysRojddxyNMkM3Ox
+bPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCBUWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDi
+xzgHcgplwLa7JSnaFp6LNYth7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED
+MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWBbj2ITY1x0kbB
+bkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6xXCX5145v9Ydkn+0UjrgEjihL
+j6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98TPLr+flaYC/NUn81ETm484T4VvwYmneTwkLbU
+wp4wLh/vx3rEUMfqe9pQy3omywC0Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7
+XwgiG/W9mR4U9s70WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH
+59yLGn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm7JFe3VE/
+23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4Snr8PyQUQ3nqjsTzyP6Wq
+J3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VNvBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyA
+HmBR3NdUIR7KYndP+tiPsys6DXhyyWhBWkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/gi
+uMod89a2GQ+fYWVq6nTIfI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuW
+l8PVP3wbI+2ksx0WckNLIOFZfsLorSa/ovc=
+-----END CERTIFICATE-----
+
+CA Disig Root R1
+================
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw
+EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
+ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx
+EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
+c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy
+3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8
+u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2
+m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk
+CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa
+YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6
+vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL
+LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX
+ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is
+XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ
+04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR
+xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B
+LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM
+CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb
+VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85
+YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS
+ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix
+lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N
+UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ
+a7+h89n07eLw4+1knj0vllJPgFOL
+-----END CERTIFICATE-----
+
+CA Disig Root R2
+================
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
+EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
+ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
+EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
+c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
+w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
+xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
+A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
+GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
+g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
+5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
+koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
+Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
+Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
+Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
+sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
+dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
+1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
+mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
+utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
+sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
+UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
+7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
+
+ACCVRAIZ1
+=========
+-----BEGIN CERTIFICATE-----
+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
+SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
+MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
+UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
+jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
+RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
+aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
+0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
+WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
+8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
+5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
+9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
+Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
+Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
+Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
+Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
+QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
+AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
+YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
+AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
+IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
+aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
+dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
+MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
+hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
+R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
+YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
+nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
+TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
+sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
+Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
+3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
+EfbRD0tVNEYqi4Y7
+-----END CERTIFICATE-----
+
+TWCA Global Root CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
+CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
+QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
+EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
+Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
+nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
+r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
+Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
+tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
+KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
+sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
+yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
+kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
+zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
+cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
+8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
+/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
+lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
+A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
+i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
+EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
+zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
+-----END CERTIFICATE-----
+
+TeliaSonera Root CA v1
+======================
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
+CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
+MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
+VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
+6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
+3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
+B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
+Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
+oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
+F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
+oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
+gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
+TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
+AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
+DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
+zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
+pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
+G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
+c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
+JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
+qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
+Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
+WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
+-----END CERTIFICATE-----
+
+E-Tugra Certification Authority
+===============================
+-----BEGIN CERTIFICATE-----
+MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
+DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
+ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
+ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
+NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
+QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
+cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
+DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
+hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
+CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
+ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
+BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
+E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
+rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
+jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
+rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
+dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
+/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
+MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
+kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
+XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
+VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
+a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
+dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
+KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
+Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
+8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
+C7TbO6Orb1wdtn7os4I07QZcJA==
+-----END CERTIFICATE-----
+
+T-TeleSec GlobalRoot Class 2
+============================
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
+IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
+cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
+MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
+dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
+ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
+SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
+vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
+2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
+WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
+YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
+r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
+vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
+3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
+9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
+-----END CERTIFICATE-----
+
+Atos TrustedRoot 2011
+=====================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
+cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
+MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
+A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
+hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
+54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
+HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
+z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
+l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
+bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
+CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
+k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
+TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
+61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
+3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
diff --git a/core/vendor/guzzle/http/Guzzle/Http/StaticClient.php b/core/vendor/guzzle/http/Guzzle/Http/StaticClient.php
new file mode 100644
index 0000000..dbd4c18
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/StaticClient.php
@@ -0,0 +1,157 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Http\Client;
+use Guzzle\Http\ClientInterface;
+use Guzzle\Stream\StreamRequestFactoryInterface;
+use Guzzle\Stream\PhpStreamRequestFactory;
+
+/**
+ * Simplified interface to Guzzle that does not require a class to be instantiated
+ */
+final class StaticClient
+{
+    /** @var Client Guzzle client */
+    private static $client;
+
+    /**
+     * Mount the client to a simpler class name for a specific client
+     *
+     * @param string          $className Class name to use to mount
+     * @param ClientInterface $client    Client used to send requests
+     */
+    public static function mount($className = 'Guzzle', ClientInterface $client = null)
+    {
+        class_alias(__CLASS__, $className);
+        if ($client) {
+            self::$client = $client;
+        }
+    }
+
+    /**
+     * @param  string $method  HTTP request method (GET, POST, HEAD, DELETE, PUT, etc)
+     * @param  string $url     URL of the request
+     * @param  array  $options Options to use with the request. See: Guzzle\Http\Message\RequestFactory::applyOptions()
+     * @return \Guzzle\Http\Message\Response|\Guzzle\Stream\Stream
+     */
+    public static function request($method, $url, $options = array())
+    {
+        // @codeCoverageIgnoreStart
+        if (!self::$client) {
+            self::$client = new Client();
+        }
+        // @codeCoverageIgnoreEnd
+
+        $request = self::$client->createRequest($method, $url, null, null, $options);
+
+        if (isset($options['stream'])) {
+            if ($options['stream'] instanceof StreamRequestFactoryInterface) {
+                return $options['stream']->fromRequest($request);
+            } elseif ($options['stream'] == true) {
+                $streamFactory = new PhpStreamRequestFactory();
+                return $streamFactory->fromRequest($request);
+            }
+        }
+
+        return $request->send();
+    }
+
+    /**
+     * Send a GET request
+     *
+     * @param string $url     URL of the request
+     * @param array  $options Array of request options
+     *
+     * @return \Guzzle\Http\Message\Response
+     * @see Guzzle::request for a list of available options
+     */
+    public static function get($url, $options = array())
+    {
+        return self::request('GET', $url, $options);
+    }
+
+    /**
+     * Send a HEAD request
+     *
+     * @param string $url     URL of the request
+     * @param array  $options Array of request options
+     *
+     * @return \Guzzle\Http\Message\Response
+     * @see Guzzle::request for a list of available options
+     */
+    public static function head($url, $options = array())
+    {
+        return self::request('HEAD', $url, $options);
+    }
+
+    /**
+     * Send a DELETE request
+     *
+     * @param string $url     URL of the request
+     * @param array  $options Array of request options
+     *
+     * @return \Guzzle\Http\Message\Response
+     * @see Guzzle::request for a list of available options
+     */
+    public static function delete($url, $options = array())
+    {
+        return self::request('DELETE', $url, $options);
+    }
+
+    /**
+     * Send a POST request
+     *
+     * @param string $url     URL of the request
+     * @param array  $options Array of request options
+     *
+     * @return \Guzzle\Http\Message\Response
+     * @see Guzzle::request for a list of available options
+     */
+    public static function post($url, $options = array())
+    {
+        return self::request('POST', $url, $options);
+    }
+
+    /**
+     * Send a PUT request
+     *
+     * @param string $url     URL of the request
+     * @param array  $options Array of request options
+     *
+     * @return \Guzzle\Http\Message\Response
+     * @see Guzzle::request for a list of available options
+     */
+    public static function put($url, $options = array())
+    {
+        return self::request('PUT', $url, $options);
+    }
+
+    /**
+     * Send a PATCH request
+     *
+     * @param string $url     URL of the request
+     * @param array  $options Array of request options
+     *
+     * @return \Guzzle\Http\Message\Response
+     * @see Guzzle::request for a list of available options
+     */
+    public static function patch($url, $options = array())
+    {
+        return self::request('PATCH', $url, $options);
+    }
+
+    /**
+     * Send an OPTIONS request
+     *
+     * @param string $url     URL of the request
+     * @param array  $options Array of request options
+     *
+     * @return \Guzzle\Http\Message\Response
+     * @see Guzzle::request for a list of available options
+     */
+    public static function options($url, $options = array())
+    {
+        return self::request('OPTIONS', $url, $options);
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/Url.php b/core/vendor/guzzle/http/Guzzle/Http/Url.php
new file mode 100644
index 0000000..6a4e772
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/Url.php
@@ -0,0 +1,554 @@
+<?php
+
+namespace Guzzle\Http;
+
+use Guzzle\Common\Exception\InvalidArgumentException;
+
+/**
+ * Parses and generates URLs based on URL parts. In favor of performance, URL parts are not validated.
+ */
+class Url
+{
+    protected $scheme;
+    protected $host;
+    protected $port;
+    protected $username;
+    protected $password;
+    protected $path = '';
+    protected $fragment;
+
+    /** @var QueryString Query part of the URL */
+    protected $query;
+
+    /**
+     * Factory method to create a new URL from a URL string
+     *
+     * @param string $url Full URL used to create a Url object
+     *
+     * @return Url
+     * @throws InvalidArgumentException
+     */
+    public static function factory($url)
+    {
+        static $defaults = array('scheme' => null, 'host' => null, 'path' => null, 'port' => null, 'query' => null,
+            'user' => null, 'pass' => null, 'fragment' => null);
+
+        if (false === ($parts = parse_url($url))) {
+            throw new InvalidArgumentException('Was unable to parse malformed url: ' . $url);
+        }
+
+        $parts += $defaults;
+
+        // Convert the query string into a QueryString object
+        if ($parts['query'] || 0 !== strlen($parts['query'])) {
+            $parts['query'] = QueryString::fromString($parts['query']);
+        }
+
+        return new static($parts['scheme'], $parts['host'], $parts['user'],
+            $parts['pass'], $parts['port'], $parts['path'], $parts['query'],
+            $parts['fragment']);
+    }
+
+    /**
+     * Build a URL from parse_url parts. The generated URL will be a relative URL if a scheme or host are not provided.
+     *
+     * @param array $parts Array of parse_url parts
+     *
+     * @return string
+     */
+    public static function buildUrl(array $parts)
+    {
+        $url = $scheme = '';
+
+        if (isset($parts['scheme'])) {
+            $scheme = $parts['scheme'];
+            $url .= $scheme . ':';
+        }
+
+        if (isset($parts['host'])) {
+            $url .= '//';
+            if (isset($parts['user'])) {
+                $url .= $parts['user'];
+                if (isset($parts['pass'])) {
+                    $url .= ':' . $parts['pass'];
+                }
+                $url .=  '@';
+            }
+
+            $url .= $parts['host'];
+
+            // Only include the port if it is not the default port of the scheme
+            if (isset($parts['port'])
+                && !(($scheme == 'http' && $parts['port'] == 80) || ($scheme == 'https' && $parts['port'] == 443))
+            ) {
+                $url .= ':' . $parts['port'];
+            }
+        }
+
+        // Add the path component if present
+        if (isset($parts['path']) && 0 !== strlen($parts['path'])) {
+            // Always ensure that the path begins with '/' if set and something is before the path
+            if ($url && $parts['path'][0] != '/' && substr($url, -1)  != '/') {
+                $url .= '/';
+            }
+            $url .= $parts['path'];
+        }
+
+        // Add the query string if present
+        if (isset($parts['query'])) {
+            $url .= '?' . $parts['query'];
+        }
+
+        // Ensure that # is only added to the url if fragment contains anything.
+        if (isset($parts['fragment'])) {
+            $url .= '#' . $parts['fragment'];
+        }
+
+        return $url;
+    }
+
+    /**
+     * Create a new URL from URL parts
+     *
+     * @param string                   $scheme   Scheme of the URL
+     * @param string                   $host     Host of the URL
+     * @param string                   $username Username of the URL
+     * @param string                   $password Password of the URL
+     * @param int                      $port     Port of the URL
+     * @param string                   $path     Path of the URL
+     * @param QueryString|array|string $query    Query string of the URL
+     * @param string                   $fragment Fragment of the URL
+     */
+    public function __construct($scheme, $host, $username = null, $password = null, $port = null, $path = null, QueryString $query = null, $fragment = null)
+    {
+        $this->scheme = $scheme;
+        $this->host = $host;
+        $this->port = $port;
+        $this->username = $username;
+        $this->password = $password;
+        $this->fragment = $fragment;
+        if (!$query) {
+            $this->query = new QueryString();
+        } else {
+            $this->setQuery($query);
+        }
+        $this->setPath($path);
+    }
+
+    /**
+     * Clone the URL
+     */
+    public function __clone()
+    {
+        $this->query = clone $this->query;
+    }
+
+    /**
+     * Returns the URL as a URL string
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return self::buildUrl($this->getParts());
+    }
+
+    /**
+     * Get the parts of the URL as an array
+     *
+     * @return array
+     */
+    public function getParts()
+    {
+        $query = (string) $this->query;
+
+        return array(
+            'scheme' => $this->scheme,
+            'user' => $this->username,
+            'pass' => $this->password,
+            'host' => $this->host,
+            'port' => $this->port,
+            'path' => $this->getPath(),
+            'query' => $query !== '' ? $query : null,
+            'fragment' => $this->fragment,
+        );
+    }
+
+    /**
+     * Set the host of the request.
+     *
+     * @param string $host Host to set (e.g. www.yahoo.com, yahoo.com)
+     *
+     * @return Url
+     */
+    public function setHost($host)
+    {
+        if (strpos($host, ':') === false) {
+            $this->host = $host;
+        } else {
+            list($host, $port) = explode(':', $host);
+            $this->host = $host;
+            $this->setPort($port);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get the host part of the URL
+     *
+     * @return string
+     */
+    public function getHost()
+    {
+        return $this->host;
+    }
+
+    /**
+     * Set the scheme part of the URL (http, https, ftp, etc)
+     *
+     * @param string $scheme Scheme to set
+     *
+     * @return Url
+     */
+    public function setScheme($scheme)
+    {
+        if ($this->scheme == 'http' && $this->port == 80) {
+            $this->port = null;
+        } elseif ($this->scheme == 'https' && $this->port == 443) {
+            $this->port = null;
+        }
+
+        $this->scheme = $scheme;
+
+        return $this;
+    }
+
+    /**
+     * Get the scheme part of the URL
+     *
+     * @return string
+     */
+    public function getScheme()
+    {
+        return $this->scheme;
+    }
+
+    /**
+     * Set the port part of the URL
+     *
+     * @param int $port Port to set
+     *
+     * @return Url
+     */
+    public function setPort($port)
+    {
+        $this->port = $port;
+
+        return $this;
+    }
+
+    /**
+     * Get the port part of the URl. Will return the default port for a given scheme if no port has been set.
+     *
+     * @return int|null
+     */
+    public function getPort()
+    {
+        if ($this->port) {
+            return $this->port;
+        } elseif ($this->scheme == 'http') {
+            return 80;
+        } elseif ($this->scheme == 'https') {
+            return 443;
+        }
+
+        return null;
+    }
+
+    /**
+     * Set the path part of the URL
+     *
+     * @param array|string $path Path string or array of path segments
+     *
+     * @return Url
+     */
+    public function setPath($path)
+    {
+        static $pathReplace = array(' ' => '%20', '?' => '%3F');
+        if (is_array($path)) {
+            $path = '/' . implode('/', $path);
+        }
+
+        $this->path = strtr($path, $pathReplace);
+
+        return $this;
+    }
+
+    /**
+     * Normalize the URL so that double slashes and relative paths are removed
+     *
+     * @return Url
+     */
+    public function normalizePath()
+    {
+        if (!$this->path || $this->path == '/' || $this->path == '*') {
+            return $this;
+        }
+
+        $results = array();
+        $segments = $this->getPathSegments();
+        foreach ($segments as $segment) {
+            if ($segment == '..') {
+                array_pop($results);
+            } elseif ($segment != '.' && $segment != '') {
+                $results[] = $segment;
+            }
+        }
+
+        // Combine the normalized parts and add the leading slash if needed
+        $this->path = ($this->path[0] == '/' ? '/' : '') . implode('/', $results);
+
+        // Add the trailing slash if necessary
+        if ($this->path != '/' && end($segments) == '') {
+            $this->path .= '/';
+        }
+
+        return $this;
+    }
+
+    /**
+     * Add a relative path to the currently set path.
+     *
+     * @param string $relativePath Relative path to add
+     *
+     * @return Url
+     */
+    public function addPath($relativePath)
+    {
+        if ($relativePath != '/' && is_string($relativePath) && strlen($relativePath) > 0) {
+            // Add a leading slash if needed
+            if ($relativePath[0] != '/') {
+                $relativePath = '/' . $relativePath;
+            }
+            $this->setPath(str_replace('//', '/', $this->path . $relativePath));
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get the path part of the URL
+     *
+     * @return string
+     */
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    /**
+     * Get the path segments of the URL as an array
+     *
+     * @return array
+     */
+    public function getPathSegments()
+    {
+        return array_slice(explode('/', $this->getPath()), 1);
+    }
+
+    /**
+     * Set the password part of the URL
+     *
+     * @param string $password Password to set
+     *
+     * @return Url
+     */
+    public function setPassword($password)
+    {
+        $this->password = $password;
+
+        return $this;
+    }
+
+    /**
+     * Get the password part of the URL
+     *
+     * @return null|string
+     */
+    public function getPassword()
+    {
+        return $this->password;
+    }
+
+    /**
+     * Set the username part of the URL
+     *
+     * @param string $username Username to set
+     *
+     * @return Url
+     */
+    public function setUsername($username)
+    {
+        $this->username = $username;
+
+        return $this;
+    }
+
+    /**
+     * Get the username part of the URl
+     *
+     * @return null|string
+     */
+    public function getUsername()
+    {
+        return $this->username;
+    }
+
+    /**
+     * Get the query part of the URL as a QueryString object
+     *
+     * @return QueryString
+     */
+    public function getQuery()
+    {
+        return $this->query;
+    }
+
+    /**
+     * Set the query part of the URL
+     *
+     * @param QueryString|string|array $query Query to set
+     *
+     * @return Url
+     */
+    public function setQuery($query)
+    {
+        if (is_string($query)) {
+            $output = null;
+            parse_str($query, $output);
+            $this->query = new QueryString($output);
+        } elseif (is_array($query)) {
+            $this->query = new QueryString($query);
+        } elseif ($query instanceof QueryString) {
+            $this->query = $query;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get the fragment part of the URL
+     *
+     * @return null|string
+     */
+    public function getFragment()
+    {
+        return $this->fragment;
+    }
+
+    /**
+     * Set the fragment part of the URL
+     *
+     * @param string $fragment Fragment to set
+     *
+     * @return Url
+     */
+    public function setFragment($fragment)
+    {
+        $this->fragment = $fragment;
+
+        return $this;
+    }
+
+    /**
+     * Check if this is an absolute URL
+     *
+     * @return bool
+     */
+    public function isAbsolute()
+    {
+        return $this->scheme && $this->host;
+    }
+
+    /**
+     * Combine the URL with another URL. Follows the rules specific in RFC 3986 section 5.4.
+     *
+     * @param string $url           Relative URL to combine with
+     * @param bool   $strictRfc3986 Set to true to use strict RFC 3986 compliance when merging paths. When first
+     *                              released, Guzzle used an incorrect algorithm for combining relative URL paths. In
+     *                              order to not break users, we introduced this flag to allow the merging of URLs based
+     *                              on strict RFC 3986 section 5.4.1. This means that "http://a.com/foo/baz" merged with
+     *                              "bar" would become "http://a.com/foo/bar". When this value is set to false, it would
+     *                              become "http://a.com/foo/baz/bar".
+     * @return Url
+     * @throws InvalidArgumentException
+     * @link http://tools.ietf.org/html/rfc3986#section-5.4
+     */
+    public function combine($url, $strictRfc3986 = false)
+    {
+        $url = self::factory($url);
+
+        // Use the more absolute URL as the base URL
+        if (!$this->isAbsolute() && $url->isAbsolute()) {
+            $url = $url->combine($this);
+        }
+
+        // Passing a URL with a scheme overrides everything
+        if ($buffer = $url->getScheme()) {
+            $this->scheme = $buffer;
+            $this->host = $url->getHost();
+            $this->port = $url->getPort();
+            $this->username = $url->getUsername();
+            $this->password = $url->getPassword();
+            $this->path = $url->getPath();
+            $this->query = $url->getQuery();
+            $this->fragment = $url->getFragment();
+            return $this;
+        }
+
+        // Setting a host overrides the entire rest of the URL
+        if ($buffer = $url->getHost()) {
+            $this->host = $buffer;
+            $this->port = $url->getPort();
+            $this->username = $url->getUsername();
+            $this->password = $url->getPassword();
+            $this->path = $url->getPath();
+            $this->query = $url->getQuery();
+            $this->fragment = $url->getFragment();
+            return $this;
+        }
+
+        $path = $url->getPath();
+        $query = $url->getQuery();
+
+        if (!$path) {
+            if (count($query)) {
+                $this->addQuery($query, $strictRfc3986);
+            }
+        } else {
+            if ($path[0] == '/') {
+                $this->path = $path;
+            } elseif ($strictRfc3986) {
+                $this->path .= '/../' . $path;
+            } else {
+                $this->path .= '/' . $path;
+            }
+            $this->normalizePath();
+            $this->addQuery($query, $strictRfc3986);
+        }
+
+        $this->fragment = $url->getFragment();
+
+        return $this;
+    }
+
+    private function addQuery(QueryString $new, $strictRfc386)
+    {
+        if (!$strictRfc386) {
+            $new->merge($this->query);
+        }
+
+        $this->query = $new;
+    }
+}
diff --git a/core/vendor/guzzle/http/Guzzle/Http/composer.json b/core/vendor/guzzle/http/Guzzle/Http/composer.json
new file mode 100644
index 0000000..9384a5b
--- /dev/null
+++ b/core/vendor/guzzle/http/Guzzle/Http/composer.json
@@ -0,0 +1,32 @@
+{
+    "name": "guzzle/http",
+    "description": "HTTP libraries used by Guzzle",
+    "homepage": "http://guzzlephp.org/",
+    "keywords": ["http client", "http", "client", "Guzzle", "curl"],
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Michael Dowling",
+            "email": "mtdowling@gmail.com",
+            "homepage": "https://github.com/mtdowling"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.2",
+        "guzzle/common": "self.version",
+        "guzzle/parser": "self.version",
+        "guzzle/stream": "self.version"
+    },
+    "suggest": {
+        "ext-curl": "*"
+    },
+    "autoload": {
+        "psr-0": { "Guzzle\\Http": "" }
+    },
+    "target-dir": "Guzzle/Http",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "3.7-dev"
+        }
+    }
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/Cookie/CookieParser.php b/core/vendor/guzzle/parser/Guzzle/Parser/Cookie/CookieParser.php
new file mode 100644
index 0000000..4349eeb
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/Cookie/CookieParser.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace Guzzle\Parser\Cookie;
+
+/**
+ * Default Guzzle implementation of a Cookie parser
+ */
+class CookieParser implements CookieParserInterface
+{
+    /** @var array Cookie part names to snake_case array values */
+    protected static $cookieParts = array(
+        'domain'      => 'Domain',
+        'path'        => 'Path',
+        'max_age'     => 'Max-Age',
+        'expires'     => 'Expires',
+        'version'     => 'Version',
+        'secure'      => 'Secure',
+        'port'        => 'Port',
+        'discard'     => 'Discard',
+        'comment'     => 'Comment',
+        'comment_url' => 'Comment-Url',
+        'http_only'   => 'HttpOnly'
+    );
+
+    public function parseCookie($cookie, $host = null, $path = null, $decode = false)
+    {
+        // Explode the cookie string using a series of semicolons
+        $pieces = array_filter(array_map('trim', explode(';', $cookie)));
+
+        // The name of the cookie (first kvp) must include an equal sign.
+        if (empty($pieces) || !strpos($pieces[0], '=')) {
+            return false;
+        }
+
+        // Create the default return array
+        $data = array_merge(array_fill_keys(array_keys(self::$cookieParts), null), array(
+            'cookies'   => array(),
+            'data'      => array(),
+            'path'      => null,
+            'http_only' => false,
+            'discard'   => false,
+            'domain'    => $host
+        ));
+        $foundNonCookies = 0;
+
+        // Add the cookie pieces into the parsed data array
+        foreach ($pieces as $part) {
+
+            $cookieParts = explode('=', $part, 2);
+            $key = trim($cookieParts[0]);
+
+            if (count($cookieParts) == 1) {
+                // Can be a single value (e.g. secure, httpOnly)
+                $value = true;
+            } else {
+                // Be sure to strip wrapping quotes
+                $value = trim($cookieParts[1], " \n\r\t\0\x0B\"");
+                if ($decode) {
+                    $value = urldecode($value);
+                }
+            }
+
+            // Only check for non-cookies when cookies have been found
+            if (!empty($data['cookies'])) {
+                foreach (self::$cookieParts as $mapValue => $search) {
+                    if (!strcasecmp($search, $key)) {
+                        $data[$mapValue] = $mapValue == 'port' ? array_map('trim', explode(',', $value)) : $value;
+                        $foundNonCookies++;
+                        continue 2;
+                    }
+                }
+            }
+
+            // If cookies have not yet been retrieved, or this value was not found in the pieces array, treat it as a
+            // cookie. IF non-cookies have been parsed, then this isn't a cookie, it's cookie data. Cookies then data.
+            $data[$foundNonCookies ? 'data' : 'cookies'][$key] = $value;
+        }
+
+        // Calculate the expires date
+        if (!$data['expires'] && $data['max_age']) {
+            $data['expires'] = time() + (int) $data['max_age'];
+        }
+
+        // Check path attribute according RFC6265 http://tools.ietf.org/search/rfc6265#section-5.2.4
+        // "If the attribute-value is empty or if the first character of the
+        // attribute-value is not %x2F ("/"):
+        //   Let cookie-path be the default-path.
+        // Otherwise:
+        //   Let cookie-path be the attribute-value."
+        if (!$data['path'] || substr($data['path'], 0, 1) !== '/') {
+            $data['path'] = $this->getDefaultPath($path);
+        }
+
+        return $data;
+    }
+
+    /**
+     * Get default cookie path according to RFC 6265
+     * http://tools.ietf.org/search/rfc6265#section-5.1.4 Paths and Path-Match
+     *
+     * @param string $path Request uri-path
+     *
+     * @return string
+     */
+    protected function getDefaultPath($path) {
+        // "The user agent MUST use an algorithm equivalent to the following algorithm
+        // to compute the default-path of a cookie:"
+
+        // "2. If the uri-path is empty or if the first character of the uri-path is not
+        // a %x2F ("/") character, output %x2F ("/") and skip the remaining steps.
+        if (empty($path) || substr($path, 0, 1) !== '/') {
+            return '/';
+        }
+
+        // "3. If the uri-path contains no more than one %x2F ("/") character, output
+        // %x2F ("/") and skip the remaining step."
+        if ($path === "/") {
+            return $path;
+        }
+
+        $rightSlashPos = strrpos($path, '/');
+        if ($rightSlashPos === 0) {
+            return "/";
+        }
+
+        // "4. Output the characters of the uri-path from the first character up to,
+        // but not including, the right-most %x2F ("/")."
+        return substr($path, 0, $rightSlashPos);
+
+    }
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/Cookie/CookieParserInterface.php b/core/vendor/guzzle/parser/Guzzle/Parser/Cookie/CookieParserInterface.php
new file mode 100644
index 0000000..d21ffe2
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/Cookie/CookieParserInterface.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Guzzle\Parser\Cookie;
+
+/**
+ * Cookie parser interface
+ */
+interface CookieParserInterface
+{
+    /**
+     * Parse a cookie string as set in a Set-Cookie HTTP header and return an associative array of data.
+     *
+     * @param string $cookie Cookie header value to parse
+     * @param string $host   Host of an associated request
+     * @param string $path   Path of an associated request
+     * @param bool   $decode Set to TRUE to urldecode cookie values
+     *
+     * @return array|bool Returns FALSE on failure or returns an array of arrays, with each of the sub arrays including:
+     *     - domain  (string) - Domain of the cookie
+     *     - path    (string) - Path of the cookie
+     *     - cookies (array)  - Associative array of cookie names and values
+     *     - max_age (int)    - Lifetime of the cookie in seconds
+     *     - version (int)    - Version of the cookie specification. RFC 2965 is 1
+     *     - secure  (bool)   - Whether or not this is a secure cookie
+     *     - discard (bool)   - Whether or not this is a discardable cookie
+     *     - custom (string)  - Custom cookie data array
+     *     - comment (string) - How the cookie is intended to be used
+     *     - comment_url (str)- URL that contains info on how it will be used
+     *     - port (array|str) - Array of ports or null
+     *     - http_only (bool) - HTTP only cookie
+     */
+    public function parseCookie($cookie, $host = null, $path = null, $decode = false);
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/Message/AbstractMessageParser.php b/core/vendor/guzzle/parser/Guzzle/Parser/Message/AbstractMessageParser.php
new file mode 100644
index 0000000..d25f9cc
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/Message/AbstractMessageParser.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace Guzzle\Parser\Message;
+
+/**
+ * Implements shared message parsing functionality
+ */
+abstract class AbstractMessageParser implements MessageParserInterface
+{
+    /**
+     * Create URL parts from HTTP message parts
+     *
+     * @param string $requestUrl Associated URL
+     * @param array  $parts      HTTP message parts
+     *
+     * @return array
+     */
+    protected function getUrlPartsFromMessage($requestUrl, array $parts)
+    {
+        // Parse the URL information from the message
+        $urlParts = array(
+            'path'   => $requestUrl,
+            'scheme' => 'http'
+        );
+
+        // Check for the Host header
+        if (isset($parts['headers']['Host'])) {
+            $urlParts['host'] = $parts['headers']['Host'];
+        } elseif (isset($parts['headers']['host'])) {
+            $urlParts['host'] = $parts['headers']['host'];
+        } else {
+            $urlParts['host'] = null;
+        }
+
+        if (false === strpos($urlParts['host'], ':')) {
+            $urlParts['port'] = '';
+        } else {
+            $hostParts = explode(':', $urlParts['host']);
+            $urlParts['host'] = trim($hostParts[0]);
+            $urlParts['port'] = (int) trim($hostParts[1]);
+            if ($urlParts['port'] == 443) {
+                $urlParts['scheme'] = 'https';
+            }
+        }
+
+        // Check if a query is present
+        $path = $urlParts['path'];
+        $qpos = strpos($path, '?');
+        if ($qpos) {
+            $urlParts['query'] = substr($path, $qpos + 1);
+            $urlParts['path'] = substr($path, 0, $qpos);
+        } else {
+            $urlParts['query'] = '';
+        }
+
+        return $urlParts;
+    }
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/Message/MessageParser.php b/core/vendor/guzzle/parser/Guzzle/Parser/Message/MessageParser.php
new file mode 100644
index 0000000..1047400
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/Message/MessageParser.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace Guzzle\Parser\Message;
+
+/**
+ * Default request and response parser used by Guzzle. Optimized for speed.
+ */
+class MessageParser extends AbstractMessageParser
+{
+    public function parseRequest($message)
+    {
+        if (!$message) {
+            return false;
+        }
+
+        $parts = $this->parseMessage($message);
+
+        // Parse the protocol and protocol version
+        if (isset($parts['start_line'][2])) {
+            $startParts = explode('/', $parts['start_line'][2]);
+            $protocol = strtoupper($startParts[0]);
+            $version = isset($startParts[1]) ? $startParts[1] : '1.1';
+        } else {
+            $protocol = 'HTTP';
+            $version = '1.1';
+        }
+
+        $parsed = array(
+            'method'   => strtoupper($parts['start_line'][0]),
+            'protocol' => $protocol,
+            'version'  => $version,
+            'headers'  => $parts['headers'],
+            'body'     => $parts['body']
+        );
+
+        $parsed['request_url'] = $this->getUrlPartsFromMessage($parts['start_line'][1], $parsed);
+
+        return $parsed;
+    }
+
+    public function parseResponse($message)
+    {
+        if (!$message) {
+            return false;
+        }
+
+        $parts = $this->parseMessage($message);
+        list($protocol, $version) = explode('/', trim($parts['start_line'][0]));
+
+        return array(
+            'protocol'      => $protocol,
+            'version'       => $version,
+            'code'          => $parts['start_line'][1],
+            'reason_phrase' => isset($parts['start_line'][2]) ? $parts['start_line'][2] : '',
+            'headers'       => $parts['headers'],
+            'body'          => $parts['body']
+        );
+    }
+
+    /**
+     * Parse a message into parts
+     *
+     * @param string $message Message to parse
+     *
+     * @return array
+     */
+    protected function parseMessage($message)
+    {
+        $startLine = null;
+        $headers = array();
+        $body = '';
+
+        // Iterate over each line in the message, accounting for line endings
+        $lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
+        for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) {
+
+            $line = $lines[$i];
+
+            // If two line breaks were encountered, then this is the end of body
+            if (empty($line)) {
+                if ($i < $totalLines - 1) {
+                    $body = implode('', array_slice($lines, $i + 2));
+                }
+                break;
+            }
+
+            // Parse message headers
+            if (!$startLine) {
+                $startLine = explode(' ', $line, 3);
+            } elseif (strpos($line, ':')) {
+                $parts = explode(':', $line, 2);
+                $key = trim($parts[0]);
+                $value = isset($parts[1]) ? trim($parts[1]) : '';
+                if (!isset($headers[$key])) {
+                    $headers[$key] = $value;
+                } elseif (!is_array($headers[$key])) {
+                    $headers[$key] = array($headers[$key], $value);
+                } else {
+                    $headers[$key][] = $value;
+                }
+            }
+        }
+
+        return array(
+            'start_line' => $startLine,
+            'headers'    => $headers,
+            'body'       => $body
+        );
+    }
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/Message/MessageParserInterface.php b/core/vendor/guzzle/parser/Guzzle/Parser/Message/MessageParserInterface.php
new file mode 100644
index 0000000..cc44808
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/Message/MessageParserInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Guzzle\Parser\Message;
+
+/**
+ * HTTP message parser interface used to parse HTTP messages into an array
+ */
+interface MessageParserInterface
+{
+    /**
+     * Parse an HTTP request message into an associative array of parts.
+     *
+     * @param string $message HTTP request to parse
+     *
+     * @return array|bool Returns false if the message is invalid
+     */
+    public function parseRequest($message);
+
+    /**
+     * Parse an HTTP response message into an associative array of parts.
+     *
+     * @param string $message HTTP response to parse
+     *
+     * @return array|bool Returns false if the message is invalid
+     */
+    public function parseResponse($message);
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/Message/PeclHttpMessageParser.php b/core/vendor/guzzle/parser/Guzzle/Parser/Message/PeclHttpMessageParser.php
new file mode 100644
index 0000000..944aaa2
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/Message/PeclHttpMessageParser.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Guzzle\Parser\Message;
+
+/**
+ * Pecl HTTP message parser
+ */
+class PeclHttpMessageParser extends AbstractMessageParser
+{
+    public function parseRequest($message)
+    {
+        if (!$message) {
+            return false;
+        }
+
+        $parts = http_parse_message($message);
+
+        $parsed = array(
+            'method'   => $parts->requestMethod,
+            'protocol' => 'HTTP',
+            'version'  => number_format($parts->httpVersion, 1),
+            'headers'  => $parts->headers,
+            'body'     => $parts->body
+        );
+
+        $parsed['request_url'] = $this->getUrlPartsFromMessage($parts->requestUrl, $parsed);
+
+        return $parsed;
+    }
+
+    public function parseResponse($message)
+    {
+        if (!$message) {
+            return false;
+        }
+
+        $parts = http_parse_message($message);
+
+        return array(
+            'protocol'      => 'HTTP',
+            'version'       => number_format($parts->httpVersion, 1),
+            'code'          => $parts->responseCode,
+            'reason_phrase' => $parts->responseStatus,
+            'headers'       => $parts->headers,
+            'body'          => $parts->body
+        );
+    }
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/ParserRegistry.php b/core/vendor/guzzle/parser/Guzzle/Parser/ParserRegistry.php
new file mode 100644
index 0000000..f838683
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/ParserRegistry.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Guzzle\Parser;
+
+/**
+ * Registry of parsers used by the application
+ */
+class ParserRegistry
+{
+    /** @var ParserRegistry Singleton instance */
+    protected static $instance;
+
+    /** @var array Array of parser instances */
+    protected $instances = array();
+
+    /** @var array Mapping of parser name to default class */
+    protected $mapping = array(
+        'message'      => 'Guzzle\\Parser\\Message\\MessageParser',
+        'cookie'       => 'Guzzle\\Parser\\Cookie\\CookieParser',
+        'url'          => 'Guzzle\\Parser\\Url\\UrlParser',
+        'uri_template' => 'Guzzle\\Parser\\UriTemplate\\UriTemplate',
+    );
+
+    /**
+     * @return self
+     * @codeCoverageIgnore
+     */
+    public static function getInstance()
+    {
+        if (!self::$instance) {
+            self::$instance = new static;
+        }
+
+        return self::$instance;
+    }
+
+    public function __construct()
+    {
+        // Use the PECL URI template parser if available
+        if (extension_loaded('uri_template')) {
+            $this->mapping['uri_template'] = 'Guzzle\\Parser\\UriTemplate\\PeclUriTemplate';
+        }
+    }
+
+    /**
+     * Get a parser by name from an instance
+     *
+     * @param string $name Name of the parser to retrieve
+     *
+     * @return mixed|null
+     */
+    public function getParser($name)
+    {
+        if (!isset($this->instances[$name])) {
+            if (!isset($this->mapping[$name])) {
+                return null;
+            }
+            $class = $this->mapping[$name];
+            $this->instances[$name] = new $class();
+        }
+
+        return $this->instances[$name];
+    }
+
+    /**
+     * Register a custom parser by name with the register
+     *
+     * @param string $name   Name or handle of the parser to register
+     * @param mixed  $parser Instantiated parser to register
+     */
+    public function registerParser($name, $parser)
+    {
+        $this->instances[$name] = $parser;
+    }
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/UriTemplate/PeclUriTemplate.php b/core/vendor/guzzle/parser/Guzzle/Parser/UriTemplate/PeclUriTemplate.php
new file mode 100644
index 0000000..b0764e8
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/UriTemplate/PeclUriTemplate.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Guzzle\Parser\UriTemplate;
+
+use Guzzle\Common\Exception\RuntimeException;
+
+/**
+ * Expands URI templates using the uri_template pecl extension (pecl install uri_template-beta)
+ *
+ * @link http://pecl.php.net/package/uri_template
+ * @link https://github.com/ioseb/uri-template
+ */
+class PeclUriTemplate implements UriTemplateInterface
+{
+    public function __construct()
+    {
+        if (!extension_loaded('uri_template')) {
+            throw new RuntimeException('uri_template PECL extension must be installed to use PeclUriTemplate');
+        }
+    }
+
+    public function expand($template, array $variables)
+    {
+        return uri_template($template, $variables);
+    }
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/UriTemplate/UriTemplate.php b/core/vendor/guzzle/parser/Guzzle/Parser/UriTemplate/UriTemplate.php
new file mode 100644
index 0000000..0df032f
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/UriTemplate/UriTemplate.php
@@ -0,0 +1,254 @@
+<?php
+
+namespace Guzzle\Parser\UriTemplate;
+
+/**
+ * Expands URI templates using an array of variables
+ *
+ * @link http://tools.ietf.org/html/draft-gregorio-uritemplate-08
+ */
+class UriTemplate implements UriTemplateInterface
+{
+    const DEFAULT_PATTERN = '/\{([^\}]+)\}/';
+
+    /** @var string URI template */
+    private $template;
+
+    /** @var array Variables to use in the template expansion */
+    private $variables;
+
+    /** @var string Regex used to parse expressions */
+    private $regex = self::DEFAULT_PATTERN;
+
+    /** @var array Hash for quick operator lookups */
+    private static $operatorHash = array(
+        '+' => true, '#' => true, '.' => true, '/' => true, ';' => true, '?' => true, '&' => true
+    );
+
+    /** @var array Delimiters */
+    private static $delims = array(
+        ':', '/', '?', '#', '[', ']', '@', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '='
+    );
+
+    /** @var array Percent encoded delimiters */
+    private static $delimsPct = array(
+        '%3A', '%2F', '%3F', '%23', '%5B', '%5D', '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
+        '%3B', '%3D'
+    );
+
+    public function expand($template, array $variables)
+    {
+        if ($this->regex == self::DEFAULT_PATTERN && false === strpos($template, '{')) {
+            return $template;
+        }
+
+        $this->template = $template;
+        $this->variables = $variables;
+
+        return preg_replace_callback($this->regex, array($this, 'expandMatch'), $this->template);
+    }
+
+    /**
+     * Set the regex patten used to expand URI templates
+     *
+     * @param string $regexPattern
+     */
+    public function setRegex($regexPattern)
+    {
+        $this->regex = $regexPattern;
+    }
+
+    /**
+     * Parse an expression into parts
+     *
+     * @param string $expression Expression to parse
+     *
+     * @return array Returns an associative array of parts
+     */
+    private function parseExpression($expression)
+    {
+        // Check for URI operators
+        $operator = '';
+
+        if (isset(self::$operatorHash[$expression[0]])) {
+            $operator = $expression[0];
+            $expression = substr($expression, 1);
+        }
+
+        $values = explode(',', $expression);
+        foreach ($values as &$value) {
+            $value = trim($value);
+            $varspec = array();
+            $substrPos = strpos($value, ':');
+            if ($substrPos) {
+                $varspec['value'] = substr($value, 0, $substrPos);
+                $varspec['modifier'] = ':';
+                $varspec['position'] = (int) substr($value, $substrPos + 1);
+            } elseif (substr($value, -1) == '*') {
+                $varspec['modifier'] = '*';
+                $varspec['value'] = substr($value, 0, -1);
+            } else {
+                $varspec['value'] = (string) $value;
+                $varspec['modifier'] = '';
+            }
+            $value = $varspec;
+        }
+
+        return array(
+            'operator' => $operator,
+            'values'   => $values
+        );
+    }
+
+    /**
+     * Process an expansion
+     *
+     * @param array $matches Matches met in the preg_replace_callback
+     *
+     * @return string Returns the replacement string
+     */
+    private function expandMatch(array $matches)
+    {
+        static $rfc1738to3986 = array(
+            '+'   => '%20',
+            '%7e' => '~'
+        );
+
+        $parsed = self::parseExpression($matches[1]);
+        $replacements = array();
+
+        $prefix = $parsed['operator'];
+        $joiner = $parsed['operator'];
+        $useQueryString = false;
+        if ($parsed['operator'] == '?') {
+            $joiner = '&';
+            $useQueryString = true;
+        } elseif ($parsed['operator'] == '&') {
+            $useQueryString = true;
+        } elseif ($parsed['operator'] == '#') {
+            $joiner = ',';
+        } elseif ($parsed['operator'] == ';') {
+            $useQueryString = true;
+        } elseif ($parsed['operator'] == '' || $parsed['operator'] == '+') {
+            $joiner = ',';
+            $prefix = '';
+        }
+
+        foreach ($parsed['values'] as $value) {
+
+            if (!array_key_exists($value['value'], $this->variables) || $this->variables[$value['value']] === null) {
+                continue;
+            }
+
+            $variable = $this->variables[$value['value']];
+            $actuallyUseQueryString = $useQueryString;
+            $expanded = '';
+
+            if (is_array($variable)) {
+
+                $isAssoc = $this->isAssoc($variable);
+                $kvp = array();
+                foreach ($variable as $key => $var) {
+
+                    if ($isAssoc) {
+                        $key = rawurlencode($key);
+                        $isNestedArray = is_array($var);
+                    } else {
+                        $isNestedArray = false;
+                    }
+
+                    if (!$isNestedArray) {
+                        $var = rawurlencode($var);
+                        if ($parsed['operator'] == '+' || $parsed['operator'] == '#') {
+                            $var = $this->decodeReserved($var);
+                        }
+                    }
+
+                    if ($value['modifier'] == '*') {
+                        if ($isAssoc) {
+                            if ($isNestedArray) {
+                                // Nested arrays must allow for deeply nested structures
+                                $var = strtr(http_build_query(array($key => $var)), $rfc1738to3986);
+                            } else {
+                                $var = $key . '=' . $var;
+                            }
+                        } elseif ($key > 0 && $actuallyUseQueryString) {
+                            $var = $value['value'] . '=' . $var;
+                        }
+                    }
+
+                    $kvp[$key] = $var;
+                }
+
+                if (empty($variable)) {
+                    $actuallyUseQueryString = false;
+                } elseif ($value['modifier'] == '*') {
+                    $expanded = implode($joiner, $kvp);
+                    if ($isAssoc) {
+                        // Don't prepend the value name when using the explode modifier with an associative array
+                        $actuallyUseQueryString = false;
+                    }
+                } else {
+                    if ($isAssoc) {
+                        // When an associative array is encountered and the explode modifier is not set, then the
+                        // result must be a comma separated list of keys followed by their respective values.
+                        foreach ($kvp as $k => &$v) {
+                            $v = $k . ',' . $v;
+                        }
+                    }
+                    $expanded = implode(',', $kvp);
+                }
+
+            } else {
+                if ($value['modifier'] == ':') {
+                    $variable = substr($variable, 0, $value['position']);
+                }
+                $expanded = rawurlencode($variable);
+                if ($parsed['operator'] == '+' || $parsed['operator'] == '#') {
+                    $expanded = $this->decodeReserved($expanded);
+                }
+            }
+
+            if ($actuallyUseQueryString) {
+                if (!$expanded && $joiner != '&') {
+                    $expanded = $value['value'];
+                } else {
+                    $expanded = $value['value'] . '=' . $expanded;
+                }
+            }
+
+            $replacements[] = $expanded;
+        }
+
+        $ret = implode($joiner, $replacements);
+        if ($ret && $prefix) {
+            return $prefix . $ret;
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Determines if an array is associative
+     *
+     * @param array $array Array to check
+     *
+     * @return bool
+     */
+    private function isAssoc(array $array)
+    {
+        return (bool) count(array_filter(array_keys($array), 'is_string'));
+    }
+
+    /**
+     * Removes percent encoding on reserved characters (used with + and # modifiers)
+     *
+     * @param string $string String to fix
+     *
+     * @return string
+     */
+    private function decodeReserved($string)
+    {
+        return str_replace(self::$delimsPct, self::$delims, $string);
+    }
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/UriTemplate/UriTemplateInterface.php b/core/vendor/guzzle/parser/Guzzle/Parser/UriTemplate/UriTemplateInterface.php
new file mode 100644
index 0000000..c81d515
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/UriTemplate/UriTemplateInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Guzzle\Parser\UriTemplate;
+
+/**
+ * Expands URI templates using an array of variables
+ *
+ * @link http://tools.ietf.org/html/rfc6570
+ */
+interface UriTemplateInterface
+{
+    /**
+     * Expand the URI template using the supplied variables
+     *
+     * @param string $template  URI Template to expand
+     * @param array  $variables Variables to use with the expansion
+     *
+     * @return string Returns the expanded template
+     */
+    public function expand($template, array $variables);
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/Url/UrlParser.php b/core/vendor/guzzle/parser/Guzzle/Parser/Url/UrlParser.php
new file mode 100644
index 0000000..c4cc896
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/Url/UrlParser.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Guzzle\Parser\Url;
+
+use Guzzle\Common\Version;
+
+/**
+ * Parses URLs into parts using PHP's built-in parse_url() function
+ * @deprecated Just use parse_url. UTF-8 characters should be percent encoded anyways.
+ * @codeCoverageIgnore
+ */
+class UrlParser implements UrlParserInterface
+{
+    /** @var bool Whether or not to work with UTF-8 strings */
+    protected $utf8 = false;
+
+    /**
+     * Set whether or not to attempt to handle UTF-8 strings (still WIP)
+     *
+     * @param bool $utf8 Set to TRUE to handle UTF string
+     */
+    public function setUtf8Support($utf8)
+    {
+        $this->utf8 = $utf8;
+    }
+
+    public function parseUrl($url)
+    {
+        Version::warn(__CLASS__ . ' is deprecated. Just use parse_url()');
+
+        static $defaults = array('scheme' => null, 'host' => null, 'path' => null, 'port' => null, 'query' => null,
+            'user' => null, 'pass' => null, 'fragment' => null);
+
+        $parts = parse_url($url);
+
+        // Need to handle query parsing specially for UTF-8 requirements
+        if ($this->utf8 && isset($parts['query'])) {
+            $queryPos = strpos($url, '?');
+            if (isset($parts['fragment'])) {
+                $parts['query'] = substr($url, $queryPos + 1, strpos($url, '#') - $queryPos - 1);
+            } else {
+                $parts['query'] = substr($url, $queryPos + 1);
+            }
+        }
+
+        return $parts + $defaults;
+    }
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/Url/UrlParserInterface.php b/core/vendor/guzzle/parser/Guzzle/Parser/Url/UrlParserInterface.php
new file mode 100644
index 0000000..89ac4b3
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/Url/UrlParserInterface.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Guzzle\Parser\Url;
+
+/**
+ * URL parser interface
+ */
+interface UrlParserInterface
+{
+    /**
+     * Parse a URL using special handling for a subset of UTF-8 characters in the query string if needed.
+     *
+     * @param string $url URL to parse
+     *
+     * @return array Returns an array identical to what is returned from parse_url().  When an array key is missing from
+     *               this array, you must fill it in with NULL to avoid warnings in calling code.
+     */
+    public function parseUrl($url);
+}
diff --git a/core/vendor/guzzle/parser/Guzzle/Parser/composer.json b/core/vendor/guzzle/parser/Guzzle/Parser/composer.json
new file mode 100644
index 0000000..378b281
--- /dev/null
+++ b/core/vendor/guzzle/parser/Guzzle/Parser/composer.json
@@ -0,0 +1,19 @@
+{
+    "name": "guzzle/parser",
+    "homepage": "http://guzzlephp.org/",
+    "description": "Interchangeable parsers used by Guzzle",
+    "keywords": ["HTTP", "message", "cookie", "URL", "URI Template"],
+    "license": "MIT",
+    "require": {
+        "php": ">=5.3.2"
+    },
+    "autoload": {
+        "psr-0": { "Guzzle\\Parser": "" }
+    },
+    "target-dir": "Guzzle/Parser",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "3.7-dev"
+        }
+    }
+}
diff --git a/core/vendor/guzzle/stream/Guzzle/Stream/PhpStreamRequestFactory.php b/core/vendor/guzzle/stream/Guzzle/Stream/PhpStreamRequestFactory.php
new file mode 100644
index 0000000..9949e45
--- /dev/null
+++ b/core/vendor/guzzle/stream/Guzzle/Stream/PhpStreamRequestFactory.php
@@ -0,0 +1,276 @@
+<?php
+
+namespace Guzzle\Stream;
+
+use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Common\Exception\RuntimeException;
+use Guzzle\Http\Message\EntityEnclosingRequestInterface;
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Url;
+
+/**
+ * Factory used to create fopen streams using PHP's http and https stream wrappers
+ *
+ * Note: PHP's http stream wrapper only supports streaming downloads. It does not support streaming uploads.
+ */
+class PhpStreamRequestFactory implements StreamRequestFactoryInterface
+{
+    /** @var resource Stream context options */
+    protected $context;
+
+    /** @var array Stream context */
+    protected $contextOptions;
+
+    /** @var Url Stream URL */
+    protected $url;
+
+    /** @var array Last response headers received by the HTTP request */
+    protected $lastResponseHeaders;
+
+    /**
+     * {@inheritdoc}
+     *
+     * The $params array can contain the following custom keys specific to the PhpStreamRequestFactory:
+     * - stream_class: The name of a class to create instead of a Guzzle\Stream\Stream object
+     */
+    public function fromRequest(RequestInterface $request, $context = array(), array $params = array())
+    {
+        if (is_resource($context)) {
+            $this->contextOptions = stream_context_get_options($context);
+            $this->context = $context;
+        } elseif (is_array($context) || !$context) {
+            $this->contextOptions = $context;
+            $this->createContext($params);
+        } elseif ($context) {
+            throw new InvalidArgumentException('$context must be an array or resource');
+        }
+
+        // Dispatch the before send event
+        $request->dispatch('request.before_send', array(
+            'request'         => $request,
+            'context'         => $this->context,
+            'context_options' => $this->contextOptions
+        ));
+
+        $this->setUrl($request);
+        $this->addDefaultContextOptions($request);
+        $this->addSslOptions($request);
+        $this->addBodyOptions($request);
+        $this->addProxyOptions($request);
+
+        // Create the file handle but silence errors
+        return $this->createStream($params)
+            ->setCustomData('request', $request)
+            ->setCustomData('response_headers', $this->getLastResponseHeaders());
+    }
+
+    /**
+     * Set an option on the context and the internal options array
+     *
+     * @param string $wrapper   Stream wrapper name of http
+     * @param string $name      Context name
+     * @param mixed  $value     Context value
+     * @param bool   $overwrite Set to true to overwrite an existing value
+     */
+    protected function setContextValue($wrapper, $name, $value, $overwrite = false)
+    {
+        if (!isset($this->contextOptions[$wrapper])) {
+            $this->contextOptions[$wrapper] = array($name => $value);
+        } elseif (!$overwrite && isset($this->contextOptions[$wrapper][$name])) {
+            return;
+        }
+        $this->contextOptions[$wrapper][$name] = $value;
+        stream_context_set_option($this->context, $wrapper, $name, $value);
+    }
+
+    /**
+     * Create a stream context
+     *
+     * @param array $params Parameter array
+     */
+    protected function createContext(array $params)
+    {
+        $options = $this->contextOptions;
+        $this->context = $this->createResource(function () use ($params, $options) {
+            return stream_context_create($options, $params);
+        });
+    }
+
+    /**
+     * Get the last response headers received by the HTTP request
+     *
+     * @return array
+     */
+    public function getLastResponseHeaders()
+    {
+        return $this->lastResponseHeaders;
+    }
+
+    /**
+     * Adds the default context options to the stream context options
+     *
+     * @param RequestInterface $request Request
+     */
+    protected function addDefaultContextOptions(RequestInterface $request)
+    {
+        $this->setContextValue('http', 'method', $request->getMethod());
+        $headers = $request->getHeaderLines();
+
+        // "Connection: close" is required to get streams to work in HTTP 1.1
+        if (!$request->hasHeader('Connection')) {
+            $headers[] = 'Connection: close';
+        }
+
+        $this->setContextValue('http', 'header', $headers);
+        $this->setContextValue('http', 'protocol_version', $request->getProtocolVersion());
+        $this->setContextValue('http', 'ignore_errors', true);
+    }
+
+    /**
+     * Set the URL to use with the factory
+     *
+     * @param RequestInterface $request Request that owns the URL
+     */
+    protected function setUrl(RequestInterface $request)
+    {
+        $this->url = $request->getUrl(true);
+
+        // Check for basic Auth username
+        if ($request->getUsername()) {
+            $this->url->setUsername($request->getUsername());
+        }
+
+        // Check for basic Auth password
+        if ($request->getPassword()) {
+            $this->url->setPassword($request->getPassword());
+        }
+    }
+
+    /**
+     * Add SSL options to the stream context
+     *
+     * @param RequestInterface $request Request
+     */
+    protected function addSslOptions(RequestInterface $request)
+    {
+        if ($request->getCurlOptions()->get(CURLOPT_SSL_VERIFYPEER)) {
+            $this->setContextValue('ssl', 'verify_peer', true, true);
+            if ($cafile = $request->getCurlOptions()->get(CURLOPT_CAINFO)) {
+                $this->setContextValue('ssl', 'cafile', $cafile, true);
+            }
+        } else {
+            $this->setContextValue('ssl', 'verify_peer', false, true);
+        }
+    }
+
+    /**
+     * Add body (content) specific options to the context options
+     *
+     * @param RequestInterface $request
+     */
+    protected function addBodyOptions(RequestInterface $request)
+    {
+        // Add the content for the request if needed
+        if (!($request instanceof EntityEnclosingRequestInterface)) {
+            return;
+        }
+
+        if (count($request->getPostFields())) {
+            $this->setContextValue('http', 'content', (string) $request->getPostFields(), true);
+        } elseif ($request->getBody()) {
+            $this->setContextValue('http', 'content', (string) $request->getBody(), true);
+        }
+
+        // Always ensure a content-length header is sent
+        if (isset($this->contextOptions['http']['content'])) {
+            $headers = isset($this->contextOptions['http']['header']) ? $this->contextOptions['http']['header'] : array();
+            $headers[] = 'Content-Length: ' . strlen($this->contextOptions['http']['content']);
+            $this->setContextValue('http', 'header', $headers, true);
+        }
+    }
+
+    /**
+     * Add proxy parameters to the context if needed
+     *
+     * @param RequestInterface $request Request
+     */
+    protected function addProxyOptions(RequestInterface $request)
+    {
+        if ($proxy = $request->getCurlOptions()->get(CURLOPT_PROXY)) {
+            $this->setContextValue('http', 'proxy', $proxy);
+        }
+    }
+
+    /**
+     * Create the stream for the request with the context options
+     *
+     * @param array $params Parameters of the stream
+     *
+     * @return StreamInterface
+     */
+    protected function createStream(array $params)
+    {
+        $http_response_header = null;
+        $url = $this->url;
+        $context = $this->context;
+        $fp = $this->createResource(function () use ($context, $url, &$http_response_header) {
+            return fopen((string) $url, 'r', false, $context);
+        });
+
+        // Determine the class to instantiate
+        $className = isset($params['stream_class']) ? $params['stream_class'] : __NAMESPACE__ . '\\Stream';
+
+        /** @var $stream StreamInterface */
+        $stream = new $className($fp);
+
+        // Track the response headers of the request
+        if (isset($http_response_header)) {
+            $this->lastResponseHeaders = $http_response_header;
+            $this->processResponseHeaders($stream);
+        }
+
+        return $stream;
+    }
+
+    /**
+     * Process response headers
+     *
+     * @param StreamInterface $stream
+     */
+    protected function processResponseHeaders(StreamInterface $stream)
+    {
+        // Set the size on the stream if it was returned in the response
+        foreach ($this->lastResponseHeaders as $header) {
+            if ((stripos($header, 'Content-Length:')) === 0) {
+                $stream->setSize(trim(substr($header, 15)));
+            }
+        }
+    }
+
+    /**
+     * Create a resource and check to ensure it was created successfully
+     *
+     * @param callable $callback Closure to invoke that must return a valid resource
+     *
+     * @return resource
+     * @throws RuntimeException on error
+     */
+    protected function createResource($callback)
+    {
+        // Turn off error reporting while we try to initiate the request
+        $level = error_reporting(0);
+        $resource = call_user_func($callback);
+        error_reporting($level);
+
+        // If the resource could not be created, then grab the last error and throw an exception
+        if (false === $resource) {
+            $message = 'Error creating resource. ';
+            foreach (error_get_last() as $key => $value) {
+                $message .= "[{$key}] {$value} ";
+            }
+            throw new RuntimeException(trim($message));
+        }
+
+        return $resource;
+    }
+}
diff --git a/core/vendor/guzzle/stream/Guzzle/Stream/Stream.php b/core/vendor/guzzle/stream/Guzzle/Stream/Stream.php
new file mode 100644
index 0000000..12bed26
--- /dev/null
+++ b/core/vendor/guzzle/stream/Guzzle/Stream/Stream.php
@@ -0,0 +1,289 @@
+<?php
+
+namespace Guzzle\Stream;
+
+use Guzzle\Common\Exception\InvalidArgumentException;
+
+/**
+ * PHP stream implementation
+ */
+class Stream implements StreamInterface
+{
+    const STREAM_TYPE = 'stream_type';
+    const WRAPPER_TYPE = 'wrapper_type';
+    const IS_LOCAL = 'is_local';
+    const IS_READABLE = 'is_readable';
+    const IS_WRITABLE = 'is_writable';
+    const SEEKABLE = 'seekable';
+
+    /** @var resource Stream resource */
+    protected $stream;
+
+    /** @var int Size of the stream contents in bytes */
+    protected $size;
+
+    /** @var array Stream cached data */
+    protected $cache = array();
+
+    /** @var array Custom stream data */
+    protected $customData = array();
+
+    /** @var array Hash table of readable and writeable stream types for fast lookups */
+    protected static $readWriteHash = array(
+        'read' => array(
+            'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
+            'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, 'c+b' => true,
+            'rt' => true, 'w+t' => true, 'r+t' => true, 'x+t' => true, 'c+t' => true, 'a+' => true
+        ),
+        'write' => array(
+            'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, 'c+' => true,
+            'wb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, 'c+b' => true,
+            'w+t' => true, 'r+t' => true, 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
+        )
+    );
+
+    /**
+     * @param resource $stream Stream resource to wrap
+     * @param int      $size   Size of the stream in bytes. Only pass if the size cannot be obtained from the stream.
+     *
+     * @throws InvalidArgumentException if the stream is not a stream resource
+     */
+    public function __construct($stream, $size = null)
+    {
+        $this->setStream($stream, $size);
+    }
+
+    /**
+     * Closes the stream when the helper is destructed
+     */
+    public function __destruct()
+    {
+        $this->close();
+    }
+
+    public function __toString()
+    {
+        if (!$this->isReadable() || (!$this->isSeekable() && $this->isConsumed())) {
+            return '';
+        }
+
+        $originalPos = $this->ftell();
+        $body = stream_get_contents($this->stream, -1, 0);
+        $this->seek($originalPos);
+
+        return $body;
+    }
+
+    public function close()
+    {
+        if (is_resource($this->stream)) {
+            fclose($this->stream);
+        }
+        $this->cache[self::IS_READABLE] = false;
+        $this->cache[self::IS_WRITABLE] = false;
+    }
+
+    /**
+     * Calculate a hash of a Stream
+     *
+     * @param StreamInterface $stream    Stream to calculate the hash for
+     * @param string          $algo      Hash algorithm (e.g. md5, crc32, etc)
+     * @param bool            $rawOutput Whether or not to use raw output
+     *
+     * @return bool|string Returns false on failure or a hash string on success
+     */
+    public static function getHash(StreamInterface $stream, $algo, $rawOutput = false)
+    {
+        $pos = $stream->ftell();
+        if (!$stream->seek(0)) {
+            return false;
+        }
+
+        $ctx = hash_init($algo);
+        while (!$stream->feof()) {
+            hash_update($ctx, $stream->read(8192));
+        }
+
+        $out = hash_final($ctx, (bool) $rawOutput);
+        $stream->seek($pos);
+
+        return $out;
+    }
+
+    public function getMetaData($key = null)
+    {
+        $meta = stream_get_meta_data($this->stream);
+
+        return !$key ? $meta : (array_key_exists($key, $meta) ? $meta[$key] : null);
+    }
+
+    public function getStream()
+    {
+        return $this->stream;
+    }
+
+    public function setStream($stream, $size = null)
+    {
+        if (!is_resource($stream)) {
+            throw new InvalidArgumentException('Stream must be a resource');
+        }
+
+        $this->size = $size;
+        $this->stream = $stream;
+        $this->rebuildCache();
+
+        return $this;
+    }
+
+    public function detachStream()
+    {
+        $this->stream = null;
+
+        return $this;
+    }
+
+    public function getWrapper()
+    {
+        return $this->cache[self::WRAPPER_TYPE];
+    }
+
+    public function getWrapperData()
+    {
+        return $this->getMetaData('wrapper_data') ?: array();
+    }
+
+    public function getStreamType()
+    {
+        return $this->cache[self::STREAM_TYPE];
+    }
+
+    public function getUri()
+    {
+        return $this->cache['uri'];
+    }
+
+    public function getSize()
+    {
+        if ($this->size !== null) {
+            return $this->size;
+        }
+
+        // If the stream is a file based stream and local, then use fstat
+        clearstatcache(true, $this->cache['uri']);
+        $stats = fstat($this->stream);
+        if (isset($stats['size'])) {
+            $this->size = $stats['size'];
+            return $this->size;
+        } elseif ($this->cache[self::IS_READABLE] && $this->cache[self::SEEKABLE]) {
+            // Only get the size based on the content if the the stream is readable and seekable
+            $pos = $this->ftell();
+            $this->size = strlen((string) $this);
+            $this->seek($pos);
+            return $this->size;
+        }
+
+        return false;
+    }
+
+    public function isReadable()
+    {
+        return $this->cache[self::IS_READABLE];
+    }
+
+    public function isRepeatable()
+    {
+        return $this->cache[self::IS_READABLE] && $this->cache[self::SEEKABLE];
+    }
+
+    public function isWritable()
+    {
+        return $this->cache[self::IS_WRITABLE];
+    }
+
+    public function isConsumed()
+    {
+        return feof($this->stream);
+    }
+
+    public function feof()
+    {
+        return $this->isConsumed();
+    }
+
+    public function isLocal()
+    {
+        return $this->cache[self::IS_LOCAL];
+    }
+
+    public function isSeekable()
+    {
+        return $this->cache[self::SEEKABLE];
+    }
+
+    public function setSize($size)
+    {
+        $this->size = $size;
+
+        return $this;
+    }
+
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        return $this->cache[self::SEEKABLE] ? fseek($this->stream, $offset, $whence) === 0 : false;
+    }
+
+    public function read($length)
+    {
+        return fread($this->stream, $length);
+    }
+
+    public function write($string)
+    {
+        // We can't know the size after writing anything
+        $this->size = null;
+
+        return fwrite($this->stream, $string);
+    }
+
+    public function ftell()
+    {
+        return ftell($this->stream);
+    }
+
+    public function rewind()
+    {
+        return $this->seek(0);
+    }
+
+    public function readLine($maxLength = null)
+    {
+        if (!$this->cache[self::IS_READABLE]) {
+            return false;
+        } else {
+            return $maxLength ? fgets($this->getStream(), $maxLength) : fgets($this->getStream());
+        }
+    }
+
+    public function setCustomData($key, $value)
+    {
+        $this->customData[$key] = $value;
+
+        return $this;
+    }
+
+    public function getCustomData($key)
+    {
+        return isset($this->customData[$key]) ? $this->customData[$key] : null;
+    }
+
+    /**
+     * Reprocess stream metadata
+     */
+    protected function rebuildCache()
+    {
+        $this->cache = stream_get_meta_data($this->stream);
+        $this->cache[self::IS_LOCAL] = stream_is_local($this->stream);
+        $this->cache[self::IS_READABLE] = isset(self::$readWriteHash['read'][$this->cache['mode']]);
+        $this->cache[self::IS_WRITABLE] = isset(self::$readWriteHash['write'][$this->cache['mode']]);
+    }
+}
diff --git a/core/vendor/guzzle/stream/Guzzle/Stream/StreamInterface.php b/core/vendor/guzzle/stream/Guzzle/Stream/StreamInterface.php
new file mode 100644
index 0000000..6d7dc37
--- /dev/null
+++ b/core/vendor/guzzle/stream/Guzzle/Stream/StreamInterface.php
@@ -0,0 +1,218 @@
+<?php
+
+namespace Guzzle\Stream;
+
+/**
+ * OO interface to PHP streams
+ */
+interface StreamInterface
+{
+    /**
+     * Convert the stream to a string if the stream is readable and the stream is seekable.
+     *
+     * @return string
+     */
+    public function __toString();
+
+    /**
+     * Close the underlying stream
+     */
+    public function close();
+
+    /**
+     * Get stream metadata
+     *
+     * @param string $key Specific metadata to retrieve
+     *
+     * @return array|mixed|null
+     */
+    public function getMetaData($key = null);
+
+    /**
+     * Get the stream resource
+     *
+     * @return resource
+     */
+    public function getStream();
+
+    /**
+     * Set the stream that is wrapped by the object
+     *
+     * @param resource $stream Stream resource to wrap
+     * @param int      $size   Size of the stream in bytes. Only pass if the size cannot be obtained from the stream.
+     *
+     * @return self
+     */
+    public function setStream($stream, $size = null);
+
+    /**
+     * Detach the current stream resource
+     *
+     * @return self
+     */
+    public function detachStream();
+
+    /**
+     * Get the stream wrapper type
+     *
+     * @return string
+     */
+    public function getWrapper();
+
+    /**
+     * Wrapper specific data attached to this stream.
+     *
+     * @return array
+     */
+    public function getWrapperData();
+
+    /**
+     * Get a label describing the underlying implementation of the stream
+     *
+     * @return string
+     */
+    public function getStreamType();
+
+    /**
+     * Get the URI/filename associated with this stream
+     *
+     * @return string
+     */
+    public function getUri();
+
+    /**
+     * Get the size of the stream if able
+     *
+     * @return int|bool
+     */
+    public function getSize();
+
+    /**
+     * Check if the stream is readable
+     *
+     * @return bool
+     */
+    public function isReadable();
+
+    /**
+     * Check if the stream is repeatable
+     *
+     * @return bool
+     */
+    public function isRepeatable();
+
+    /**
+     * Check if the stream is writable
+     *
+     * @return bool
+     */
+    public function isWritable();
+
+    /**
+     * Check if the stream has been consumed
+     *
+     * @return bool
+     */
+    public function isConsumed();
+
+    /**
+     * Alias of isConsumed
+     *
+     * @return bool
+     */
+    public function feof();
+
+    /**
+     * Check if the stream is a local stream vs a remote stream
+     *
+     * @return bool
+     */
+    public function isLocal();
+
+    /**
+     * Check if the string is repeatable
+     *
+     * @return bool
+     */
+    public function isSeekable();
+
+    /**
+     * Specify the size of the stream in bytes
+     *
+     * @param int $size Size of the stream contents in bytes
+     *
+     * @return self
+     */
+    public function setSize($size);
+
+    /**
+     * Seek to a position in the stream
+     *
+     * @param int $offset Stream offset
+     * @param int $whence Where the offset is applied
+     *
+     * @return bool Returns TRUE on success or FALSE on failure
+     * @link   http://www.php.net/manual/en/function.fseek.php
+     */
+    public function seek($offset, $whence = SEEK_SET);
+
+    /**
+     * Read data from the stream
+     *
+     * @param int $length Up to length number of bytes read.
+     *
+     * @return string|bool Returns the data read from the stream or FALSE on failure or EOF
+     */
+    public function read($length);
+
+    /**
+     * Write data to the stream
+     *
+     * @param string $string The string that is to be written.
+     *
+     * @return int|bool Returns the number of bytes written to the stream on success or FALSE on failure.
+     */
+    public function write($string);
+
+    /**
+     * Returns the current position of the file read/write pointer
+     *
+     * @return int|bool Returns the position of the file pointer or false on error
+     */
+    public function ftell();
+
+    /**
+     * Rewind to the beginning of the stream
+     *
+     * @return bool Returns true on success or false on failure
+     */
+    public function rewind();
+
+    /**
+     * Read a line from the stream up to the maximum allowed buffer length
+     *
+     * @param int $maxLength Maximum buffer length
+     *
+     * @return string|bool
+     */
+    public function readLine($maxLength = null);
+
+    /**
+     * Set custom data on the stream
+     *
+     * @param string $key   Key to set
+     * @param mixed  $value Value to set
+     *
+     * @return self
+     */
+    public function setCustomData($key, $value);
+
+    /**
+     * Get custom data from the stream
+     *
+     * @param string $key Key to retrieve
+     *
+     * @return null|mixed
+     */
+    public function getCustomData($key);
+}
diff --git a/core/vendor/guzzle/stream/Guzzle/Stream/StreamRequestFactoryInterface.php b/core/vendor/guzzle/stream/Guzzle/Stream/StreamRequestFactoryInterface.php
new file mode 100644
index 0000000..d00e622
--- /dev/null
+++ b/core/vendor/guzzle/stream/Guzzle/Stream/StreamRequestFactoryInterface.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Guzzle\Stream;
+
+use Guzzle\Http\Message\RequestInterface;
+
+/**
+ * Interface used for creating streams from requests
+ */
+interface StreamRequestFactoryInterface
+{
+    /**
+     * Create a stream based on a request object
+     *
+     * @param RequestInterface $request Base the stream on a request
+     * @param array|resource   $context A stream_context_options resource or array of parameters used to create a
+     *                                  stream context.
+     * @param array            $params  Optional array of parameters specific to the factory
+     *
+     * @return StreamInterface Returns a stream object
+     * @throws \Guzzle\Common\Exception\RuntimeException if the stream cannot be opened or an error occurs
+     */
+    public function fromRequest(RequestInterface $request, $context = array(), array $params = array());
+}
diff --git a/core/vendor/guzzle/stream/Guzzle/Stream/composer.json b/core/vendor/guzzle/stream/Guzzle/Stream/composer.json
new file mode 100644
index 0000000..9c19d2b
--- /dev/null
+++ b/core/vendor/guzzle/stream/Guzzle/Stream/composer.json
@@ -0,0 +1,30 @@
+{
+    "name": "guzzle/stream",
+    "description": "Guzzle stream wrapper component",
+    "homepage": "http://guzzlephp.org/",
+    "keywords": ["stream", "component", "guzzle"],
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Michael Dowling",
+            "email": "mtdowling@gmail.com",
+            "homepage": "https://github.com/mtdowling"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.2",
+        "guzzle/common": "self.version"
+    },
+    "suggest": {
+        "guzzle/http": "To convert Guzzle request objects to PHP streams"
+    },
+    "autoload": {
+        "psr-0": { "Guzzle\\Stream": "" }
+    },
+    "target-dir": "Guzzle/Stream",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "3.7-dev"
+        }
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/.gitignore b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/.gitignore
new file mode 100644
index 0000000..c49a5d8
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/CHANGELOG.md b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/CHANGELOG.md
new file mode 100644
index 0000000..85fd24d
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/CHANGELOG.md
@@ -0,0 +1,18 @@
+CHANGELOG
+=========
+
+2.3.0
+-----
+
+ * [BC BREAK] `Client::followRedirect()` won't redirect responses with
+   a non-3xx Status Code and `Location` header anymore, as per
+   http://tools.ietf.org/html/rfc2616#section-14.30
+
+ * added `Client::getInternalRequest()` and `Client::getInternalResponse()` to
+   have access to the BrowserKit internal request and response objects
+
+2.1.0
+-----
+
+ * [BC BREAK] The CookieJar internals have changed to allow cookies with the
+   same name on different sub-domains/sub-paths
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Client.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Client.php
new file mode 100644
index 0000000..90df108
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Client.php
@@ -0,0 +1,619 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit;
+
+use Symfony\Component\DomCrawler\Crawler;
+use Symfony\Component\DomCrawler\Link;
+use Symfony\Component\DomCrawler\Form;
+use Symfony\Component\Process\PhpProcess;
+
+/**
+ * Client simulates a browser.
+ *
+ * To make the actual request, you need to implement the doRequest() method.
+ *
+ * If you want to be able to run requests in their own process (insulated flag),
+ * you need to also implement the getScript() method.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+abstract class Client
+{
+    protected $history;
+    protected $cookieJar;
+    protected $server = array();
+    protected $internalRequest;
+    protected $request;
+    protected $internalResponse;
+    protected $response;
+    protected $crawler;
+    protected $insulated = false;
+    protected $redirect;
+    protected $followRedirects = true;
+
+    private $maxRedirects = -1;
+    private $redirectCount = 0;
+    private $isMainRequest = true;
+
+    /**
+     * Constructor.
+     *
+     * @param array     $server    The server parameters (equivalent of $_SERVER)
+     * @param History   $history   A History instance to store the browser history
+     * @param CookieJar $cookieJar A CookieJar instance to store the cookies
+     *
+     * @api
+     */
+    public function __construct(array $server = array(), History $history = null, CookieJar $cookieJar = null)
+    {
+        $this->setServerParameters($server);
+        $this->history = $history ?: new History();
+        $this->cookieJar = $cookieJar ?: new CookieJar();
+    }
+
+    /**
+     * Sets whether to automatically follow redirects or not.
+     *
+     * @param bool $followRedirect Whether to follow redirects
+     *
+     * @api
+     */
+    public function followRedirects($followRedirect = true)
+    {
+        $this->followRedirects = (bool) $followRedirect;
+    }
+
+    /**
+     * Sets the maximum number of requests that crawler can follow.
+     *
+     * @param int $maxRedirects
+     */
+    public function setMaxRedirects($maxRedirects)
+    {
+        $this->maxRedirects = $maxRedirects < 0 ? -1 : $maxRedirects;
+        $this->followRedirects = -1 != $this->maxRedirects;
+    }
+
+    /**
+     * Sets the insulated flag.
+     *
+     * @param bool $insulated Whether to insulate the requests or not
+     *
+     * @throws \RuntimeException When Symfony Process Component is not installed
+     *
+     * @api
+     */
+    public function insulate($insulated = true)
+    {
+        if ($insulated && !class_exists('Symfony\\Component\\Process\\Process')) {
+            throw new \RuntimeException('Unable to isolate requests as the Symfony Process Component is not installed.');
+        }
+
+        $this->insulated = (bool) $insulated;
+    }
+
+    /**
+     * Sets server parameters.
+     *
+     * @param array $server An array of server parameters
+     *
+     * @api
+     */
+    public function setServerParameters(array $server)
+    {
+        $this->server = array_merge(array(
+            'HTTP_HOST' => 'localhost',
+            'HTTP_USER_AGENT' => 'Symfony2 BrowserKit',
+        ), $server);
+    }
+
+    /**
+     * Sets single server parameter.
+     *
+     * @param string $key   A key of the parameter
+     * @param string $value A value of the parameter
+     */
+    public function setServerParameter($key, $value)
+    {
+        $this->server[$key] = $value;
+    }
+
+    /**
+     * Gets single server parameter for specified key.
+     *
+     * @param string $key     A key of the parameter to get
+     * @param string $default A default value when key is undefined
+     *
+     * @return string A value of the parameter
+     */
+    public function getServerParameter($key, $default = '')
+    {
+        return (isset($this->server[$key])) ? $this->server[$key] : $default;
+    }
+
+    /**
+     * Returns the History instance.
+     *
+     * @return History A History instance
+     *
+     * @api
+     */
+    public function getHistory()
+    {
+        return $this->history;
+    }
+
+    /**
+     * Returns the CookieJar instance.
+     *
+     * @return CookieJar A CookieJar instance
+     *
+     * @api
+     */
+    public function getCookieJar()
+    {
+        return $this->cookieJar;
+    }
+
+    /**
+     * Returns the current Crawler instance.
+     *
+     * @return Crawler|null A Crawler instance
+     *
+     * @api
+     */
+    public function getCrawler()
+    {
+        return $this->crawler;
+    }
+
+    /**
+     * Returns the current BrowserKit Response instance.
+     *
+     * @return Response|null A BrowserKit Response instance
+     *
+     * @api
+     */
+    public function getInternalResponse()
+    {
+        return $this->internalResponse;
+    }
+
+    /**
+     * Returns the current origin response instance.
+     *
+     * The origin response is the response instance that is returned
+     * by the code that handles requests.
+     *
+     * @return object|null A response instance
+     *
+     * @see doRequest()
+     *
+     * @api
+     */
+    public function getResponse()
+    {
+        return $this->response;
+    }
+
+    /**
+     * Returns the current BrowserKit Request instance.
+     *
+     * @return Request|null A BrowserKit Request instance
+     *
+     * @api
+     */
+    public function getInternalRequest()
+    {
+        return $this->internalRequest;
+    }
+
+    /**
+     * Returns the current origin Request instance.
+     *
+     * The origin request is the request instance that is sent
+     * to the code that handles requests.
+     *
+     * @return object|null A Request instance
+     *
+     * @see doRequest()
+     *
+     * @api
+     */
+    public function getRequest()
+    {
+        return $this->request;
+    }
+
+    /**
+     * Clicks on a given link.
+     *
+     * @param Link $link A Link instance
+     *
+     * @return Crawler
+     *
+     * @api
+     */
+    public function click(Link $link)
+    {
+        if ($link instanceof Form) {
+            return $this->submit($link);
+        }
+
+        return $this->request($link->getMethod(), $link->getUri());
+    }
+
+    /**
+     * Submits a form.
+     *
+     * @param Form  $form   A Form instance
+     * @param array $values An array of form field values
+     *
+     * @return Crawler
+     *
+     * @api
+     */
+    public function submit(Form $form, array $values = array())
+    {
+        $form->setValues($values);
+
+        return $this->request($form->getMethod(), $form->getUri(), $form->getPhpValues(), $form->getPhpFiles());
+    }
+
+    /**
+     * Calls a URI.
+     *
+     * @param string $method        The request method
+     * @param string $uri           The URI to fetch
+     * @param array  $parameters    The Request parameters
+     * @param array  $files         The files
+     * @param array  $server        The server parameters (HTTP headers are referenced with a HTTP_ prefix as PHP does)
+     * @param string $content       The raw body data
+     * @param bool   $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload())
+     *
+     * @return Crawler
+     *
+     * @api
+     */
+    public function request($method, $uri, array $parameters = array(), array $files = array(), array $server = array(), $content = null, $changeHistory = true)
+    {
+        if ($this->isMainRequest) {
+            $this->redirectCount = 0;
+        } else {
+            ++$this->redirectCount;
+        }
+
+        $uri = $this->getAbsoluteUri($uri);
+
+        if (!empty($server['HTTP_HOST'])) {
+            $uri = preg_replace('{^(https?\://)'.preg_quote($this->extractHost($uri)).'}', '${1}'.$server['HTTP_HOST'], $uri);
+        }
+
+        if (isset($server['HTTPS'])) {
+            $uri = preg_replace('{^'.parse_url($uri, PHP_URL_SCHEME).'}', $server['HTTPS'] ? 'https' : 'http', $uri);
+        }
+
+        $server = array_merge($this->server, $server);
+
+        if (!$this->history->isEmpty()) {
+            $server['HTTP_REFERER'] = $this->history->current()->getUri();
+        }
+
+        $server['HTTP_HOST'] = $this->extractHost($uri);
+        $server['HTTPS'] = 'https' == parse_url($uri, PHP_URL_SCHEME);
+
+        $this->internalRequest = new Request($uri, $method, $parameters, $files, $this->cookieJar->allValues($uri), $server, $content);
+
+        $this->request = $this->filterRequest($this->internalRequest);
+
+        if (true === $changeHistory) {
+            $this->history->add($this->internalRequest);
+        }
+
+        if ($this->insulated) {
+            $this->response = $this->doRequestInProcess($this->request);
+        } else {
+            $this->response = $this->doRequest($this->request);
+        }
+
+        $this->internalResponse = $this->filterResponse($this->response);
+
+        $this->cookieJar->updateFromResponse($this->internalResponse, $uri);
+
+        $status = $this->internalResponse->getStatus();
+
+        if ($status >= 300 && $status < 400) {
+            $this->redirect = $this->internalResponse->getHeader('Location');
+        } else {
+            $this->redirect = null;
+        }
+
+        if ($this->followRedirects && $this->redirect) {
+            return $this->crawler = $this->followRedirect();
+        }
+
+        return $this->crawler = $this->createCrawlerFromContent($this->internalRequest->getUri(), $this->internalResponse->getContent(), $this->internalResponse->getHeader('Content-Type'));
+    }
+
+    /**
+     * Makes a request in another process.
+     *
+     * @param object $request An origin request instance
+     *
+     * @return object An origin response instance
+     *
+     * @throws \RuntimeException When processing returns exit code
+     */
+    protected function doRequestInProcess($request)
+    {
+        // We set the TMPDIR (for Macs) and TEMP (for Windows), because on these platforms the temp directory changes based on the user.
+        $process = new PhpProcess($this->getScript($request), null, array('TMPDIR' => sys_get_temp_dir(), 'TEMP' => sys_get_temp_dir()));
+        $process->run();
+
+        if (!$process->isSuccessful() || !preg_match('/^O\:\d+\:/', $process->getOutput())) {
+            throw new \RuntimeException(sprintf('OUTPUT: %s ERROR OUTPUT: %s', $process->getOutput(), $process->getErrorOutput()));
+        }
+
+        return unserialize($process->getOutput());
+    }
+
+    /**
+     * Makes a request.
+     *
+     * @param object $request An origin request instance
+     *
+     * @return object An origin response instance
+     */
+    abstract protected function doRequest($request);
+
+    /**
+     * Returns the script to execute when the request must be insulated.
+     *
+     * @param object $request An origin request instance
+     *
+     * @throws \LogicException When this abstract class is not implemented
+     */
+    protected function getScript($request)
+    {
+        throw new \LogicException('To insulate requests, you need to override the getScript() method.');
+    }
+
+    /**
+     * Filters the BrowserKit request to the origin one.
+     *
+     * @param Request $request The BrowserKit Request to filter
+     *
+     * @return object An origin request instance
+     */
+    protected function filterRequest(Request $request)
+    {
+        return $request;
+    }
+
+    /**
+     * Filters the origin response to the BrowserKit one.
+     *
+     * @param object $response The origin response to filter
+     *
+     * @return Response An BrowserKit Response instance
+     */
+    protected function filterResponse($response)
+    {
+        return $response;
+    }
+
+    /**
+     * Creates a crawler.
+     *
+     * This method returns null if the DomCrawler component is not available.
+     *
+     * @param string $uri     A URI
+     * @param string $content Content for the crawler to use
+     * @param string $type    Content type
+     *
+     * @return Crawler|null
+     */
+    protected function createCrawlerFromContent($uri, $content, $type)
+    {
+        if (!class_exists('Symfony\Component\DomCrawler\Crawler')) {
+            return;
+        }
+
+        $crawler = new Crawler(null, $uri);
+        $crawler->addContent($content, $type);
+
+        return $crawler;
+    }
+
+    /**
+     * Goes back in the browser history.
+     *
+     * @return Crawler
+     *
+     * @api
+     */
+    public function back()
+    {
+        return $this->requestFromRequest($this->history->back(), false);
+    }
+
+    /**
+     * Goes forward in the browser history.
+     *
+     * @return Crawler
+     *
+     * @api
+     */
+    public function forward()
+    {
+        return $this->requestFromRequest($this->history->forward(), false);
+    }
+
+    /**
+     * Reloads the current browser.
+     *
+     * @return Crawler
+     *
+     * @api
+     */
+    public function reload()
+    {
+        return $this->requestFromRequest($this->history->current(), false);
+    }
+
+    /**
+     * Follow redirects?
+     *
+     * @return Crawler
+     *
+     * @throws \LogicException If request was not a redirect
+     *
+     * @api
+     */
+    public function followRedirect()
+    {
+        if (empty($this->redirect)) {
+            throw new \LogicException('The request was not redirected.');
+        }
+
+        if (-1 !== $this->maxRedirects) {
+            if ($this->redirectCount > $this->maxRedirects) {
+                throw new \LogicException(sprintf('The maximum number (%d) of redirections was reached.', $this->maxRedirects));
+            }
+        }
+
+        $request = $this->internalRequest;
+
+        if (in_array($this->internalResponse->getStatus(), array(302, 303))) {
+            $method = 'get';
+            $files = array();
+            $content = null;
+        } else {
+            $method = $request->getMethod();
+            $files = $request->getFiles();
+            $content = $request->getContent();
+        }
+
+        if ('get' === strtolower($method)) {
+            // Don't forward parameters for GET request as it should reach the redirection URI
+            $parameters = array();
+        } else {
+            $parameters = $request->getParameters();
+        }
+
+        $server = $request->getServer();
+        $server = $this->updateServerFromUri($server, $this->redirect);
+
+        $this->isMainRequest = false;
+
+        $response = $this->request($method, $this->redirect, $parameters, $files, $server, $content);
+
+        $this->isMainRequest = true;
+
+        return $response;
+    }
+
+    /**
+     * Restarts the client.
+     *
+     * It flushes history and all cookies.
+     *
+     * @api
+     */
+    public function restart()
+    {
+        $this->cookieJar->clear();
+        $this->history->clear();
+    }
+
+    /**
+     * Takes a URI and converts it to absolute if it is not already absolute.
+     *
+     * @param string $uri A URI
+     *
+     * @return string An absolute URI
+     */
+    protected function getAbsoluteUri($uri)
+    {
+        // already absolute?
+        if (0 === strpos($uri, 'http')) {
+            return $uri;
+        }
+
+        if (!$this->history->isEmpty()) {
+            $currentUri = $this->history->current()->getUri();
+        } else {
+            $currentUri = sprintf('http%s://%s/',
+                isset($this->server['HTTPS']) ? 's' : '',
+                isset($this->server['HTTP_HOST']) ? $this->server['HTTP_HOST'] : 'localhost'
+            );
+        }
+
+        // protocol relative URL
+        if (0 === strpos($uri, '//')) {
+            return parse_url($currentUri, PHP_URL_SCHEME).':'.$uri;
+        }
+
+        // anchor?
+        if (!$uri || '#' == $uri[0]) {
+            return preg_replace('/#.*?$/', '', $currentUri).$uri;
+        }
+
+        if ('/' !== $uri[0]) {
+            $path = parse_url($currentUri, PHP_URL_PATH);
+
+            if ('/' !== substr($path, -1)) {
+                $path = substr($path, 0, strrpos($path, '/') + 1);
+            }
+
+            $uri = $path.$uri;
+        }
+
+        return preg_replace('#^(.*?//[^/]+)\/.*$#', '$1', $currentUri).$uri;
+    }
+
+    /**
+     * Makes a request from a Request object directly.
+     *
+     * @param Request $request       A Request instance
+     * @param bool    $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload())
+     *
+     * @return Crawler
+     */
+    protected function requestFromRequest(Request $request, $changeHistory = true)
+    {
+        return $this->request($request->getMethod(), $request->getUri(), $request->getParameters(), $request->getFiles(), $request->getServer(), $request->getContent(), $changeHistory);
+    }
+
+    private function updateServerFromUri($server, $uri)
+    {
+        $server['HTTP_HOST'] = $this->extractHost($uri);
+        $scheme = parse_url($uri, PHP_URL_SCHEME);
+        $server['HTTPS'] = null === $scheme ? $server['HTTPS'] : 'https' == $scheme;
+        unset($server['HTTP_IF_NONE_MATCH'], $server['HTTP_IF_MODIFIED_SINCE']);
+
+        return $server;
+    }
+
+    private function extractHost($uri)
+    {
+        $host = parse_url($uri, PHP_URL_HOST);
+
+        if ($port = parse_url($uri, PHP_URL_PORT)) {
+            return $host.':'.$port;
+        }
+
+        return $host;
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Cookie.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Cookie.php
new file mode 100644
index 0000000..e937a62
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Cookie.php
@@ -0,0 +1,332 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit;
+
+/**
+ * Cookie represents an HTTP cookie.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Cookie
+{
+    /**
+     * Handles dates as defined by RFC 2616 section 3.3.1, and also some other
+     * non-standard, but common formats.
+     *
+     * @var array
+     */
+    private static $dateFormats = array(
+        'D, d M Y H:i:s T',
+        'D, d-M-y H:i:s T',
+        'D, d-M-Y H:i:s T',
+        'D, d-m-y H:i:s T',
+        'D, d-m-Y H:i:s T',
+        'D M j G:i:s Y',
+        'D M d H:i:s Y T',
+    );
+
+    protected $name;
+    protected $value;
+    protected $expires;
+    protected $path;
+    protected $domain;
+    protected $secure;
+    protected $httponly;
+    protected $rawValue;
+
+    /**
+     * Sets a cookie.
+     *
+     * @param string $name         The cookie name
+     * @param string $value        The value of the cookie
+     * @param string $expires      The time the cookie expires
+     * @param string $path         The path on the server in which the cookie will be available on
+     * @param string $domain       The domain that the cookie is available
+     * @param bool   $secure       Indicates that the cookie should only be transmitted over a secure HTTPS connection from the client
+     * @param bool   $httponly     The cookie httponly flag
+     * @param bool   $encodedValue Whether the value is encoded or not
+     *
+     * @api
+     */
+    public function __construct($name, $value, $expires = null, $path = null, $domain = '', $secure = false, $httponly = true, $encodedValue = false)
+    {
+        if ($encodedValue) {
+            $this->value = urldecode($value);
+            $this->rawValue = $value;
+        } else {
+            $this->value = $value;
+            $this->rawValue = urlencode($value);
+        }
+        $this->name = $name;
+        $this->expires = null === $expires ? null : (int) $expires;
+        $this->path = empty($path) ? '/' : $path;
+        $this->domain = $domain;
+        $this->secure = (bool) $secure;
+        $this->httponly = (bool) $httponly;
+    }
+
+    /**
+     * Returns the HTTP representation of the Cookie.
+     *
+     * @return string The HTTP representation of the Cookie
+     *
+     * @throws \UnexpectedValueException
+     *
+     * @api
+     */
+    public function __toString()
+    {
+        $cookie = sprintf('%s=%s', $this->name, $this->rawValue);
+
+        if (null !== $this->expires) {
+            $dateTime = \DateTime::createFromFormat('U', $this->expires, new \DateTimeZone('GMT'));
+
+            if ($dateTime === false) {
+                throw new \UnexpectedValueException(sprintf('The cookie expiration time "%s" is not valid.'), $this->expires);
+            }
+
+            $cookie .= '; expires='.str_replace('+0000', '', $dateTime->format(self::$dateFormats[0]));
+        }
+
+        if ('' !== $this->domain) {
+            $cookie .= '; domain='.$this->domain;
+        }
+
+        if ($this->path) {
+            $cookie .= '; path='.$this->path;
+        }
+
+        if ($this->secure) {
+            $cookie .= '; secure';
+        }
+
+        if ($this->httponly) {
+            $cookie .= '; httponly';
+        }
+
+        return $cookie;
+    }
+
+    /**
+     * Creates a Cookie instance from a Set-Cookie header value.
+     *
+     * @param string $cookie A Set-Cookie header value
+     * @param string $url    The base URL
+     *
+     * @return Cookie A Cookie instance
+     *
+     * @throws \InvalidArgumentException
+     *
+     * @api
+     */
+    public static function fromString($cookie, $url = null)
+    {
+        $parts = explode(';', $cookie);
+
+        if (false === strpos($parts[0], '=')) {
+            throw new \InvalidArgumentException(sprintf('The cookie string "%s" is not valid.', $parts[0]));
+        }
+
+        list($name, $value) = explode('=', array_shift($parts), 2);
+
+        $values = array(
+            'name' => trim($name),
+            'value' => trim($value),
+            'expires' => null,
+            'path' => '/',
+            'domain' => '',
+            'secure' => false,
+            'httponly' => false,
+            'passedRawValue' => true,
+        );
+
+        if (null !== $url) {
+            if ((false === $urlParts = parse_url($url)) || !isset($urlParts['host'])) {
+                throw new \InvalidArgumentException(sprintf('The URL "%s" is not valid.', $url));
+            }
+
+            $values['domain'] = $urlParts['host'];
+            $values['path'] = isset($urlParts['path']) ? substr($urlParts['path'], 0, strrpos($urlParts['path'], '/')) : '';
+        }
+
+        foreach ($parts as $part) {
+            $part = trim($part);
+
+            if ('secure' === strtolower($part)) {
+                // Ignore the secure flag if the original URI is not given or is not HTTPS
+                if (!$url || !isset($urlParts['scheme']) || 'https' != $urlParts['scheme']) {
+                    continue;
+                }
+
+                $values['secure'] = true;
+
+                continue;
+            }
+
+            if ('httponly' === strtolower($part)) {
+                $values['httponly'] = true;
+
+                continue;
+            }
+
+            if (2 === count($elements = explode('=', $part, 2))) {
+                if ('expires' === strtolower($elements[0])) {
+                    $elements[1] = self::parseDate($elements[1]);
+                }
+
+                $values[strtolower($elements[0])] = $elements[1];
+            }
+        }
+
+        return new static(
+            $values['name'],
+            $values['value'],
+            $values['expires'],
+            $values['path'],
+            $values['domain'],
+            $values['secure'],
+            $values['httponly'],
+            $values['passedRawValue']
+        );
+    }
+
+    private static function parseDate($dateValue)
+    {
+        // trim single quotes around date if present
+        if (($length = strlen($dateValue)) > 1 && "'" === $dateValue[0] && "'" === $dateValue[$length-1]) {
+            $dateValue = substr($dateValue, 1, -1);
+        }
+
+        foreach (self::$dateFormats as $dateFormat) {
+            if (false !== $date = \DateTime::createFromFormat($dateFormat, $dateValue, new \DateTimeZone('GMT'))) {
+                return $date->getTimestamp();
+            }
+        }
+
+        // attempt a fallback for unusual formatting
+        if (false !== $date = date_create($dateValue, new \DateTimeZone('GMT'))) {
+            return $date->getTimestamp();
+        }
+
+        throw new \InvalidArgumentException(sprintf('Could not parse date "%s".', $dateValue));
+    }
+
+    /**
+     * Gets the name of the cookie.
+     *
+     * @return string The cookie name
+     *
+     * @api
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Gets the value of the cookie.
+     *
+     * @return string The cookie value
+     *
+     * @api
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Gets the raw value of the cookie.
+     *
+     * @return string The cookie value
+     *
+     * @api
+     */
+    public function getRawValue()
+    {
+        return $this->rawValue;
+    }
+
+    /**
+     * Gets the expires time of the cookie.
+     *
+     * @return string The cookie expires time
+     *
+     * @api
+     */
+    public function getExpiresTime()
+    {
+        return $this->expires;
+    }
+
+    /**
+     * Gets the path of the cookie.
+     *
+     * @return string The cookie path
+     *
+     * @api
+     */
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    /**
+     * Gets the domain of the cookie.
+     *
+     * @return string The cookie domain
+     *
+     * @api
+     */
+    public function getDomain()
+    {
+        return $this->domain;
+    }
+
+    /**
+     * Returns the secure flag of the cookie.
+     *
+     * @return bool The cookie secure flag
+     *
+     * @api
+     */
+    public function isSecure()
+    {
+        return $this->secure;
+    }
+
+    /**
+     * Returns the httponly flag of the cookie.
+     *
+     * @return bool The cookie httponly flag
+     *
+     * @api
+     */
+    public function isHttpOnly()
+    {
+        return $this->httponly;
+    }
+
+    /**
+     * Returns true if the cookie has expired.
+     *
+     * @return bool true if the cookie has expired, false otherwise
+     *
+     * @api
+     */
+    public function isExpired()
+    {
+        return null !== $this->expires && 0 !== $this->expires && $this->expires < time();
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/CookieJar.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/CookieJar.php
new file mode 100644
index 0000000..1a36818
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/CookieJar.php
@@ -0,0 +1,265 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit;
+
+/**
+ * CookieJar.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class CookieJar
+{
+    protected $cookieJar = array();
+
+    /**
+     * Sets a cookie.
+     *
+     * @param Cookie $cookie A Cookie instance
+     *
+     * @api
+     */
+    public function set(Cookie $cookie)
+    {
+        $this->cookieJar[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie;
+    }
+
+    /**
+     * Gets a cookie by name.
+     *
+     * You should never use an empty domain, but if you do so,
+     * this method returns the first cookie for the given name/path
+     * (this behavior ensures a BC behavior with previous versions of
+     * Symfony).
+     *
+     * @param string $name   The cookie name
+     * @param string $path   The cookie path
+     * @param string $domain The cookie domain
+     *
+     * @return Cookie|null A Cookie instance or null if the cookie does not exist
+     *
+     * @api
+     */
+    public function get($name, $path = '/', $domain = null)
+    {
+        $this->flushExpiredCookies();
+
+        if (!empty($domain)) {
+            foreach ($this->cookieJar as $cookieDomain => $pathCookies) {
+                if ($cookieDomain) {
+                    $cookieDomain = '.'.ltrim($cookieDomain, '.');
+                    if ($cookieDomain != substr('.'.$domain, -strlen($cookieDomain))) {
+                        continue;
+                    }
+                }
+
+                foreach ($pathCookies as $cookiePath => $namedCookies) {
+                    if ($cookiePath != substr($path, 0, strlen($cookiePath))) {
+                        continue;
+                    }
+                    if (isset($namedCookies[$name])) {
+                        return $namedCookies[$name];
+                    }
+                }
+            }
+
+            return;
+        }
+
+        // avoid relying on this behavior that is mainly here for BC reasons
+        foreach ($this->cookieJar as $cookies) {
+            if (isset($cookies[$path][$name])) {
+                return $cookies[$path][$name];
+            }
+        }
+    }
+
+    /**
+     * Removes a cookie by name.
+     *
+     * You should never use an empty domain, but if you do so,
+     * all cookies for the given name/path expire (this behavior
+     * ensures a BC behavior with previous versions of Symfony).
+     *
+     * @param string $name   The cookie name
+     * @param string $path   The cookie path
+     * @param string $domain The cookie domain
+     *
+     * @api
+     */
+    public function expire($name, $path = '/', $domain = null)
+    {
+        if (null === $path) {
+            $path = '/';
+        }
+
+        if (empty($domain)) {
+            // an empty domain means any domain
+            // this should never happen but it allows for a better BC
+            $domains = array_keys($this->cookieJar);
+        } else {
+            $domains = array($domain);
+        }
+
+        foreach ($domains as $domain) {
+            unset($this->cookieJar[$domain][$path][$name]);
+
+            if (empty($this->cookieJar[$domain][$path])) {
+                unset($this->cookieJar[$domain][$path]);
+
+                if (empty($this->cookieJar[$domain])) {
+                    unset($this->cookieJar[$domain]);
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes all the cookies from the jar.
+     *
+     * @api
+     */
+    public function clear()
+    {
+        $this->cookieJar = array();
+    }
+
+    /**
+     * Updates the cookie jar from a response Set-Cookie headers.
+     *
+     * @param array  $setCookies Set-Cookie headers from an HTTP response
+     * @param string $uri        The base URL
+     */
+    public function updateFromSetCookie(array $setCookies, $uri = null)
+    {
+        $cookies = array();
+
+        foreach ($setCookies as $cookie) {
+            foreach (explode(',', $cookie) as $i => $part) {
+                if (0 === $i || preg_match('/^(?P<token>\s*[0-9A-Za-z!#\$%\&\'\*\+\-\.^_`\|~]+)=/', $part)) {
+                    $cookies[] = ltrim($part);
+                } else {
+                    $cookies[count($cookies) - 1] .= ','.$part;
+                }
+            }
+        }
+
+        foreach ($cookies as $cookie) {
+            try {
+                $this->set(Cookie::fromString($cookie, $uri));
+            } catch (\InvalidArgumentException $e) {
+                // invalid cookies are just ignored
+            }
+        }
+    }
+
+    /**
+     * Updates the cookie jar from a Response object.
+     *
+     * @param Response $response A Response object
+     * @param string   $uri      The base URL
+     */
+    public function updateFromResponse(Response $response, $uri = null)
+    {
+        $this->updateFromSetCookie($response->getHeader('Set-Cookie', false), $uri);
+    }
+
+    /**
+     * Returns not yet expired cookies.
+     *
+     * @return Cookie[] An array of cookies
+     */
+    public function all()
+    {
+        $this->flushExpiredCookies();
+
+        $flattenedCookies = array();
+        foreach ($this->cookieJar as $path) {
+            foreach ($path as $cookies) {
+                foreach ($cookies as $cookie) {
+                    $flattenedCookies[] = $cookie;
+                }
+            }
+        }
+
+        return $flattenedCookies;
+    }
+
+    /**
+     * Returns not yet expired cookie values for the given URI.
+     *
+     * @param string $uri             A URI
+     * @param bool   $returnsRawValue Returns raw value or urldecoded value
+     *
+     * @return array An array of cookie values
+     */
+    public function allValues($uri, $returnsRawValue = false)
+    {
+        $this->flushExpiredCookies();
+
+        $parts = array_replace(array('path' => '/'), parse_url($uri));
+        $cookies = array();
+        foreach ($this->cookieJar as $domain => $pathCookies) {
+            if ($domain) {
+                $domain = '.'.ltrim($domain, '.');
+                if ($domain != substr('.'.$parts['host'], -strlen($domain))) {
+                    continue;
+                }
+            }
+
+            foreach ($pathCookies as $path => $namedCookies) {
+                if ($path != substr($parts['path'], 0, strlen($path))) {
+                    continue;
+                }
+
+                foreach ($namedCookies as $cookie) {
+                    if ($cookie->isSecure() && 'https' != $parts['scheme']) {
+                        continue;
+                    }
+
+                    $cookies[$cookie->getName()] = $returnsRawValue ? $cookie->getRawValue() : $cookie->getValue();
+                }
+            }
+        }
+
+        return $cookies;
+    }
+
+    /**
+     * Returns not yet expired raw cookie values for the given URI.
+     *
+     * @param string $uri A URI
+     *
+     * @return array An array of cookie values
+     */
+    public function allRawValues($uri)
+    {
+        return $this->allValues($uri, true);
+    }
+
+    /**
+     * Removes all expired cookies.
+     */
+    public function flushExpiredCookies()
+    {
+        foreach ($this->cookieJar as $domain => $pathCookies) {
+            foreach ($pathCookies as $path => $namedCookies) {
+                foreach ($namedCookies as $name => $cookie) {
+                    if ($cookie->isExpired()) {
+                        unset($this->cookieJar[$domain][$path][$name]);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/History.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/History.php
new file mode 100644
index 0000000..8e38fe5
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/History.php
@@ -0,0 +1,102 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit;
+
+/**
+ * History.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class History
+{
+    protected $stack = array();
+    protected $position = -1;
+
+    /**
+     * Clears the history.
+     */
+    public function clear()
+    {
+        $this->stack = array();
+        $this->position = -1;
+    }
+
+    /**
+     * Adds a Request to the history.
+     *
+     * @param Request $request A Request instance
+     */
+    public function add(Request $request)
+    {
+        $this->stack = array_slice($this->stack, 0, $this->position + 1);
+        $this->stack[] = clone $request;
+        $this->position = count($this->stack) - 1;
+    }
+
+    /**
+     * Returns true if the history is empty.
+     *
+     * @return bool true if the history is empty, false otherwise
+     */
+    public function isEmpty()
+    {
+        return count($this->stack) == 0;
+    }
+
+    /**
+     * Goes back in the history.
+     *
+     * @return Request A Request instance
+     *
+     * @throws \LogicException if the stack is already on the first page
+     */
+    public function back()
+    {
+        if ($this->position < 1) {
+            throw new \LogicException('You are already on the first page.');
+        }
+
+        return clone $this->stack[--$this->position];
+    }
+
+    /**
+     * Goes forward in the history.
+     *
+     * @return Request A Request instance
+     *
+     * @throws \LogicException if the stack is already on the last page
+     */
+    public function forward()
+    {
+        if ($this->position > count($this->stack) - 2) {
+            throw new \LogicException('You are already on the last page.');
+        }
+
+        return clone $this->stack[++$this->position];
+    }
+
+    /**
+     * Returns the current element in the history.
+     *
+     * @return Request A Request instance
+     *
+     * @throws \LogicException if the stack is empty
+     */
+    public function current()
+    {
+        if (-1 == $this->position) {
+            throw new \LogicException('The page history is empty.');
+        }
+
+        return clone $this->stack[$this->position];
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/LICENSE b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/LICENSE
new file mode 100644
index 0000000..43028bc
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2015 Fabien Potencier
+
+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:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+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.
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/README.md b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/README.md
new file mode 100644
index 0000000..1b40c9f
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/README.md
@@ -0,0 +1,23 @@
+BrowserKit Component
+====================
+
+BrowserKit simulates the behavior of a web browser.
+
+The component only provide an abstract client and does not provide any
+"default" backend for the HTTP layer.
+
+Resources
+---------
+
+For a simple implementation of a browser based on an HTTP layer, have a look
+at [Goutte](https://github.com/fabpot/Goutte).
+
+For an implementation based on HttpKernelInterface, have a look at the
+[Client](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/Client.php)
+provided by the HttpKernel component.
+
+You can run the unit tests with the following command:
+
+    $ cd path/to/Symfony/Component/BrowserKit/
+    $ composer.phar install
+    $ phpunit
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Request.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Request.php
new file mode 100644
index 0000000..6d381d2
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Request.php
@@ -0,0 +1,138 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit;
+
+/**
+ * Request object.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Request
+{
+    protected $uri;
+    protected $method;
+    protected $parameters;
+    protected $files;
+    protected $cookies;
+    protected $server;
+    protected $content;
+
+    /**
+     * Constructor.
+     *
+     * @param string $uri        The request URI
+     * @param string $method     The HTTP method request
+     * @param array  $parameters The request parameters
+     * @param array  $files      An array of uploaded files
+     * @param array  $cookies    An array of cookies
+     * @param array  $server     An array of server parameters
+     * @param string $content    The raw body data
+     *
+     * @api
+     */
+    public function __construct($uri, $method, array $parameters = array(), array $files = array(), array $cookies = array(), array $server = array(), $content = null)
+    {
+        $this->uri = $uri;
+        $this->method = $method;
+        $this->parameters = $parameters;
+        $this->files = $files;
+        $this->cookies = $cookies;
+        $this->server = $server;
+        $this->content = $content;
+    }
+
+    /**
+     * Gets the request URI.
+     *
+     * @return string The request URI
+     *
+     * @api
+     */
+    public function getUri()
+    {
+        return $this->uri;
+    }
+
+    /**
+     * Gets the request HTTP method.
+     *
+     * @return string The request HTTP method
+     *
+     * @api
+     */
+    public function getMethod()
+    {
+        return $this->method;
+    }
+
+    /**
+     * Gets the request parameters.
+     *
+     * @return array The request parameters
+     *
+     * @api
+     */
+    public function getParameters()
+    {
+        return $this->parameters;
+    }
+
+    /**
+     * Gets the request server files.
+     *
+     * @return array The request files
+     *
+     * @api
+     */
+    public function getFiles()
+    {
+        return $this->files;
+    }
+
+    /**
+     * Gets the request cookies.
+     *
+     * @return array The request cookies
+     *
+     * @api
+     */
+    public function getCookies()
+    {
+        return $this->cookies;
+    }
+
+    /**
+     * Gets the request server parameters.
+     *
+     * @return array The request server parameters
+     *
+     * @api
+     */
+    public function getServer()
+    {
+        return $this->server;
+    }
+
+    /**
+     * Gets the request raw body data.
+     *
+     * @return string The request raw body data.
+     *
+     * @api
+     */
+    public function getContent()
+    {
+        return $this->content;
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Response.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Response.php
new file mode 100644
index 0000000..d00836f
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Response.php
@@ -0,0 +1,138 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit;
+
+/**
+ * Response object.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Response
+{
+    protected $content;
+    protected $status;
+    protected $headers;
+
+    /**
+     * Constructor.
+     *
+     * The headers array is a set of key/value pairs. If a header is present multiple times
+     * then the value is an array of all the values.
+     *
+     * @param string $content The content of the response
+     * @param int    $status  The response status code
+     * @param array  $headers An array of headers
+     *
+     * @api
+     */
+    public function __construct($content = '', $status = 200, array $headers = array())
+    {
+        $this->content = $content;
+        $this->status = $status;
+        $this->headers = $headers;
+    }
+
+    /**
+     * Converts the response object to string containing all headers and the response content.
+     *
+     * @return string The response with headers and content
+     */
+    public function __toString()
+    {
+        $headers = '';
+        foreach ($this->headers as $name => $value) {
+            if (is_string($value)) {
+                $headers .= $this->buildHeader($name, $value);
+            } else {
+                foreach ($value as $headerValue) {
+                    $headers .= $this->buildHeader($name, $headerValue);
+                }
+            }
+        }
+
+        return $headers."\n".$this->content;
+    }
+
+    /**
+     * Returns the build header line.
+     *
+     * @param string $name  The header name
+     * @param string $value The header value
+     *
+     * @return string The built header line
+     */
+    protected function buildHeader($name, $value)
+    {
+        return sprintf("%s: %s\n", $name, $value);
+    }
+
+    /**
+     * Gets the response content.
+     *
+     * @return string The response content
+     *
+     * @api
+     */
+    public function getContent()
+    {
+        return $this->content;
+    }
+
+    /**
+     * Gets the response status code.
+     *
+     * @return int The response status code
+     *
+     * @api
+     */
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    /**
+     * Gets the response headers.
+     *
+     * @return array The response headers
+     *
+     * @api
+     */
+    public function getHeaders()
+    {
+        return $this->headers;
+    }
+
+    /**
+     * Gets a response header.
+     *
+     * @param string $header The header name
+     * @param bool   $first  Whether to return the first value or all header values
+     *
+     * @return string|array The first header value if $first is true, an array of values otherwise
+     */
+    public function getHeader($header, $first = true)
+    {
+        foreach ($this->headers as $key => $value) {
+            if (str_replace('-', '_', strtolower($key)) == str_replace('-', '_', strtolower($header))) {
+                if ($first) {
+                    return is_array($value) ? (count($value) ? $value[0] : '') : $value;
+                }
+
+                return is_array($value) ? $value : array($value);
+            }
+        }
+
+        return $first ? null : array();
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/ClientTest.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/ClientTest.php
new file mode 100644
index 0000000..a6e5ba9
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/ClientTest.php
@@ -0,0 +1,624 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit\Tests;
+
+use Symfony\Component\BrowserKit\Client;
+use Symfony\Component\BrowserKit\History;
+use Symfony\Component\BrowserKit\CookieJar;
+use Symfony\Component\BrowserKit\Response;
+
+class SpecialResponse extends Response
+{
+}
+
+class TestClient extends Client
+{
+    protected $nextResponse = null;
+    protected $nextScript = null;
+
+    public function setNextResponse(Response $response)
+    {
+        $this->nextResponse = $response;
+    }
+
+    public function setNextScript($script)
+    {
+        $this->nextScript = $script;
+    }
+
+    protected function doRequest($request)
+    {
+        if (null === $this->nextResponse) {
+            return new Response();
+        }
+
+        $response = $this->nextResponse;
+        $this->nextResponse = null;
+
+        return $response;
+    }
+
+    protected function filterResponse($response)
+    {
+        if ($response instanceof SpecialResponse) {
+            return new Response($response->getContent(), $response->getStatus(), $response->getHeaders());
+        }
+
+        return $response;
+    }
+
+    protected function getScript($request)
+    {
+        $r = new \ReflectionClass('Symfony\Component\BrowserKit\Response');
+        $path = $r->getFileName();
+
+        return <<<EOF
+<?php
+
+require_once('$path');
+
+echo serialize($this->nextScript);
+EOF;
+    }
+}
+
+class ClientTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @covers Symfony\Component\BrowserKit\Client::getHistory
+     */
+    public function testGetHistory()
+    {
+        $client = new TestClient(array(), $history = new History());
+        $this->assertSame($history, $client->getHistory(), '->getHistory() returns the History');
+    }
+
+    /**
+     * @covers Symfony\Component\BrowserKit\Client::getCookieJar
+     */
+    public function testGetCookieJar()
+    {
+        $client = new TestClient(array(), null, $cookieJar = new CookieJar());
+        $this->assertSame($cookieJar, $client->getCookieJar(), '->getCookieJar() returns the CookieJar');
+    }
+
+    /**
+     * @covers Symfony\Component\BrowserKit\Client::getRequest
+     */
+    public function testGetRequest()
+    {
+        $client = new TestClient();
+        $client->request('GET', 'http://example.com/');
+
+        $this->assertEquals('http://example.com/', $client->getRequest()->getUri(), '->getCrawler() returns the Request of the last request');
+    }
+
+    public function testGetRequestWithIpAsHost()
+    {
+        $client = new TestClient();
+        $client->request('GET', 'https://example.com/foo', array(), array(), array('HTTP_HOST' => '127.0.0.1'));
+
+        $this->assertEquals('https://127.0.0.1/foo', $client->getRequest()->getUri());
+    }
+
+    public function testGetResponse()
+    {
+        $client = new TestClient();
+        $client->setNextResponse(new Response('foo'));
+        $client->request('GET', 'http://example.com/');
+
+        $this->assertEquals('foo', $client->getResponse()->getContent(), '->getCrawler() returns the Response of the last request');
+        $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getResponse(), '->getCrawler() returns the Response of the last request');
+    }
+
+    public function testGetInternalResponse()
+    {
+        $client = new TestClient();
+        $client->setNextResponse(new SpecialResponse('foo'));
+        $client->request('GET', 'http://example.com/');
+
+        $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getInternalResponse());
+        $this->assertNotInstanceOf('Symfony\Component\BrowserKit\Tests\SpecialResponse', $client->getInternalResponse());
+        $this->assertInstanceOf('Symfony\Component\BrowserKit\Tests\SpecialResponse', $client->getResponse());
+    }
+
+    public function testGetContent()
+    {
+        $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}';
+
+        $client = new TestClient();
+        $client->request('POST', 'http://example.com/jsonrpc', array(), array(), array(), $json);
+        $this->assertEquals($json, $client->getRequest()->getContent());
+    }
+
+    /**
+     * @covers Symfony\Component\BrowserKit\Client::getCrawler
+     */
+    public function testGetCrawler()
+    {
+        $client = new TestClient();
+        $client->setNextResponse(new Response('foo'));
+        $crawler = $client->request('GET', 'http://example.com/');
+
+        $this->assertSame($crawler, $client->getCrawler(), '->getCrawler() returns the Crawler of the last request');
+    }
+
+    public function testRequestHttpHeaders()
+    {
+        $client = new TestClient();
+        $client->request('GET', '/');
+        $headers = $client->getRequest()->getServer();
+        $this->assertEquals('localhost', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header');
+
+        $client = new TestClient();
+        $client->request('GET', 'http://www.example.com');
+        $headers = $client->getRequest()->getServer();
+        $this->assertEquals('www.example.com', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header');
+
+        $client->request('GET', 'https://www.example.com');
+        $headers = $client->getRequest()->getServer();
+        $this->assertTrue($headers['HTTPS'], '->request() sets the HTTPS header');
+
+        $client = new TestClient();
+        $client->request('GET', 'http://www.example.com:8080');
+        $headers = $client->getRequest()->getServer();
+        $this->assertEquals('www.example.com:8080', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header with port');
+    }
+
+    public function testRequestURIConversion()
+    {
+        $client = new TestClient();
+        $client->request('GET', '/foo');
+        $this->assertEquals('http://localhost/foo', $client->getRequest()->getUri(), '->request() converts the URI to an absolute one');
+
+        $client = new TestClient();
+        $client->request('GET', 'http://www.example.com');
+        $this->assertEquals('http://www.example.com', $client->getRequest()->getUri(), '->request() does not change absolute URIs');
+
+        $client = new TestClient();
+        $client->request('GET', 'http://www.example.com/');
+        $client->request('GET', '/foo');
+        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
+
+        $client = new TestClient();
+        $client->request('GET', 'http://www.example.com/foo');
+        $client->request('GET', '#');
+        $this->assertEquals('http://www.example.com/foo#', $client->getRequest()->getUri(), '->request() uses the previous request for #');
+        $client->request('GET', '#');
+        $this->assertEquals('http://www.example.com/foo#', $client->getRequest()->getUri(), '->request() uses the previous request for #');
+        $client->request('GET', '#foo');
+        $this->assertEquals('http://www.example.com/foo#foo', $client->getRequest()->getUri(), '->request() uses the previous request for #');
+
+        $client = new TestClient();
+        $client->request('GET', 'http://www.example.com/foo/');
+        $client->request('GET', 'bar');
+        $this->assertEquals('http://www.example.com/foo/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
+
+        $client = new TestClient();
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $client->request('GET', 'bar');
+        $this->assertEquals('http://www.example.com/foo/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
+    }
+
+    public function testRequestURIConversionByServerHost()
+    {
+        $client = new TestClient();
+
+        $server = array('HTTP_HOST' => 'www.exampl+e.com:8000');
+        $parameters = array();
+        $files = array();
+
+        $client->request('GET', 'http://exampl+e.com', $parameters, $files, $server);
+        $this->assertEquals('http://www.exampl+e.com:8000', $client->getRequest()->getUri(), '->request() uses HTTP_HOST to add port');
+
+        $client->request('GET', 'http://exampl+e.com:8888', $parameters, $files, $server);
+        $this->assertEquals('http://www.exampl+e.com:8000', $client->getRequest()->getUri(), '->request() uses HTTP_HOST to modify existing port');
+
+        $client->request('GET', 'http://exampl+e.com:8000', $parameters, $files, $server);
+        $this->assertEquals('http://www.exampl+e.com:8000', $client->getRequest()->getUri(), '->request() uses HTTP_HOST respects correct set port');
+    }
+
+    public function testRequestReferer()
+    {
+        $client = new TestClient();
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $client->request('GET', 'bar');
+        $server = $client->getRequest()->getServer();
+        $this->assertEquals('http://www.example.com/foo/foobar', $server['HTTP_REFERER'], '->request() sets the referer');
+    }
+
+    public function testRequestHistory()
+    {
+        $client = new TestClient();
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $client->request('GET', 'bar');
+
+        $this->assertEquals('http://www.example.com/foo/bar', $client->getHistory()->current()->getUri(), '->request() updates the History');
+        $this->assertEquals('http://www.example.com/foo/foobar', $client->getHistory()->back()->getUri(), '->request() updates the History');
+    }
+
+    public function testRequestCookies()
+    {
+        $client = new TestClient();
+        $client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>', 200, array('Set-Cookie' => 'foo=bar')));
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $this->assertEquals(array('foo' => 'bar'), $client->getCookieJar()->allValues('http://www.example.com/foo/foobar'), '->request() updates the CookieJar');
+
+        $client->request('GET', 'bar');
+        $this->assertEquals(array('foo' => 'bar'), $client->getCookieJar()->allValues('http://www.example.com/foo/foobar'), '->request() updates the CookieJar');
+    }
+
+    public function testRequestSecureCookies()
+    {
+        $client = new TestClient();
+        $client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>', 200, array('Set-Cookie' => 'foo=bar; path=/; secure')));
+        $client->request('GET', 'https://www.example.com/foo/foobar');
+
+        $this->assertTrue($client->getCookieJar()->get('foo', '/', 'www.example.com')->isSecure());
+    }
+
+    public function testClick()
+    {
+        $client = new TestClient();
+        $client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>'));
+        $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
+
+        $client->click($crawler->filter('a')->link());
+
+        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->click() clicks on links');
+    }
+
+    public function testClickForm()
+    {
+        $client = new TestClient();
+        $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
+        $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
+
+        $client->click($crawler->filter('input')->form());
+
+        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->click() Form submit forms');
+    }
+
+    public function testSubmit()
+    {
+        $client = new TestClient();
+        $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
+        $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
+
+        $client->submit($crawler->filter('input')->form());
+
+        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->submit() submit forms');
+    }
+
+    public function testSubmitPreserveAuth()
+    {
+        $client = new TestClient(array('PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar'));
+        $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
+        $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
+
+        $server = $client->getRequest()->getServer();
+        $this->assertArrayHasKey('PHP_AUTH_USER', $server);
+        $this->assertEquals('foo', $server['PHP_AUTH_USER']);
+        $this->assertArrayHasKey('PHP_AUTH_PW', $server);
+        $this->assertEquals('bar', $server['PHP_AUTH_PW']);
+
+        $client->submit($crawler->filter('input')->form());
+
+        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->submit() submit forms');
+
+        $server = $client->getRequest()->getServer();
+        $this->assertArrayHasKey('PHP_AUTH_USER', $server);
+        $this->assertEquals('foo', $server['PHP_AUTH_USER']);
+        $this->assertArrayHasKey('PHP_AUTH_PW', $server);
+        $this->assertEquals('bar', $server['PHP_AUTH_PW']);
+    }
+
+    public function testFollowRedirect()
+    {
+        $client = new TestClient();
+        $client->followRedirects(false);
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+
+        try {
+            $client->followRedirect();
+            $this->fail('->followRedirect() throws a \LogicException if the request was not redirected');
+        } catch (\Exception $e) {
+            $this->assertInstanceof('LogicException', $e, '->followRedirect() throws a \LogicException if the request was not redirected');
+        }
+
+        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $client->followRedirect();
+
+        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');
+
+        $client = new TestClient();
+        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+
+        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() automatically follows redirects if followRedirects is true');
+
+        $client = new TestClient();
+        $client->setNextResponse(new Response('', 201, array('Location' => 'http://www.example.com/redirected')));
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+
+        $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->followRedirect() does not follow redirect if HTTP Code is not 30x');
+
+        $client = new TestClient();
+        $client->setNextResponse(new Response('', 201, array('Location' => 'http://www.example.com/redirected')));
+        $client->followRedirects(false);
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+
+        try {
+            $client->followRedirect();
+            $this->fail('->followRedirect() throws a \LogicException if the request did not respond with 30x HTTP Code');
+        } catch (\Exception $e) {
+            $this->assertInstanceof('LogicException', $e, '->followRedirect() throws a \LogicException if the request did not respond with 30x HTTP Code');
+        }
+    }
+
+    public function testFollowRelativeRedirect()
+    {
+        $client = new TestClient();
+        $client->setNextResponse(new Response('', 302, array('Location' => '/redirected')));
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');
+
+        $client = new TestClient();
+        $client->setNextResponse(new Response('', 302, array('Location' => '/redirected:1234')));
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $this->assertEquals('http://www.example.com/redirected:1234', $client->getRequest()->getUri(), '->followRedirect() follows relative urls');
+    }
+
+    public function testFollowRedirectWithMaxRedirects()
+    {
+        $client = new TestClient();
+        $client->setMaxRedirects(1);
+        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');
+
+        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected2')));
+        try {
+            $client->followRedirect();
+            $this->fail('->followRedirect() throws a \LogicException if the request was redirected and limit of redirections was reached');
+        } catch (\Exception $e) {
+            $this->assertInstanceof('LogicException', $e, '->followRedirect() throws a \LogicException if the request was redirected and limit of redirections was reached');
+        }
+
+        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');
+
+        $client->setNextResponse(new Response('', 302, array('Location' => '/redirected')));
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+
+        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows relative URLs');
+
+        $client = new TestClient();
+        $client->setNextResponse(new Response('', 302, array('Location' => '//www.example.org/')));
+        $client->request('GET', 'https://www.example.com/');
+
+        $this->assertEquals('https://www.example.org/', $client->getRequest()->getUri(), '->followRedirect() follows protocol-relative URLs');
+
+        $client = new TestClient();
+        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
+        $client->request('POST', 'http://www.example.com/foo/foobar', array('name' => 'bar'));
+
+        $this->assertEquals('get', $client->getRequest()->getMethod(), '->followRedirect() uses a get for 302');
+        $this->assertEquals(array(), $client->getRequest()->getParameters(), '->followRedirect() does not submit parameters when changing the method');
+    }
+
+    public function testFollowRedirectWithCookies()
+    {
+        $client = new TestClient();
+        $client->followRedirects(false);
+        $client->setNextResponse(new Response('', 302, array(
+            'Location' => 'http://www.example.com/redirected',
+            'Set-Cookie' => 'foo=bar',
+        )));
+        $client->request('GET', 'http://www.example.com/');
+        $this->assertEquals(array(), $client->getRequest()->getCookies());
+        $client->followRedirect();
+        $this->assertEquals(array('foo' => 'bar'), $client->getRequest()->getCookies());
+    }
+
+    public function testFollowRedirectWithHeaders()
+    {
+        $headers = array(
+            'HTTP_HOST' => 'www.example.com',
+            'HTTP_USER_AGENT' => 'Symfony2 BrowserKit',
+            'CONTENT_TYPE' => 'application/vnd.custom+xml',
+            'HTTPS' => false,
+        );
+
+        $client = new TestClient();
+        $client->followRedirects(false);
+        $client->setNextResponse(new Response('', 302, array(
+            'Location' => 'http://www.example.com/redirected',
+        )));
+        $client->request('GET', 'http://www.example.com/', array(), array(), array(
+            'CONTENT_TYPE' => 'application/vnd.custom+xml',
+        ));
+
+        $this->assertEquals($headers, $client->getRequest()->getServer());
+
+        $client->followRedirect();
+
+        $headers['HTTP_REFERER'] = 'http://www.example.com/';
+
+        $this->assertEquals($headers, $client->getRequest()->getServer());
+    }
+
+    public function testFollowRedirectWithPort()
+    {
+        $headers = array(
+            'HTTP_HOST' => 'www.example.com:8080',
+            'HTTP_USER_AGENT' => 'Symfony2 BrowserKit',
+            'HTTPS' => false,
+            'HTTP_REFERER' => 'http://www.example.com:8080/',
+        );
+
+        $client = new TestClient();
+        $client->setNextResponse(new Response('', 302, array(
+            'Location' => 'http://www.example.com:8080/redirected',
+        )));
+        $client->request('GET', 'http://www.example.com:8080/');
+
+        $this->assertEquals($headers, $client->getRequest()->getServer());
+    }
+
+    public function testBack()
+    {
+        $client = new TestClient();
+
+        $parameters = array('foo' => 'bar');
+        $files = array('myfile.foo' => 'baz');
+        $server = array('X_TEST_FOO' => 'bazbar');
+        $content = 'foobarbaz';
+
+        $client->request('GET', 'http://www.example.com/foo/foobar', $parameters, $files, $server, $content);
+        $client->request('GET', 'http://www.example.com/foo');
+        $client->back();
+
+        $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->back() goes back in the history');
+        $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->back() keeps parameters');
+        $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->back() keeps files');
+        $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->back() keeps $_SERVER');
+        $this->assertEquals($content, $client->getRequest()->getContent(), '->back() keeps content');
+    }
+
+    public function testForward()
+    {
+        $client = new TestClient();
+
+        $parameters = array('foo' => 'bar');
+        $files = array('myfile.foo' => 'baz');
+        $server = array('X_TEST_FOO' => 'bazbar');
+        $content = 'foobarbaz';
+
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $client->request('GET', 'http://www.example.com/foo', $parameters, $files, $server, $content);
+        $client->back();
+        $client->forward();
+
+        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->forward() goes forward in the history');
+        $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->forward() keeps parameters');
+        $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->forward() keeps files');
+        $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->forward() keeps $_SERVER');
+        $this->assertEquals($content, $client->getRequest()->getContent(), '->forward() keeps content');
+    }
+
+    public function testReload()
+    {
+        $client = new TestClient();
+
+        $parameters = array('foo' => 'bar');
+        $files = array('myfile.foo' => 'baz');
+        $server = array('X_TEST_FOO' => 'bazbar');
+        $content = 'foobarbaz';
+
+        $client->request('GET', 'http://www.example.com/foo/foobar', $parameters, $files, $server, $content);
+        $client->reload();
+
+        $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->reload() reloads the current page');
+        $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->reload() keeps parameters');
+        $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->reload() keeps files');
+        $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->reload() keeps $_SERVER');
+        $this->assertEquals($content, $client->getRequest()->getContent(), '->reload() keeps content');
+    }
+
+    public function testRestart()
+    {
+        $client = new TestClient();
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+        $client->restart();
+
+        $this->assertTrue($client->getHistory()->isEmpty(), '->restart() clears the history');
+        $this->assertEquals(array(), $client->getCookieJar()->all(), '->restart() clears the cookies');
+    }
+
+    public function testInsulatedRequests()
+    {
+        $client = new TestClient();
+        $client->insulate();
+        $client->setNextScript("new Symfony\Component\BrowserKit\Response('foobar')");
+        $client->request('GET', 'http://www.example.com/foo/foobar');
+
+        $this->assertEquals('foobar', $client->getResponse()->getContent(), '->insulate() process the request in a forked process');
+
+        $client->setNextScript("new Symfony\Component\BrowserKit\Response('foobar)");
+
+        try {
+            $client->request('GET', 'http://www.example.com/foo/foobar');
+            $this->fail('->request() throws a \RuntimeException if the script has an error');
+        } catch (\Exception $e) {
+            $this->assertInstanceof('RuntimeException', $e, '->request() throws a \RuntimeException if the script has an error');
+        }
+    }
+
+    public function testGetServerParameter()
+    {
+        $client = new TestClient();
+        $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST'));
+        $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));
+        $this->assertEquals('testvalue', $client->getServerParameter('testkey', 'testvalue'));
+    }
+
+    public function testSetServerParameter()
+    {
+        $client = new TestClient();
+
+        $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST'));
+        $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));
+
+        $client->setServerParameter('HTTP_HOST', 'testhost');
+        $this->assertEquals('testhost', $client->getServerParameter('HTTP_HOST'));
+
+        $client->setServerParameter('HTTP_USER_AGENT', 'testua');
+        $this->assertEquals('testua', $client->getServerParameter('HTTP_USER_AGENT'));
+    }
+
+    public function testSetServerParameterInRequest()
+    {
+        $client = new TestClient();
+
+        $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST'));
+        $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));
+
+        $client->request('GET', 'https://www.example.com/https/www.example.com', array(), array(), array(
+            'HTTP_HOST' => 'testhost',
+            'HTTP_USER_AGENT' => 'testua',
+            'HTTPS' => false,
+            'NEW_SERVER_KEY' => 'new-server-key-value',
+        ));
+
+        $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST'));
+        $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));
+
+        $this->assertEquals('http://testhost/https/www.example.com', $client->getRequest()->getUri());
+
+        $server = $client->getRequest()->getServer();
+
+        $this->assertArrayHasKey('HTTP_USER_AGENT', $server);
+        $this->assertEquals('testua', $server['HTTP_USER_AGENT']);
+
+        $this->assertArrayHasKey('HTTP_HOST', $server);
+        $this->assertEquals('testhost', $server['HTTP_HOST']);
+
+        $this->assertArrayHasKey('NEW_SERVER_KEY', $server);
+        $this->assertEquals('new-server-key-value', $server['NEW_SERVER_KEY']);
+
+        $this->assertArrayHasKey('HTTPS', $server);
+        $this->assertFalse($server['HTTPS']);
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/CookieJarTest.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/CookieJarTest.php
new file mode 100644
index 0000000..4da4404
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/CookieJarTest.php
@@ -0,0 +1,231 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit\Tests;
+
+use Symfony\Component\BrowserKit\CookieJar;
+use Symfony\Component\BrowserKit\Cookie;
+use Symfony\Component\BrowserKit\Response;
+
+class CookieJarTest extends \PHPUnit_Framework_TestCase
+{
+    public function testSetGet()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie = new Cookie('foo', 'bar'));
+
+        $this->assertEquals($cookie, $cookieJar->get('foo'), '->set() sets a cookie');
+
+        $this->assertNull($cookieJar->get('foobar'), '->get() returns null if the cookie does not exist');
+
+        $cookieJar->set($cookie = new Cookie('foo', 'bar', time() - 86400));
+        $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired');
+    }
+
+    public function testExpire()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie = new Cookie('foo', 'bar'));
+        $cookieJar->expire('foo');
+        $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired');
+    }
+
+    public function testAll()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie1 = new Cookie('foo', 'bar'));
+        $cookieJar->set($cookie2 = new Cookie('bar', 'foo'));
+
+        $this->assertEquals(array($cookie1, $cookie2), $cookieJar->all(), '->all() returns all cookies in the jar');
+    }
+
+    public function testClear()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie1 = new Cookie('foo', 'bar'));
+        $cookieJar->set($cookie2 = new Cookie('bar', 'foo'));
+
+        $cookieJar->clear();
+
+        $this->assertEquals(array(), $cookieJar->all(), '->clear() expires all cookies');
+    }
+
+    public function testUpdateFromResponse()
+    {
+        $response = new Response('', 200, array('Set-Cookie' => 'foo=foo'));
+
+        $cookieJar = new CookieJar();
+        $cookieJar->updateFromResponse($response);
+
+        $this->assertEquals('foo', $cookieJar->get('foo')->getValue(), '->updateFromResponse() updates cookies from a Response objects');
+    }
+
+    public function testUpdateFromSetCookie()
+    {
+        $setCookies = array('foo=foo');
+
+        $cookieJar = new CookieJar();
+        $cookieJar->set(new Cookie('bar', 'bar'));
+        $cookieJar->updateFromSetCookie($setCookies);
+
+        $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $cookieJar->get('foo'));
+        $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $cookieJar->get('bar'));
+        $this->assertEquals('foo', $cookieJar->get('foo')->getValue(), '->updateFromSetCookie() updates cookies from a Set-Cookie header');
+        $this->assertEquals('bar', $cookieJar->get('bar')->getValue(), '->updateFromSetCookie() keeps existing cookies');
+    }
+
+    public function testUpdateFromEmptySetCookie()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->updateFromSetCookie(array(''));
+        $this->assertEquals(array(), $cookieJar->all());
+    }
+
+    public function testUpdateFromSetCookieWithMultipleCookies()
+    {
+        $timestamp = time() + 3600;
+        $date = gmdate('D, d M Y H:i:s \G\M\T', $timestamp);
+        $setCookies = array(sprintf('foo=foo; expires=%s; domain=.symfony.com; path=/, bar=bar; domain=.blog.symfony.com, PHPSESSID=id; expires=%s', $date, $date));
+
+        $cookieJar = new CookieJar();
+        $cookieJar->updateFromSetCookie($setCookies);
+
+        $fooCookie = $cookieJar->get('foo', '/', '.symfony.com');
+        $barCookie = $cookieJar->get('bar', '/', '.blog.symfony.com');
+        $phpCookie = $cookieJar->get('PHPSESSID');
+
+        $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $fooCookie);
+        $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $barCookie);
+        $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $phpCookie);
+        $this->assertEquals('foo', $fooCookie->getValue());
+        $this->assertEquals('bar', $barCookie->getValue());
+        $this->assertEquals('id', $phpCookie->getValue());
+        $this->assertEquals($timestamp, $fooCookie->getExpiresTime());
+        $this->assertNull($barCookie->getExpiresTime());
+        $this->assertEquals($timestamp, $phpCookie->getExpiresTime());
+    }
+
+    /**
+     * @dataProvider provideAllValuesValues
+     */
+    public function testAllValues($uri, $values)
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie1 = new Cookie('foo_nothing', 'foo'));
+        $cookieJar->set($cookie2 = new Cookie('foo_expired', 'foo', time() - 86400));
+        $cookieJar->set($cookie3 = new Cookie('foo_path', 'foo', null, '/foo'));
+        $cookieJar->set($cookie4 = new Cookie('foo_domain', 'foo', null, '/', '.example.com'));
+        $cookieJar->set($cookie4 = new Cookie('foo_strict_domain', 'foo', null, '/', '.www4.example.com'));
+        $cookieJar->set($cookie5 = new Cookie('foo_secure', 'foo', null, '/', '', true));
+
+        $this->assertEquals($values, array_keys($cookieJar->allValues($uri)), '->allValues() returns the cookie for a given URI');
+    }
+
+    public function provideAllValuesValues()
+    {
+        return array(
+            array('http://www.example.com', array('foo_nothing', 'foo_domain')),
+            array('http://www.example.com/', array('foo_nothing', 'foo_domain')),
+            array('http://foo.example.com/', array('foo_nothing', 'foo_domain')),
+            array('http://foo.example1.com/', array('foo_nothing')),
+            array('https://foo.example.com/', array('foo_nothing', 'foo_secure', 'foo_domain')),
+            array('http://www.example.com/foo/bar', array('foo_nothing', 'foo_path', 'foo_domain')),
+            array('http://www4.example.com/', array('foo_nothing', 'foo_domain', 'foo_strict_domain')),
+        );
+    }
+
+    public function testEncodedValues()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie = new Cookie('foo', 'bar%3Dbaz', null, '/', '', false, true, true));
+
+        $this->assertEquals(array('foo' => 'bar=baz'), $cookieJar->allValues('/'));
+        $this->assertEquals(array('foo' => 'bar%3Dbaz'), $cookieJar->allRawValues('/'));
+    }
+
+    public function testCookieExpireWithSameNameButDifferentPaths()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/foo'));
+        $cookieJar->set($cookie2 = new Cookie('foo', 'bar2', null, '/bar'));
+        $cookieJar->expire('foo', '/foo');
+
+        $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired');
+        $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/')));
+        $this->assertEquals(array(), $cookieJar->allValues('http://example.com/foo'));
+        $this->assertEquals(array('foo' => 'bar2'), $cookieJar->allValues('http://example.com/bar'));
+    }
+
+    public function testCookieExpireWithNullPaths()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/'));
+        $cookieJar->expire('foo', null);
+
+        $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired');
+        $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/')));
+    }
+
+    public function testCookieWithSameNameButDifferentPaths()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/foo'));
+        $cookieJar->set($cookie2 = new Cookie('foo', 'bar2', null, '/bar'));
+
+        $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/')));
+        $this->assertEquals(array('foo' => 'bar1'), $cookieJar->allValues('http://example.com/foo'));
+        $this->assertEquals(array('foo' => 'bar2'), $cookieJar->allValues('http://example.com/bar'));
+    }
+
+    public function testCookieWithSameNameButDifferentDomains()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/', 'foo.example.com'));
+        $cookieJar->set($cookie2 = new Cookie('foo', 'bar2', null, '/', 'bar.example.com'));
+
+        $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/')));
+        $this->assertEquals(array('foo' => 'bar1'), $cookieJar->allValues('http://foo.example.com/'));
+        $this->assertEquals(array('foo' => 'bar2'), $cookieJar->allValues('http://bar.example.com/'));
+    }
+
+    public function testCookieGetWithSubdomain()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie1 = new Cookie('foo', 'bar', null, '/', '.example.com'));
+        $cookieJar->set($cookie2 = new Cookie('foo1', 'bar', null, '/', 'test.example.com'));
+
+        $this->assertEquals($cookie1, $cookieJar->get('foo', '/', 'foo.example.com'));
+        $this->assertEquals($cookie1, $cookieJar->get('foo', '/', 'example.com'));
+        $this->assertEquals($cookie2, $cookieJar->get('foo1', '/', 'test.example.com'));
+    }
+
+    public function testCookieGetWithSubdirectory()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set($cookie1 = new Cookie('foo', 'bar', null, '/test', '.example.com'));
+        $cookieJar->set($cookie2 = new Cookie('foo1', 'bar1', null, '/', '.example.com'));
+
+        $this->assertNull($cookieJar->get('foo', '/', '.example.com'));
+        $this->assertNull($cookieJar->get('foo', '/bar', '.example.com'));
+        $this->assertEquals($cookie1, $cookieJar->get('foo', '/test', 'example.com'));
+        $this->assertEquals($cookie2, $cookieJar->get('foo1', '/', 'example.com'));
+        $this->assertEquals($cookie2, $cookieJar->get('foo1', '/bar', 'example.com'));
+    }
+
+    public function testCookieWithWildcardDomain()
+    {
+        $cookieJar = new CookieJar();
+        $cookieJar->set(new Cookie('foo', 'bar', null, '/', '.example.com'));
+
+        $this->assertEquals(array('foo' => 'bar'), $cookieJar->allValues('http://www.example.com'));
+        $this->assertEmpty($cookieJar->allValues('http://wwwexample.com'));
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/CookieTest.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/CookieTest.php
new file mode 100644
index 0000000..8e3578a
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/CookieTest.php
@@ -0,0 +1,179 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit\Tests;
+
+use Symfony\Component\BrowserKit\Cookie;
+
+class CookieTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider getTestsForToFromString
+     */
+    public function testToFromString($cookie, $url = null)
+    {
+        $this->assertEquals($cookie, (string) Cookie::fromString($cookie, $url));
+    }
+
+    public function getTestsForToFromString()
+    {
+        return array(
+            array('foo=bar; path=/'),
+            array('foo=bar; path=/foo'),
+            array('foo=bar; domain=google.com; path=/'),
+            array('foo=bar; domain=example.com; path=/; secure', 'https://example.com/'),
+            array('foo=bar; path=/; httponly'),
+            array('foo=bar; domain=google.com; path=/foo; secure; httponly', 'https://google.com/'),
+            array('foo=bar=baz; path=/'),
+            array('foo=bar%3Dbaz; path=/'),
+        );
+    }
+
+    public function testFromStringIgnoreSecureFlag()
+    {
+        $this->assertFalse(Cookie::fromString('foo=bar; secure')->isSecure());
+        $this->assertFalse(Cookie::fromString('foo=bar; secure', 'http://example.com/')->isSecure());
+    }
+
+    /**
+     * @dataProvider getExpireCookieStrings
+     */
+    public function testFromStringAcceptsSeveralExpiresDateFormats($cookie)
+    {
+        $this->assertEquals(1596185377, Cookie::fromString($cookie)->getExpiresTime());
+    }
+
+    public function getExpireCookieStrings()
+    {
+        return array(
+            array('foo=bar; expires=Fri, 31-Jul-2020 08:49:37 GMT'),
+            array('foo=bar; expires=Fri, 31 Jul 2020 08:49:37 GMT'),
+            array('foo=bar; expires=Fri, 31-07-2020 08:49:37 GMT'),
+            array('foo=bar; expires=Fri, 31-07-20 08:49:37 GMT'),
+            array('foo=bar; expires=Friday, 31-Jul-20 08:49:37 GMT'),
+            array('foo=bar; expires=Fri Jul 31 08:49:37 2020'),
+            array('foo=bar; expires=\'Fri Jul 31 08:49:37 2020\''),
+            array('foo=bar; expires=Friday July 31st 2020, 08:49:37 GMT'),
+        );
+    }
+
+    public function testFromStringWithCapitalization()
+    {
+        $this->assertEquals('Foo=Bar; path=/', (string) Cookie::fromString('Foo=Bar'));
+        $this->assertEquals('foo=bar; expires=Fri, 31 Dec 2010 23:59:59 GMT; path=/', (string) Cookie::fromString('foo=bar; Expires=Fri, 31 Dec 2010 23:59:59 GMT'));
+        $this->assertEquals('foo=bar; domain=www.example.org; path=/; httponly', (string) Cookie::fromString('foo=bar; DOMAIN=www.example.org; HttpOnly'));
+    }
+
+    public function testFromStringWithUrl()
+    {
+        $this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar', 'http://www.example.com/'));
+        $this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar', 'http://www.example.com'));
+        $this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar', 'http://www.example.com?foo'));
+        $this->assertEquals('foo=bar; domain=www.example.com; path=/foo', (string) Cookie::FromString('foo=bar', 'http://www.example.com/foo/bar'));
+        $this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar; path=/', 'http://www.example.com/foo/bar'));
+        $this->assertEquals('foo=bar; domain=www.myotherexample.com; path=/', (string) Cookie::FromString('foo=bar; domain=www.myotherexample.com', 'http://www.example.com/'));
+    }
+
+    public function testFromStringThrowsAnExceptionIfCookieIsNotValid()
+    {
+        $this->setExpectedException('InvalidArgumentException');
+        Cookie::FromString('foo');
+    }
+
+    public function testFromStringThrowsAnExceptionIfCookieDateIsNotValid()
+    {
+        $this->setExpectedException('InvalidArgumentException');
+        Cookie::FromString('foo=bar; expires=Flursday July 31st 2020, 08:49:37 GMT');
+    }
+
+    public function testFromStringThrowsAnExceptionIfUrlIsNotValid()
+    {
+        $this->setExpectedException('InvalidArgumentException');
+        Cookie::FromString('foo=bar', 'foobar');
+    }
+
+    public function testGetName()
+    {
+        $cookie = new Cookie('foo', 'bar');
+        $this->assertEquals('foo', $cookie->getName(), '->getName() returns the cookie name');
+    }
+
+    public function testGetValue()
+    {
+        $cookie = new Cookie('foo', 'bar');
+        $this->assertEquals('bar', $cookie->getValue(), '->getValue() returns the cookie value');
+
+        $cookie = new Cookie('foo', 'bar%3Dbaz', null, '/', '', false, true, true); // raw value
+        $this->assertEquals('bar=baz', $cookie->getValue(), '->getValue() returns the urldecoded cookie value');
+    }
+
+    public function testGetRawValue()
+    {
+        $cookie = new Cookie('foo', 'bar=baz'); // decoded value
+        $this->assertEquals('bar%3Dbaz', $cookie->getRawValue(), '->getRawValue() returns the urlencoded cookie value');
+        $cookie = new Cookie('foo', 'bar%3Dbaz', null, '/', '', false, true, true); // raw value
+        $this->assertEquals('bar%3Dbaz', $cookie->getRawValue(), '->getRawValue() returns the non-urldecoded cookie value');
+    }
+
+    public function testGetPath()
+    {
+        $cookie = new Cookie('foo', 'bar', 0);
+        $this->assertEquals('/', $cookie->getPath(), '->getPath() returns / is no path is defined');
+
+        $cookie = new Cookie('foo', 'bar', 0, '/foo');
+        $this->assertEquals('/foo', $cookie->getPath(), '->getPath() returns the cookie path');
+    }
+
+    public function testGetDomain()
+    {
+        $cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com');
+        $this->assertEquals('foo.com', $cookie->getDomain(), '->getDomain() returns the cookie domain');
+    }
+
+    public function testIsSecure()
+    {
+        $cookie = new Cookie('foo', 'bar');
+        $this->assertFalse($cookie->isSecure(), '->isSecure() returns false if not defined');
+
+        $cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com', true);
+        $this->assertTrue($cookie->isSecure(), '->isSecure() returns the cookie secure flag');
+    }
+
+    public function testIsHttponly()
+    {
+        $cookie = new Cookie('foo', 'bar');
+        $this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns false if not defined');
+
+        $cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com', false, true);
+        $this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns the cookie httponly flag');
+    }
+
+    public function testGetExpiresTime()
+    {
+        $cookie = new Cookie('foo', 'bar');
+        $this->assertNull($cookie->getExpiresTime(), '->getExpiresTime() returns the expires time');
+
+        $cookie = new Cookie('foo', 'bar', $time = time() - 86400);
+        $this->assertEquals($time, $cookie->getExpiresTime(), '->getExpiresTime() returns the expires time');
+    }
+
+    public function testIsExpired()
+    {
+        $cookie = new Cookie('foo', 'bar');
+        $this->assertFalse($cookie->isExpired(), '->isExpired() returns false when the cookie never expires (null as expires time)');
+
+        $cookie = new Cookie('foo', 'bar', time() - 86400);
+        $this->assertTrue($cookie->isExpired(), '->isExpired() returns true when the cookie is expired');
+
+        $cookie = new Cookie('foo', 'bar', 0);
+        $this->assertFalse($cookie->isExpired());
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/HistoryTest.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/HistoryTest.php
new file mode 100644
index 0000000..882b730
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/HistoryTest.php
@@ -0,0 +1,101 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit\Tests;
+
+use Symfony\Component\BrowserKit\History;
+use Symfony\Component\BrowserKit\Request;
+
+class HistoryTest extends \PHPUnit_Framework_TestCase
+{
+    public function testAdd()
+    {
+        $history = new History();
+        $history->add(new Request('http://www.example1.com/', 'get'));
+        $this->assertSame('http://www.example1.com/', $history->current()->getUri(), '->add() adds a request to the history');
+
+        $history->add(new Request('http://www.example2.com/', 'get'));
+        $this->assertSame('http://www.example2.com/', $history->current()->getUri(), '->add() adds a request to the history');
+
+        $history->add(new Request('http://www.example3.com/', 'get'));
+        $history->back();
+        $history->add(new Request('http://www.example4.com/', 'get'));
+        $this->assertSame('http://www.example4.com/', $history->current()->getUri(), '->add() adds a request to the history');
+
+        $history->back();
+        $this->assertSame('http://www.example2.com/', $history->current()->getUri(), '->add() adds a request to the history');
+    }
+
+    public function testClearIsEmpty()
+    {
+        $history = new History();
+        $history->add(new Request('http://www.example.com/', 'get'));
+
+        $this->assertFalse($history->isEmpty(), '->isEmpty() returns false if the history is not empty');
+
+        $history->clear();
+
+        $this->assertTrue($history->isEmpty(), '->isEmpty() true if the history is empty');
+    }
+
+    public function testCurrent()
+    {
+        $history = new History();
+
+        try {
+            $history->current();
+            $this->fail('->current() throws a \LogicException if the history is empty');
+        } catch (\Exception $e) {
+            $this->assertInstanceof('LogicException', $e, '->current() throws a \LogicException if the history is empty');
+        }
+
+        $history->add(new Request('http://www.example.com/', 'get'));
+
+        $this->assertSame('http://www.example.com/', $history->current()->getUri(), '->current() returns the current request in the history');
+    }
+
+    public function testBack()
+    {
+        $history = new History();
+        $history->add(new Request('http://www.example.com/', 'get'));
+
+        try {
+            $history->back();
+            $this->fail('->back() throws a \LogicException if the history is already on the first page');
+        } catch (\Exception $e) {
+            $this->assertInstanceof('LogicException', $e, '->current() throws a \LogicException if the history is already on the first page');
+        }
+
+        $history->add(new Request('http://www.example1.com/', 'get'));
+        $history->back();
+
+        $this->assertSame('http://www.example.com/', $history->current()->getUri(), '->back() returns the previous request in the history');
+    }
+
+    public function testForward()
+    {
+        $history = new History();
+        $history->add(new Request('http://www.example.com/', 'get'));
+        $history->add(new Request('http://www.example1.com/', 'get'));
+
+        try {
+            $history->forward();
+            $this->fail('->forward() throws a \LogicException if the history is already on the last page');
+        } catch (\Exception $e) {
+            $this->assertInstanceof('LogicException', $e, '->forward() throws a \LogicException if the history is already on the last page');
+        }
+
+        $history->back();
+        $history->forward();
+
+        $this->assertSame('http://www.example1.com/', $history->current()->getUri(), '->forward() returns the next request in the history');
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/RequestTest.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/RequestTest.php
new file mode 100644
index 0000000..b75b5fb
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/RequestTest.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit\Tests;
+
+use Symfony\Component\BrowserKit\Request;
+
+class RequestTest extends \PHPUnit_Framework_TestCase
+{
+    public function testGetUri()
+    {
+        $request = new Request('http://www.example.com/', 'get');
+        $this->assertEquals('http://www.example.com/', $request->getUri(), '->getUri() returns the URI of the request');
+    }
+
+    public function testGetMethod()
+    {
+        $request = new Request('http://www.example.com/', 'get');
+        $this->assertEquals('get', $request->getMethod(), '->getMethod() returns the method of the request');
+    }
+
+    public function testGetParameters()
+    {
+        $request = new Request('http://www.example.com/', 'get', array('foo' => 'bar'));
+        $this->assertEquals(array('foo' => 'bar'), $request->getParameters(), '->getParameters() returns the parameters of the request');
+    }
+
+    public function testGetFiles()
+    {
+        $request = new Request('http://www.example.com/', 'get', array(), array('foo' => 'bar'));
+        $this->assertEquals(array('foo' => 'bar'), $request->getFiles(), '->getFiles() returns the uploaded files of the request');
+    }
+
+    public function testGetCookies()
+    {
+        $request = new Request('http://www.example.com/', 'get', array(), array(), array('foo' => 'bar'));
+        $this->assertEquals(array('foo' => 'bar'), $request->getCookies(), '->getCookies() returns the cookies of the request');
+    }
+
+    public function testGetServer()
+    {
+        $request = new Request('http://www.example.com/', 'get', array(), array(), array(), array('foo' => 'bar'));
+        $this->assertEquals(array('foo' => 'bar'), $request->getServer(), '->getServer() returns the server parameters of the request');
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/ResponseTest.php b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/ResponseTest.php
new file mode 100644
index 0000000..bfe3cd5
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Tests/ResponseTest.php
@@ -0,0 +1,76 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\BrowserKit\Tests;
+
+use Symfony\Component\BrowserKit\Response;
+
+class ResponseTest extends \PHPUnit_Framework_TestCase
+{
+    public function testGetUri()
+    {
+        $response = new Response('foo');
+        $this->assertEquals('foo', $response->getContent(), '->getContent() returns the content of the response');
+    }
+
+    public function testGetStatus()
+    {
+        $response = new Response('foo', 304);
+        $this->assertEquals('304', $response->getStatus(), '->getStatus() returns the status of the response');
+    }
+
+    public function testGetHeaders()
+    {
+        $response = new Response('foo', 200, array('foo' => 'bar'));
+        $this->assertEquals(array('foo' => 'bar'), $response->getHeaders(), '->getHeaders() returns the headers of the response');
+    }
+
+    public function testGetHeader()
+    {
+        $response = new Response('foo', 200, array(
+            'Content-Type' => 'text/html',
+            'Set-Cookie' => array('foo=bar', 'bar=foo'),
+        ));
+
+        $this->assertEquals('text/html', $response->getHeader('Content-Type'), '->getHeader() returns a header of the response');
+        $this->assertEquals('text/html', $response->getHeader('content-type'), '->getHeader() returns a header of the response');
+        $this->assertEquals('text/html', $response->getHeader('content_type'), '->getHeader() returns a header of the response');
+        $this->assertEquals('foo=bar', $response->getHeader('Set-Cookie'), '->getHeader() returns the first header value');
+        $this->assertEquals(array('foo=bar', 'bar=foo'), $response->getHeader('Set-Cookie', false), '->getHeader() returns all header values if first is false');
+
+        $this->assertNull($response->getHeader('foo'), '->getHeader() returns null if the header is not defined');
+        $this->assertEquals(array(), $response->getHeader('foo', false), '->getHeader() returns an empty array if the header is not defined and first is set to false');
+    }
+
+    public function testMagicToString()
+    {
+        $response = new Response('foo', 304, array('foo' => 'bar'));
+
+        $this->assertEquals("foo: bar\n\nfoo", $response->__toString(), '->__toString() returns the headers and the content as a string');
+    }
+
+    public function testMagicToStringWithMultipleSetCookieHeader()
+    {
+        $headers = array(
+            'content-type' => 'text/html; charset=utf-8',
+            'set-cookie' => array('foo=bar', 'bar=foo'),
+        );
+
+        $expected = 'content-type: text/html; charset=utf-8'."\n";
+        $expected .= 'set-cookie: foo=bar'."\n";
+        $expected .= 'set-cookie: bar=foo'."\n\n";
+        $expected .= 'foo';
+
+        $response = new Response('foo', 304, $headers);
+
+        $this->assertEquals($expected, $response->__toString(), '->__toString() returns the headers and the content as a string');
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/composer.json b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/composer.json
new file mode 100644
index 0000000..aa9f119
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/composer.json
@@ -0,0 +1,39 @@
+{
+    "name": "symfony/browser-kit",
+    "type": "library",
+    "description": "Symfony BrowserKit Component",
+    "keywords": [],
+    "homepage": "http://symfony.com",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Fabien Potencier",
+            "email": "fabien@symfony.com"
+        },
+        {
+            "name": "Symfony Community",
+            "homepage": "http://symfony.com/contributors"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.3",
+        "symfony/dom-crawler": "~2.0,>=2.0.5"
+    },
+    "require-dev": {
+        "symfony/process": "~2.0,>=2.0.5",
+        "symfony/css-selector": "~2.0,>=2.0.5"
+    },
+    "suggest": {
+        "symfony/process": ""
+    },
+    "autoload": {
+        "psr-0": { "Symfony\\Component\\BrowserKit\\": "" }
+    },
+    "target-dir": "Symfony/Component/BrowserKit",
+    "minimum-stability": "dev",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.6-dev"
+        }
+    }
+}
diff --git a/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/phpunit.xml.dist b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/phpunit.xml.dist
new file mode 100644
index 0000000..78f8da9
--- /dev/null
+++ b/core/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/phpunit.xml.dist
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
+         backupGlobals="false"
+         colors="true"
+         bootstrap="vendor/autoload.php"
+>
+    <php>
+        <!-- Silence E_USER_DEPRECATED (-16385 == -1 & ~E_USER_DEPRECATED) -->
+        <ini name="error_reporting" value="-16385"/>
+    </php>
+    <testsuites>
+        <testsuite name="Symfony BrowserKit Component Test Suite">
+            <directory>./Tests/</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory>./</directory>
+            <exclude>
+                <directory>./Resources</directory>
+                <directory>./Tests</directory>
+                <directory>./vendor</directory>
+            </exclude>
+        </whitelist>
+    </filter>
+</phpunit>
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/.gitignore b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/.gitignore
new file mode 100644
index 0000000..c49a5d8
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/CHANGELOG.md b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/CHANGELOG.md
new file mode 100644
index 0000000..48fd323
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/CHANGELOG.md
@@ -0,0 +1,45 @@
+CHANGELOG
+=========
+
+2.5.0
+-----
+
+* [BC BREAK] The default value for checkbox and radio inputs without a value attribute have changed
+  from '1' to 'on' to match the HTML specification.
+* [BC BREAK] The typehints on the `Link`, `Form` and `FormField` classes have been changed from
+  `\DOMNode` to `DOMElement`. Using any other type of `DOMNode` was triggering fatal errors in previous
+  versions. Code extending these classes will need to update the typehints when overwriting these methods.
+
+2.4.0
+-----
+
+ * `Crawler::addXmlContent()` removes the default document namespace again if it's an only namespace.
+ * added support for automatic discovery and explicit registration of document
+   namespaces for `Crawler::filterXPath()` and `Crawler::filter()`
+ * improved content type guessing in `Crawler::addContent()`
+ * [BC BREAK] `Crawler::addXmlContent()` no longer removes the default document
+   namespace
+
+2.3.0
+-----
+
+ * added Crawler::html()
+ * [BC BREAK] Crawler::each() and Crawler::reduce() now return Crawler instances instead of DomElement instances
+ * added schema relative URL support to links
+ * added support for HTML5 'form' attribute
+
+2.2.0
+-----
+
+ * added a way to set raw path to the file in FileFormField - necessary for
+   simulating HTTP requests
+
+2.1.0
+-----
+
+ * added support for the HTTP PATCH method
+ * refactored the Form class internals to support multi-dimensional fields
+   (the public API is backward compatible)
+ * added a way to get parsing errors for Crawler::addHtmlContent() and
+   Crawler::addXmlContent() via libxml functions
+ * added support for submitting a form without a submit button
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Crawler.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Crawler.php
new file mode 100644
index 0000000..9471d54
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Crawler.php
@@ -0,0 +1,1035 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler;
+
+use Symfony\Component\CssSelector\CssSelector;
+
+/**
+ * Crawler eases navigation of a list of \DOMElement objects.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Crawler extends \SplObjectStorage
+{
+    /**
+     * @var string The current URI
+     */
+    protected $uri;
+
+    /**
+     * @var string The default namespace prefix to be used with XPath and CSS expressions
+     */
+    private $defaultNamespacePrefix = 'default';
+
+    /**
+     * @var array A map of manually registered namespaces
+     */
+    private $namespaces = array();
+
+    /**
+     * @var string The base href value
+     */
+    private $baseHref;
+
+    /**
+     * Constructor.
+     *
+     * @param mixed  $node A Node to use as the base for the crawling
+     * @param string $currentUri The current URI
+     * @param string $baseHref The base href value
+     * @api
+     */
+    public function __construct($node = null, $currentUri = null, $baseHref = null)
+    {
+        $this->uri = $currentUri;
+        $this->baseHref = $baseHref ?: $currentUri;
+
+        $this->add($node);
+    }
+
+    /**
+     * Removes all the nodes.
+     *
+     * @api
+     */
+    public function clear()
+    {
+        $this->removeAll($this);
+    }
+
+    /**
+     * Adds a node to the current list of nodes.
+     *
+     * This method uses the appropriate specialized add*() method based
+     * on the type of the argument.
+     *
+     * @param \DOMNodeList|\DOMNode|array|string|null $node A node
+     *
+     * @throws \InvalidArgumentException When node is not the expected type.
+     *
+     * @api
+     */
+    public function add($node)
+    {
+        if ($node instanceof \DOMNodeList) {
+            $this->addNodeList($node);
+        } elseif ($node instanceof \DOMNode) {
+            $this->addNode($node);
+        } elseif (is_array($node)) {
+            $this->addNodes($node);
+        } elseif (is_string($node)) {
+            $this->addContent($node);
+        } elseif (null !== $node) {
+            throw new \InvalidArgumentException(sprintf('Expecting a DOMNodeList or DOMNode instance, an array, a string, or null, but got "%s".', is_object($node) ? get_class($node) : gettype($node)));
+        }
+    }
+
+    /**
+     * Adds HTML/XML content.
+     *
+     * If the charset is not set via the content type, it is assumed
+     * to be ISO-8859-1, which is the default charset defined by the
+     * HTTP 1.1 specification.
+     *
+     * @param string      $content A string to parse as HTML/XML
+     * @param null|string $type    The content type of the string
+     */
+    public function addContent($content, $type = null)
+    {
+        if (empty($type)) {
+            $type = 0 === strpos($content, '<?xml') ? 'application/xml' : 'text/html';
+        }
+
+        // DOM only for HTML/XML content
+        if (!preg_match('/(x|ht)ml/i', $type, $xmlMatches)) {
+            return;
+        }
+
+        $charset = null;
+        if (false !== $pos = stripos($type, 'charset=')) {
+            $charset = substr($type, $pos + 8);
+            if (false !== $pos = strpos($charset, ';')) {
+                $charset = substr($charset, 0, $pos);
+            }
+        }
+
+        // http://www.w3.org/TR/encoding/#encodings
+        // http://www.w3.org/TR/REC-xml/#NT-EncName
+        if (null === $charset &&
+            preg_match('/\<meta[^\>]+charset *= *["\']?([a-zA-Z\-0-9_:.]+)/i', $content, $matches)) {
+            $charset = $matches[1];
+        }
+
+        if (null === $charset) {
+            $charset = 'ISO-8859-1';
+        }
+
+        if ('x' === $xmlMatches[1]) {
+            $this->addXmlContent($content, $charset);
+        } else {
+            $this->addHtmlContent($content, $charset);
+        }
+    }
+
+    /**
+     * Adds an HTML content to the list of nodes.
+     *
+     * The libxml errors are disabled when the content is parsed.
+     *
+     * If you want to get parsing errors, be sure to enable
+     * internal errors via libxml_use_internal_errors(true)
+     * and then, get the errors via libxml_get_errors(). Be
+     * sure to clear errors with libxml_clear_errors() afterward.
+     *
+     * @param string $content The HTML content
+     * @param string $charset The charset
+     *
+     * @api
+     */
+    public function addHtmlContent($content, $charset = 'UTF-8')
+    {
+        $internalErrors = libxml_use_internal_errors(true);
+        $disableEntities = libxml_disable_entity_loader(true);
+
+        $dom = new \DOMDocument('1.0', $charset);
+        $dom->validateOnParse = true;
+
+        if (function_exists('mb_convert_encoding')) {
+            $hasError = false;
+            set_error_handler(function () use (&$hasError) {
+                $hasError = true;
+            });
+            $tmpContent = @mb_convert_encoding($content, 'HTML-ENTITIES', $charset);
+
+            restore_error_handler();
+
+            if (!$hasError) {
+                $content = $tmpContent;
+            }
+        }
+
+        if ('' !== trim($content)) {
+            @$dom->loadHTML($content);
+        }
+
+        libxml_use_internal_errors($internalErrors);
+        libxml_disable_entity_loader($disableEntities);
+
+        $this->addDocument($dom);
+
+        $base = $this->filterRelativeXPath('descendant-or-self::base')->extract(array('href'));
+
+        $baseHref = current($base);
+        if (count($base) && !empty($baseHref)) {
+            if ($this->baseHref) {
+                $linkNode = $dom->createElement('a');
+                $linkNode->setAttribute('href', $baseHref);
+                $link = new Link($linkNode, $this->baseHref);
+                $this->baseHref = $link->getUri();
+            } else {
+                $this->baseHref = $baseHref;
+            }
+        }
+    }
+
+    /**
+     * Adds an XML content to the list of nodes.
+     *
+     * The libxml errors are disabled when the content is parsed.
+     *
+     * If you want to get parsing errors, be sure to enable
+     * internal errors via libxml_use_internal_errors(true)
+     * and then, get the errors via libxml_get_errors(). Be
+     * sure to clear errors with libxml_clear_errors() afterward.
+     *
+     * @param string $content The XML content
+     * @param string $charset The charset
+     *
+     * @api
+     */
+    public function addXmlContent($content, $charset = 'UTF-8')
+    {
+        // remove the default namespace if it's the only namespace to make XPath expressions simpler
+        if (!preg_match('/xmlns:/', $content)) {
+            $content = str_replace('xmlns', 'ns', $content);
+        }
+
+        $internalErrors = libxml_use_internal_errors(true);
+        $disableEntities = libxml_disable_entity_loader(true);
+
+        $dom = new \DOMDocument('1.0', $charset);
+        $dom->validateOnParse = true;
+
+        if ('' !== trim($content)) {
+            @$dom->loadXML($content, LIBXML_NONET);
+        }
+
+        libxml_use_internal_errors($internalErrors);
+        libxml_disable_entity_loader($disableEntities);
+
+        $this->addDocument($dom);
+    }
+
+    /**
+     * Adds a \DOMDocument to the list of nodes.
+     *
+     * @param \DOMDocument $dom A \DOMDocument instance
+     *
+     * @api
+     */
+    public function addDocument(\DOMDocument $dom)
+    {
+        if ($dom->documentElement) {
+            $this->addNode($dom->documentElement);
+        }
+    }
+
+    /**
+     * Adds a \DOMNodeList to the list of nodes.
+     *
+     * @param \DOMNodeList $nodes A \DOMNodeList instance
+     *
+     * @api
+     */
+    public function addNodeList(\DOMNodeList $nodes)
+    {
+        foreach ($nodes as $node) {
+            if ($node instanceof \DOMNode) {
+                $this->addNode($node);
+            }
+        }
+    }
+
+    /**
+     * Adds an array of \DOMNode instances to the list of nodes.
+     *
+     * @param \DOMNode[] $nodes An array of \DOMNode instances
+     *
+     * @api
+     */
+    public function addNodes(array $nodes)
+    {
+        foreach ($nodes as $node) {
+            $this->add($node);
+        }
+    }
+
+    /**
+     * Adds a \DOMNode instance to the list of nodes.
+     *
+     * @param \DOMNode $node A \DOMNode instance
+     *
+     * @api
+     */
+    public function addNode(\DOMNode $node)
+    {
+        if ($node instanceof \DOMDocument) {
+            $this->attach($node->documentElement);
+        } else {
+            $this->attach($node);
+        }
+    }
+
+    /**
+     * Returns a node given its position in the node list.
+     *
+     * @param int $position The position
+     *
+     * @return Crawler A new instance of the Crawler with the selected node, or an empty Crawler if it does not exist.
+     *
+     * @api
+     */
+    public function eq($position)
+    {
+        foreach ($this as $i => $node) {
+            if ($i == $position) {
+                return new static($node, $this->uri, $this->baseHref);
+            }
+        }
+
+        return new static(null, $this->uri, $this->baseHref);
+    }
+
+    /**
+     * Calls an anonymous function on each node of the list.
+     *
+     * The anonymous function receives the position and the node wrapped
+     * in a Crawler instance as arguments.
+     *
+     * Example:
+     *
+     *     $crawler->filter('h1')->each(function ($node, $i) {
+     *         return $node->text();
+     *     });
+     *
+     * @param \Closure $closure An anonymous function
+     *
+     * @return array An array of values returned by the anonymous function
+     *
+     * @api
+     */
+    public function each(\Closure $closure)
+    {
+        $data = array();
+        foreach ($this as $i => $node) {
+            $data[] = $closure(new static($node, $this->uri, $this->baseHref), $i);
+        }
+
+        return $data;
+    }
+
+    /**
+     * Slices the list of nodes by $offset and $length.
+     *
+     * @param int $offset
+     * @param int $length
+     *
+     * @return Crawler A Crawler instance with the sliced nodes
+     */
+    public function slice($offset = 0, $length = -1)
+    {
+        return new static(iterator_to_array(new \LimitIterator($this, $offset, $length)), $this->uri);
+    }
+
+    /**
+     * Reduces the list of nodes by calling an anonymous function.
+     *
+     * To remove a node from the list, the anonymous function must return false.
+     *
+     * @param \Closure $closure An anonymous function
+     *
+     * @return Crawler A Crawler instance with the selected nodes.
+     *
+     * @api
+     */
+    public function reduce(\Closure $closure)
+    {
+        $nodes = array();
+        foreach ($this as $i => $node) {
+            if (false !== $closure(new static($node, $this->uri, $this->baseHref), $i)) {
+                $nodes[] = $node;
+            }
+        }
+
+        return new static($nodes, $this->uri, $this->baseHref);
+    }
+
+    /**
+     * Returns the first node of the current selection.
+     *
+     * @return Crawler A Crawler instance with the first selected node
+     *
+     * @api
+     */
+    public function first()
+    {
+        return $this->eq(0);
+    }
+
+    /**
+     * Returns the last node of the current selection.
+     *
+     * @return Crawler A Crawler instance with the last selected node
+     *
+     * @api
+     */
+    public function last()
+    {
+        return $this->eq(count($this) - 1);
+    }
+
+    /**
+     * Returns the siblings nodes of the current selection.
+     *
+     * @return Crawler A Crawler instance with the sibling nodes
+     *
+     * @throws \InvalidArgumentException When current node is empty
+     *
+     * @api
+     */
+    public function siblings()
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        return new static($this->sibling($this->getNode(0)->parentNode->firstChild), $this->uri, $this->baseHref);
+    }
+
+    /**
+     * Returns the next siblings nodes of the current selection.
+     *
+     * @return Crawler A Crawler instance with the next sibling nodes
+     *
+     * @throws \InvalidArgumentException When current node is empty
+     *
+     * @api
+     */
+    public function nextAll()
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        return new static($this->sibling($this->getNode(0)), $this->uri, $this->baseHref);
+    }
+
+    /**
+     * Returns the previous sibling nodes of the current selection.
+     *
+     * @return Crawler A Crawler instance with the previous sibling nodes
+     *
+     * @throws \InvalidArgumentException
+     *
+     * @api
+     */
+    public function previousAll()
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        return new static($this->sibling($this->getNode(0), 'previousSibling'), $this->uri, $this->baseHref);
+    }
+
+    /**
+     * Returns the parents nodes of the current selection.
+     *
+     * @return Crawler A Crawler instance with the parents nodes of the current selection
+     *
+     * @throws \InvalidArgumentException When current node is empty
+     *
+     * @api
+     */
+    public function parents()
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        $node = $this->getNode(0);
+        $nodes = array();
+
+        while ($node = $node->parentNode) {
+            if (1 === $node->nodeType) {
+                $nodes[] = $node;
+            }
+        }
+
+        return new static($nodes, $this->uri, $this->baseHref);
+    }
+
+    /**
+     * Returns the children nodes of the current selection.
+     *
+     * @return Crawler A Crawler instance with the children nodes
+     *
+     * @throws \InvalidArgumentException When current node is empty
+     *
+     * @api
+     */
+    public function children()
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        $node = $this->getNode(0)->firstChild;
+
+        return new static($node ? $this->sibling($node) : array(), $this->uri, $this->baseHref);
+    }
+
+    /**
+     * Returns the attribute value of the first node of the list.
+     *
+     * @param string $attribute The attribute name
+     *
+     * @return string|null The attribute value or null if the attribute does not exist
+     *
+     * @throws \InvalidArgumentException When current node is empty
+     *
+     * @api
+     */
+    public function attr($attribute)
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        $node = $this->getNode(0);
+
+        return $node->hasAttribute($attribute) ? $node->getAttribute($attribute) : null;
+    }
+
+    /**
+     * Returns the node name of the first node of the list.
+     *
+     * @return string The node name
+     *
+     * @throws \InvalidArgumentException When current node is empty
+     */
+    public function nodeName()
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        return $this->getNode(0)->nodeName;
+    }
+
+    /**
+     * Returns the node value of the first node of the list.
+     *
+     * @return string The node value
+     *
+     * @throws \InvalidArgumentException When current node is empty
+     *
+     * @api
+     */
+    public function text()
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        return $this->getNode(0)->nodeValue;
+    }
+
+    /**
+     * Returns the first node of the list as HTML.
+     *
+     * @return string The node html
+     *
+     * @throws \InvalidArgumentException When current node is empty
+     */
+    public function html()
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        $html = '';
+        foreach ($this->getNode(0)->childNodes as $child) {
+            if (PHP_VERSION_ID >= 50306) {
+                // node parameter was added to the saveHTML() method in PHP 5.3.6
+                // @see http://php.net/manual/en/domdocument.savehtml.php
+                $html .= $child->ownerDocument->saveHTML($child);
+            } else {
+                $document = new \DOMDocument('1.0', 'UTF-8');
+                $document->appendChild($document->importNode($child, true));
+                $html .= rtrim($document->saveHTML());
+            }
+        }
+
+        return $html;
+    }
+
+    /**
+     * Extracts information from the list of nodes.
+     *
+     * You can extract attributes or/and the node value (_text).
+     *
+     * Example:
+     *
+     * $crawler->filter('h1 a')->extract(array('_text', 'href'));
+     *
+     * @param array $attributes An array of attributes
+     *
+     * @return array An array of extracted values
+     *
+     * @api
+     */
+    public function extract($attributes)
+    {
+        $attributes = (array) $attributes;
+        $count = count($attributes);
+
+        $data = array();
+        foreach ($this as $node) {
+            $elements = array();
+            foreach ($attributes as $attribute) {
+                if ('_text' === $attribute) {
+                    $elements[] = $node->nodeValue;
+                } else {
+                    $elements[] = $node->getAttribute($attribute);
+                }
+            }
+
+            $data[] = $count > 1 ? $elements : $elements[0];
+        }
+
+        return $data;
+    }
+
+    /**
+     * Filters the list of nodes with an XPath expression.
+     *
+     * The XPath expression is evaluated in the context of the crawler, which
+     * is considered as a fake parent of the elements inside it.
+     * This means that a child selector "div" or "./div" will match only
+     * the div elements of the current crawler, not their children.
+     *
+     * @param string $xpath An XPath expression
+     *
+     * @return Crawler A new instance of Crawler with the filtered list of nodes
+     *
+     * @api
+     */
+    public function filterXPath($xpath)
+    {
+        $xpath = $this->relativize($xpath);
+
+        // If we dropped all expressions in the XPath while preparing it, there would be no match
+        if ('' === $xpath) {
+            return new static(null, $this->uri, $this->baseHref);
+        }
+
+        return $this->filterRelativeXPath($xpath);
+    }
+
+    /**
+     * Filters the list of nodes with a CSS selector.
+     *
+     * This method only works if you have installed the CssSelector Symfony Component.
+     *
+     * @param string $selector A CSS selector
+     *
+     * @return Crawler A new instance of Crawler with the filtered list of nodes
+     *
+     * @throws \RuntimeException if the CssSelector Component is not available
+     *
+     * @api
+     */
+    public function filter($selector)
+    {
+        if (!class_exists('Symfony\\Component\\CssSelector\\CssSelector')) {
+            throw new \RuntimeException('Unable to filter with a CSS selector as the Symfony CssSelector is not installed (you can use filterXPath instead).');
+        }
+
+        // The CssSelector already prefixes the selector with descendant-or-self::
+        return $this->filterRelativeXPath(CssSelector::toXPath($selector));
+    }
+
+    /**
+     * Selects links by name or alt value for clickable images.
+     *
+     * @param string $value The link text
+     *
+     * @return Crawler A new instance of Crawler with the filtered list of nodes
+     *
+     * @api
+     */
+    public function selectLink($value)
+    {
+        $xpath = sprintf('descendant-or-self::a[contains(concat(\' \', normalize-space(string(.)), \' \'), %s) ', static::xpathLiteral(' '.$value.' ')).
+                            sprintf('or ./img[contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)]]', static::xpathLiteral(' '.$value.' '));
+
+        return $this->filterRelativeXPath($xpath);
+    }
+
+    /**
+     * Selects a button by name or alt value for images.
+     *
+     * @param string $value The button text
+     *
+     * @return Crawler A new instance of Crawler with the filtered list of nodes
+     *
+     * @api
+     */
+    public function selectButton($value)
+    {
+        $translate = 'translate(@type, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")';
+        $xpath = sprintf('descendant-or-self::input[((contains(%s, "submit") or contains(%s, "button")) and contains(concat(\' \', normalize-space(string(@value)), \' \'), %s)) ', $translate, $translate, static::xpathLiteral(' '.$value.' ')).
+                         sprintf('or (contains(%s, "image") and contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)) or @id=%s or @name=%s] ', $translate, static::xpathLiteral(' '.$value.' '), static::xpathLiteral($value), static::xpathLiteral($value)).
+                         sprintf('| descendant-or-self::button[contains(concat(\' \', normalize-space(string(.)), \' \'), %s) or @id=%s or @name=%s]', static::xpathLiteral(' '.$value.' '), static::xpathLiteral($value), static::xpathLiteral($value));
+
+        return $this->filterRelativeXPath($xpath);
+    }
+
+    /**
+     * Returns a Link object for the first node in the list.
+     *
+     * @param string $method The method for the link (get by default)
+     *
+     * @return Link A Link instance
+     *
+     * @throws \InvalidArgumentException If the current node list is empty
+     *
+     * @api
+     */
+    public function link($method = 'get')
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        $node = $this->getNode(0);
+
+        return new Link($node, $this->baseHref, $method);
+    }
+
+    /**
+     * Returns an array of Link objects for the nodes in the list.
+     *
+     * @return Link[] An array of Link instances
+     *
+     * @api
+     */
+    public function links()
+    {
+        $links = array();
+        foreach ($this as $node) {
+            $links[] = new Link($node, $this->baseHref, 'get');
+        }
+
+        return $links;
+    }
+
+    /**
+     * Returns a Form object for the first node in the list.
+     *
+     * @param array  $values An array of values for the form fields
+     * @param string $method The method for the form
+     *
+     * @return Form A Form instance
+     *
+     * @throws \InvalidArgumentException If the current node list is empty
+     *
+     * @api
+     */
+    public function form(array $values = null, $method = null)
+    {
+        if (!count($this)) {
+            throw new \InvalidArgumentException('The current node list is empty.');
+        }
+
+        $form = new Form($this->getNode(0), $this->uri, $method);
+
+        if (null !== $values) {
+            $form->setValues($values);
+        }
+
+        return $form;
+    }
+
+    /**
+     * Overloads a default namespace prefix to be used with XPath and CSS expressions.
+     *
+     * @param string $prefix
+     */
+    public function setDefaultNamespacePrefix($prefix)
+    {
+        $this->defaultNamespacePrefix = $prefix;
+    }
+
+    /**
+     * @param string $prefix
+     * @param string $namespace
+     */
+    public function registerNamespace($prefix, $namespace)
+    {
+        $this->namespaces[$prefix] = $namespace;
+    }
+
+    /**
+     * Converts string for XPath expressions.
+     *
+     * Escaped characters are: quotes (") and apostrophe (').
+     *
+     *  Examples:
+     *  <code>
+     *     echo Crawler::xpathLiteral('foo " bar');
+     *     //prints 'foo " bar'
+     *
+     *     echo Crawler::xpathLiteral("foo ' bar");
+     *     //prints "foo ' bar"
+     *
+     *     echo Crawler::xpathLiteral('a\'b"c');
+     *     //prints concat('a', "'", 'b"c')
+     *  </code>
+     *
+     * @param string $s String to be escaped
+     *
+     * @return string Converted string
+     */
+    public static function xpathLiteral($s)
+    {
+        if (false === strpos($s, "'")) {
+            return sprintf("'%s'", $s);
+        }
+
+        if (false === strpos($s, '"')) {
+            return sprintf('"%s"', $s);
+        }
+
+        $string = $s;
+        $parts = array();
+        while (true) {
+            if (false !== $pos = strpos($string, "'")) {
+                $parts[] = sprintf("'%s'", substr($string, 0, $pos));
+                $parts[] = "\"'\"";
+                $string = substr($string, $pos + 1);
+            } else {
+                $parts[] = "'$string'";
+                break;
+            }
+        }
+
+        return sprintf("concat(%s)", implode($parts, ', '));
+    }
+
+    /**
+     * Filters the list of nodes with an XPath expression.
+     *
+     * The XPath expression should already be processed to apply it in the context of each node.
+     *
+     * @param string $xpath
+     *
+     * @return Crawler
+     */
+    private function filterRelativeXPath($xpath)
+    {
+        $prefixes = $this->findNamespacePrefixes($xpath);
+
+        $crawler = new static(null, $this->uri, $this->baseHref);
+
+        foreach ($this as $node) {
+            $domxpath = $this->createDOMXPath($node->ownerDocument, $prefixes);
+            $crawler->add($domxpath->query($xpath, $node));
+        }
+
+        return $crawler;
+    }
+
+    /**
+     * Make the XPath relative to the current context.
+     *
+     * The returned XPath will match elements matching the XPath inside the current crawler
+     * when running in the context of a node of the crawler.
+     *
+     * @param string $xpath
+     *
+     * @return string
+     */
+    private function relativize($xpath)
+    {
+        $expressions = array();
+
+        $unionPattern = '/\|(?![^\[]*\])/';
+        // An expression which will never match to replace expressions which cannot match in the crawler
+        // We cannot simply drop
+        $nonMatchingExpression = 'a[name() = "b"]';
+
+        // Split any unions into individual expressions.
+        foreach (preg_split($unionPattern, $xpath) as $expression) {
+            $expression = trim($expression);
+            $parenthesis = '';
+
+            // If the union is inside some braces, we need to preserve the opening braces and apply
+            // the change only inside it.
+            if (preg_match('/^[\(\s*]+/', $expression, $matches)) {
+                $parenthesis = $matches[0];
+                $expression = substr($expression, strlen($parenthesis));
+            }
+
+            // BC for Symfony 2.4 and lower were elements were adding in a fake _root parent
+            if (0 === strpos($expression, '/_root/')) {
+                $expression = './'.substr($expression, 7);
+            } elseif (0 === strpos($expression, 'self::*/')) {
+                $expression = './'.substr($expression, 8);
+            }
+
+            // add prefix before absolute element selector
+            if (empty($expression)) {
+                $expression = $nonMatchingExpression;
+            } elseif (0 === strpos($expression, '//')) {
+                $expression = 'descendant-or-self::'.substr($expression, 2);
+            } elseif (0 === strpos($expression, './/')) {
+                $expression = 'descendant-or-self::'.substr($expression, 3);
+            } elseif (0 === strpos($expression, './')) {
+                $expression = 'self::'.substr($expression, 2);
+            } elseif (0 === strpos($expression, 'child::')) {
+                $expression = 'self::'.substr($expression, 7);
+            } elseif ('/' === $expression[0] || 0 === strpos($expression, 'self::')) {
+                // the only direct child in Symfony 2.4 and lower is _root, which is already handled previously
+                // so let's drop the expression entirely
+                $expression = $nonMatchingExpression;
+            } elseif ('.' === $expression[0]) {
+                // '.' is the fake root element in Symfony 2.4 and lower, which is excluded from results
+                $expression = $nonMatchingExpression;
+            } elseif (0 === strpos($expression, 'descendant::')) {
+                $expression = 'descendant-or-self::'.substr($expression, strlen('descendant::'));
+            } elseif (preg_match('/^(ancestor|ancestor-or-self|attribute|following|following-sibling|namespace|parent|preceding|preceding-sibling)::/', $expression)) {
+                // the fake root has no parent, preceding or following nodes and also no attributes (even no namespace attributes)
+                $expression = $nonMatchingExpression;
+            } elseif (0 !== strpos($expression, 'descendant-or-self::')) {
+                $expression = 'self::'.$expression;
+            }
+            $expressions[] = $parenthesis.$expression;
+        }
+
+        return implode(' | ', $expressions);
+    }
+
+    /**
+     * @param int $position
+     *
+     * @return \DOMElement|null
+     */
+    public function getNode($position)
+    {
+        foreach ($this as $i => $node) {
+            if ($i == $position) {
+                return $node;
+            }
+        }
+    }
+
+    /**
+     * @param \DOMElement $node
+     * @param string      $siblingDir
+     *
+     * @return array
+     */
+    protected function sibling($node, $siblingDir = 'nextSibling')
+    {
+        $nodes = array();
+
+        do {
+            if ($node !== $this->getNode(0) && $node->nodeType === 1) {
+                $nodes[] = $node;
+            }
+        } while ($node = $node->$siblingDir);
+
+        return $nodes;
+    }
+
+    /**
+     * @param \DOMDocument $document
+     * @param array        $prefixes
+     *
+     * @return \DOMXPath
+     *
+     * @throws \InvalidArgumentException
+     */
+    private function createDOMXPath(\DOMDocument $document, array $prefixes = array())
+    {
+        $domxpath = new \DOMXPath($document);
+
+        foreach ($prefixes as $prefix) {
+            $namespace = $this->discoverNamespace($domxpath, $prefix);
+            if (null !== $namespace) {
+                $domxpath->registerNamespace($prefix, $namespace);
+            }
+        }
+
+        return $domxpath;
+    }
+
+    /**
+     * @param \DOMXPath $domxpath
+     * @param string    $prefix
+     *
+     * @return string
+     *
+     * @throws \InvalidArgumentException
+     */
+    private function discoverNamespace(\DOMXPath $domxpath, $prefix)
+    {
+        if (isset($this->namespaces[$prefix])) {
+            return $this->namespaces[$prefix];
+        }
+
+        // ask for one namespace, otherwise we'd get a collection with an item for each node
+        $namespaces = $domxpath->query(sprintf('(//namespace::*[name()="%s"])[last()]', $this->defaultNamespacePrefix === $prefix ? '' : $prefix));
+
+        if ($node = $namespaces->item(0)) {
+            return $node->nodeValue;
+        }
+    }
+
+    /**
+     * @param $xpath
+     *
+     * @return array
+     */
+    private function findNamespacePrefixes($xpath)
+    {
+        if (preg_match_all('/(?P<prefix>[a-z_][a-z_0-9\-\.]*):[^"\/]/i', $xpath, $matches)) {
+            return array_unique($matches['prefix']);
+        }
+
+        return array();
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/ChoiceFormField.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/ChoiceFormField.php
new file mode 100644
index 0000000..ae7f4d1
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/ChoiceFormField.php
@@ -0,0 +1,327 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Field;
+
+/**
+ * ChoiceFormField represents a choice form field.
+ *
+ * It is constructed from a HTML select tag, or a HTML checkbox, or radio inputs.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class ChoiceFormField extends FormField
+{
+    /**
+     * @var string
+     */
+    private $type;
+    /**
+     * @var bool
+     */
+    private $multiple;
+    /**
+     * @var array
+     */
+    private $options;
+    /**
+     * @var bool
+     */
+    private $validationDisabled = false;
+
+    /**
+     * Returns true if the field should be included in the submitted values.
+     *
+     * @return bool true if the field should be included in the submitted values, false otherwise
+     */
+    public function hasValue()
+    {
+        // don't send a value for unchecked checkboxes
+        if (in_array($this->type, array('checkbox', 'radio')) && null === $this->value) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check if the current selected option is disabled.
+     *
+     * @return bool
+     */
+    public function isDisabled()
+    {
+        foreach ($this->options as $option) {
+            if ($option['value'] == $this->value && $option['disabled']) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Sets the value of the field.
+     *
+     * @param string $value The value of the field
+     *
+     * @api
+     */
+    public function select($value)
+    {
+        $this->setValue($value);
+    }
+
+    /**
+     * Ticks a checkbox.
+     *
+     * @throws \LogicException When the type provided is not correct
+     *
+     * @api
+     */
+    public function tick()
+    {
+        if ('checkbox' !== $this->type) {
+            throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type));
+        }
+
+        $this->setValue(true);
+    }
+
+    /**
+     * Ticks a checkbox.
+     *
+     * @throws \LogicException When the type provided is not correct
+     *
+     * @api
+     */
+    public function untick()
+    {
+        if ('checkbox' !== $this->type) {
+            throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type));
+        }
+
+        $this->setValue(false);
+    }
+
+    /**
+     * Sets the value of the field.
+     *
+     * @param string $value The value of the field
+     *
+     * @throws \InvalidArgumentException When value type provided is not correct
+     */
+    public function setValue($value)
+    {
+        if ('checkbox' === $this->type && false === $value) {
+            // uncheck
+            $this->value = null;
+        } elseif ('checkbox' === $this->type && true === $value) {
+            // check
+            $this->value = $this->options[0]['value'];
+        } else {
+            if (is_array($value)) {
+                if (!$this->multiple) {
+                    throw new \InvalidArgumentException(sprintf('The value for "%s" cannot be an array.', $this->name));
+                }
+
+                foreach ($value as $v) {
+                    if (!$this->containsOption($v, $this->options)) {
+                        throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $v, implode(', ', $this->availableOptionValues())));
+                    }
+                }
+            } elseif (!$this->containsOption($value, $this->options)) {
+                throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $value, implode(', ', $this->availableOptionValues())));
+            }
+
+            if ($this->multiple) {
+                $value = (array) $value;
+            }
+
+            if (is_array($value)) {
+                $this->value = $value;
+            } else {
+                parent::setValue($value);
+            }
+        }
+    }
+
+    /**
+     * Adds a choice to the current ones.
+     *
+     * This method should only be used internally.
+     *
+     * @param \DOMElement $node
+     *
+     * @throws \LogicException When choice provided is not multiple nor radio
+     */
+    public function addChoice(\DOMElement $node)
+    {
+        if (!$this->multiple && 'radio' !== $this->type) {
+            throw new \LogicException(sprintf('Unable to add a choice for "%s" as it is not multiple or is not a radio button.', $this->name));
+        }
+
+        $option = $this->buildOptionValue($node);
+        $this->options[] = $option;
+
+        if ($node->hasAttribute('checked')) {
+            $this->value = $option['value'];
+        }
+    }
+
+    /**
+     * Returns the type of the choice field (radio, select, or checkbox).
+     *
+     * @return string The type
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * Returns true if the field accepts multiple values.
+     *
+     * @return bool true if the field accepts multiple values, false otherwise
+     */
+    public function isMultiple()
+    {
+        return $this->multiple;
+    }
+
+    /**
+     * Initializes the form field.
+     *
+     * @throws \LogicException When node type is incorrect
+     */
+    protected function initialize()
+    {
+        if ('input' !== $this->node->nodeName && 'select' !== $this->node->nodeName) {
+            throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input or select tag (%s given).', $this->node->nodeName));
+        }
+
+        if ('input' === $this->node->nodeName && 'checkbox' !== strtolower($this->node->getAttribute('type')) && 'radio' !== strtolower($this->node->getAttribute('type'))) {
+            throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input tag with a type of checkbox or radio (given type is %s).', $this->node->getAttribute('type')));
+        }
+
+        $this->value = null;
+        $this->options = array();
+        $this->multiple = false;
+
+        if ('input' == $this->node->nodeName) {
+            $this->type = strtolower($this->node->getAttribute('type'));
+            $optionValue = $this->buildOptionValue($this->node);
+            $this->options[] = $optionValue;
+
+            if ($this->node->hasAttribute('checked')) {
+                $this->value = $optionValue['value'];
+            }
+        } else {
+            $this->type = 'select';
+            if ($this->node->hasAttribute('multiple')) {
+                $this->multiple = true;
+                $this->value = array();
+                $this->name = str_replace('[]', '', $this->name);
+            }
+
+            $found = false;
+            foreach ($this->xpath->query('descendant::option', $this->node) as $option) {
+                $optionValue = $this->buildOptionValue($option);
+                $this->options[] = $optionValue;
+
+                if ($option->hasAttribute('selected')) {
+                    $found = true;
+                    if ($this->multiple) {
+                        $this->value[] = $optionValue['value'];
+                    } else {
+                        $this->value = $optionValue['value'];
+                    }
+                }
+            }
+
+            // if no option is selected and if it is a simple select box, take the first option as the value
+            if (!$found && !$this->multiple && !empty($this->options)) {
+                $this->value = $this->options[0]['value'];
+            }
+        }
+    }
+
+    /**
+     * Returns option value with associated disabled flag.
+     *
+     * @param \DOMElement $node
+     *
+     * @return array
+     */
+    private function buildOptionValue(\DOMElement $node)
+    {
+        $option = array();
+
+        $defaultValue = (isset($node->nodeValue) && !empty($node->nodeValue)) ? $node->nodeValue : 'on';
+        $option['value'] = $node->hasAttribute('value') ? $node->getAttribute('value') : $defaultValue;
+        $option['disabled'] = $node->hasAttribute('disabled');
+
+        return $option;
+    }
+
+    /**
+     * Checks whether given value is in the existing options.
+     *
+     * @param string $optionValue
+     * @param array  $options
+     *
+     * @return bool
+     */
+    public function containsOption($optionValue, $options)
+    {
+        if ($this->validationDisabled) {
+            return true;
+        }
+
+        foreach ($options as $option) {
+            if ($option['value'] == $optionValue) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns list of available field options.
+     *
+     * @return array
+     */
+    public function availableOptionValues()
+    {
+        $values = array();
+
+        foreach ($this->options as $option) {
+            $values[] = $option['value'];
+        }
+
+        return $values;
+    }
+
+    /**
+     * Disables the internal validation of the field.
+     *
+     * @return self
+     */
+    public function disableValidation()
+    {
+        $this->validationDisabled = true;
+
+        return $this;
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/FileFormField.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/FileFormField.php
new file mode 100644
index 0000000..c3423b2
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/FileFormField.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Field;
+
+/**
+ * FileFormField represents a file form field (an HTML file input tag).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class FileFormField extends FormField
+{
+    /**
+     * Sets the PHP error code associated with the field.
+     *
+     * @param int $error The error code (one of UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, or UPLOAD_ERR_EXTENSION)
+     *
+     * @throws \InvalidArgumentException When error code doesn't exist
+     */
+    public function setErrorCode($error)
+    {
+        $codes = array(UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, UPLOAD_ERR_EXTENSION);
+        if (!in_array($error, $codes)) {
+            throw new \InvalidArgumentException(sprintf('The error code %s is not valid.', $error));
+        }
+
+        $this->value = array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => $error, 'size' => 0);
+    }
+
+    /**
+     * Sets the value of the field.
+     *
+     * @param string $value The value of the field
+     *
+     * @api
+     */
+    public function upload($value)
+    {
+        $this->setValue($value);
+    }
+
+    /**
+     * Sets the value of the field.
+     *
+     * @param string $value The value of the field
+     */
+    public function setValue($value)
+    {
+        if (null !== $value && is_readable($value)) {
+            $error = UPLOAD_ERR_OK;
+            $size = filesize($value);
+            $info = pathinfo($value);
+            $name = $info['basename'];
+
+            // copy to a tmp location
+            $tmp = sys_get_temp_dir().'/'.sha1(uniqid(mt_rand(), true));
+            if (array_key_exists('extension', $info)) {
+                $tmp .= '.'.$info['extension'];
+            }
+            if (is_file($tmp)) {
+                unlink($tmp);
+            }
+            copy($value, $tmp);
+            $value = $tmp;
+        } else {
+            $error = UPLOAD_ERR_NO_FILE;
+            $size = 0;
+            $name = '';
+            $value = '';
+        }
+
+        $this->value = array('name' => $name, 'type' => '', 'tmp_name' => $value, 'error' => $error, 'size' => $size);
+    }
+
+    /**
+     * Sets path to the file as string for simulating HTTP request.
+     *
+     * @param string $path The path to the file
+     */
+    public function setFilePath($path)
+    {
+        parent::setValue($path);
+    }
+
+    /**
+     * Initializes the form field.
+     *
+     * @throws \LogicException When node type is incorrect
+     */
+    protected function initialize()
+    {
+        if ('input' !== $this->node->nodeName) {
+            throw new \LogicException(sprintf('A FileFormField can only be created from an input tag (%s given).', $this->node->nodeName));
+        }
+
+        if ('file' !== strtolower($this->node->getAttribute('type'))) {
+            throw new \LogicException(sprintf('A FileFormField can only be created from an input tag with a type of file (given type is %s).', $this->node->getAttribute('type')));
+        }
+
+        $this->setValue(null);
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/FormField.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/FormField.php
new file mode 100644
index 0000000..5d70292
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/FormField.php
@@ -0,0 +1,116 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Field;
+
+/**
+ * FormField is the abstract class for all form fields.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class FormField
+{
+    /**
+     * @var \DOMElement
+     */
+    protected $node;
+    /**
+     * @var string
+     */
+    protected $name;
+    /**
+     * @var string
+     */
+    protected $value;
+    /**
+     * @var \DOMDocument
+     */
+    protected $document;
+    /**
+     * @var \DOMXPath
+     */
+    protected $xpath;
+    /**
+     * @var bool
+     */
+    protected $disabled;
+
+    /**
+     * Constructor.
+     *
+     * @param \DOMElement $node The node associated with this field
+     */
+    public function __construct(\DOMElement $node)
+    {
+        $this->node = $node;
+        $this->name = $node->getAttribute('name');
+        $this->xpath = new \DOMXPath($node->ownerDocument);
+
+        $this->initialize();
+    }
+
+    /**
+     * Returns the name of the field.
+     *
+     * @return string The name of the field
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Gets the value of the field.
+     *
+     * @return string|array The value of the field
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Sets the value of the field.
+     *
+     * @param string $value The value of the field
+     *
+     * @api
+     */
+    public function setValue($value)
+    {
+        $this->value = (string) $value;
+    }
+
+    /**
+     * Returns true if the field should be included in the submitted values.
+     *
+     * @return bool true if the field should be included in the submitted values, false otherwise
+     */
+    public function hasValue()
+    {
+        return true;
+    }
+
+    /**
+     * Check if the current field is disabled.
+     *
+     * @return bool
+     */
+    public function isDisabled()
+    {
+        return $this->node->hasAttribute('disabled');
+    }
+
+    /**
+     * Initializes the form field.
+     */
+    abstract protected function initialize();
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/InputFormField.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/InputFormField.php
new file mode 100644
index 0000000..b9bd0a4
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/InputFormField.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Field;
+
+/**
+ * InputFormField represents an input form field (an HTML input tag).
+ *
+ * For inputs with type of file, checkbox, or radio, there are other more
+ * specialized classes (cf. FileFormField and ChoiceFormField).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class InputFormField extends FormField
+{
+    /**
+     * Initializes the form field.
+     *
+     * @throws \LogicException When node type is incorrect
+     */
+    protected function initialize()
+    {
+        if ('input' !== $this->node->nodeName && 'button' !== $this->node->nodeName) {
+            throw new \LogicException(sprintf('An InputFormField can only be created from an input or button tag (%s given).', $this->node->nodeName));
+        }
+
+        if ('checkbox' === strtolower($this->node->getAttribute('type'))) {
+            throw new \LogicException('Checkboxes should be instances of ChoiceFormField.');
+        }
+
+        if ('file' === strtolower($this->node->getAttribute('type'))) {
+            throw new \LogicException('File inputs should be instances of FileFormField.');
+        }
+
+        $this->value = $this->node->getAttribute('value');
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/TextareaFormField.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/TextareaFormField.php
new file mode 100644
index 0000000..a14e707
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Field/TextareaFormField.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Field;
+
+/**
+ * TextareaFormField represents a textarea form field (an HTML textarea tag).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class TextareaFormField extends FormField
+{
+    /**
+     * Initializes the form field.
+     *
+     * @throws \LogicException When node type is incorrect
+     */
+    protected function initialize()
+    {
+        if ('textarea' !== $this->node->nodeName) {
+            throw new \LogicException(sprintf('A TextareaFormField can only be created from a textarea tag (%s given).', $this->node->nodeName));
+        }
+
+        $this->value = '';
+        foreach ($this->node->childNodes as $node) {
+            $this->value .= $node->wholeText;
+        }
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Form.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Form.php
new file mode 100644
index 0000000..528ad36
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Form.php
@@ -0,0 +1,479 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler;
+
+use Symfony\Component\DomCrawler\Field\ChoiceFormField;
+use Symfony\Component\DomCrawler\Field\FormField;
+
+/**
+ * Form represents an HTML form.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Form extends Link implements \ArrayAccess
+{
+    /**
+     * @var \DOMElement
+     */
+    private $button;
+
+    /**
+     * @var FormFieldRegistry
+     */
+    private $fields;
+
+    /**
+     * Constructor.
+     *
+     * @param \DOMElement $node       A \DOMElement instance
+     * @param string      $currentUri The URI of the page where the form is embedded
+     * @param string      $method     The method to use for the link (if null, it defaults to the method defined by the form)
+     *
+     * @throws \LogicException if the node is not a button inside a form tag
+     *
+     * @api
+     */
+    public function __construct(\DOMElement $node, $currentUri, $method = null)
+    {
+        parent::__construct($node, $currentUri, $method);
+
+        $this->initialize();
+    }
+
+    /**
+     * Gets the form node associated with this form.
+     *
+     * @return \DOMElement A \DOMElement instance
+     */
+    public function getFormNode()
+    {
+        return $this->node;
+    }
+
+    /**
+     * Sets the value of the fields.
+     *
+     * @param array $values An array of field values
+     *
+     * @return Form
+     *
+     * @api
+     */
+    public function setValues(array $values)
+    {
+        foreach ($values as $name => $value) {
+            $this->fields->set($name, $value);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Gets the field values.
+     *
+     * The returned array does not include file fields (@see getFiles).
+     *
+     * @return array An array of field values.
+     *
+     * @api
+     */
+    public function getValues()
+    {
+        $values = array();
+        foreach ($this->fields->all() as $name => $field) {
+            if ($field->isDisabled()) {
+                continue;
+            }
+
+            if (!$field instanceof Field\FileFormField && $field->hasValue()) {
+                $values[$name] = $field->getValue();
+            }
+        }
+
+        return $values;
+    }
+
+    /**
+     * Gets the file field values.
+     *
+     * @return array An array of file field values.
+     *
+     * @api
+     */
+    public function getFiles()
+    {
+        if (!in_array($this->getMethod(), array('POST', 'PUT', 'DELETE', 'PATCH'))) {
+            return array();
+        }
+
+        $files = array();
+
+        foreach ($this->fields->all() as $name => $field) {
+            if ($field->isDisabled()) {
+                continue;
+            }
+
+            if ($field instanceof Field\FileFormField) {
+                $files[$name] = $field->getValue();
+            }
+        }
+
+        return $files;
+    }
+
+    /**
+     * Gets the field values as PHP.
+     *
+     * This method converts fields with the array notation
+     * (like foo[bar] to arrays) like PHP does.
+     *
+     * @return array An array of field values.
+     *
+     * @api
+     */
+    public function getPhpValues()
+    {
+        $values = array();
+        foreach ($this->getValues() as $name => $value) {
+            $qs = http_build_query(array($name => $value), '', '&');
+            if (!empty($qs)) {
+                parse_str($qs, $expandedValue);
+                $varName = substr($name, 0, strlen(key($expandedValue)));
+                $values = array_replace_recursive($values, array($varName => current($expandedValue)));
+            }
+        }
+
+        return $values;
+    }
+
+    /**
+     * Gets the file field values as PHP.
+     *
+     * This method converts fields with the array notation
+     * (like foo[bar] to arrays) like PHP does.
+     *
+     * @return array An array of field values.
+     *
+     * @api
+     */
+    public function getPhpFiles()
+    {
+        $values = array();
+        foreach ($this->getFiles() as $name => $value) {
+            $qs = http_build_query(array($name => $value), '', '&');
+            if (!empty($qs)) {
+                parse_str($qs, $expandedValue);
+                $varName = substr($name, 0, strlen(key($expandedValue)));
+                $values = array_replace_recursive($values, array($varName => current($expandedValue)));
+            }
+        }
+
+        return $values;
+    }
+
+    /**
+     * Gets the URI of the form.
+     *
+     * The returned URI is not the same as the form "action" attribute.
+     * This method merges the value if the method is GET to mimics
+     * browser behavior.
+     *
+     * @return string The URI
+     *
+     * @api
+     */
+    public function getUri()
+    {
+        $uri = parent::getUri();
+
+        if (!in_array($this->getMethod(), array('POST', 'PUT', 'DELETE', 'PATCH')) && $queryString = http_build_query($this->getValues(), null, '&')) {
+            $sep = false === strpos($uri, '?') ? '?' : '&';
+            $uri .= $sep.$queryString;
+        }
+
+        return $uri;
+    }
+
+    protected function getRawUri()
+    {
+        return $this->node->getAttribute('action');
+    }
+
+    /**
+     * Gets the form method.
+     *
+     * If no method is defined in the form, GET is returned.
+     *
+     * @return string The method
+     *
+     * @api
+     */
+    public function getMethod()
+    {
+        if (null !== $this->method) {
+            return $this->method;
+        }
+
+        return $this->node->getAttribute('method') ? strtoupper($this->node->getAttribute('method')) : 'GET';
+    }
+
+    /**
+     * Returns true if the named field exists.
+     *
+     * @param string $name The field name
+     *
+     * @return bool true if the field exists, false otherwise
+     *
+     * @api
+     */
+    public function has($name)
+    {
+        return $this->fields->has($name);
+    }
+
+    /**
+     * Removes a field from the form.
+     *
+     * @param string $name The field name
+     *
+     * @throws \InvalidArgumentException when the name is malformed
+     *
+     * @api
+     */
+    public function remove($name)
+    {
+        $this->fields->remove($name);
+    }
+
+    /**
+     * Gets a named field.
+     *
+     * @param string $name The field name
+     *
+     * @return FormField The field instance
+     *
+     * @throws \InvalidArgumentException When field is not present in this form
+     *
+     * @api
+     */
+    public function get($name)
+    {
+        return $this->fields->get($name);
+    }
+
+    /**
+     * Sets a named field.
+     *
+     * @param FormField $field The field
+     *
+     * @api
+     */
+    public function set(FormField $field)
+    {
+        $this->fields->add($field);
+    }
+
+    /**
+     * Gets all fields.
+     *
+     * @return FormField[] An array of fields
+     *
+     * @api
+     */
+    public function all()
+    {
+        return $this->fields->all();
+    }
+
+    /**
+     * Returns true if the named field exists.
+     *
+     * @param string $name The field name
+     *
+     * @return bool true if the field exists, false otherwise
+     */
+    public function offsetExists($name)
+    {
+        return $this->has($name);
+    }
+
+    /**
+     * Gets the value of a field.
+     *
+     * @param string $name The field name
+     *
+     * @return FormField The associated Field instance
+     *
+     * @throws \InvalidArgumentException if the field does not exist
+     */
+    public function offsetGet($name)
+    {
+        return $this->fields->get($name);
+    }
+
+    /**
+     * Sets the value of a field.
+     *
+     * @param string       $name  The field name
+     * @param string|array $value The value of the field
+     *
+     * @throws \InvalidArgumentException if the field does not exist
+     */
+    public function offsetSet($name, $value)
+    {
+        $this->fields->set($name, $value);
+    }
+
+    /**
+     * Removes a field from the form.
+     *
+     * @param string $name The field name
+     */
+    public function offsetUnset($name)
+    {
+        $this->fields->remove($name);
+    }
+
+    /**
+     * Disables validation
+     *
+     * @return self
+     */
+    public function disableValidation()
+    {
+        foreach ($this->fields->all() as $field) {
+            if ($field instanceof Field\ChoiceFormField) {
+                $field->disableValidation();
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Sets the node for the form.
+     *
+     * Expects a 'submit' button \DOMElement and finds the corresponding form element, or the form element itself.
+     *
+     * @param \DOMElement $node A \DOMElement instance
+     *
+     * @throws \LogicException If given node is not a button or input or does not have a form ancestor
+     */
+    protected function setNode(\DOMElement $node)
+    {
+        $this->button = $node;
+        if ('button' === $node->nodeName || ('input' === $node->nodeName && in_array(strtolower($node->getAttribute('type')), array('submit', 'button', 'image')))) {
+            if ($node->hasAttribute('form')) {
+                // if the node has the HTML5-compliant 'form' attribute, use it
+                $formId = $node->getAttribute('form');
+                $form = $node->ownerDocument->getElementById($formId);
+                if (null === $form) {
+                    throw new \LogicException(sprintf('The selected node has an invalid form attribute (%s).', $formId));
+                }
+                $this->node = $form;
+
+                return;
+            }
+            // we loop until we find a form ancestor
+            do {
+                if (null === $node = $node->parentNode) {
+                    throw new \LogicException('The selected node does not have a form ancestor.');
+                }
+            } while ('form' !== $node->nodeName);
+        } elseif ('form' !== $node->nodeName) {
+            throw new \LogicException(sprintf('Unable to submit on a "%s" tag.', $node->nodeName));
+        }
+
+        $this->node = $node;
+    }
+
+    /**
+     * Adds form elements related to this form.
+     *
+     * Creates an internal copy of the submitted 'button' element and
+     * the form node or the entire document depending on whether we need
+     * to find non-descendant elements through HTML5 'form' attribute.
+     */
+    private function initialize()
+    {
+        $this->fields = new FormFieldRegistry();
+
+        $xpath = new \DOMXPath($this->node->ownerDocument);
+
+        // add submitted button if it has a valid name
+        if ('form' !== $this->button->nodeName && $this->button->hasAttribute('name') && $this->button->getAttribute('name')) {
+            if ('input' == $this->button->nodeName && 'image' == strtolower($this->button->getAttribute('type'))) {
+                $name = $this->button->getAttribute('name');
+                $this->button->setAttribute('value', '0');
+
+                // temporarily change the name of the input node for the x coordinate
+                $this->button->setAttribute('name', $name.'.x');
+                $this->set(new Field\InputFormField($this->button));
+
+                // temporarily change the name of the input node for the y coordinate
+                $this->button->setAttribute('name', $name.'.y');
+                $this->set(new Field\InputFormField($this->button));
+
+                // restore the original name of the input node
+                $this->button->setAttribute('name', $name);
+            } else {
+                $this->set(new Field\InputFormField($this->button));
+            }
+        }
+
+        // find form elements corresponding to the current form
+        if ($this->node->hasAttribute('id')) {
+            // corresponding elements are either descendants or have a matching HTML5 form attribute
+            $formId = Crawler::xpathLiteral($this->node->getAttribute('id'));
+
+            $fieldNodes = $xpath->query(sprintf('descendant::input[@form=%s] | descendant::button[@form=%s] | descendant::textarea[@form=%s] | descendant::select[@form=%s] | //form[@id=%s]//input[not(@form)] | //form[@id=%s]//button[not(@form)] | //form[@id=%s]//textarea[not(@form)] | //form[@id=%s]//select[not(@form)]', $formId, $formId, $formId, $formId, $formId, $formId, $formId, $formId));
+            foreach ($fieldNodes as $node) {
+                $this->addField($node);
+            }
+        } else {
+            // do the xpath query with $this->node as the context node, to only find descendant elements
+            // however, descendant elements with form attribute are not part of this form
+            $fieldNodes = $xpath->query('descendant::input[not(@form)] | descendant::button[not(@form)] | descendant::textarea[not(@form)] | descendant::select[not(@form)]', $this->node);
+            foreach ($fieldNodes as $node) {
+                $this->addField($node);
+            }
+        }
+    }
+
+    private function addField(\DOMElement $node)
+    {
+        if (!$node->hasAttribute('name') || !$node->getAttribute('name')) {
+            return;
+        }
+
+        $nodeName = $node->nodeName;
+        if ('select' == $nodeName || 'input' == $nodeName && 'checkbox' == strtolower($node->getAttribute('type'))) {
+            $this->set(new Field\ChoiceFormField($node));
+        } elseif ('input' == $nodeName && 'radio' == strtolower($node->getAttribute('type'))) {
+            // there may be other fields with the same name that are no choice
+            // fields already registered (see https://github.com/symfony/symfony/issues/11689)
+            if ($this->has($node->getAttribute('name')) && $this->get($node->getAttribute('name')) instanceof ChoiceFormField) {
+                $this->get($node->getAttribute('name'))->addChoice($node);
+            } else {
+                $this->set(new Field\ChoiceFormField($node));
+            }
+        } elseif ('input' == $nodeName && 'file' == strtolower($node->getAttribute('type'))) {
+            $this->set(new Field\FileFormField($node));
+        } elseif ('input' == $nodeName && !in_array(strtolower($node->getAttribute('type')), array('submit', 'button', 'image'))) {
+            $this->set(new Field\InputFormField($node));
+        } elseif ('textarea' == $nodeName) {
+            $this->set(new Field\TextareaFormField($node));
+        }
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/FormFieldRegistry.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/FormFieldRegistry.php
new file mode 100644
index 0000000..95dc878
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/FormFieldRegistry.php
@@ -0,0 +1,220 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler;
+
+use Symfony\Component\DomCrawler\Field\FormField;
+
+/**
+ * This is an internal class that must not be used directly.
+ */
+class FormFieldRegistry
+{
+    private $fields = array();
+
+    private $base;
+
+    /**
+     * Adds a field to the registry.
+     *
+     * @param FormField $field The field
+     *
+     * @throws \InvalidArgumentException when the name is malformed
+     */
+    public function add(FormField $field)
+    {
+        $segments = $this->getSegments($field->getName());
+
+        $target = & $this->fields;
+        while ($segments) {
+            if (!is_array($target)) {
+                $target = array();
+            }
+            $path = array_shift($segments);
+            if ('' === $path) {
+                $target = & $target[];
+            } else {
+                $target = & $target[$path];
+            }
+        }
+        $target = $field;
+    }
+
+    /**
+     * Removes a field and its children from the registry.
+     *
+     * @param string $name The fully qualified name of the base field
+     *
+     * @throws \InvalidArgumentException when the name is malformed
+     */
+    public function remove($name)
+    {
+        $segments = $this->getSegments($name);
+        $target = & $this->fields;
+        while (count($segments) > 1) {
+            $path = array_shift($segments);
+            if (!array_key_exists($path, $target)) {
+                return;
+            }
+            $target = & $target[$path];
+        }
+        unset($target[array_shift($segments)]);
+    }
+
+    /**
+     * Returns the value of the field and its children.
+     *
+     * @param string $name The fully qualified name of the field
+     *
+     * @return mixed The value of the field
+     *
+     * @throws \InvalidArgumentException when the name is malformed
+     * @throws \InvalidArgumentException if the field does not exist
+     */
+    public function &get($name)
+    {
+        $segments = $this->getSegments($name);
+        $target = & $this->fields;
+        while ($segments) {
+            $path = array_shift($segments);
+            if (!array_key_exists($path, $target)) {
+                throw new \InvalidArgumentException(sprintf('Unreachable field "%s"', $path));
+            }
+            $target = & $target[$path];
+        }
+
+        return $target;
+    }
+
+    /**
+     * Tests whether the form has the given field.
+     *
+     * @param string $name The fully qualified name of the field
+     *
+     * @return bool Whether the form has the given field
+     */
+    public function has($name)
+    {
+        try {
+            $this->get($name);
+
+            return true;
+        } catch (\InvalidArgumentException $e) {
+            return false;
+        }
+    }
+
+    /**
+     * Set the value of a field and its children.
+     *
+     * @param string $name  The fully qualified name of the field
+     * @param mixed  $value The value
+     *
+     * @throws \InvalidArgumentException when the name is malformed
+     * @throws \InvalidArgumentException if the field does not exist
+     */
+    public function set($name, $value)
+    {
+        $target = & $this->get($name);
+        if (!is_array($value) || $target instanceof Field\ChoiceFormField) {
+            $target->setValue($value);
+        } else {
+            $fields = self::create($name, $value);
+            foreach ($fields->all() as $k => $v) {
+                $this->set($k, $v);
+            }
+        }
+    }
+
+    /**
+     * Returns the list of field with their value.
+     *
+     * @return FormField[] The list of fields as array((string) Fully qualified name => (mixed) value)
+     */
+    public function all()
+    {
+        return $this->walk($this->fields, $this->base);
+    }
+
+    /**
+     * Creates an instance of the class.
+     *
+     * This function is made private because it allows overriding the $base and
+     * the $values properties without any type checking.
+     *
+     * @param string $base   The fully qualified name of the base field
+     * @param array  $values The values of the fields
+     *
+     * @return FormFieldRegistry
+     */
+    private static function create($base, array $values)
+    {
+        $registry = new static();
+        $registry->base = $base;
+        $registry->fields = $values;
+
+        return $registry;
+    }
+
+    /**
+     * Transforms a PHP array in a list of fully qualified name / value.
+     *
+     * @param array  $array  The PHP array
+     * @param string $base   The name of the base field
+     * @param array  $output The initial values
+     *
+     * @return array The list of fields as array((string) Fully qualified name => (mixed) value)
+     */
+    private function walk(array $array, $base = '', array &$output = array())
+    {
+        foreach ($array as $k => $v) {
+            $path = empty($base) ? $k : sprintf("%s[%s]", $base, $k);
+            if (is_array($v)) {
+                $this->walk($v, $path, $output);
+            } else {
+                $output[$path] = $v;
+            }
+        }
+
+        return $output;
+    }
+
+    /**
+     * Splits a field name into segments as a web browser would do.
+     *
+     * <code>
+     *     getSegments('base[foo][3][]') = array('base', 'foo, '3', '');
+     * </code>
+     *
+     * @param string $name The name of the field
+     *
+     * @return string[] The list of segments
+     *
+     * @throws \InvalidArgumentException when the name is malformed
+     */
+    private function getSegments($name)
+    {
+        if (preg_match('/^(?P<base>[^[]+)(?P<extra>(\[.*)|$)/', $name, $m)) {
+            $segments = array($m['base']);
+            while (!empty($m['extra'])) {
+                if (preg_match('/^\[(?P<segment>.*?)\](?P<extra>.*)$/', $m['extra'], $m)) {
+                    $segments[] = $m['segment'];
+                } else {
+                    throw new \InvalidArgumentException(sprintf('Malformed field path "%s"', $name));
+                }
+            }
+
+            return $segments;
+        }
+
+        throw new \InvalidArgumentException(sprintf('Malformed field path "%s"', $name));
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/LICENSE b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/LICENSE
new file mode 100644
index 0000000..43028bc
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2015 Fabien Potencier
+
+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:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+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.
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Link.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Link.php
new file mode 100644
index 0000000..03149f2
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Link.php
@@ -0,0 +1,232 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler;
+
+/**
+ * Link represents an HTML link (an HTML a, area or link tag).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Link
+{
+    /**
+     * @var \DOMElement
+     */
+    protected $node;
+
+    /**
+     * @var string The method to use for the link
+     */
+    protected $method;
+
+    /**
+     * @var string The URI of the page where the link is embedded (or the base href)
+     */
+    protected $currentUri;
+
+    /**
+     * Constructor.
+     *
+     * @param \DOMElement $node       A \DOMElement instance
+     * @param string      $currentUri The URI of the page where the link is embedded (or the base href)
+     * @param string      $method     The method to use for the link (get by default)
+     *
+     * @throws \InvalidArgumentException if the node is not a link
+     *
+     * @api
+     */
+    public function __construct(\DOMElement $node, $currentUri, $method = 'GET')
+    {
+        if (!in_array(strtolower(substr($currentUri, 0, 4)), array('http', 'file'))) {
+            throw new \InvalidArgumentException(sprintf('Current URI must be an absolute URL ("%s").', $currentUri));
+        }
+
+        $this->setNode($node);
+        $this->method = $method ? strtoupper($method) : null;
+        $this->currentUri = $currentUri;
+    }
+
+    /**
+     * Gets the node associated with this link.
+     *
+     * @return \DOMElement A \DOMElement instance
+     */
+    public function getNode()
+    {
+        return $this->node;
+    }
+
+    /**
+     * Gets the method associated with this link.
+     *
+     * @return string The method
+     *
+     * @api
+     */
+    public function getMethod()
+    {
+        return $this->method;
+    }
+
+    /**
+     * Gets the URI associated with this link.
+     *
+     * @return string The URI
+     *
+     * @api
+     */
+    public function getUri()
+    {
+        $uri = trim($this->getRawUri());
+
+        // absolute URL?
+        if (null !== parse_url($uri, PHP_URL_SCHEME)) {
+            return $uri;
+        }
+
+        // empty URI
+        if (!$uri) {
+            return $this->currentUri;
+        }
+
+        // an anchor
+        if ('#' === $uri[0]) {
+            return $this->cleanupAnchor($this->currentUri).$uri;
+        }
+
+        $baseUri = $this->cleanupUri($this->currentUri);
+
+        if ('?' === $uri[0]) {
+            return $baseUri.$uri;
+        }
+
+        // absolute URL with relative schema
+        if (0 === strpos($uri, '//')) {
+            return preg_replace('#^([^/]*)//.*$#', '$1', $baseUri).$uri;
+        }
+
+        $baseUri = preg_replace('#^(.*?//[^/]*)(?:\/.*)?$#', '$1', $baseUri);
+
+        // absolute path
+        if ('/' === $uri[0]) {
+            return $baseUri.$uri;
+        }
+
+        // relative path
+        $path = parse_url(substr($this->currentUri, strlen($baseUri)), PHP_URL_PATH);
+        $path = $this->canonicalizePath(substr($path, 0, strrpos($path, '/')).'/'.$uri);
+
+        return $baseUri.('' === $path || '/' !== $path[0] ? '/' : '').$path;
+    }
+
+    /**
+     * Returns raw URI data.
+     *
+     * @return string
+     */
+    protected function getRawUri()
+    {
+        return $this->node->getAttribute('href');
+    }
+
+    /**
+     * Returns the canonicalized URI path (see RFC 3986, section 5.2.4).
+     *
+     * @param string $path URI path
+     *
+     * @return string
+     */
+    protected function canonicalizePath($path)
+    {
+        if ('' === $path || '/' === $path) {
+            return $path;
+        }
+
+        if ('.' === substr($path, -1)) {
+            $path = $path.'/';
+        }
+
+        $output = array();
+
+        foreach (explode('/', $path) as $segment) {
+            if ('..' === $segment) {
+                array_pop($output);
+            } elseif ('.' !== $segment) {
+                array_push($output, $segment);
+            }
+        }
+
+        return implode('/', $output);
+    }
+
+    /**
+     * Sets current \DOMElement instance.
+     *
+     * @param \DOMElement $node A \DOMElement instance
+     *
+     * @throws \LogicException If given node is not an anchor
+     */
+    protected function setNode(\DOMElement $node)
+    {
+        if ('a' !== $node->nodeName && 'area' !== $node->nodeName && 'link' !== $node->nodeName) {
+            throw new \LogicException(sprintf('Unable to navigate from a "%s" tag.', $node->nodeName));
+        }
+
+        $this->node = $node;
+    }
+
+    /**
+     * Removes the query string and the anchor from the given uri.
+     *
+     * @param string $uri The uri to clean
+     *
+     * @return string
+     */
+    private function cleanupUri($uri)
+    {
+        return $this->cleanupQuery($this->cleanupAnchor($uri));
+    }
+
+    /**
+     * Remove the query string from the uri.
+     *
+     * @param string $uri
+     *
+     * @return string
+     */
+    private function cleanupQuery($uri)
+    {
+        if (false !== $pos = strpos($uri, '?')) {
+            return substr($uri, 0, $pos);
+        }
+
+        return $uri;
+    }
+
+    /**
+     * Remove the anchor from the uri.
+     *
+     * @param string $uri
+     *
+     * @return string
+     */
+    private function cleanupAnchor($uri)
+    {
+        if (false !== $pos = strpos($uri, '#')) {
+            return substr($uri, 0, $pos);
+        }
+
+        return $uri;
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/README.md b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/README.md
new file mode 100644
index 0000000..646573f
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/README.md
@@ -0,0 +1,36 @@
+DomCrawler Component
+====================
+
+DomCrawler eases DOM navigation for HTML and XML documents.
+
+If you are familiar with jQuery, DomCrawler is a PHP equivalent:
+
+```php
+use Symfony\Component\DomCrawler\Crawler;
+
+$crawler = new Crawler();
+$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
+
+print $crawler->filterXPath('descendant-or-self::body/p')->text();
+```
+
+If you are also using the CssSelector component, you can use CSS Selectors
+instead of XPath expressions:
+
+```php
+use Symfony\Component\DomCrawler\Crawler;
+
+$crawler = new Crawler();
+$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
+
+print $crawler->filter('body > p')->text();
+```
+
+Resources
+---------
+
+You can run the unit tests with the following command:
+
+    $ cd path/to/Symfony/Component/DomCrawler/
+    $ composer.phar install
+    $ phpunit
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/CrawlerTest.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/CrawlerTest.php
new file mode 100644
index 0000000..82045a1
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/CrawlerTest.php
@@ -0,0 +1,1072 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Tests;
+
+use Symfony\Component\CssSelector\CssSelector;
+use Symfony\Component\DomCrawler\Crawler;
+
+class CrawlerTest extends \PHPUnit_Framework_TestCase
+{
+    public function testConstructor()
+    {
+        $crawler = new Crawler();
+        $this->assertCount(0, $crawler, '__construct() returns an empty crawler');
+
+        $crawler = new Crawler(new \DOMNode());
+        $this->assertCount(1, $crawler, '__construct() takes a node as a first argument');
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::add
+     */
+    public function testAdd()
+    {
+        $crawler = new Crawler();
+        $crawler->add($this->createDomDocument());
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMDocument');
+
+        $crawler = new Crawler();
+        $crawler->add($this->createNodeList());
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMNodeList');
+
+        foreach ($this->createNodeList() as $node) {
+            $list[] = $node;
+        }
+        $crawler = new Crawler();
+        $crawler->add($list);
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from an array of nodes');
+
+        $crawler = new Crawler();
+        $crawler->add($this->createNodeList()->item(0));
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMElement');
+
+        $crawler = new Crawler();
+        $crawler->add('<html><body>Foo</body></html>');
+        $this->assertEquals('Foo', $crawler->filterXPath('//body')->text(), '->add() adds nodes from a string');
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testAddInvalidNode()
+    {
+        $crawler = new Crawler();
+        $crawler->add(1);
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
+     */
+    public function testAddHtmlContent()
+    {
+        $crawler = new Crawler();
+        $crawler->addHtmlContent('<html><div class="foo"></html>', 'UTF-8');
+
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addHtmlContent() adds nodes from an HTML string');
+
+        $crawler->addHtmlContent('<html><head><base href="http://symfony.com"></head><a href="/contact"></a></html>', 'UTF-8');
+
+        $this->assertEquals('http://symfony.com', $crawler->filterXPath('//base')->attr('href'), '->addHtmlContent() adds nodes from an HTML string');
+        $this->assertEquals('http://symfony.com/contact', $crawler->filterXPath('//a')->link()->getUri(), '->addHtmlContent() adds nodes from an HTML string');
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
+     */
+    public function testAddHtmlContentCharset()
+    {
+        $crawler = new Crawler();
+        $crawler->addHtmlContent('<html><div class="foo">Tiáº¿ng Viá»‡t</html>', 'UTF-8');
+
+        $this->assertEquals('Tiáº¿ng Viá»‡t', $crawler->filterXPath('//div')->text());
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
+     */
+    public function testAddHtmlContentInvalidBaseTag()
+    {
+        $crawler = new Crawler(null, 'http://symfony.com');
+
+        $crawler->addHtmlContent('<html><head><base target="_top"></head><a href="/contact"></a></html>', 'UTF-8');
+
+        $this->assertEquals('http://symfony.com/contact', current($crawler->filterXPath('//a')->links())->getUri(), '->addHtmlContent() correctly handles a non-existent base tag href attribute');
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
+     */
+    public function testAddHtmlContentUnsupportedCharset()
+    {
+        $crawler = new Crawler();
+        $crawler->addHtmlContent(file_get_contents(__DIR__.'/Fixtures/windows-1250.html'), 'Windows-1250');
+
+        $this->assertEquals('Å½Å¥ÄÃ½Å¯', $crawler->filterXPath('//p')->text());
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
+     */
+    public function testAddHtmlContentCharsetGbk()
+    {
+        $crawler = new Crawler();
+        //gbk encode of <html><p>ä¸­æ–‡</p></html>
+        $crawler->addHtmlContent(base64_decode('PGh0bWw+PHA+1tDOxDwvcD48L2h0bWw+'), 'gbk');
+
+        $this->assertEquals('ä¸­æ–‡', $crawler->filterXPath('//p')->text());
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
+     */
+    public function testAddHtmlContentWithErrors()
+    {
+        $internalErrors = libxml_use_internal_errors(true);
+
+        $crawler = new Crawler();
+        $crawler->addHtmlContent(<<<EOF
+<!DOCTYPE html>
+<html>
+    <head>
+    </head>
+    <body>
+        <nav><a href="#"><a href="#"></nav>
+    </body>
+</html>
+EOF
+        , 'UTF-8');
+
+        $errors = libxml_get_errors();
+        $this->assertCount(1, $errors);
+        $this->assertEquals("Tag nav invalid\n", $errors[0]->message);
+
+        libxml_clear_errors();
+        libxml_use_internal_errors($internalErrors);
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addXmlContent
+     */
+    public function testAddXmlContent()
+    {
+        $crawler = new Crawler();
+        $crawler->addXmlContent('<html><div class="foo"></div></html>', 'UTF-8');
+
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addXmlContent() adds nodes from an XML string');
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addXmlContent
+     */
+    public function testAddXmlContentCharset()
+    {
+        $crawler = new Crawler();
+        $crawler->addXmlContent('<html><div class="foo">Tiáº¿ng Viá»‡t</div></html>', 'UTF-8');
+
+        $this->assertEquals('Tiáº¿ng Viá»‡t', $crawler->filterXPath('//div')->text());
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addXmlContent
+     */
+    public function testAddXmlContentWithErrors()
+    {
+        $internalErrors = libxml_use_internal_errors(true);
+
+        $crawler = new Crawler();
+        $crawler->addXmlContent(<<<EOF
+<!DOCTYPE html>
+<html>
+    <head>
+    </head>
+    <body>
+        <nav><a href="#"><a href="#"></nav>
+    </body>
+</html>
+EOF
+        , 'UTF-8');
+
+        $this->assertTrue(count(libxml_get_errors()) > 1);
+
+        libxml_clear_errors();
+        libxml_use_internal_errors($internalErrors);
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addContent
+     */
+    public function testAddContent()
+    {
+        $crawler = new Crawler();
+        $crawler->addContent('<html><div class="foo"></html>', 'text/html; charset=UTF-8');
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an HTML string');
+
+        $crawler = new Crawler();
+        $crawler->addContent('<html><div class="foo"></html>', 'text/html; charset=UTF-8; dir=RTL');
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an HTML string with extended content type');
+
+        $crawler = new Crawler();
+        $crawler->addContent('<html><div class="foo"></html>');
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() uses text/html as the default type');
+
+        $crawler = new Crawler();
+        $crawler->addContent('<html><div class="foo"></div></html>', 'text/xml; charset=UTF-8');
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an XML string');
+
+        $crawler = new Crawler();
+        $crawler->addContent('<html><div class="foo"></div></html>', 'text/xml');
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an XML string');
+
+        $crawler = new Crawler();
+        $crawler->addContent('foo bar', 'text/plain');
+        $this->assertCount(0, $crawler, '->addContent() does nothing if the type is not (x|ht)ml');
+
+        $crawler = new Crawler();
+        $crawler->addContent('<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><span>ä¸­æ–‡</span></html>');
+        $this->assertEquals('ä¸­æ–‡', $crawler->filterXPath('//span')->text(), '->addContent() guess wrong charset');
+
+        $crawler = new Crawler();
+        $crawler->addContent(mb_convert_encoding('<html><head><meta charset="Shift_JIS"></head><body>æ—¥æœ¬èªž</body></html>', 'SJIS', 'UTF-8'));
+        $this->assertEquals('æ—¥æœ¬èªž', $crawler->filterXPath('//body')->text(), '->addContent() can recognize "Shift_JIS" in html5 meta charset tag');
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addDocument
+     */
+    public function testAddDocument()
+    {
+        $crawler = new Crawler();
+        $crawler->addDocument($this->createDomDocument());
+
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addDocument() adds nodes from a \DOMDocument');
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addNodeList
+     */
+    public function testAddNodeList()
+    {
+        $crawler = new Crawler();
+        $crawler->addNodeList($this->createNodeList());
+
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNodeList() adds nodes from a \DOMNodeList');
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addNodes
+     */
+    public function testAddNodes()
+    {
+        foreach ($this->createNodeList() as $node) {
+            $list[] = $node;
+        }
+
+        $crawler = new Crawler();
+        $crawler->addNodes($list);
+
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNodes() adds nodes from an array of nodes');
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::addNode
+     */
+    public function testAddNode()
+    {
+        $crawler = new Crawler();
+        $crawler->addNode($this->createNodeList()->item(0));
+
+        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNode() adds nodes from a \DOMElement');
+    }
+
+    public function testClear()
+    {
+        $crawler = new Crawler(new \DOMNode());
+        $crawler->clear();
+        $this->assertCount(0, $crawler, '->clear() removes all the nodes from the crawler');
+    }
+
+    public function testEq()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//li');
+        $this->assertNotSame($crawler, $crawler->eq(0), '->eq() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->eq() returns a new instance of a crawler');
+
+        $this->assertEquals('Two', $crawler->eq(1)->text(), '->eq() returns the nth node of the list');
+        $this->assertCount(0, $crawler->eq(100), '->eq() returns an empty crawler if the nth node does not exist');
+    }
+
+    public function testEach()
+    {
+        $data = $this->createTestCrawler()->filterXPath('//ul[1]/li')->each(function ($node, $i) {
+            return $i.'-'.$node->text();
+        });
+
+        $this->assertEquals(array('0-One', '1-Two', '2-Three'), $data, '->each() executes an anonymous function on each node of the list');
+    }
+
+    public function testSlice()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li');
+        $this->assertNotSame($crawler->slice(), $crawler, '->slice() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler->slice(), '->slice() returns a new instance of a crawler');
+
+        $this->assertCount(3, $crawler->slice(), '->slice() does not slice the nodes in the list if any param is entered');
+        $this->assertCount(1, $crawler->slice(1, 1), '->slice() slices the nodes in the list');
+    }
+
+    public function testReduce()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li');
+        $nodes = $crawler->reduce(function ($node, $i) {
+            return $i == 1 ? false : true;
+        });
+        $this->assertNotSame($nodes, $crawler, '->reduce() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $nodes, '->reduce() returns a new instance of a crawler');
+
+        $this->assertCount(2, $nodes, '->reduce() filters the nodes in the list');
+    }
+
+    public function testAttr()
+    {
+        $this->assertEquals('first', $this->createTestCrawler()->filterXPath('//li')->attr('class'), '->attr() returns the attribute of the first element of the node list');
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->attr('class');
+            $this->fail('->attr() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->attr() throws an \InvalidArgumentException if the node list is empty');
+        }
+    }
+
+    public function testMissingAttrValueIsNull()
+    {
+        $crawler = new Crawler();
+        $crawler->addContent('<html><div non-empty-attr="sample value" empty-attr=""></div></html>', 'text/html; charset=UTF-8');
+        $div = $crawler->filterXPath('//div');
+
+        $this->assertEquals('sample value', $div->attr('non-empty-attr'), '->attr() reads non-empty attributes correctly');
+        $this->assertEquals('', $div->attr('empty-attr'), '->attr() reads empty attributes correctly');
+        $this->assertNull($div->attr('missing-attr'), '->attr() reads missing attributes correctly');
+    }
+
+    public function testNodeName()
+    {
+        $this->assertEquals('li', $this->createTestCrawler()->filterXPath('//li')->nodeName(), '->nodeName() returns the node name of the first element of the node list');
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->nodeName();
+            $this->fail('->nodeName() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->nodeName() throws an \InvalidArgumentException if the node list is empty');
+        }
+    }
+
+    public function testText()
+    {
+        $this->assertEquals('One', $this->createTestCrawler()->filterXPath('//li')->text(), '->text() returns the node value of the first element of the node list');
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->text();
+            $this->fail('->text() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->text() throws an \InvalidArgumentException if the node list is empty');
+        }
+    }
+
+    public function testHtml()
+    {
+        $this->assertEquals('<img alt="Bar">', $this->createTestCrawler()->filterXPath('//a[5]')->html());
+        $this->assertEquals('<input type="text" value="TextValue" name="TextName"><input type="submit" value="FooValue" name="FooName" id="FooId"><input type="button" value="BarValue" name="BarName" id="BarId"><button value="ButtonValue" name="ButtonName" id="ButtonId"></button>', trim($this->createTestCrawler()->filterXPath('//form[@id="FooFormId"]')->html()));
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->html();
+            $this->fail('->html() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->html() throws an \InvalidArgumentException if the node list is empty');
+        }
+    }
+
+    public function testExtract()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li');
+
+        $this->assertEquals(array('One', 'Two', 'Three'), $crawler->extract('_text'), '->extract() returns an array of extracted data from the node list');
+        $this->assertEquals(array(array('One', 'first'), array('Two', ''), array('Three', '')), $crawler->extract(array('_text', 'class')), '->extract() returns an array of extracted data from the node list');
+
+        $this->assertEquals(array(), $this->createTestCrawler()->filterXPath('//ol')->extract('_text'), '->extract() returns an empty array if the node list is empty');
+    }
+
+    public function testFilterXpathComplexQueries()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//body');
+
+        $this->assertCount(0, $crawler->filterXPath('/input'));
+        $this->assertCount(0, $crawler->filterXPath('/body'));
+        $this->assertCount(1, $crawler->filterXPath('/_root/body'));
+        $this->assertCount(1, $crawler->filterXPath('./body'));
+        $this->assertCount(1, $crawler->filterXPath('.//body'));
+        $this->assertCount(5, $crawler->filterXPath('.//input'));
+        $this->assertCount(4, $crawler->filterXPath('//form')->filterXPath('//button | //input'));
+        $this->assertCount(1, $crawler->filterXPath('body'));
+        $this->assertCount(6, $crawler->filterXPath('//button | //input'));
+        $this->assertCount(1, $crawler->filterXPath('//body'));
+        $this->assertCount(1, $crawler->filterXPath('descendant-or-self::body'));
+        $this->assertCount(1, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('./div'), 'A child selection finds only the current div');
+        $this->assertCount(3, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('descendant::div'), 'A descendant selector matches the current div and its child');
+        $this->assertCount(3, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('//div'), 'A descendant selector matches the current div and its child');
+        $this->assertCount(5, $crawler->filterXPath('(//a | //div)//img'));
+        $this->assertCount(7, $crawler->filterXPath('((//a | //div)//img | //ul)'));
+        $this->assertCount(7, $crawler->filterXPath('( ( //a | //div )//img | //ul )'));
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::filterXPath
+     */
+    public function testFilterXPath()
+    {
+        $crawler = $this->createTestCrawler();
+        $this->assertNotSame($crawler, $crawler->filterXPath('//li'), '->filterXPath() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->filterXPath() returns a new instance of a crawler');
+
+        $crawler = $this->createTestCrawler()->filterXPath('//ul');
+        $this->assertCount(6, $crawler->filterXPath('//li'), '->filterXPath() filters the node list with the XPath expression');
+
+        $crawler = $this->createTestCrawler();
+        $this->assertCount(3, $crawler->filterXPath('//body')->filterXPath('//button')->parents(), '->filterXpath() preserves parents when chained');
+    }
+
+    public function testFilterXPathWithDefaultNamespace()
+    {
+        $crawler = $this->createTestXmlCrawler()->filterXPath('//default:entry/default:id');
+        $this->assertCount(1, $crawler, '->filterXPath() automatically registers a namespace');
+        $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
+    }
+
+    public function testFilterXPathWithCustomDefaultNamespace()
+    {
+        $crawler = $this->createTestXmlCrawler();
+        $crawler->setDefaultNamespacePrefix('x');
+        $crawler = $crawler->filterXPath('//x:entry/x:id');
+
+        $this->assertCount(1, $crawler, '->filterXPath() lets to override the default namespace prefix');
+        $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
+    }
+
+    public function testFilterXPathWithNamespace()
+    {
+        $crawler = $this->createTestXmlCrawler()->filterXPath('//yt:accessControl');
+        $this->assertCount(2, $crawler, '->filterXPath() automatically registers a namespace');
+    }
+
+    public function testFilterXPathWithMultipleNamespaces()
+    {
+        $crawler = $this->createTestXmlCrawler()->filterXPath('//media:group/yt:aspectRatio');
+        $this->assertCount(1, $crawler, '->filterXPath() automatically registers multiple namespaces');
+        $this->assertSame('widescreen', $crawler->text());
+    }
+
+    public function testFilterXPathWithManuallyRegisteredNamespace()
+    {
+        $crawler = $this->createTestXmlCrawler();
+        $crawler->registerNamespace('m', 'http://search.yahoo.com/mrss/');
+
+        $crawler = $crawler->filterXPath('//m:group/yt:aspectRatio');
+        $this->assertCount(1, $crawler, '->filterXPath() uses manually registered namespace');
+        $this->assertSame('widescreen', $crawler->text());
+    }
+
+    public function testFilterXPathWithAnUrl()
+    {
+        $crawler = $this->createTestXmlCrawler();
+
+        $crawler = $crawler->filterXPath('//media:category[@scheme="http://gdata.youtube.com/schemas/2007/categories.cat"]');
+        $this->assertCount(1, $crawler);
+        $this->assertSame('Music', $crawler->text());
+    }
+
+    public function testFilterXPathWithFakeRoot()
+    {
+        $crawler = $this->createTestCrawler();
+        $this->assertCount(0, $crawler->filterXPath('.'), '->filterXPath() returns an empty result if the XPath references the fake root node');
+        $this->assertCount(0, $crawler->filterXPath('/_root'), '->filterXPath() returns an empty result if the XPath references the fake root node');
+        $this->assertCount(0, $crawler->filterXPath('self::*'), '->filterXPath() returns an empty result if the XPath references the fake root node');
+        $this->assertCount(0, $crawler->filterXPath('self::_root'), '->filterXPath() returns an empty result if the XPath references the fake root node');
+    }
+
+    public function testFilterXPathWithAncestorAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//form');
+
+        $this->assertCount(0, $crawler->filterXPath('ancestor::*'), 'The fake root node has no ancestor nodes');
+    }
+
+    public function testFilterXPathWithAncestorOrSelfAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//form');
+
+        $this->assertCount(0, $crawler->filterXPath('ancestor-or-self::*'), 'The fake root node has no ancestor nodes');
+    }
+
+    public function testFilterXPathWithAttributeAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//form');
+
+        $this->assertCount(0, $crawler->filterXPath('attribute::*'), 'The fake root node has no attribute nodes');
+    }
+
+    public function testFilterXPathWithAttributeAxisAfterElementAxis()
+    {
+        $this->assertCount(3, $this->createTestCrawler()->filterXPath('//form/button/attribute::*'), '->filterXPath() handles attribute axes properly when they are preceded by an element filtering axis');
+    }
+
+    public function testFilterXPathWithChildAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//div[@id="parent"]');
+
+        $this->assertCount(1, $crawler->filterXPath('child::div'), 'A child selection finds only the current div');
+    }
+
+    public function testFilterXPathWithFollowingAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//a');
+
+        $this->assertCount(0, $crawler->filterXPath('following::div'), 'The fake root node has no following nodes');
+    }
+
+    public function testFilterXPathWithFollowingSiblingAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//a');
+
+        $this->assertCount(0, $crawler->filterXPath('following-sibling::div'), 'The fake root node has no following nodes');
+    }
+
+    public function testFilterXPathWithNamespaceAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//button');
+
+        $this->assertCount(0, $crawler->filterXPath('namespace::*'), 'The fake root node has no namespace nodes');
+    }
+
+    public function testFilterXPathWithNamespaceAxisAfterElementAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//div[@id="parent"]/namespace::*');
+
+        $this->assertCount(0, $crawler->filterXPath('namespace::*'), 'Namespace axes cannot be requested');
+    }
+
+    public function testFilterXPathWithParentAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//button');
+
+        $this->assertCount(0, $crawler->filterXPath('parent::*'), 'The fake root node has no parent nodes');
+    }
+
+    public function testFilterXPathWithPrecedingAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//form');
+
+        $this->assertCount(0, $crawler->filterXPath('preceding::*'), 'The fake root node has no preceding nodes');
+    }
+
+    public function testFilterXPathWithPrecedingSiblingAxis()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//form');
+
+        $this->assertCount(0, $crawler->filterXPath('preceding-sibling::*'), 'The fake root node has no preceding nodes');
+    }
+
+    public function testFilterXPathWithSelfAxes()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//a');
+
+        $this->assertCount(0, $crawler->filterXPath('self::a'), 'The fake root node has no "real" element name');
+        $this->assertCount(0, $crawler->filterXPath('self::a/img'), 'The fake root node has no "real" element name');
+        $this->assertCount(9, $crawler->filterXPath('self::*/a'));
+    }
+
+    /**
+     * @covers Symfony\Component\DomCrawler\Crawler::filter
+     */
+    public function testFilter()
+    {
+        $crawler = $this->createTestCrawler();
+        $this->assertNotSame($crawler, $crawler->filter('li'), '->filter() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->filter() returns a new instance of a crawler');
+
+        $crawler = $this->createTestCrawler()->filter('ul');
+
+        $this->assertCount(6, $crawler->filter('li'), '->filter() filters the node list with the CSS selector');
+    }
+
+    public function testFilterWithDefaultNamespace()
+    {
+        $crawler = $this->createTestXmlCrawler()->filter('default|entry default|id');
+        $this->assertCount(1, $crawler, '->filter() automatically registers namespaces');
+        $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
+    }
+
+    public function testFilterWithNamespace()
+    {
+        CssSelector::disableHtmlExtension();
+
+        $crawler = $this->createTestXmlCrawler()->filter('yt|accessControl');
+        $this->assertCount(2, $crawler, '->filter() automatically registers namespaces');
+    }
+
+    public function testFilterWithMultipleNamespaces()
+    {
+        CssSelector::disableHtmlExtension();
+
+        $crawler = $this->createTestXmlCrawler()->filter('media|group yt|aspectRatio');
+        $this->assertCount(1, $crawler, '->filter() automatically registers namespaces');
+        $this->assertSame('widescreen', $crawler->text());
+    }
+
+    public function testFilterWithDefaultNamespaceOnly()
+    {
+        $crawler = new Crawler('<?xml version="1.0" encoding="UTF-8"?>
+            <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+                <url>
+                    <loc>http://localhost/foo</loc>
+                    <changefreq>weekly</changefreq>
+                    <priority>0.5</priority>
+                    <lastmod>2012-11-16</lastmod>
+               </url>
+               <url>
+                    <loc>http://localhost/bar</loc>
+                    <changefreq>weekly</changefreq>
+                    <priority>0.5</priority>
+                    <lastmod>2012-11-16</lastmod>
+                </url>
+            </urlset>
+        ');
+
+        $this->assertEquals(2, $crawler->filter('url')->count());
+    }
+
+    public function testSelectLink()
+    {
+        $crawler = $this->createTestCrawler();
+        $this->assertNotSame($crawler, $crawler->selectLink('Foo'), '->selectLink() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->selectLink() returns a new instance of a crawler');
+
+        $this->assertCount(1, $crawler->selectLink('Fabien\'s Foo'), '->selectLink() selects links by the node values');
+        $this->assertCount(1, $crawler->selectLink('Fabien\'s Bar'), '->selectLink() selects links by the alt attribute of a clickable image');
+
+        $this->assertCount(2, $crawler->selectLink('Fabien"s Foo'), '->selectLink() selects links by the node values');
+        $this->assertCount(2, $crawler->selectLink('Fabien"s Bar'), '->selectLink() selects links by the alt attribute of a clickable image');
+
+        $this->assertCount(1, $crawler->selectLink('\' Fabien"s Foo'), '->selectLink() selects links by the node values');
+        $this->assertCount(1, $crawler->selectLink('\' Fabien"s Bar'), '->selectLink() selects links by the alt attribute of a clickable image');
+
+        $this->assertCount(4, $crawler->selectLink('Foo'), '->selectLink() selects links by the node values');
+        $this->assertCount(4, $crawler->selectLink('Bar'), '->selectLink() selects links by the node values');
+    }
+
+    public function testSelectButton()
+    {
+        $crawler = $this->createTestCrawler();
+        $this->assertNotSame($crawler, $crawler->selectButton('FooValue'), '->selectButton() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->selectButton() returns a new instance of a crawler');
+
+        $this->assertEquals(1, $crawler->selectButton('FooValue')->count(), '->selectButton() selects buttons');
+        $this->assertEquals(1, $crawler->selectButton('FooName')->count(), '->selectButton() selects buttons');
+        $this->assertEquals(1, $crawler->selectButton('FooId')->count(), '->selectButton() selects buttons');
+
+        $this->assertEquals(1, $crawler->selectButton('BarValue')->count(), '->selectButton() selects buttons');
+        $this->assertEquals(1, $crawler->selectButton('BarName')->count(), '->selectButton() selects buttons');
+        $this->assertEquals(1, $crawler->selectButton('BarId')->count(), '->selectButton() selects buttons');
+
+        $this->assertEquals(1, $crawler->selectButton('FooBarValue')->count(), '->selectButton() selects buttons with form attribute too');
+        $this->assertEquals(1, $crawler->selectButton('FooBarName')->count(), '->selectButton() selects buttons with form attribute too');
+    }
+
+    public function testSelectButtonWithSingleQuotesInNameAttribute()
+    {
+        $html = <<<HTML
+<!DOCTYPE html>
+<html lang="en">
+<body>
+    <div id="action">
+        <a href="/index.php?r=site/login">Login</a>
+    </div>
+    <form id="login-form" action="/index.php?r=site/login" method="post">
+        <button type="submit" name="Click 'Here'">Submit</button>
+    </form>
+</body>
+</html>
+HTML;
+
+        $crawler = new Crawler($html);
+
+        $this->assertCount(1, $crawler->selectButton('Click \'Here\''));
+    }
+
+    public function testSelectButtonWithDoubleQuotesInNameAttribute()
+    {
+        $html = <<<HTML
+<!DOCTYPE html>
+<html lang="en">
+<body>
+    <div id="action">
+        <a href="/index.php?r=site/login">Login</a>
+    </div>
+    <form id="login-form" action="/index.php?r=site/login" method="post">
+        <button type="submit" name='Click "Here"'>Submit</button>
+    </form>
+</body>
+</html>
+HTML;
+
+        $crawler = new Crawler($html);
+
+        $this->assertCount(1, $crawler->selectButton('Click "Here"'));
+    }
+
+    public function testLink()
+    {
+        $crawler = $this->createTestCrawler('http://example.com/bar/')->selectLink('Foo');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Link', $crawler->link(), '->link() returns a Link instance');
+
+        $this->assertEquals('POST', $crawler->link('post')->getMethod(), '->link() takes a method as its argument');
+
+        $crawler = $this->createTestCrawler('http://example.com/bar')->selectLink('GetLink');
+        $this->assertEquals('http://example.com/bar?get=param', $crawler->link()->getUri(), '->link() returns a Link instance');
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->link();
+            $this->fail('->link() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->link() throws an \InvalidArgumentException if the node list is empty');
+        }
+    }
+
+    public function testSelectLinkAndLinkFiltered()
+    {
+        $html = <<<HTML
+<!DOCTYPE html>
+<html lang="en">
+<body>
+    <div id="action">
+        <a href="/index.php?r=site/login">Login</a>
+    </div>
+    <form id="login-form" action="/index.php?r=site/login" method="post">
+        <button type="submit">Submit</button>
+    </form>
+</body>
+</html>
+HTML;
+
+        $crawler = new Crawler($html);
+        $filtered = $crawler->filterXPath("descendant-or-self::*[@id = 'login-form']");
+
+        $this->assertCount(0, $filtered->selectLink('Login'));
+        $this->assertCount(1, $filtered->selectButton('Submit'));
+
+        $filtered = $crawler->filterXPath("descendant-or-self::*[@id = 'action']");
+
+        $this->assertCount(1, $filtered->selectLink('Login'));
+        $this->assertCount(0, $filtered->selectButton('Submit'));
+
+        $this->assertCount(1, $crawler->selectLink('Login')->selectLink('Login'));
+        $this->assertCount(1, $crawler->selectButton('Submit')->selectButton('Submit'));
+    }
+
+    public function testChaining()
+    {
+        $crawler = new Crawler('<div name="a"><div name="b"><div name="c"></div></div></div>');
+
+        $this->assertEquals('a', $crawler->filterXPath('//div')->filterXPath('div')->filterXPath('div')->attr('name'));
+    }
+
+    public function testLinks()
+    {
+        $crawler = $this->createTestCrawler('http://example.com/bar/')->selectLink('Foo');
+        $this->assertInternalType('array', $crawler->links(), '->links() returns an array');
+
+        $this->assertCount(4, $crawler->links(), '->links() returns an array');
+        $links = $crawler->links();
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Link', $links[0], '->links() returns an array of Link instances');
+
+        $this->assertEquals(array(), $this->createTestCrawler()->filterXPath('//ol')->links(), '->links() returns an empty array if the node selection is empty');
+    }
+
+    public function testForm()
+    {
+        $testCrawler = $this->createTestCrawler('http://example.com/bar/');
+        $crawler = $testCrawler->selectButton('FooValue');
+        $crawler2 = $testCrawler->selectButton('FooBarValue');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Form', $crawler->form(), '->form() returns a Form instance');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Form', $crawler2->form(), '->form() returns a Form instance');
+
+        $this->assertEquals($crawler->form()->getFormNode()->getAttribute('id'), $crawler2->form()->getFormNode()->getAttribute('id'), '->form() works on elements with form attribute');
+
+        $this->assertEquals(array('FooName' => 'FooBar', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'), $crawler->form(array('FooName' => 'FooBar'))->getValues(), '->form() takes an array of values to submit as its first argument');
+        $this->assertEquals(array('FooName' => 'FooValue', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'), $crawler->form()->getValues(), '->getValues() returns correct form values');
+        $this->assertEquals(array('FooBarName' => 'FooBarValue', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'), $crawler2->form()->getValues(), '->getValues() returns correct form values');
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->form();
+            $this->fail('->form() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->form() throws an \InvalidArgumentException if the node list is empty');
+        }
+    }
+
+    public function testLast()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li');
+        $this->assertNotSame($crawler, $crawler->last(), '->last() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->last() returns a new instance of a crawler');
+
+        $this->assertEquals('Three', $crawler->last()->text());
+    }
+
+    public function testFirst()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//li');
+        $this->assertNotSame($crawler, $crawler->first(), '->first() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->first() returns a new instance of a crawler');
+
+        $this->assertEquals('One', $crawler->first()->text());
+    }
+
+    public function testSiblings()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(1);
+        $this->assertNotSame($crawler, $crawler->siblings(), '->siblings() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->siblings() returns a new instance of a crawler');
+
+        $nodes = $crawler->siblings();
+        $this->assertEquals(2, $nodes->count());
+        $this->assertEquals('One', $nodes->eq(0)->text());
+        $this->assertEquals('Three', $nodes->eq(1)->text());
+
+        $nodes = $this->createTestCrawler()->filterXPath('//li')->eq(0)->siblings();
+        $this->assertEquals(2, $nodes->count());
+        $this->assertEquals('Two', $nodes->eq(0)->text());
+        $this->assertEquals('Three', $nodes->eq(1)->text());
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->siblings();
+            $this->fail('->siblings() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->siblings() throws an \InvalidArgumentException if the node list is empty');
+        }
+    }
+
+    public function testNextAll()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(1);
+        $this->assertNotSame($crawler, $crawler->nextAll(), '->nextAll() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->nextAll() returns a new instance of a crawler');
+
+        $nodes = $crawler->nextAll();
+        $this->assertEquals(1, $nodes->count());
+        $this->assertEquals('Three', $nodes->eq(0)->text());
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->nextAll();
+            $this->fail('->nextAll() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->nextAll() throws an \InvalidArgumentException if the node list is empty');
+        }
+    }
+
+    public function testPreviousAll()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(2);
+        $this->assertNotSame($crawler, $crawler->previousAll(), '->previousAll() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->previousAll() returns a new instance of a crawler');
+
+        $nodes = $crawler->previousAll();
+        $this->assertEquals(2, $nodes->count());
+        $this->assertEquals('Two', $nodes->eq(0)->text());
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->previousAll();
+            $this->fail('->previousAll() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->previousAll() throws an \InvalidArgumentException if the node list is empty');
+        }
+    }
+
+    public function testChildren()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//ul');
+        $this->assertNotSame($crawler, $crawler->children(), '->children() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->children() returns a new instance of a crawler');
+
+        $nodes = $crawler->children();
+        $this->assertEquals(3, $nodes->count());
+        $this->assertEquals('One', $nodes->eq(0)->text());
+        $this->assertEquals('Two', $nodes->eq(1)->text());
+        $this->assertEquals('Three', $nodes->eq(2)->text());
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->children();
+            $this->fail('->children() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->children() throws an \InvalidArgumentException if the node list is empty');
+        }
+
+        try {
+            $crawler = new Crawler('<p></p>');
+            $crawler->filter('p')->children();
+            $this->assertTrue(true, '->children() does not trigger a notice if the node has no children');
+        } catch (\PHPUnit_Framework_Error_Notice $e) {
+            $this->fail('->children() does not trigger a notice if the node has no children');
+        }
+    }
+
+    public function testParents()
+    {
+        $crawler = $this->createTestCrawler()->filterXPath('//li[1]');
+        $this->assertNotSame($crawler, $crawler->parents(), '->parents() returns a new instance of a crawler');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->parents() returns a new instance of a crawler');
+
+        $nodes = $crawler->parents();
+        $this->assertEquals(3, $nodes->count());
+
+        $nodes = $this->createTestCrawler()->filterXPath('//html')->parents();
+        $this->assertEquals(0, $nodes->count());
+
+        try {
+            $this->createTestCrawler()->filterXPath('//ol')->parents();
+            $this->fail('->parents() throws an \InvalidArgumentException if the node list is empty');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->parents() throws an \InvalidArgumentException if the node list is empty');
+        }
+    }
+
+    /**
+     * @dataProvider getBaseTagData
+     */
+    public function testBaseTag($baseValue, $linkValue, $expectedUri, $currentUri = null, $description = null)
+    {
+        $crawler = new Crawler('<html><base href="'.$baseValue.'"><a href="'.$linkValue.'"></a></html>', $currentUri);
+        $this->assertEquals($expectedUri, $crawler->filterXPath('//a')->link()->getUri(), $description);
+    }
+
+    public function getBaseTagData()
+    {
+        return array(
+            array('http://base.com', 'link', 'http://base.com/link'),
+            array('//base.com', 'link', 'https://base.com/link', 'https://domain.com', '<base> tag can use a schema-less URL'),
+            array('path/', 'link', 'https://domain.com/path/link', 'https://domain.com', '<base> tag can set a path'),
+            array('http://base.com', '#', 'http://base.com#', 'http://domain.com/path/link', '<base> tag does work with links to an anchor'),
+            array('http://base.com', '', 'http://base.com', 'http://domain.com/path/link', '<base> tag does work with empty links'),
+        );
+    }
+
+    /**
+     * @dataProvider getBaseTagWithFormData
+     */
+    public function testBaseTagWithForm($baseValue, $actionValue, $expectedUri, $currentUri = null, $description = null)
+    {
+        $crawler = new Crawler('<html><base href="'.$baseValue.'"><form method="post" action="'.$actionValue.'"><button type="submit" name="submit"/></form></html>', $currentUri);
+        $this->assertEquals($expectedUri, $crawler->filterXPath('//button')->form()->getUri(), $description);
+    }
+
+    public function getBaseTagWithFormData()
+    {
+        return array(
+            array('/basepath', '/registration', 'http://domain.com/registration', 'http://domain.com/registration', '<base> tag does work with a path and form action'),
+            array('/basepath', '', 'http://domain.com/registration', 'http://domain.com/registration', '<base> tag does work with a path and empty form action'),
+            array('http://base.com', '', 'http://domain.com/path/form', 'http://domain.com/path/form', '<base> tag does work with a URL and an empty form action'),
+        );
+    }
+
+    public function createTestCrawler($uri = null)
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('
+            <html>
+                <body>
+                    <a href="foo">Foo</a>
+                    <a href="/foo">   Fabien\'s Foo   </a>
+                    <a href="/foo">Fabien"s Foo</a>
+                    <a href="/foo">\' Fabien"s Foo</a>
+
+                    <a href="/bar"><img alt="Bar"/></a>
+                    <a href="/bar"><img alt="   Fabien\'s Bar   "/></a>
+                    <a href="/bar"><img alt="Fabien&quot;s Bar"/></a>
+                    <a href="/bar"><img alt="\' Fabien&quot;s Bar"/></a>
+
+                    <a href="?get=param">GetLink</a>
+
+                    <form action="foo" id="FooFormId">
+                        <input type="text" value="TextValue" name="TextName" />
+                        <input type="submit" value="FooValue" name="FooName" id="FooId" />
+                        <input type="button" value="BarValue" name="BarName" id="BarId" />
+                        <button value="ButtonValue" name="ButtonName" id="ButtonId" />
+                    </form>
+
+                    <input type="submit" value="FooBarValue" name="FooBarName" form="FooFormId" />
+                    <input type="text" value="FooTextValue" name="FooTextName" form="FooFormId" />
+
+                    <ul class="first">
+                        <li class="first">One</li>
+                        <li>Two</li>
+                        <li>Three</li>
+                    </ul>
+                    <ul>
+                        <li>One Bis</li>
+                        <li>Two Bis</li>
+                        <li>Three Bis</li>
+                    </ul>
+                    <div id="parent">
+                        <div id="child"></div>
+                        <div id="child2" xmlns:foo="http://example.com"></div>
+                    </div>
+                    <div id="sibling"><img /></div>
+                </body>
+            </html>
+        ');
+
+        return new Crawler($dom, $uri);
+    }
+
+    protected function createTestXmlCrawler($uri = null)
+    {
+        $xml = '<?xml version="1.0" encoding="UTF-8"?>
+            <entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">
+                <id>tag:youtube.com,2008:video:kgZRZmEc9j4</id>
+                <yt:accessControl action="comment" permission="allowed"/>
+                <yt:accessControl action="videoRespond" permission="moderated"/>
+                <media:group>
+                    <media:title type="plain">Chordates - CrashCourse Biology #24</media:title>
+                    <yt:aspectRatio>widescreen</yt:aspectRatio>
+                </media:group>
+                <media:category label="Music" scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Music</media:category>
+            </entry>';
+
+        return new Crawler($xml, $uri);
+    }
+
+    protected function createDomDocument()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadXML('<html><div class="foo"></div></html>');
+
+        return $dom;
+    }
+
+    protected function createNodeList()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadXML('<html><div class="foo"></div></html>');
+        $domxpath = new \DOMXPath($dom);
+
+        return $domxpath->query('//div');
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php
new file mode 100644
index 0000000..9b31945
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php
@@ -0,0 +1,388 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Tests\Field;
+
+use Symfony\Component\DomCrawler\Field\ChoiceFormField;
+
+class ChoiceFormFieldTest extends FormFieldTestCase
+{
+    public function testInitialize()
+    {
+        $node = $this->createNode('textarea', '');
+        try {
+            $field = new ChoiceFormField($node);
+            $this->fail('->initialize() throws a \LogicException if the node is not an input or a select');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is not an input or a select');
+        }
+
+        $node = $this->createNode('input', '', array('type' => 'text'));
+        try {
+            $field = new ChoiceFormField($node);
+            $this->fail('->initialize() throws a \LogicException if the node is an input with a type different from checkbox or radio');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is an input with a type different from checkbox or radio');
+        }
+    }
+
+    public function testGetType()
+    {
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo'));
+        $field = new ChoiceFormField($node);
+
+        $this->assertEquals('radio', $field->getType(), '->getType() returns radio for radio buttons');
+
+        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'value' => 'foo'));
+        $field = new ChoiceFormField($node);
+
+        $this->assertEquals('checkbox', $field->getType(), '->getType() returns radio for a checkbox');
+
+        $node = $this->createNode('select', '');
+        $field = new ChoiceFormField($node);
+
+        $this->assertEquals('select', $field->getType(), '->getType() returns radio for a select');
+    }
+
+    public function testIsMultiple()
+    {
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo'));
+        $field = new ChoiceFormField($node);
+
+        $this->assertFalse($field->isMultiple(), '->isMultiple() returns false for radio buttons');
+
+        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'value' => 'foo'));
+        $field = new ChoiceFormField($node);
+
+        $this->assertFalse($field->isMultiple(), '->isMultiple() returns false for checkboxes');
+
+        $node = $this->createNode('select', '');
+        $field = new ChoiceFormField($node);
+
+        $this->assertFalse($field->isMultiple(), '->isMultiple() returns false for selects without the multiple attribute');
+
+        $node = $this->createNode('select', '', array('multiple' => 'multiple'));
+        $field = new ChoiceFormField($node);
+
+        $this->assertTrue($field->isMultiple(), '->isMultiple() returns true for selects with the multiple attribute');
+
+        $node = $this->createNode('select', '', array('multiple' => ''));
+        $field = new ChoiceFormField($node);
+
+        $this->assertTrue($field->isMultiple(), '->isMultiple() returns true for selects with an empty multiple attribute');
+    }
+
+    public function testSelects()
+    {
+        $node = $this->createSelectNode(array('foo' => false, 'bar' => false));
+        $field = new ChoiceFormField($node);
+
+        $this->assertTrue($field->hasValue(), '->hasValue() returns true for selects');
+        $this->assertEquals('foo', $field->getValue(), '->getValue() returns the first option if none are selected');
+        $this->assertFalse($field->isMultiple(), '->isMultiple() returns false when no multiple attribute is defined');
+
+        $node = $this->createSelectNode(array('foo' => false, 'bar' => true));
+        $field = new ChoiceFormField($node);
+
+        $this->assertEquals('bar', $field->getValue(), '->getValue() returns the selected option');
+
+        $field->setValue('foo');
+        $this->assertEquals('foo', $field->getValue(), '->setValue() changes the selected option');
+
+        try {
+            $field->setValue('foobar');
+            $this->fail('->setValue() throws an \InvalidArgumentException if the value is not one of the selected options');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->setValue() throws an \InvalidArgumentException if the value is not one of the selected options');
+        }
+
+        try {
+            $field->setValue(array('foobar'));
+            $this->fail('->setValue() throws an \InvalidArgumentException if the value is an array');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->setValue() throws an \InvalidArgumentException if the value is an array');
+        }
+    }
+
+    public function testSelectWithEmptyBooleanAttribute()
+    {
+        $node = $this->createSelectNode(array('foo' => false, 'bar' => true), array(), '');
+        $field = new ChoiceFormField($node);
+
+        $this->assertEquals('bar', $field->getValue());
+    }
+
+    public function testMultipleSelects()
+    {
+        $node = $this->createSelectNode(array('foo' => false, 'bar' => false), array('multiple' => 'multiple'));
+        $field = new ChoiceFormField($node);
+
+        $this->assertEquals(array(), $field->getValue(), '->setValue() returns an empty array if multiple is true and no option is selected');
+
+        $field->setValue('foo');
+        $this->assertEquals(array('foo'), $field->getValue(), '->setValue() returns an array of options if multiple is true');
+
+        $field->setValue('bar');
+        $this->assertEquals(array('bar'), $field->getValue(), '->setValue() returns an array of options if multiple is true');
+
+        $field->setValue(array('foo', 'bar'));
+        $this->assertEquals(array('foo', 'bar'), $field->getValue(), '->setValue() returns an array of options if multiple is true');
+
+        $node = $this->createSelectNode(array('foo' => true, 'bar' => true), array('multiple' => 'multiple'));
+        $field = new ChoiceFormField($node);
+
+        $this->assertEquals(array('foo', 'bar'), $field->getValue(), '->getValue() returns the selected options');
+
+        try {
+            $field->setValue(array('foobar'));
+            $this->fail('->setValue() throws an \InvalidArgumentException if the value is not one of the options');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->setValue() throws an \InvalidArgumentException if the value is not one of the options');
+        }
+    }
+
+    public function testRadioButtons()
+    {
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo'));
+        $field = new ChoiceFormField($node);
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'bar'));
+        $field->addChoice($node);
+
+        $this->assertFalse($field->hasValue(), '->hasValue() returns false when no radio button is selected');
+        $this->assertNull($field->getValue(), '->getValue() returns null if no radio button is selected');
+        $this->assertFalse($field->isMultiple(), '->isMultiple() returns false for radio buttons');
+
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo'));
+        $field = new ChoiceFormField($node);
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'bar', 'checked' => 'checked'));
+        $field->addChoice($node);
+
+        $this->assertTrue($field->hasValue(), '->hasValue() returns true when a radio button is selected');
+        $this->assertEquals('bar', $field->getValue(), '->getValue() returns the value attribute of the selected radio button');
+
+        $field->setValue('foo');
+        $this->assertEquals('foo', $field->getValue(), '->setValue() changes the selected radio button');
+
+        try {
+            $field->setValue('foobar');
+            $this->fail('->setValue() throws an \InvalidArgumentException if the value is not one of the radio button values');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->setValue() throws an \InvalidArgumentException if the value is not one of the radio button values');
+        }
+    }
+
+    public function testRadioButtonsWithEmptyBooleanAttribute()
+    {
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo'));
+        $field = new ChoiceFormField($node);
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'bar', 'checked' => ''));
+        $field->addChoice($node);
+
+        $this->assertTrue($field->hasValue(), '->hasValue() returns true when a radio button is selected');
+        $this->assertEquals('bar', $field->getValue(), '->getValue() returns the value attribute of the selected radio button');
+    }
+
+    public function testRadioButtonIsDisabled()
+    {
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo', 'disabled' => 'disabled'));
+        $field = new ChoiceFormField($node);
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'bar'));
+        $field->addChoice($node);
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'baz', 'disabled' => ''));
+        $field->addChoice($node);
+
+        $field->select('foo');
+        $this->assertEquals('foo', $field->getValue(), '->getValue() returns the value attribute of the selected radio button');
+        $this->assertTrue($field->isDisabled());
+
+        $field->select('bar');
+        $this->assertEquals('bar', $field->getValue(), '->getValue() returns the value attribute of the selected radio button');
+        $this->assertFalse($field->isDisabled());
+
+        $field->select('baz');
+        $this->assertEquals('baz', $field->getValue(), '->getValue() returns the value attribute of the selected radio button');
+        $this->assertTrue($field->isDisabled());
+    }
+
+    public function testCheckboxes()
+    {
+        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name'));
+        $field = new ChoiceFormField($node);
+
+        $this->assertFalse($field->hasValue(), '->hasValue() returns false when the checkbox is not checked');
+        $this->assertNull($field->getValue(), '->getValue() returns null if the checkbox is not checked');
+        $this->assertFalse($field->isMultiple(), '->hasValue() returns false for checkboxes');
+        try {
+            $field->addChoice(new \DOMElement('input'));
+            $this->fail('->addChoice() throws a \LogicException for checkboxes');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->initialize() throws a \LogicException for checkboxes');
+        }
+
+        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'checked' => 'checked'));
+        $field = new ChoiceFormField($node);
+
+        $this->assertTrue($field->hasValue(), '->hasValue() returns true when the checkbox is checked');
+        $this->assertEquals('on', $field->getValue(), '->getValue() returns 1 if the checkbox is checked and has no value attribute');
+
+        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'checked' => 'checked', 'value' => 'foo'));
+        $field = new ChoiceFormField($node);
+
+        $this->assertEquals('foo', $field->getValue(), '->getValue() returns the value attribute if the checkbox is checked');
+
+        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'checked' => 'checked', 'value' => 'foo'));
+        $field = new ChoiceFormField($node);
+
+        $field->setValue(false);
+        $this->assertNull($field->getValue(), '->setValue() unchecks the checkbox is value is false');
+
+        $field->setValue(true);
+        $this->assertEquals('foo', $field->getValue(), '->setValue() checks the checkbox is value is true');
+
+        try {
+            $field->setValue('bar');
+            $this->fail('->setValue() throws an \InvalidArgumentException if the value is not one from the value attribute');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->setValue() throws an \InvalidArgumentException if the value is not one from the value attribute');
+        }
+    }
+
+    public function testCheckboxWithEmptyBooleanAttribute()
+    {
+        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'value' => 'foo', 'checked' => ''));
+        $field = new ChoiceFormField($node);
+
+        $this->assertTrue($field->hasValue(), '->hasValue() returns true when the checkbox is checked');
+        $this->assertEquals('foo', $field->getValue());
+    }
+
+    public function testTick()
+    {
+        $node = $this->createSelectNode(array('foo' => false, 'bar' => false));
+        $field = new ChoiceFormField($node);
+
+        try {
+            $field->tick();
+            $this->fail('->tick() throws a \LogicException for select boxes');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->tick() throws a \LogicException for select boxes');
+        }
+
+        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name'));
+        $field = new ChoiceFormField($node);
+        $field->tick();
+        $this->assertEquals('on', $field->getValue(), '->tick() ticks checkboxes');
+    }
+
+    public function testUntick()
+    {
+        $node = $this->createSelectNode(array('foo' => false, 'bar' => false));
+        $field = new ChoiceFormField($node);
+
+        try {
+            $field->untick();
+            $this->fail('->untick() throws a \LogicException for select boxes');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->untick() throws a \LogicException for select boxes');
+        }
+
+        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'checked' => 'checked'));
+        $field = new ChoiceFormField($node);
+        $field->untick();
+        $this->assertNull($field->getValue(), '->untick() unticks checkboxes');
+    }
+
+    public function testSelect()
+    {
+        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'checked' => 'checked'));
+        $field = new ChoiceFormField($node);
+        $field->select(true);
+        $this->assertEquals('on', $field->getValue(), '->select() changes the value of the field');
+        $field->select(false);
+        $this->assertNull($field->getValue(), '->select() changes the value of the field');
+
+        $node = $this->createSelectNode(array('foo' => false, 'bar' => false));
+        $field = new ChoiceFormField($node);
+        $field->select('foo');
+        $this->assertEquals('foo', $field->getValue(), '->select() changes the selected option');
+    }
+
+    public function testOptionWithNoValue()
+    {
+        $node = $this->createSelectNodeWithEmptyOption(array('foo' => false, 'bar' => false));
+        $field = new ChoiceFormField($node);
+        $this->assertEquals('foo', $field->getValue());
+
+        $node = $this->createSelectNodeWithEmptyOption(array('foo' => false, 'bar' => true));
+        $field = new ChoiceFormField($node);
+        $this->assertEquals('bar', $field->getValue());
+        $field->select('foo');
+        $this->assertEquals('foo', $field->getValue(), '->select() changes the selected option');
+    }
+
+    public function testDisableValidation()
+    {
+        $node = $this->createSelectNode(array('foo' => false, 'bar' => false));
+        $field = new ChoiceFormField($node);
+        $field->disableValidation();
+        $field->setValue('foobar');
+        $this->assertEquals('foobar', $field->getValue(), '->disableValidation() allows to set a value which is not in the selected options.');
+
+        $node = $this->createSelectNode(array('foo' => false, 'bar' => false), array('multiple' => 'multiple'));
+        $field = new ChoiceFormField($node);
+        $field->disableValidation();
+        $field->setValue(array('foobar'));
+        $this->assertEquals(array('foobar'), $field->getValue(), '->disableValidation() allows to set a value which is not in the selected options.');
+    }
+
+    protected function createSelectNode($options, $attributes = array(), $selectedAttrText = 'selected')
+    {
+        $document = new \DOMDocument();
+        $node = $document->createElement('select');
+
+        foreach ($attributes as $name => $value) {
+            $node->setAttribute($name, $value);
+        }
+        $node->setAttribute('name', 'name');
+
+        foreach ($options as $value => $selected) {
+            $option = $document->createElement('option', $value);
+            $option->setAttribute('value', $value);
+            if ($selected) {
+                $option->setAttribute('selected', $selectedAttrText);
+            }
+            $node->appendChild($option);
+        }
+
+        return $node;
+    }
+
+    protected function createSelectNodeWithEmptyOption($options, $attributes = array())
+    {
+        $document = new \DOMDocument();
+        $node = $document->createElement('select');
+
+        foreach ($attributes as $name => $value) {
+            $node->setAttribute($name, $value);
+        }
+        $node->setAttribute('name', 'name');
+
+        foreach ($options as $value => $selected) {
+            $option = $document->createElement('option', $value);
+            if ($selected) {
+                $option->setAttribute('selected', 'selected');
+            }
+            $node->appendChild($option);
+        }
+
+        return $node;
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.php
new file mode 100644
index 0000000..3ce49a4
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.php
@@ -0,0 +1,114 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Tests\Field;
+
+use Symfony\Component\DomCrawler\Field\FileFormField;
+
+class FileFormFieldTest extends FormFieldTestCase
+{
+    public function testInitialize()
+    {
+        $node = $this->createNode('input', '', array('type' => 'file'));
+        $field = new FileFormField($node);
+
+        $this->assertEquals(array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => UPLOAD_ERR_NO_FILE, 'size' => 0), $field->getValue(), '->initialize() sets the value of the field to no file uploaded');
+
+        $node = $this->createNode('textarea', '');
+        try {
+            $field = new FileFormField($node);
+            $this->fail('->initialize() throws a \LogicException if the node is not an input field');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is not an input field');
+        }
+
+        $node = $this->createNode('input', '', array('type' => 'text'));
+        try {
+            $field = new FileFormField($node);
+            $this->fail('->initialize() throws a \LogicException if the node is not a file input field');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is not a file input field');
+        }
+    }
+
+    /**
+     * @dataProvider getSetValueMethods
+     */
+    public function testSetValue($method)
+    {
+        $node = $this->createNode('input', '', array('type' => 'file'));
+        $field = new FileFormField($node);
+
+        $field->$method(null);
+        $this->assertEquals(array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => UPLOAD_ERR_NO_FILE, 'size' => 0), $field->getValue(), "->$method() clears the uploaded file if the value is null");
+
+        $field->$method(__FILE__);
+        $value = $field->getValue();
+
+        $this->assertEquals(basename(__FILE__), $value['name'], "->$method() sets the name of the file field");
+        $this->assertEquals('', $value['type'], "->$method() sets the type of the file field");
+        $this->assertInternalType('string', $value['tmp_name'], "->$method() sets the tmp_name of the file field");
+        $this->assertFileExists($value['tmp_name'], "->$method() creates a copy of the file at the tmp_name path");
+        $this->assertEquals(0, $value['error'], "->$method() sets the error of the file field");
+        $this->assertEquals(filesize(__FILE__), $value['size'], "->$method() sets the size of the file field");
+
+        $origInfo = pathinfo(__FILE__);
+        $tmpInfo = pathinfo($value['tmp_name']);
+        $this->assertEquals(
+            $origInfo['extension'],
+            $tmpInfo['extension'],
+            "->$method() keeps the same file extension in the tmp_name copy"
+        );
+
+        $field->$method(__DIR__.'/../Fixtures/no-extension');
+        $value = $field->getValue();
+
+        $this->assertArrayNotHasKey(
+            'extension',
+            pathinfo($value['tmp_name']),
+            "->$method() does not add a file extension in the tmp_name copy"
+        );
+    }
+
+    public function getSetValueMethods()
+    {
+        return array(
+            array('setValue'),
+            array('upload'),
+        );
+    }
+
+    public function testSetErrorCode()
+    {
+        $node = $this->createNode('input', '', array('type' => 'file'));
+        $field = new FileFormField($node);
+
+        $field->setErrorCode(UPLOAD_ERR_FORM_SIZE);
+        $value = $field->getValue();
+        $this->assertEquals(UPLOAD_ERR_FORM_SIZE, $value['error'], '->setErrorCode() sets the file input field error code');
+
+        try {
+            $field->setErrorCode('foobar');
+            $this->fail('->setErrorCode() throws a \InvalidArgumentException if the error code is not valid');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->setErrorCode() throws a \InvalidArgumentException if the error code is not valid');
+        }
+    }
+
+    public function testSetRawFilePath()
+    {
+        $node = $this->createNode('input', '', array('type' => 'file'));
+        $field = new FileFormField($node);
+        $field->setFilePath(__FILE__);
+
+        $this->assertEquals(__FILE__, $field->getValue());
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.php
new file mode 100644
index 0000000..510f762
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Tests\Field;
+
+use Symfony\Component\DomCrawler\Field\InputFormField;
+
+class FormFieldTest extends FormFieldTestCase
+{
+    public function testGetName()
+    {
+        $node = $this->createNode('input', '', array('type' => 'text', 'name' => 'name', 'value' => 'value'));
+        $field = new InputFormField($node);
+
+        $this->assertEquals('name', $field->getName(), '->getName() returns the name of the field');
+    }
+
+    public function testGetSetHasValue()
+    {
+        $node = $this->createNode('input', '', array('type' => 'text', 'name' => 'name', 'value' => 'value'));
+        $field = new InputFormField($node);
+
+        $this->assertEquals('value', $field->getValue(), '->getValue() returns the value of the field');
+
+        $field->setValue('foo');
+        $this->assertEquals('foo', $field->getValue(), '->setValue() sets the value of the field');
+
+        $this->assertTrue($field->hasValue(), '->hasValue() always returns true');
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.php
new file mode 100644
index 0000000..26b1b0e
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Tests\Field;
+
+class FormFieldTestCase extends \PHPUnit_Framework_TestCase
+{
+    protected function createNode($tag, $value, $attributes = array())
+    {
+        $document = new \DOMDocument();
+        $node = $document->createElement($tag, $value);
+
+        foreach ($attributes as $name => $value) {
+            $node->setAttribute($name, $value);
+        }
+
+        return $node;
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.php
new file mode 100644
index 0000000..193d301
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Tests\Field;
+
+use Symfony\Component\DomCrawler\Field\InputFormField;
+
+class InputFormFieldTest extends FormFieldTestCase
+{
+    public function testInitialize()
+    {
+        $node = $this->createNode('input', '', array('type' => 'text', 'name' => 'name', 'value' => 'value'));
+        $field = new InputFormField($node);
+
+        $this->assertEquals('value', $field->getValue(), '->initialize() sets the value of the field to the value attribute value');
+
+        $node = $this->createNode('textarea', '');
+        try {
+            $field = new InputFormField($node);
+            $this->fail('->initialize() throws a \LogicException if the node is not an input');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is not an input');
+        }
+
+        $node = $this->createNode('input', '', array('type' => 'checkbox'));
+        try {
+            $field = new InputFormField($node);
+            $this->fail('->initialize() throws a \LogicException if the node is a checkbox');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is a checkbox');
+        }
+
+        $node = $this->createNode('input', '', array('type' => 'file'));
+        try {
+            $field = new InputFormField($node);
+            $this->fail('->initialize() throws a \LogicException if the node is a file');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is a file');
+        }
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.php
new file mode 100644
index 0000000..5d4d003
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Tests\Field;
+
+use Symfony\Component\DomCrawler\Field\TextareaFormField;
+
+class TextareaFormFieldTest extends FormFieldTestCase
+{
+    public function testInitialize()
+    {
+        $node = $this->createNode('textarea', 'foo bar');
+        $field = new TextareaFormField($node);
+
+        $this->assertEquals('foo bar', $field->getValue(), '->initialize() sets the value of the field to the textarea node value');
+
+        $node = $this->createNode('input', '');
+        try {
+            $field = new TextareaFormField($node);
+            $this->fail('->initialize() throws a \LogicException if the node is not a textarea');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is not a textarea');
+        }
+
+        // Ensure that valid HTML can be used on a textarea.
+        $node = $this->createNode('textarea', 'foo bar <h1>Baz</h1>');
+        $field = new TextareaFormField($node);
+
+        $this->assertEquals('foo bar <h1>Baz</h1>', $field->getValue(), '->initialize() sets the value of the field to the textarea node value');
+
+        // Ensure that we don't do any DOM manipulation/validation by passing in
+        // "invalid" HTML.
+        $node = $this->createNode('textarea', 'foo bar <h1>Baz</h2>');
+        $field = new TextareaFormField($node);
+
+        $this->assertEquals('foo bar <h1>Baz</h2>', $field->getValue(), '->initialize() sets the value of the field to the textarea node value');
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Fixtures/no-extension b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Fixtures/no-extension
new file mode 100644
index 0000000..345e6ae
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Fixtures/no-extension
@@ -0,0 +1 @@
+Test
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.html b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.html
new file mode 100644
index 0000000..c26dc77
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.html
@@ -0,0 +1,8 @@
+<html>
+    <head>
+        <meta http-equiv="content-type" content="text/html;charset=windows-1250">
+    </head>
+    <body>
+        <p>Žèýù</p>
+    </body>
+</html>
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/FormTest.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/FormTest.php
new file mode 100644
index 0000000..5fd2b18
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/FormTest.php
@@ -0,0 +1,943 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Tests;
+
+use Symfony\Component\DomCrawler\Form;
+use Symfony\Component\DomCrawler\FormFieldRegistry;
+use Symfony\Component\DomCrawler\Field;
+
+class FormTest extends \PHPUnit_Framework_TestCase
+{
+    public static function setUpBeforeClass()
+    {
+        // Ensure that the private helper class FormFieldRegistry is loaded
+        class_exists('Symfony\\Component\\DomCrawler\\Form');
+    }
+
+    public function testConstructorThrowsExceptionIfTheNodeHasNoFormAncestor()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('
+            <html>
+                <input type="submit" />
+                <form>
+                    <input type="foo" />
+                </form>
+                <button />
+            </html>
+        ');
+
+        $nodes = $dom->getElementsByTagName('input');
+
+        try {
+            $form = new Form($nodes->item(0), 'http://example.com');
+            $this->fail('__construct() throws a \\LogicException if the node has no form ancestor');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '__construct() throws a \\LogicException if the node has no form ancestor');
+        }
+
+        try {
+            $form = new Form($nodes->item(1), 'http://example.com');
+            $this->fail('__construct() throws a \\LogicException if the input type is not submit, button, or image');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '__construct() throws a \\LogicException if the input type is not submit, button, or image');
+        }
+
+        $nodes = $dom->getElementsByTagName('button');
+
+        try {
+            $form = new Form($nodes->item(0), 'http://example.com');
+            $this->fail('__construct() throws a \\LogicException if the node has no form ancestor');
+        } catch (\LogicException $e) {
+            $this->assertTrue(true, '__construct() throws a \\LogicException if the node has no form ancestor');
+        }
+    }
+
+    /**
+     * __construct() should throw \\LogicException if the form attribute is invalid.
+     *
+     * @expectedException \LogicException
+     */
+    public function testConstructorThrowsExceptionIfNoRelatedForm()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('
+            <html>
+                <form id="bar">
+                    <input type="submit" form="nonexistent" />
+                </form>
+                <input type="text" form="nonexistent" />
+                <button />
+            </html>
+        ');
+
+        $nodes = $dom->getElementsByTagName('input');
+
+        $form = new Form($nodes->item(0), 'http://example.com');
+        $form = new Form($nodes->item(1), 'http://example.com');
+    }
+
+    public function testConstructorLoadsOnlyFieldsOfTheRightForm()
+    {
+        $dom = $this->createTestMultipleForm();
+
+        $nodes = $dom->getElementsByTagName('form');
+        $buttonElements = $dom->getElementsByTagName('button');
+
+        $form = new Form($nodes->item(0), 'http://example.com');
+        $this->assertCount(3, $form->all());
+
+        $form = new Form($buttonElements->item(1), 'http://example.com');
+        $this->assertCount(5, $form->all());
+    }
+
+    public function testConstructorHandlesFormAttribute()
+    {
+        $dom = $this->createTestHtml5Form();
+
+        $inputElements = $dom->getElementsByTagName('input');
+        $buttonElements = $dom->getElementsByTagName('button');
+
+        // Tests if submit buttons are correctly assigned to forms
+        $form1 = new Form($buttonElements->item(1), 'http://example.com');
+        $this->assertSame($dom->getElementsByTagName('form')->item(0), $form1->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');
+
+        $form1 = new Form($inputElements->item(3), 'http://example.com');
+        $this->assertSame($dom->getElementsByTagName('form')->item(0), $form1->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');
+
+        $form2 = new Form($buttonElements->item(0), 'http://example.com');
+        $this->assertSame($dom->getElementsByTagName('form')->item(1), $form2->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');
+    }
+
+    public function testConstructorHandlesFormValues()
+    {
+        $dom = $this->createTestHtml5Form();
+
+        $inputElements = $dom->getElementsByTagName('input');
+        $buttonElements = $dom->getElementsByTagName('button');
+
+        $form1 = new Form($inputElements->item(3), 'http://example.com');
+        $form2 = new Form($buttonElements->item(0), 'http://example.com');
+
+        // Tests if form values are correctly assigned to forms
+        $values1 = array(
+            'apples' => array('1', '2'),
+            'form_name' => 'form-1',
+            'button_1' => 'Capture fields',
+            'outer_field' => 'success',
+        );
+        $values2 = array(
+            'oranges' => array('1', '2', '3'),
+            'form_name' => 'form_2',
+            'button_2' => '',
+            'app_frontend_form_type_contact_form_type' => array('contactType' => '', 'firstName' => 'John'),
+        );
+
+        $this->assertEquals($values1, $form1->getPhpValues(), 'HTML5-compliant form attribute handled incorrectly');
+        $this->assertEquals($values2, $form2->getPhpValues(), 'HTML5-compliant form attribute handled incorrectly');
+    }
+
+    public function testMultiValuedFields()
+    {
+        $form = $this->createForm('<form>
+            <input type="text" name="foo[4]" value="foo" disabled="disabled" />
+            <input type="text" name="foo" value="foo" disabled="disabled" />
+            <input type="text" name="foo[2]" value="foo" disabled="disabled" />
+            <input type="text" name="foo[]" value="foo" disabled="disabled" />
+            <input type="text" name="bar[foo][]" value="foo" disabled="disabled" />
+            <input type="text" name="bar[foo][foobar]" value="foo" disabled="disabled" />
+            <input type="submit" />
+        </form>
+        ');
+
+        $this->assertEquals(
+            array_keys($form->all()),
+            array('foo[2]', 'foo[3]', 'bar[foo][0]', 'bar[foo][foobar]')
+        );
+
+        $this->assertEquals($form->get('foo[2]')->getValue(), 'foo');
+        $this->assertEquals($form->get('foo[3]')->getValue(), 'foo');
+        $this->assertEquals($form->get('bar[foo][0]')->getValue(), 'foo');
+        $this->assertEquals($form->get('bar[foo][foobar]')->getValue(), 'foo');
+
+        $form['foo[2]'] = 'bar';
+        $form['foo[3]'] = 'bar';
+
+        $this->assertEquals($form->get('foo[2]')->getValue(), 'bar');
+        $this->assertEquals($form->get('foo[3]')->getValue(), 'bar');
+
+        $form['bar'] = array('foo' => array('0' => 'bar', 'foobar' => 'foobar'));
+
+        $this->assertEquals($form->get('bar[foo][0]')->getValue(), 'bar');
+        $this->assertEquals($form->get('bar[foo][foobar]')->getValue(), 'foobar');
+    }
+
+    /**
+     * @dataProvider provideInitializeValues
+     */
+    public function testConstructor($message, $form, $values)
+    {
+        $form = $this->createForm('<form>'.$form.'</form>');
+        $this->assertEquals(
+            $values,
+            array_map(function ($field) {
+                    $class = get_class($field);
+
+                    return array(substr($class, strrpos($class, '\\') + 1), $field->getValue());
+                },
+                $form->all()
+            ),
+            '->getDefaultValues() '.$message
+        );
+    }
+
+    public function provideInitializeValues()
+    {
+        return array(
+            array(
+                'does not take into account input fields without a name attribute',
+                '<input type="text" value="foo" />
+                 <input type="submit" />',
+                array(),
+            ),
+            array(
+                'does not take into account input fields with an empty name attribute value',
+                '<input type="text" name="" value="foo" />
+                 <input type="submit" />',
+                array(),
+            ),
+            array(
+                'takes into account disabled input fields',
+                '<input type="text" name="foo" value="foo" disabled="disabled" />
+                 <input type="submit" />',
+                array('foo' => array('InputFormField', 'foo')),
+            ),
+            array(
+                'appends the submitted button value',
+                '<input type="submit" name="bar" value="bar" />',
+                array('bar' => array('InputFormField', 'bar')),
+            ),
+            array(
+                'appends the submitted button value for Button element',
+                '<button type="submit" name="bar" value="bar">Bar</button>',
+                array('bar' => array('InputFormField', 'bar')),
+            ),
+            array(
+                'appends the submitted button value but not other submit buttons',
+                '<input type="submit" name="bar" value="bar" />
+                 <input type="submit" name="foobar" value="foobar" />',
+                 array('foobar' => array('InputFormField', 'foobar')),
+            ),
+            array(
+                'turns an image input into x and y fields',
+                '<input type="image" name="bar" />',
+                array('bar.x' => array('InputFormField', '0'), 'bar.y' => array('InputFormField', '0')),
+            ),
+            array(
+                'returns textareas',
+                '<textarea name="foo">foo</textarea>
+                 <input type="submit" />',
+                 array('foo' => array('TextareaFormField', 'foo')),
+            ),
+            array(
+                'returns inputs',
+                '<input type="text" name="foo" value="foo" />
+                 <input type="submit" />',
+                 array('foo' => array('InputFormField', 'foo')),
+            ),
+            array(
+                'returns checkboxes',
+                '<input type="checkbox" name="foo" value="foo" checked="checked" />
+                 <input type="submit" />',
+                 array('foo' => array('ChoiceFormField', 'foo')),
+            ),
+            array(
+                'returns not-checked checkboxes',
+                '<input type="checkbox" name="foo" value="foo" />
+                 <input type="submit" />',
+                 array('foo' => array('ChoiceFormField', false)),
+            ),
+            array(
+                'returns radio buttons',
+                '<input type="radio" name="foo" value="foo" />
+                 <input type="radio" name="foo" value="bar" checked="bar" />
+                 <input type="submit" />',
+                 array('foo' => array('ChoiceFormField', 'bar')),
+            ),
+            array(
+                'returns file inputs',
+                '<input type="file" name="foo" />
+                 <input type="submit" />',
+                 array('foo' => array('FileFormField', array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0))),
+            ),
+        );
+    }
+
+    public function testGetFormNode()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('<html><form><input type="submit" /></form></html>');
+
+        $form = new Form($dom->getElementsByTagName('input')->item(0), 'http://example.com');
+
+        $this->assertSame($dom->getElementsByTagName('form')->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form');
+    }
+
+    public function testGetFormNodeFromNamedForm()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('<html><form name="my_form"><input type="submit" /></form></html>');
+
+        $form = new Form($dom->getElementsByTagName('form')->item(0), 'http://example.com');
+
+        $this->assertSame($dom->getElementsByTagName('form')->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form');
+    }
+
+    public function testGetMethod()
+    {
+        $form = $this->createForm('<form><input type="submit" /></form>');
+        $this->assertEquals('GET', $form->getMethod(), '->getMethod() returns get if no method is defined');
+
+        $form = $this->createForm('<form method="post"><input type="submit" /></form>');
+        $this->assertEquals('POST', $form->getMethod(), '->getMethod() returns the method attribute value of the form');
+
+        $form = $this->createForm('<form method="post"><input type="submit" /></form>', 'put');
+        $this->assertEquals('PUT', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided');
+
+        $form = $this->createForm('<form method="post"><input type="submit" /></form>', 'delete');
+        $this->assertEquals('DELETE', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided');
+
+        $form = $this->createForm('<form method="post"><input type="submit" /></form>', 'patch');
+        $this->assertEquals('PATCH', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided');
+    }
+
+    public function testGetSetValue()
+    {
+        $form = $this->createForm('<form><input type="text" name="foo" value="foo" /><input type="submit" /></form>');
+
+        $this->assertEquals('foo', $form['foo']->getValue(), '->offsetGet() returns the value of a form field');
+
+        $form['foo'] = 'bar';
+
+        $this->assertEquals('bar', $form['foo']->getValue(), '->offsetSet() changes the value of a form field');
+
+        try {
+            $form['foobar'] = 'bar';
+            $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the field does not exist');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the field does not exist');
+        }
+
+        try {
+            $form['foobar'];
+            $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the field does not exist');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the field does not exist');
+        }
+    }
+
+    public function testSetValueOnMultiValuedFieldsWithMalformedName()
+    {
+        $form = $this->createForm('<form><input type="text" name="foo[bar]" value="bar" /><input type="text" name="foo[baz]" value="baz" /><input type="submit" /></form>');
+
+        try {
+            $form['foo[bar'] = 'bar';
+            $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the name is malformed.');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the name is malformed.');
+        }
+    }
+
+    public function testDisableValidation()
+    {
+        $form = $this->createForm('<form>
+            <select name="foo[bar]">
+                <option value="bar">bar</option>
+            </select>
+            <select name="foo[baz]">
+                <option value="foo">foo</option>
+            </select>
+            <input type="submit" />
+        </form>');
+
+        $form->disableValidation();
+
+        $form['foo[bar]']->select('foo');
+        $form['foo[baz]']->select('bar');
+        $this->assertEquals('foo', $form['foo[bar]']->getValue(), '->disableValidation() disables validation of all ChoiceFormField.');
+        $this->assertEquals('bar', $form['foo[baz]']->getValue(), '->disableValidation() disables validation of all ChoiceFormField.');
+    }
+
+    public function testOffsetUnset()
+    {
+        $form = $this->createForm('<form><input type="text" name="foo" value="foo" /><input type="submit" /></form>');
+        unset($form['foo']);
+        $this->assertFalse(isset($form['foo']), '->offsetUnset() removes a field');
+    }
+
+    public function testOffsetExists()
+    {
+        $form = $this->createForm('<form><input type="text" name="foo" value="foo" /><input type="submit" /></form>');
+
+        $this->assertTrue(isset($form['foo']), '->offsetExists() return true if the field exists');
+        $this->assertFalse(isset($form['bar']), '->offsetExists() return false if the field does not exist');
+    }
+
+    public function testGetValues()
+    {
+        $form = $this->createForm('<form><input type="text" name="foo[bar]" value="foo" /><input type="text" name="bar" value="bar" /><select multiple="multiple" name="baz[]"></select><input type="submit" /></form>');
+        $this->assertEquals(array('foo[bar]' => 'foo', 'bar' => 'bar', 'baz' => array()), $form->getValues(), '->getValues() returns all form field values');
+
+        $form = $this->createForm('<form><input type="checkbox" name="foo" value="foo" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include not-checked checkboxes');
+
+        $form = $this->createForm('<form><input type="file" name="foo" value="foo" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include file input fields');
+
+        $form = $this->createForm('<form><input type="text" name="foo" value="foo" disabled="disabled" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include disabled fields');
+    }
+
+    public function testSetValues()
+    {
+        $form = $this->createForm('<form><input type="checkbox" name="foo" value="foo" checked="checked" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $form->setValues(array('foo' => false, 'bar' => 'foo'));
+        $this->assertEquals(array('bar' => 'foo'), $form->getValues(), '->setValues() sets the values of fields');
+    }
+
+    public function testMultiselectSetValues()
+    {
+        $form = $this->createForm('<form><select multiple="multiple" name="multi"><option value="foo">foo</option><option value="bar">bar</option></select><input type="submit" /></form>');
+        $form->setValues(array('multi' => array("foo", "bar")));
+        $this->assertEquals(array('multi' => array('foo', 'bar')), $form->getValues(), '->setValue() sets the values of select');
+    }
+
+    public function testGetPhpValues()
+    {
+        $form = $this->createForm('<form><input type="text" name="foo[bar]" value="foo" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array('foo' => array('bar' => 'foo'), 'bar' => 'bar'), $form->getPhpValues(), '->getPhpValues() converts keys with [] to arrays');
+
+        $form = $this->createForm('<form><input type="text" name="fo.o[ba.r]" value="foo" /><input type="text" name="ba r" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array('fo.o' => array('ba.r' => 'foo'), 'ba r' => 'bar'), $form->getPhpValues(), '->getPhpValues() preserves periods and spaces in names');
+
+        $form = $this->createForm('<form><input type="text" name="fo.o[ba.r][]" value="foo" /><input type="text" name="fo.o[ba.r][ba.z]" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array('fo.o' => array('ba.r' => array('foo', 'ba.z' => 'bar'))), $form->getPhpValues(), '->getPhpValues() preserves periods and spaces in names recursively');
+
+        $form = $this->createForm('<form><input type="text" name="foo[bar]" value="foo" /><input type="text" name="bar" value="bar" /><select multiple="multiple" name="baz[]"></select><input type="submit" /></form>');
+        $this->assertEquals(array('foo' => array('bar' => 'foo'), 'bar' => 'bar'), $form->getPhpValues(), "->getPhpValues() doesn't return empty values");
+    }
+
+    public function testGetFiles()
+    {
+        $form = $this->createForm('<form><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array(), $form->getFiles(), '->getFiles() returns an empty array if method is get');
+
+        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for POST');
+
+        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>', 'put');
+        $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for PUT');
+
+        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>', 'delete');
+        $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for DELETE');
+
+        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>', 'patch');
+        $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for PATCH');
+
+        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" disabled="disabled" /><input type="submit" /></form>');
+        $this->assertEquals(array(), $form->getFiles(), '->getFiles() does not include disabled file fields');
+    }
+
+    public function testGetPhpFiles()
+    {
+        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array('foo' => array('bar' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0))), $form->getPhpFiles(), '->getPhpFiles() converts keys with [] to arrays');
+
+        $form = $this->createForm('<form method="post"><input type="file" name="f.o o[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array('f.o o' => array('bar' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0))), $form->getPhpFiles(), '->getPhpFiles() preserves periods and spaces in names');
+
+        $form = $this->createForm('<form method="post"><input type="file" name="f.o o[bar][ba.z]" /><input type="file" name="f.o o[bar][]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $this->assertEquals(array('f.o o' => array('bar' => array('ba.z' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0), array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)))), $form->getPhpFiles(), '->getPhpFiles() preserves periods and spaces in names recursively');
+    }
+
+    /**
+     * @dataProvider provideGetUriValues
+     */
+    public function testGetUri($message, $form, $values, $uri, $method = null)
+    {
+        $form = $this->createForm($form, $method);
+        $form->setValues($values);
+
+        $this->assertEquals('http://example.com'.$uri, $form->getUri(), '->getUri() '.$message);
+    }
+
+    public function testGetBaseUri()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('<form method="post" action="foo.php"><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+
+        $nodes = $dom->getElementsByTagName('input');
+        $form = new Form($nodes->item($nodes->length - 1), 'http://www.foo.com/');
+        $this->assertEquals('http://www.foo.com/foo.php', $form->getUri());
+    }
+
+    public function testGetUriWithAnchor()
+    {
+        $form = $this->createForm('<form action="#foo"><input type="submit" /></form>', null, 'http://example.com/id/123');
+
+        $this->assertEquals('http://example.com/id/123#foo', $form->getUri());
+    }
+
+    public function testGetUriActionAbsolute()
+    {
+        $formHtml = '<form id="login_form" action="https://login.foo.com/login.php?login_attempt=1" method="POST"><input type="text" name="foo" value="foo" /><input type="submit" /></form>';
+
+        $form = $this->createForm($formHtml);
+        $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form');
+
+        $form = $this->createForm($formHtml, null, 'https://login.foo.com');
+        $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form');
+
+        $form = $this->createForm($formHtml, null, 'https://login.foo.com/bar/');
+        $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form');
+
+        // The action URI haven't the same domain Host have an another domain as Host
+        $form = $this->createForm($formHtml, null, 'https://www.foo.com');
+        $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form');
+
+        $form = $this->createForm($formHtml, null, 'https://www.foo.com/bar/');
+        $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form');
+    }
+
+    public function testGetUriAbsolute()
+    {
+        $form = $this->createForm('<form action="foo"><input type="submit" /></form>', null, 'http://localhost/foo/');
+        $this->assertEquals('http://localhost/foo/foo', $form->getUri(), '->getUri() returns absolute URIs');
+
+        $form = $this->createForm('<form action="/foo"><input type="submit" /></form>', null, 'http://localhost/foo/');
+        $this->assertEquals('http://localhost/foo', $form->getUri(), '->getUri() returns absolute URIs');
+    }
+
+    public function testGetUriWithOnlyQueryString()
+    {
+        $form = $this->createForm('<form action="?get=param"><input type="submit" /></form>', null, 'http://localhost/foo/bar');
+        $this->assertEquals('http://localhost/foo/bar?get=param', $form->getUri(), '->getUri() returns absolute URIs only if the host has been defined in the constructor');
+    }
+
+    public function testGetUriWithoutAction()
+    {
+        $form = $this->createForm('<form><input type="submit" /></form>', null, 'http://localhost/foo/bar');
+        $this->assertEquals('http://localhost/foo/bar', $form->getUri(), '->getUri() returns path if no action defined');
+    }
+
+    public function provideGetUriValues()
+    {
+        return array(
+            array(
+                'returns the URI of the form',
+                '<form action="/foo"><input type="submit" /></form>',
+                array(),
+                '/foo',
+            ),
+            array(
+                'appends the form values if the method is get',
+                '<form action="/foo"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
+                array(),
+                '/foo?foo=foo',
+            ),
+            array(
+                'appends the form values and merges the submitted values',
+                '<form action="/foo"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
+                array('foo' => 'bar'),
+                '/foo?foo=bar',
+            ),
+            array(
+                'does not append values if the method is post',
+                '<form action="/foo" method="post"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
+                array(),
+                '/foo',
+            ),
+            array(
+                'does not append values if the method is patch',
+                '<form action="/foo" method="post"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
+                array(),
+                '/foo',
+                'PUT',
+            ),
+            array(
+                'does not append values if the method is delete',
+                '<form action="/foo" method="post"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
+                array(),
+                '/foo',
+                'DELETE',
+            ),
+            array(
+                'does not append values if the method is put',
+                '<form action="/foo" method="post"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
+                array(),
+                '/foo',
+                'PATCH',
+            ),
+            array(
+                'appends the form values to an existing query string',
+                '<form action="/foo?bar=bar"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
+                array(),
+                '/foo?bar=bar&foo=foo',
+            ),
+            array(
+                'returns an empty URI if the action is empty',
+                '<form><input type="submit" /></form>',
+                array(),
+                '/',
+            ),
+            array(
+                'appends the form values even if the action is empty',
+                '<form><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
+                array(),
+                '/?foo=foo',
+            ),
+            array(
+                'chooses the path if the action attribute value is a sharp (#)',
+                '<form action="#" method="post"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
+                array(),
+                '/#',
+            ),
+        );
+    }
+
+    public function testHas()
+    {
+        $form = $this->createForm('<form method="post"><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+
+        $this->assertFalse($form->has('foo'), '->has() returns false if a field is not in the form');
+        $this->assertTrue($form->has('bar'), '->has() returns true if a field is in the form');
+    }
+
+    public function testRemove()
+    {
+        $form = $this->createForm('<form method="post"><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+        $form->remove('bar');
+        $this->assertFalse($form->has('bar'), '->remove() removes a field');
+    }
+
+    public function testGet()
+    {
+        $form = $this->createForm('<form method="post"><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Field\\InputFormField', $form->get('bar'), '->get() returns the field object associated with the given name');
+
+        try {
+            $form->get('foo');
+            $this->fail('->get() throws an \InvalidArgumentException if the field does not exist');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(true, '->get() throws an \InvalidArgumentException if the field does not exist');
+        }
+    }
+
+    public function testAll()
+    {
+        $form = $this->createForm('<form method="post"><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
+
+        $fields = $form->all();
+        $this->assertCount(1, $fields, '->all() return an array of form field objects');
+        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Field\\InputFormField', $fields['bar'], '->all() return an array of form field objects');
+    }
+
+    public function testSubmitWithoutAFormButton()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('
+            <html>
+                <form>
+                    <input type="foo" />
+                </form>
+            </html>
+        ');
+
+        $nodes = $dom->getElementsByTagName('form');
+        $form = new Form($nodes->item(0), 'http://example.com');
+        $this->assertSame($nodes->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form');
+    }
+
+    public function testTypeAttributeIsCaseInsensitive()
+    {
+        $form = $this->createForm('<form method="post"><input type="IMAGE" name="example" /></form>');
+        $this->assertTrue($form->has('example.x'), '->has() returns true if the image input was correctly turned into an x and a y fields');
+        $this->assertTrue($form->has('example.y'), '->has() returns true if the image input was correctly turned into an x and a y fields');
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testFormFieldRegistryAddThrowAnExceptionWhenTheNameIsMalformed()
+    {
+        $registry = new FormFieldRegistry();
+        $registry->add($this->getFormFieldMock('[foo]'));
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testFormFieldRegistryRemoveThrowAnExceptionWhenTheNameIsMalformed()
+    {
+        $registry = new FormFieldRegistry();
+        $registry->remove('[foo]');
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testFormFieldRegistryGetThrowAnExceptionWhenTheNameIsMalformed()
+    {
+        $registry = new FormFieldRegistry();
+        $registry->get('[foo]');
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testFormFieldRegistryGetThrowAnExceptionWhenTheFieldDoesNotExist()
+    {
+        $registry = new FormFieldRegistry();
+        $registry->get('foo');
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testFormFieldRegistrySetThrowAnExceptionWhenTheNameIsMalformed()
+    {
+        $registry = new FormFieldRegistry();
+        $registry->set('[foo]', null);
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testFormFieldRegistrySetThrowAnExceptionWhenTheFieldDoesNotExist()
+    {
+        $registry = new FormFieldRegistry();
+        $registry->set('foo', null);
+    }
+
+    public function testFormFieldRegistryHasReturnsTrueWhenTheFQNExists()
+    {
+        $registry = new FormFieldRegistry();
+        $registry->add($this->getFormFieldMock('foo[bar]'));
+
+        $this->assertTrue($registry->has('foo'));
+        $this->assertTrue($registry->has('foo[bar]'));
+        $this->assertFalse($registry->has('bar'));
+        $this->assertFalse($registry->has('foo[foo]'));
+    }
+
+    public function testFormRegistryFieldsCanBeRemoved()
+    {
+        $registry = new FormFieldRegistry();
+        $registry->add($this->getFormFieldMock('foo'));
+        $registry->remove('foo');
+        $this->assertFalse($registry->has('foo'));
+    }
+
+    public function testFormRegistrySupportsMultivaluedFields()
+    {
+        $registry = new FormFieldRegistry();
+        $registry->add($this->getFormFieldMock('foo[]'));
+        $registry->add($this->getFormFieldMock('foo[]'));
+        $registry->add($this->getFormFieldMock('bar[5]'));
+        $registry->add($this->getFormFieldMock('bar[]'));
+        $registry->add($this->getFormFieldMock('bar[baz]'));
+
+        $this->assertEquals(
+            array('foo[0]', 'foo[1]', 'bar[5]', 'bar[6]', 'bar[baz]'),
+            array_keys($registry->all())
+        );
+    }
+
+    public function testFormRegistrySetValues()
+    {
+        $registry = new FormFieldRegistry();
+        $registry->add($f2 = $this->getFormFieldMock('foo[2]'));
+        $registry->add($f3 = $this->getFormFieldMock('foo[3]'));
+        $registry->add($fbb = $this->getFormFieldMock('foo[bar][baz]'));
+
+        $f2
+            ->expects($this->exactly(2))
+            ->method('setValue')
+            ->with(2)
+        ;
+
+        $f3
+            ->expects($this->exactly(2))
+            ->method('setValue')
+            ->with(3)
+        ;
+
+        $fbb
+            ->expects($this->exactly(2))
+            ->method('setValue')
+            ->with('fbb')
+        ;
+
+        $registry->set('foo[2]', 2);
+        $registry->set('foo[3]', 3);
+        $registry->set('foo[bar][baz]', 'fbb');
+
+        $registry->set('foo', array(
+            2 => 2,
+            3 => 3,
+            'bar' => array(
+                'baz' => 'fbb',
+             ),
+        ));
+    }
+
+    public function testDifferentFieldTypesWithSameName()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('
+            <html>
+                <body>
+                    <form action="/">
+                        <input type="hidden" name="option" value="default">
+                        <input type="radio" name="option" value="A">
+                        <input type="radio" name="option" value="B">
+                        <input type="hidden" name="settings[1]" value="0">
+                        <input type="checkbox" name="settings[1]" value="1" id="setting-1">
+                        <button>klickme</button>
+                    </form>
+                </body>
+            </html>
+        ');
+        $form = new Form($dom->getElementsByTagName('form')->item(0), 'http://example.com');
+
+        $this->assertInstanceOf('Symfony\Component\DomCrawler\Field\ChoiceFormField', $form->get('option'));
+    }
+
+    protected function getFormFieldMock($name, $value = null)
+    {
+        $field = $this
+            ->getMockBuilder('Symfony\\Component\\DomCrawler\\Field\\FormField')
+            ->setMethods(array('getName', 'getValue', 'setValue', 'initialize'))
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $field
+            ->expects($this->any())
+            ->method('getName')
+            ->will($this->returnValue($name))
+        ;
+
+        $field
+            ->expects($this->any())
+            ->method('getValue')
+            ->will($this->returnValue($value))
+        ;
+
+        return $field;
+    }
+
+    protected function createForm($form, $method = null, $currentUri = null)
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('<html>'.$form.'</html>');
+
+        $xPath = new \DOMXPath($dom);
+        $nodes = $xPath->query('//input | //button');
+
+        if (null === $currentUri) {
+            $currentUri = 'http://example.com/';
+        }
+
+        return new Form($nodes->item($nodes->length - 1), $currentUri, $method);
+    }
+
+    protected function createTestHtml5Form()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('
+        <html>
+            <h1>Hello form</h1>
+            <form id="form-1" action="" method="POST">
+                <div><input type="checkbox" name="apples[]" value="1" checked /></div>
+                <input form="form_2" type="checkbox" name="oranges[]" value="1" checked />
+                <div><label></label><input form="form-1" type="hidden" name="form_name" value="form-1" /></div>
+                <input form="form-1" type="submit" name="button_1" value="Capture fields" />
+                <button form="form_2" type="submit" name="button_2">Submit form_2</button>
+            </form>
+            <input form="form-1" type="checkbox" name="apples[]" value="2" checked />
+            <form id="form_2" action="" method="POST">
+                <div><div><input type="checkbox" name="oranges[]" value="2" checked />
+                <input type="checkbox" name="oranges[]" value="3" checked /></div></div>
+                <input form="form_2" type="hidden" name="form_name" value="form_2" />
+                <input form="form-1" type="hidden" name="outer_field" value="success" />
+                <button form="form-1" type="submit" name="button_3">Submit from outside the form</button>
+                <div>
+                    <label for="app_frontend_form_type_contact_form_type_contactType">Message subject</label>
+                    <div>
+                        <select name="app_frontend_form_type_contact_form_type[contactType]" id="app_frontend_form_type_contact_form_type_contactType"><option selected="selected" value="">Please select subject</option><option id="1">Test type</option></select>
+                    </div>
+                </div>
+                <div>
+                    <label for="app_frontend_form_type_contact_form_type_firstName">Firstname</label>
+                    <input type="text" name="app_frontend_form_type_contact_form_type[firstName]" value="John" id="app_frontend_form_type_contact_form_type_firstName"/>
+                </div>
+            </form>
+            <button />
+        </html>');
+
+        return $dom;
+    }
+
+    protected function createTestMultipleForm()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('
+        <html>
+            <h1>Hello form</h1>
+            <form action="" method="POST">
+                <div><input type="checkbox" name="apples[]" value="1" checked /></div>
+                <input type="checkbox" name="oranges[]" value="1" checked />
+                <div><label></label><input type="hidden" name="form_name" value="form-1" /></div>
+                <input type="submit" name="button_1" value="Capture fields" />
+                <button type="submit" name="button_2">Submit form_2</button>
+            </form>
+            <form action="" method="POST">
+                <div><div><input type="checkbox" name="oranges[]" value="2" checked />
+                <input type="checkbox" name="oranges[]" value="3" checked /></div></div>
+                <input type="hidden" name="form_name" value="form_2" />
+                <input type="hidden" name="outer_field" value="success" />
+                <button type="submit" name="button_3">Submit from outside the form</button>
+            </form>
+            <button />
+        </html>');
+
+        return $dom;
+    }
+
+    public function testgetPhpValuesWithEmptyTextarea()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('
+              <html>
+                  <form>
+                      <textarea name="example"></textarea>
+                  </form>
+              </html>
+          ');
+
+        $nodes = $dom->getElementsByTagName('form');
+        $form = new Form($nodes->item(0), 'http://example.com');
+        $this->assertEquals($form->getPhpValues(), array('example' => ''));
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/LinkTest.php b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/LinkTest.php
new file mode 100644
index 0000000..98a45a3
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/Tests/LinkTest.php
@@ -0,0 +1,160 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DomCrawler\Tests;
+
+use Symfony\Component\DomCrawler\Link;
+
+class LinkTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @expectedException \LogicException
+     */
+    public function testConstructorWithANonATag()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('<html><div><div></html>');
+
+        new Link($dom->getElementsByTagName('div')->item(0), 'http://www.example.com/');
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testConstructorWithAnInvalidCurrentUri()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('<html><a href="/foo">foo</a></html>');
+
+        new Link($dom->getElementsByTagName('a')->item(0), 'example.com');
+    }
+
+    public function testGetNode()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('<html><a href="/foo">foo</a></html>');
+
+        $node = $dom->getElementsByTagName('a')->item(0);
+        $link = new Link($node, 'http://example.com/');
+
+        $this->assertEquals($node, $link->getNode(), '->getNode() returns the node associated with the link');
+    }
+
+    public function testGetMethod()
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML('<html><a href="/foo">foo</a></html>');
+
+        $node = $dom->getElementsByTagName('a')->item(0);
+        $link = new Link($node, 'http://example.com/');
+
+        $this->assertEquals('GET', $link->getMethod(), '->getMethod() returns the method of the link');
+
+        $link = new Link($node, 'http://example.com/', 'post');
+        $this->assertEquals('POST', $link->getMethod(), '->getMethod() returns the method of the link');
+    }
+
+    /**
+     * @dataProvider getGetUriTests
+     */
+    public function testGetUri($url, $currentUri, $expected)
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML(sprintf('<html><a href="%s">foo</a></html>', $url));
+        $link = new Link($dom->getElementsByTagName('a')->item(0), $currentUri);
+
+        $this->assertEquals($expected, $link->getUri());
+    }
+
+    /**
+     * @dataProvider getGetUriTests
+     */
+    public function testGetUriOnArea($url, $currentUri, $expected)
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML(sprintf('<html><map><area href="%s" /></map></html>', $url));
+        $link = new Link($dom->getElementsByTagName('area')->item(0), $currentUri);
+
+        $this->assertEquals($expected, $link->getUri());
+    }
+
+    /**
+     * @dataProvider getGetUriTests
+     */
+    public function testGetUriOnLink($url, $currentUri, $expected)
+    {
+        $dom = new \DOMDocument();
+        $dom->loadHTML(sprintf('<html><head><link href="%s" /></head></html>', $url));
+        $link = new Link($dom->getElementsByTagName('link')->item(0), $currentUri);
+
+        $this->assertEquals($expected, $link->getUri());
+    }
+
+    public function getGetUriTests()
+    {
+        return array(
+            array('/foo', 'http://localhost/bar/foo/', 'http://localhost/foo'),
+            array('/foo', 'http://localhost/bar/foo', 'http://localhost/foo'),
+            array('
+            /foo', 'http://localhost/bar/foo/', 'http://localhost/foo'),
+            array('/foo
+            ', 'http://localhost/bar/foo', 'http://localhost/foo'),
+
+            array('foo', 'http://localhost/bar/foo/', 'http://localhost/bar/foo/foo'),
+            array('foo', 'http://localhost/bar/foo', 'http://localhost/bar/foo'),
+
+            array('', 'http://localhost/bar/', 'http://localhost/bar/'),
+            array('#', 'http://localhost/bar/', 'http://localhost/bar/#'),
+            array('#bar', 'http://localhost/bar?a=b', 'http://localhost/bar?a=b#bar'),
+            array('#bar', 'http://localhost/bar/#foo', 'http://localhost/bar/#bar'),
+            array('?a=b', 'http://localhost/bar#foo', 'http://localhost/bar?a=b'),
+            array('?a=b', 'http://localhost/bar/', 'http://localhost/bar/?a=b'),
+
+            array('http://login.foo.com/foo', 'http://localhost/bar/', 'http://login.foo.com/foo'),
+            array('https://login.foo.com/foo', 'https://localhost/bar/', 'https://login.foo.com/foo'),
+            array('mailto:foo@bar.com', 'http://localhost/foo', 'mailto:foo@bar.com'),
+
+            // tests schema relative URL (issue #7169)
+            array('//login.foo.com/foo', 'http://localhost/bar/', 'http://login.foo.com/foo'),
+            array('//login.foo.com/foo', 'https://localhost/bar/', 'https://login.foo.com/foo'),
+
+            array('?foo=2', 'http://localhost?foo=1', 'http://localhost?foo=2'),
+            array('?foo=2', 'http://localhost/?foo=1', 'http://localhost/?foo=2'),
+            array('?foo=2', 'http://localhost/bar?foo=1', 'http://localhost/bar?foo=2'),
+            array('?foo=2', 'http://localhost/bar/?foo=1', 'http://localhost/bar/?foo=2'),
+            array('?bar=2', 'http://localhost?foo=1', 'http://localhost?bar=2'),
+
+            array('foo', 'http://login.foo.com/bar/baz?/query/string', 'http://login.foo.com/bar/foo'),
+
+            array('.', 'http://localhost/foo/bar/baz', 'http://localhost/foo/bar/'),
+            array('./', 'http://localhost/foo/bar/baz', 'http://localhost/foo/bar/'),
+            array('./foo', 'http://localhost/foo/bar/baz', 'http://localhost/foo/bar/foo'),
+            array('..', 'http://localhost/foo/bar/baz', 'http://localhost/foo/'),
+            array('../', 'http://localhost/foo/bar/baz', 'http://localhost/foo/'),
+            array('../foo', 'http://localhost/foo/bar/baz', 'http://localhost/foo/foo'),
+            array('../..', 'http://localhost/foo/bar/baz', 'http://localhost/'),
+            array('../../', 'http://localhost/foo/bar/baz', 'http://localhost/'),
+            array('../../foo', 'http://localhost/foo/bar/baz', 'http://localhost/foo'),
+            array('../../foo', 'http://localhost/bar/foo/', 'http://localhost/foo'),
+            array('../bar/../../foo', 'http://localhost/bar/foo/', 'http://localhost/foo'),
+            array('../bar/./../../foo', 'http://localhost/bar/foo/', 'http://localhost/foo'),
+            array('../../', 'http://localhost/', 'http://localhost/'),
+            array('../../', 'http://localhost', 'http://localhost/'),
+
+            array('/foo', 'http://localhost?bar=1', 'http://localhost/foo'),
+            array('/foo', 'http://localhost#bar', 'http://localhost/foo'),
+            array('/foo', 'file:///', 'file:///foo'),
+            array('/foo', 'file:///bar/baz', 'file:///foo'),
+            array('foo', 'file:///', 'file:///foo'),
+            array('foo', 'file:///bar/baz', 'file:///bar/foo'),
+        );
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/composer.json b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/composer.json
new file mode 100644
index 0000000..5bc3192
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/composer.json
@@ -0,0 +1,37 @@
+{
+    "name": "symfony/dom-crawler",
+    "type": "library",
+    "description": "Symfony DomCrawler Component",
+    "keywords": [],
+    "homepage": "http://symfony.com",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Fabien Potencier",
+            "email": "fabien@symfony.com"
+        },
+        {
+            "name": "Symfony Community",
+            "homepage": "http://symfony.com/contributors"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.3"
+    },
+    "require-dev": {
+        "symfony/css-selector": "~2.3"
+    },
+    "suggest": {
+        "symfony/css-selector": ""
+    },
+    "autoload": {
+        "psr-0": { "Symfony\\Component\\DomCrawler\\": "" }
+    },
+    "target-dir": "Symfony/Component/DomCrawler",
+    "minimum-stability": "dev",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.6-dev"
+        }
+    }
+}
diff --git a/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/phpunit.xml.dist b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/phpunit.xml.dist
new file mode 100644
index 0000000..5ce15ec
--- /dev/null
+++ b/core/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler/phpunit.xml.dist
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
+         backupGlobals="false"
+         colors="true"
+         bootstrap="vendor/autoload.php"
+>
+    <php>
+        <!-- Silence E_USER_DEPRECATED (-16385 == -1 & ~E_USER_DEPRECATED) -->
+        <ini name="error_reporting" value="-16385"/>
+    </php>
+
+    <testsuites>
+        <testsuite name="Symfony DomCrawler Component Test Suite">
+            <directory>./Tests/</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory>./</directory>
+            <exclude>
+                <directory>./Resources</directory>
+                <directory>./Tests</directory>
+                <directory>./vendor</directory>
+            </exclude>
+        </whitelist>
+    </filter>
+</phpunit>
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/.gitignore b/core/vendor/symfony/finder/Symfony/Component/Finder/.gitignore
new file mode 100644
index 0000000..c49a5d8
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php
new file mode 100644
index 0000000..4ddd913
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php
@@ -0,0 +1,236 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Adapter;
+
+/**
+ * Interface for finder engine implementations.
+ *
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+abstract class AbstractAdapter implements AdapterInterface
+{
+    protected $followLinks = false;
+    protected $mode = 0;
+    protected $minDepth = 0;
+    protected $maxDepth = PHP_INT_MAX;
+    protected $exclude = array();
+    protected $names = array();
+    protected $notNames = array();
+    protected $contains = array();
+    protected $notContains = array();
+    protected $sizes = array();
+    protected $dates = array();
+    protected $filters = array();
+    protected $sort = false;
+    protected $paths = array();
+    protected $notPaths = array();
+    protected $ignoreUnreadableDirs = false;
+
+    private static $areSupported = array();
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isSupported()
+    {
+        $name = $this->getName();
+
+        if (!array_key_exists($name, self::$areSupported)) {
+            self::$areSupported[$name] = $this->canBeUsed();
+        }
+
+        return self::$areSupported[$name];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setFollowLinks($followLinks)
+    {
+        $this->followLinks = $followLinks;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setMode($mode)
+    {
+        $this->mode = $mode;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setDepths(array $depths)
+    {
+        $this->minDepth = 0;
+        $this->maxDepth = PHP_INT_MAX;
+
+        foreach ($depths as $comparator) {
+            switch ($comparator->getOperator()) {
+                case '>':
+                    $this->minDepth = $comparator->getTarget() + 1;
+                    break;
+                case '>=':
+                    $this->minDepth = $comparator->getTarget();
+                    break;
+                case '<':
+                    $this->maxDepth = $comparator->getTarget() - 1;
+                    break;
+                case '<=':
+                    $this->maxDepth = $comparator->getTarget();
+                    break;
+                default:
+                    $this->minDepth = $this->maxDepth = $comparator->getTarget();
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setExclude(array $exclude)
+    {
+        $this->exclude = $exclude;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setNames(array $names)
+    {
+        $this->names = $names;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setNotNames(array $notNames)
+    {
+        $this->notNames = $notNames;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setContains(array $contains)
+    {
+        $this->contains = $contains;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setNotContains(array $notContains)
+    {
+        $this->notContains = $notContains;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setSizes(array $sizes)
+    {
+        $this->sizes = $sizes;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setDates(array $dates)
+    {
+        $this->dates = $dates;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setFilters(array $filters)
+    {
+        $this->filters = $filters;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setSort($sort)
+    {
+        $this->sort = $sort;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setPath(array $paths)
+    {
+        $this->paths = $paths;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setNotPath(array $notPaths)
+    {
+        $this->notPaths = $notPaths;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function ignoreUnreadableDirs($ignore = true)
+    {
+        $this->ignoreUnreadableDirs = (bool) $ignore;
+
+        return $this;
+    }
+
+    /**
+     * Returns whether the adapter is supported in the current environment.
+     *
+     * This method should be implemented in all adapters. Do not implement
+     * isSupported in the adapters as the generic implementation provides a cache
+     * layer.
+     *
+     * @see isSupported()
+     *
+     * @return bool Whether the adapter is supported
+     */
+    abstract protected function canBeUsed();
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php
new file mode 100644
index 0000000..4d73b32
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php
@@ -0,0 +1,327 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Adapter;
+
+use Symfony\Component\Finder\Exception\AccessDeniedException;
+use Symfony\Component\Finder\Iterator;
+use Symfony\Component\Finder\Shell\Shell;
+use Symfony\Component\Finder\Expression\Expression;
+use Symfony\Component\Finder\Shell\Command;
+use Symfony\Component\Finder\Comparator\NumberComparator;
+use Symfony\Component\Finder\Comparator\DateComparator;
+
+/**
+ * Shell engine implementation using GNU find command.
+ *
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+abstract class AbstractFindAdapter extends AbstractAdapter
+{
+    /**
+     * @var Shell
+     */
+    protected $shell;
+
+    /**
+     * Constructor.
+     */
+    public function __construct()
+    {
+        $this->shell = new Shell();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function searchInDirectory($dir)
+    {
+        // having "/../" in path make find fail
+        $dir = realpath($dir);
+
+        // searching directories containing or not containing strings leads to no result
+        if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
+            return new Iterator\FilePathsIterator(array(), $dir);
+        }
+
+        $command = Command::create();
+        $find = $this->buildFindCommand($command, $dir);
+
+        if ($this->followLinks) {
+            $find->add('-follow');
+        }
+
+        $find->add('-mindepth')->add($this->minDepth + 1);
+
+        if (PHP_INT_MAX !== $this->maxDepth) {
+            $find->add('-maxdepth')->add($this->maxDepth + 1);
+        }
+
+        if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
+            $find->add('-type d');
+        } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
+            $find->add('-type f');
+        }
+
+        $this->buildNamesFiltering($find, $this->names);
+        $this->buildNamesFiltering($find, $this->notNames, true);
+        $this->buildPathsFiltering($find, $dir, $this->paths);
+        $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
+        $this->buildSizesFiltering($find, $this->sizes);
+        $this->buildDatesFiltering($find, $this->dates);
+
+        $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
+        $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
+
+        if ($useGrep && ($this->contains || $this->notContains)) {
+            $grep = $command->ins('grep');
+            $this->buildContentFiltering($grep, $this->contains);
+            $this->buildContentFiltering($grep, $this->notContains, true);
+        }
+
+        if ($useSort) {
+            $this->buildSorting($command, $this->sort);
+        }
+
+        $command->setErrorHandler(
+            $this->ignoreUnreadableDirs
+                // If directory is unreadable and finder is set to ignore it, `stderr` is ignored.
+                ? function ($stderr) { return; }
+                : function ($stderr) { throw new AccessDeniedException($stderr); }
+        );
+
+        $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
+        $iterator = new Iterator\FilePathsIterator($paths, $dir);
+
+        if ($this->exclude) {
+            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
+        }
+
+        if (!$useGrep && ($this->contains || $this->notContains)) {
+            $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
+        }
+
+        if ($this->filters) {
+            $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
+        }
+
+        if (!$useSort && $this->sort) {
+            $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
+            $iterator = $iteratorAggregate->getIterator();
+        }
+
+        return $iterator;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function canBeUsed()
+    {
+        return $this->shell->testCommand('find');
+    }
+
+    /**
+     * @param Command $command
+     * @param string  $dir
+     *
+     * @return Command
+     */
+    protected function buildFindCommand(Command $command, $dir)
+    {
+        return $command
+            ->ins('find')
+            ->add('find ')
+            ->arg($dir)
+            ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions
+    }
+
+    /**
+     * @param Command  $command
+     * @param string[] $names
+     * @param bool     $not
+     */
+    private function buildNamesFiltering(Command $command, array $names, $not = false)
+    {
+        if (0 === count($names)) {
+            return;
+        }
+
+        $command->add($not ? '-not' : null)->cmd('(');
+
+        foreach ($names as $i => $name) {
+            $expr = Expression::create($name);
+
+            // Find does not support expandable globs ("*.{a,b}" syntax).
+            if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
+                $expr = Expression::create($expr->getGlob()->toRegex(false));
+            }
+
+            // Fixes 'not search' and 'full path matching' regex problems.
+            // - Jokers '.' are replaced by [^/].
+            // - We add '[^/]*' before and after regex (if no ^|$ flags are present).
+            if ($expr->isRegex()) {
+                $regex = $expr->getRegex();
+                $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
+                    ->setStartFlag(false)
+                    ->setStartJoker(true)
+                    ->replaceJokers('[^/]');
+                if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
+                    $regex->setEndJoker(false)->append('[^/]*');
+                }
+            }
+
+            $command
+                ->add($i > 0 ? '-or' : null)
+                ->add($expr->isRegex()
+                    ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
+                    : ($expr->isCaseSensitive() ? '-name' : '-iname')
+                )
+                ->arg($expr->renderPattern());
+        }
+
+        $command->cmd(')');
+    }
+
+    /**
+     * @param Command  $command
+     * @param string   $dir
+     * @param string[] $paths
+     * @param bool     $not
+     */
+    private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
+    {
+        if (0 === count($paths)) {
+            return;
+        }
+
+        $command->add($not ? '-not' : null)->cmd('(');
+
+        foreach ($paths as $i => $path) {
+            $expr = Expression::create($path);
+
+            // Find does not support expandable globs ("*.{a,b}" syntax).
+            if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
+                $expr = Expression::create($expr->getGlob()->toRegex(false));
+            }
+
+            // Fixes 'not search' regex problems.
+            if ($expr->isRegex()) {
+                $regex = $expr->getRegex();
+                $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
+            } else {
+                $expr->prepend('*')->append('*');
+            }
+
+            $command
+                ->add($i > 0 ? '-or' : null)
+                ->add($expr->isRegex()
+                    ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
+                    : ($expr->isCaseSensitive() ? '-path' : '-ipath')
+                )
+                ->arg($expr->renderPattern());
+        }
+
+        $command->cmd(')');
+    }
+
+    /**
+     * @param Command            $command
+     * @param NumberComparator[] $sizes
+     */
+    private function buildSizesFiltering(Command $command, array $sizes)
+    {
+        foreach ($sizes as $i => $size) {
+            $command->add($i > 0 ? '-and' : null);
+
+            switch ($size->getOperator()) {
+                case '<=':
+                    $command->add('-size -'.($size->getTarget() + 1).'c');
+                    break;
+                case '>=':
+                    $command->add('-size +'.($size->getTarget() - 1).'c');
+                    break;
+                case '>':
+                    $command->add('-size +'.$size->getTarget().'c');
+                    break;
+                case '!=':
+                    $command->add('-size -'.$size->getTarget().'c');
+                    $command->add('-size +'.$size->getTarget().'c');
+                    break;
+                case '<':
+                default:
+                    $command->add('-size -'.$size->getTarget().'c');
+            }
+        }
+    }
+
+    /**
+     * @param Command          $command
+     * @param DateComparator[] $dates
+     */
+    private function buildDatesFiltering(Command $command, array $dates)
+    {
+        foreach ($dates as $i => $date) {
+            $command->add($i > 0 ? '-and' : null);
+
+            $mins = (int) round((time()-$date->getTarget()) / 60);
+
+            if (0 > $mins) {
+                // mtime is in the future
+                $command->add(' -mmin -0');
+                // we will have no result so we don't need to continue
+                return;
+            }
+
+            switch ($date->getOperator()) {
+                case '<=':
+                    $command->add('-mmin +'.($mins - 1));
+                    break;
+                case '>=':
+                    $command->add('-mmin -'.($mins + 1));
+                    break;
+                case '>':
+                    $command->add('-mmin -'.$mins);
+                    break;
+                case '!=':
+                    $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
+                    break;
+                case '<':
+                default:
+                    $command->add('-mmin +'.$mins);
+            }
+        }
+    }
+
+    /**
+     * @param Command $command
+     * @param string  $sort
+     *
+     * @throws \InvalidArgumentException
+     */
+    private function buildSorting(Command $command, $sort)
+    {
+        $this->buildFormatSorting($command, $sort);
+    }
+
+    /**
+     * @param Command $command
+     * @param string  $sort
+     */
+    abstract protected function buildFormatSorting(Command $command, $sort);
+
+    /**
+     * @param Command $command
+     * @param array   $contains
+     * @param bool    $not
+     */
+    abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php
new file mode 100644
index 0000000..bdc3a93
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php
@@ -0,0 +1,144 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Adapter;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+interface AdapterInterface
+{
+    /**
+     * @param bool $followLinks
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setFollowLinks($followLinks);
+
+    /**
+     * @param int $mode
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setMode($mode);
+
+    /**
+     * @param array $exclude
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setExclude(array $exclude);
+
+    /**
+     * @param array $depths
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setDepths(array $depths);
+
+    /**
+     * @param array $names
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setNames(array $names);
+
+    /**
+     * @param array $notNames
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setNotNames(array $notNames);
+
+    /**
+     * @param array $contains
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setContains(array $contains);
+
+    /**
+     * @param array $notContains
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setNotContains(array $notContains);
+
+    /**
+     * @param array $sizes
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setSizes(array $sizes);
+
+    /**
+     * @param array $dates
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setDates(array $dates);
+
+    /**
+     * @param array $filters
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setFilters(array $filters);
+
+    /**
+     * @param \Closure|int $sort
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setSort($sort);
+
+    /**
+     * @param array $paths
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setPath(array $paths);
+
+    /**
+     * @param array $notPaths
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function setNotPath(array $notPaths);
+
+    /**
+     * @param bool $ignore
+     *
+     * @return AdapterInterface Current instance
+     */
+    public function ignoreUnreadableDirs($ignore = true);
+
+    /**
+     * @param string $dir
+     *
+     * @return \Iterator Result iterator
+     */
+    public function searchInDirectory($dir);
+
+    /**
+     * Tests adapter support for current platform.
+     *
+     * @return bool
+     */
+    public function isSupported();
+
+    /**
+     * Returns adapter name.
+     *
+     * @return string
+     */
+    public function getName();
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php
new file mode 100644
index 0000000..4a25bae
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php
@@ -0,0 +1,103 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Adapter;
+
+use Symfony\Component\Finder\Shell\Shell;
+use Symfony\Component\Finder\Shell\Command;
+use Symfony\Component\Finder\Iterator\SortableIterator;
+use Symfony\Component\Finder\Expression\Expression;
+
+/**
+ * Shell engine implementation using BSD find command.
+ *
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class BsdFindAdapter extends AbstractFindAdapter
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'bsd_find';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function canBeUsed()
+    {
+        return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function buildFormatSorting(Command $command, $sort)
+    {
+        switch ($sort) {
+            case SortableIterator::SORT_BY_NAME:
+                $command->ins('sort')->add('| sort');
+
+                return;
+            case SortableIterator::SORT_BY_TYPE:
+                $format = '%HT';
+                break;
+            case SortableIterator::SORT_BY_ACCESSED_TIME:
+                $format = '%a';
+                break;
+            case SortableIterator::SORT_BY_CHANGED_TIME:
+                $format = '%c';
+                break;
+            case SortableIterator::SORT_BY_MODIFIED_TIME:
+                $format = '%m';
+                break;
+            default:
+                throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
+        }
+
+        $command
+            ->add('-print0 | xargs -0 stat -f')
+            ->arg($format.'%t%N')
+            ->add('| sort | cut -f 2');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function buildFindCommand(Command $command, $dir)
+    {
+        parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
+
+        return $command;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function buildContentFiltering(Command $command, array $contains, $not = false)
+    {
+        foreach ($contains as $contain) {
+            $expr = Expression::create($contain);
+
+            // todo: avoid forking process for each $pattern by using multiple -e options
+            $command
+                ->add('| grep -v \'^$\'')
+                ->add('| xargs -I{} grep -I')
+                ->add($expr->isCaseSensitive() ? null : '-i')
+                ->add($not ? '-L' : '-l')
+                ->add('-Ee')->arg($expr->renderPattern())
+                ->add('{}')
+            ;
+        }
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php
new file mode 100644
index 0000000..0fbf48f
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php
@@ -0,0 +1,104 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Adapter;
+
+use Symfony\Component\Finder\Shell\Shell;
+use Symfony\Component\Finder\Shell\Command;
+use Symfony\Component\Finder\Iterator\SortableIterator;
+use Symfony\Component\Finder\Expression\Expression;
+
+/**
+ * Shell engine implementation using GNU find command.
+ *
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class GnuFindAdapter extends AbstractFindAdapter
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'gnu_find';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function buildFormatSorting(Command $command, $sort)
+    {
+        switch ($sort) {
+            case SortableIterator::SORT_BY_NAME:
+                $command->ins('sort')->add('| sort');
+
+                return;
+            case SortableIterator::SORT_BY_TYPE:
+                $format = '%y';
+                break;
+            case SortableIterator::SORT_BY_ACCESSED_TIME:
+                $format = '%A@';
+                break;
+            case SortableIterator::SORT_BY_CHANGED_TIME:
+                $format = '%C@';
+                break;
+            case SortableIterator::SORT_BY_MODIFIED_TIME:
+                $format = '%T@';
+                break;
+            default:
+                throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
+        }
+
+        $command
+            ->get('find')
+            ->add('-printf')
+            ->arg($format.' %h/%f\\n')
+            ->add('| sort | cut')
+            ->arg('-d ')
+            ->arg('-f2-')
+        ;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function canBeUsed()
+    {
+        return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function buildFindCommand(Command $command, $dir)
+    {
+        return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function buildContentFiltering(Command $command, array $contains, $not = false)
+    {
+        foreach ($contains as $contain) {
+            $expr = Expression::create($contain);
+
+            // todo: avoid forking process for each $pattern by using multiple -e options
+            $command
+                ->add('| xargs -I{} -r grep -I')
+                ->add($expr->isCaseSensitive() ? null : '-i')
+                ->add($not ? '-L' : '-l')
+                ->add('-Ee')->arg($expr->renderPattern())
+                ->add('{}')
+            ;
+        }
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php
new file mode 100644
index 0000000..378a26a
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php
@@ -0,0 +1,98 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Adapter;
+
+use Symfony\Component\Finder\Iterator;
+
+/**
+ * PHP finder engine implementation.
+ *
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class PhpAdapter extends AbstractAdapter
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function searchInDirectory($dir)
+    {
+        $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
+
+        if ($this->followLinks) {
+            $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
+        }
+
+        $iterator = new \RecursiveIteratorIterator(
+            new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs),
+            \RecursiveIteratorIterator::SELF_FIRST
+        );
+
+        if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
+            $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
+        }
+
+        if ($this->mode) {
+            $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
+        }
+
+        if ($this->exclude) {
+            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
+        }
+
+        if ($this->names || $this->notNames) {
+            $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
+        }
+
+        if ($this->contains || $this->notContains) {
+            $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
+        }
+
+        if ($this->sizes) {
+            $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
+        }
+
+        if ($this->dates) {
+            $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
+        }
+
+        if ($this->filters) {
+            $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
+        }
+
+        if ($this->sort) {
+            $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
+            $iterator = $iteratorAggregate->getIterator();
+        }
+
+        if ($this->paths || $this->notPaths) {
+            $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
+        }
+
+        return $iterator;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'php';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function canBeUsed()
+    {
+        return true;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/CHANGELOG.md b/core/vendor/symfony/finder/Symfony/Component/Finder/CHANGELOG.md
new file mode 100644
index 0000000..f1dd7d5
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/CHANGELOG.md
@@ -0,0 +1,34 @@
+CHANGELOG
+=========
+
+2.5.0
+-----
+ * added support for GLOB_BRACE in the paths passed to Finder::in()
+
+2.3.0
+-----
+
+ * added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs())
+ * unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception
+
+2.2.0
+-----
+
+ * added Finder::path() and Finder::notPath() methods
+ * added finder adapters to improve performance on specific platforms
+ * added support for wildcard characters (glob patterns) in the paths passed
+   to Finder::in()
+
+2.1.0
+-----
+
+ * added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and
+   Finder::sortByModifiedTime()
+ * added Countable to Finder
+ * added support for an array of directories as an argument to
+   Finder::exclude()
+ * added searching based on the file content via Finder::contains() and
+   Finder::notContains()
+ * added support for the != operator in the Comparator
+ * [BC BREAK] filter expressions (used for file name and content) are no more
+   considered as regexps but glob patterns when they are enclosed in '*' or '?'
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Comparator/Comparator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Comparator/Comparator.php
new file mode 100644
index 0000000..4f5e1ff
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Comparator/Comparator.php
@@ -0,0 +1,98 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Comparator;
+
+/**
+ * Comparator.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Comparator
+{
+    private $target;
+    private $operator = '==';
+
+    /**
+     * Gets the target value.
+     *
+     * @return string The target value
+     */
+    public function getTarget()
+    {
+        return $this->target;
+    }
+
+    /**
+     * Sets the target value.
+     *
+     * @param string $target The target value
+     */
+    public function setTarget($target)
+    {
+        $this->target = $target;
+    }
+
+    /**
+     * Gets the comparison operator.
+     *
+     * @return string The operator
+     */
+    public function getOperator()
+    {
+        return $this->operator;
+    }
+
+    /**
+     * Sets the comparison operator.
+     *
+     * @param string $operator A valid operator
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function setOperator($operator)
+    {
+        if (!$operator) {
+            $operator = '==';
+        }
+
+        if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
+            throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
+        }
+
+        $this->operator = $operator;
+    }
+
+    /**
+     * Tests against the target.
+     *
+     * @param mixed $test A test value
+     *
+     * @return bool
+     */
+    public function test($test)
+    {
+        switch ($this->operator) {
+            case '>':
+                return $test > $this->target;
+            case '>=':
+                return $test >= $this->target;
+            case '<':
+                return $test < $this->target;
+            case '<=':
+                return $test <= $this->target;
+            case '!=':
+                return $test != $this->target;
+        }
+
+        return $test == $this->target;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php
new file mode 100644
index 0000000..8b7746b
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Comparator;
+
+/**
+ * DateCompare compiles date comparisons.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class DateComparator extends Comparator
+{
+    /**
+     * Constructor.
+     *
+     * @param string $test A comparison string
+     *
+     * @throws \InvalidArgumentException If the test is not understood
+     */
+    public function __construct($test)
+    {
+        if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
+            throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
+        }
+
+        try {
+            $date = new \DateTime($matches[2]);
+            $target = $date->format('U');
+        } catch (\Exception $e) {
+            throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
+        }
+
+        $operator = isset($matches[1]) ? $matches[1] : '==';
+        if ('since' === $operator || 'after' === $operator) {
+            $operator = '>';
+        }
+
+        if ('until' === $operator || 'before' === $operator) {
+            $operator = '<';
+        }
+
+        $this->setOperator($operator);
+        $this->setTarget($target);
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php
new file mode 100644
index 0000000..c8587dc
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php
@@ -0,0 +1,81 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Comparator;
+
+/**
+ * NumberComparator compiles a simple comparison to an anonymous
+ * subroutine, which you can call with a value to be tested again.
+ *
+ * Now this would be very pointless, if NumberCompare didn't understand
+ * magnitudes.
+ *
+ * The target value may use magnitudes of kilobytes (k, ki),
+ * megabytes (m, mi), or gigabytes (g, gi).  Those suffixed
+ * with an i use the appropriate 2**n version in accordance with the
+ * IEC standard: http://physics.nist.gov/cuu/Units/binary.html
+ *
+ * Based on the Perl Number::Compare module.
+ *
+ * @author    Fabien Potencier <fabien@symfony.com> PHP port
+ * @author    Richard Clamp <richardc@unixbeard.net> Perl version
+ * @copyright 2004-2005 Fabien Potencier <fabien@symfony.com>
+ * @copyright 2002 Richard Clamp <richardc@unixbeard.net>
+ *
+ * @see http://physics.nist.gov/cuu/Units/binary.html
+ */
+class NumberComparator extends Comparator
+{
+    /**
+     * Constructor.
+     *
+     * @param string $test A comparison string
+     *
+     * @throws \InvalidArgumentException If the test is not understood
+     */
+    public function __construct($test)
+    {
+        if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
+            throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
+        }
+
+        $target = $matches[2];
+        if (!is_numeric($target)) {
+            throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
+        }
+        if (isset($matches[3])) {
+            // magnitude
+            switch (strtolower($matches[3])) {
+                case 'k':
+                    $target *= 1000;
+                    break;
+                case 'ki':
+                    $target *= 1024;
+                    break;
+                case 'm':
+                    $target *= 1000000;
+                    break;
+                case 'mi':
+                    $target *= 1024*1024;
+                    break;
+                case 'g':
+                    $target *= 1000000000;
+                    break;
+                case 'gi':
+                    $target *= 1024*1024*1024;
+                    break;
+            }
+        }
+
+        $this->setTarget($target);
+        $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php
new file mode 100644
index 0000000..ee195ea
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php
@@ -0,0 +1,19 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Exception;
+
+/**
+ * @author Jean-FranÃ§ois Simon <jeanfrancois.simon@sensiolabs.com>
+ */
+class AccessDeniedException extends \UnexpectedValueException
+{
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php
new file mode 100644
index 0000000..15fa221
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Exception;
+
+use Symfony\Component\Finder\Adapter\AdapterInterface;
+
+/**
+ * Base exception for all adapter failures.
+ *
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class AdapterFailureException extends \RuntimeException implements ExceptionInterface
+{
+    /**
+     * @var \Symfony\Component\Finder\Adapter\AdapterInterface
+     */
+    private $adapter;
+
+    /**
+     * @param AdapterInterface $adapter
+     * @param string|null      $message
+     * @param \Exception|null  $previous
+     */
+    public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
+    {
+        $this->adapter = $adapter;
+        parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getAdapter()
+    {
+        return $this->adapter;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..bff0214
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Exception;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+interface ExceptionInterface
+{
+    /**
+     * @return \Symfony\Component\Finder\Adapter\AdapterInterface
+     */
+    public function getAdapter();
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.php
new file mode 100644
index 0000000..3663112
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.php
@@ -0,0 +1,19 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Exception;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class OperationNotPermitedException extends AdapterFailureException
+{
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php
new file mode 100644
index 0000000..2658f6a
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Exception;
+
+use Symfony\Component\Finder\Adapter\AdapterInterface;
+use Symfony\Component\Finder\Shell\Command;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class ShellCommandFailureException extends AdapterFailureException
+{
+    /**
+     * @var Command
+     */
+    private $command;
+
+    /**
+     * @param AdapterInterface $adapter
+     * @param Command          $command
+     * @param \Exception|null  $previous
+     */
+    public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
+    {
+        $this->command = $command;
+        parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
+    }
+
+    /**
+     * @return Command
+     */
+    public function getCommand()
+    {
+        return $this->command;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/Expression.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/Expression.php
new file mode 100644
index 0000000..9002607
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/Expression.php
@@ -0,0 +1,146 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Expression;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class Expression implements ValueInterface
+{
+    const TYPE_REGEX = 1;
+    const TYPE_GLOB = 2;
+
+    /**
+     * @var ValueInterface
+     */
+    private $value;
+
+    /**
+     * @param string $expr
+     *
+     * @return Expression
+     */
+    public static function create($expr)
+    {
+        return new self($expr);
+    }
+
+    /**
+     * @param string $expr
+     */
+    public function __construct($expr)
+    {
+        try {
+            $this->value = Regex::create($expr);
+        } catch (\InvalidArgumentException $e) {
+            $this->value = new Glob($expr);
+        }
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->render();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function render()
+    {
+        return $this->value->render();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function renderPattern()
+    {
+        return $this->value->renderPattern();
+    }
+
+    /**
+     * @return bool
+     */
+    public function isCaseSensitive()
+    {
+        return $this->value->isCaseSensitive();
+    }
+
+    /**
+     * @return int
+     */
+    public function getType()
+    {
+        return $this->value->getType();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function prepend($expr)
+    {
+        $this->value->prepend($expr);
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function append($expr)
+    {
+        $this->value->append($expr);
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isRegex()
+    {
+        return self::TYPE_REGEX === $this->value->getType();
+    }
+
+    /**
+     * @return bool
+     */
+    public function isGlob()
+    {
+        return self::TYPE_GLOB === $this->value->getType();
+    }
+
+    /**
+     * @throws \LogicException
+     *
+     * @return Glob
+     */
+    public function getGlob()
+    {
+        if (self::TYPE_GLOB !== $this->value->getType()) {
+            throw new \LogicException('Regex can\'t be transformed to glob.');
+        }
+
+        return $this->value;
+    }
+
+    /**
+     * @return Regex
+     */
+    public function getRegex()
+    {
+        return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/Glob.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/Glob.php
new file mode 100644
index 0000000..3023cee
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/Glob.php
@@ -0,0 +1,157 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Expression;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class Glob implements ValueInterface
+{
+    /**
+     * @var string
+     */
+    private $pattern;
+
+    /**
+     * @param string $pattern
+     */
+    public function __construct($pattern)
+    {
+        $this->pattern = $pattern;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function render()
+    {
+        return $this->pattern;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function renderPattern()
+    {
+        return $this->pattern;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return Expression::TYPE_GLOB;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isCaseSensitive()
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function prepend($expr)
+    {
+        $this->pattern = $expr.$this->pattern;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function append($expr)
+    {
+        $this->pattern .= $expr;
+
+        return $this;
+    }
+
+    /**
+     * Tests if glob is expandable ("*.{a,b}" syntax).
+     *
+     * @return bool
+     */
+    public function isExpandable()
+    {
+        return false !== strpos($this->pattern, '{')
+            && false !== strpos($this->pattern, '}');
+    }
+
+    /**
+     * @param bool $strictLeadingDot
+     * @param bool $strictWildcardSlash
+     *
+     * @return Regex
+     */
+    public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
+    {
+        $firstByte = true;
+        $escaping = false;
+        $inCurlies = 0;
+        $regex = '';
+        $sizeGlob = strlen($this->pattern);
+        for ($i = 0; $i < $sizeGlob; $i++) {
+            $car = $this->pattern[$i];
+            if ($firstByte) {
+                if ($strictLeadingDot && '.' !== $car) {
+                    $regex .= '(?=[^\.])';
+                }
+
+                $firstByte = false;
+            }
+
+            if ('/' === $car) {
+                $firstByte = true;
+            }
+
+            if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
+                $regex .= "\\$car";
+            } elseif ('*' === $car) {
+                $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
+            } elseif ('?' === $car) {
+                $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
+            } elseif ('{' === $car) {
+                $regex .= $escaping ? '\\{' : '(';
+                if (!$escaping) {
+                    ++$inCurlies;
+                }
+            } elseif ('}' === $car && $inCurlies) {
+                $regex .= $escaping ? '}' : ')';
+                if (!$escaping) {
+                    --$inCurlies;
+                }
+            } elseif (',' === $car && $inCurlies) {
+                $regex .= $escaping ? ',' : '|';
+            } elseif ('\\' === $car) {
+                if ($escaping) {
+                    $regex .= '\\\\';
+                    $escaping = false;
+                } else {
+                    $escaping = true;
+                }
+
+                continue;
+            } else {
+                $regex .= $car;
+            }
+            $escaping = false;
+        }
+
+        return new Regex('^'.$regex.'$');
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/Regex.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/Regex.php
new file mode 100644
index 0000000..a249fc2
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/Regex.php
@@ -0,0 +1,321 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Expression;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class Regex implements ValueInterface
+{
+    const START_FLAG = '^';
+    const END_FLAG = '$';
+    const BOUNDARY = '~';
+    const JOKER = '.*';
+    const ESCAPING = '\\';
+
+    /**
+     * @var string
+     */
+    private $pattern;
+
+    /**
+     * @var array
+     */
+    private $options;
+
+    /**
+     * @var bool
+     */
+    private $startFlag;
+
+    /**
+     * @var bool
+     */
+    private $endFlag;
+
+    /**
+     * @var bool
+     */
+    private $startJoker;
+
+    /**
+     * @var bool
+     */
+    private $endJoker;
+
+    /**
+     * @param string $expr
+     *
+     * @return Regex
+     *
+     * @throws \InvalidArgumentException
+     */
+    public static function create($expr)
+    {
+        if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
+            $start = substr($m[1], 0, 1);
+            $end = substr($m[1], -1);
+
+            if (
+                ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
+                || ($start === '{' && $end === '}')
+                || ($start === '(' && $end === ')')
+            ) {
+                return new self(substr($m[1], 1, -1), $m[2], $end);
+            }
+        }
+
+        throw new \InvalidArgumentException('Given expression is not a regex.');
+    }
+
+    /**
+     * @param string $pattern
+     * @param string $options
+     * @param string $delimiter
+     */
+    public function __construct($pattern, $options = '', $delimiter = null)
+    {
+        if (null !== $delimiter) {
+            // removes delimiter escaping
+            $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
+        }
+
+        $this->parsePattern($pattern);
+        $this->options = $options;
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->render();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function render()
+    {
+        return self::BOUNDARY
+            .$this->renderPattern()
+            .self::BOUNDARY
+            .$this->options;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function renderPattern()
+    {
+        return ($this->startFlag ? self::START_FLAG : '')
+            .($this->startJoker ? self::JOKER : '')
+            .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
+            .($this->endJoker ? self::JOKER : '')
+            .($this->endFlag ? self::END_FLAG : '');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isCaseSensitive()
+    {
+        return !$this->hasOption('i');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return Expression::TYPE_REGEX;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function prepend($expr)
+    {
+        $this->pattern = $expr.$this->pattern;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function append($expr)
+    {
+        $this->pattern .= $expr;
+
+        return $this;
+    }
+
+    /**
+     * @param string $option
+     *
+     * @return bool
+     */
+    public function hasOption($option)
+    {
+        return false !== strpos($this->options, $option);
+    }
+
+    /**
+     * @param string $option
+     *
+     * @return Regex
+     */
+    public function addOption($option)
+    {
+        if (!$this->hasOption($option)) {
+            $this->options .= $option;
+        }
+
+        return $this;
+    }
+
+    /**
+     * @param string $option
+     *
+     * @return Regex
+     */
+    public function removeOption($option)
+    {
+        $this->options = str_replace($option, '', $this->options);
+
+        return $this;
+    }
+
+    /**
+     * @param bool $startFlag
+     *
+     * @return Regex
+     */
+    public function setStartFlag($startFlag)
+    {
+        $this->startFlag = $startFlag;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasStartFlag()
+    {
+        return $this->startFlag;
+    }
+
+    /**
+     * @param bool $endFlag
+     *
+     * @return Regex
+     */
+    public function setEndFlag($endFlag)
+    {
+        $this->endFlag = (bool) $endFlag;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasEndFlag()
+    {
+        return $this->endFlag;
+    }
+
+    /**
+     * @param bool $startJoker
+     *
+     * @return Regex
+     */
+    public function setStartJoker($startJoker)
+    {
+        $this->startJoker = $startJoker;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasStartJoker()
+    {
+        return $this->startJoker;
+    }
+
+    /**
+     * @param bool $endJoker
+     *
+     * @return Regex
+     */
+    public function setEndJoker($endJoker)
+    {
+        $this->endJoker = (bool) $endJoker;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasEndJoker()
+    {
+        return $this->endJoker;
+    }
+
+    /**
+     * @param array $replacement
+     *
+     * @return Regex
+     */
+    public function replaceJokers($replacement)
+    {
+        $replace = function ($subject) use ($replacement) {
+            $subject = $subject[0];
+            $replace = 0 === substr_count($subject, '\\') % 2;
+
+            return $replace ? str_replace('.', $replacement, $subject) : $subject;
+        };
+
+        $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
+
+        return $this;
+    }
+
+    /**
+     * @param string $pattern
+     */
+    private function parsePattern($pattern)
+    {
+        if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
+            $pattern = substr($pattern, 1);
+        }
+
+        if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
+            $pattern = substr($pattern, 2);
+        }
+
+        if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
+            $pattern = substr($pattern, 0, -1);
+        }
+
+        if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
+            $pattern = substr($pattern, 0, -2);
+        }
+
+        $this->pattern = $pattern;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/ValueInterface.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/ValueInterface.php
new file mode 100644
index 0000000..34ce0e7
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Expression/ValueInterface.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Expression;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+interface ValueInterface
+{
+    /**
+     * Renders string representation of expression.
+     *
+     * @return string
+     */
+    public function render();
+
+    /**
+     * Renders string representation of pattern.
+     *
+     * @return string
+     */
+    public function renderPattern();
+
+    /**
+     * Returns value case sensitivity.
+     *
+     * @return bool
+     */
+    public function isCaseSensitive();
+
+    /**
+     * Returns expression type.
+     *
+     * @return int
+     */
+    public function getType();
+
+    /**
+     * @param string $expr
+     *
+     * @return ValueInterface
+     */
+    public function prepend($expr);
+
+    /**
+     * @param string $expr
+     *
+     * @return ValueInterface
+     */
+    public function append($expr);
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Finder.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Finder.php
new file mode 100644
index 0000000..91a2992
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Finder.php
@@ -0,0 +1,840 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder;
+
+use Symfony\Component\Finder\Adapter\AdapterInterface;
+use Symfony\Component\Finder\Adapter\GnuFindAdapter;
+use Symfony\Component\Finder\Adapter\BsdFindAdapter;
+use Symfony\Component\Finder\Adapter\PhpAdapter;
+use Symfony\Component\Finder\Comparator\DateComparator;
+use Symfony\Component\Finder\Comparator\NumberComparator;
+use Symfony\Component\Finder\Exception\ExceptionInterface;
+use Symfony\Component\Finder\Iterator\CustomFilterIterator;
+use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
+use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
+use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
+use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
+use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
+use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
+use Symfony\Component\Finder\Iterator\SortableIterator;
+
+/**
+ * Finder allows to build rules to find files and directories.
+ *
+ * It is a thin wrapper around several specialized iterator classes.
+ *
+ * All rules may be invoked several times.
+ *
+ * All methods return the current Finder object to allow easy chaining:
+ *
+ * $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Finder implements \IteratorAggregate, \Countable
+{
+    const IGNORE_VCS_FILES = 1;
+    const IGNORE_DOT_FILES = 2;
+
+    private $mode = 0;
+    private $names = array();
+    private $notNames = array();
+    private $exclude = array();
+    private $filters = array();
+    private $depths = array();
+    private $sizes = array();
+    private $followLinks = false;
+    private $sort = false;
+    private $ignore = 0;
+    private $dirs = array();
+    private $dates = array();
+    private $iterators = array();
+    private $contains = array();
+    private $notContains = array();
+    private $adapters = array();
+    private $paths = array();
+    private $notPaths = array();
+    private $ignoreUnreadableDirs = false;
+
+    private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
+
+    /**
+     * Constructor.
+     */
+    public function __construct()
+    {
+        $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
+
+        $this
+            ->addAdapter(new GnuFindAdapter())
+            ->addAdapter(new BsdFindAdapter())
+            ->addAdapter(new PhpAdapter(), -50)
+            ->setAdapter('php')
+        ;
+    }
+
+    /**
+     * Creates a new Finder.
+     *
+     * @return Finder A new Finder instance
+     *
+     * @api
+     */
+    public static function create()
+    {
+        return new static();
+    }
+
+    /**
+     * Registers a finder engine implementation.
+     *
+     * @param AdapterInterface $adapter  An adapter instance
+     * @param int              $priority Highest is selected first
+     *
+     * @return Finder The current Finder instance
+     */
+    public function addAdapter(AdapterInterface $adapter, $priority = 0)
+    {
+        $this->adapters[$adapter->getName()] = array(
+            'adapter' => $adapter,
+            'priority' => $priority,
+            'selected' => false,
+        );
+
+        return $this->sortAdapters();
+    }
+
+    /**
+     * Sets the selected adapter to the best one according to the current platform the code is run on.
+     *
+     * @return Finder The current Finder instance
+     */
+    public function useBestAdapter()
+    {
+        $this->resetAdapterSelection();
+
+        return $this->sortAdapters();
+    }
+
+    /**
+     * Selects the adapter to use.
+     *
+     * @param string $name
+     *
+     * @throws \InvalidArgumentException
+     *
+     * @return Finder The current Finder instance
+     */
+    public function setAdapter($name)
+    {
+        if (!isset($this->adapters[$name])) {
+            throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
+        }
+
+        $this->resetAdapterSelection();
+        $this->adapters[$name]['selected'] = true;
+
+        return $this->sortAdapters();
+    }
+
+    /**
+     * Removes all adapters registered in the finder.
+     *
+     * @return Finder The current Finder instance
+     */
+    public function removeAdapters()
+    {
+        $this->adapters = array();
+
+        return $this;
+    }
+
+    /**
+     * Returns registered adapters ordered by priority without extra information.
+     *
+     * @return AdapterInterface[]
+     */
+    public function getAdapters()
+    {
+        return array_values(array_map(function (array $adapter) {
+            return $adapter['adapter'];
+        }, $this->adapters));
+    }
+
+    /**
+     * Restricts the matching to directories only.
+     *
+     * @return Finder The current Finder instance
+     *
+     * @api
+     */
+    public function directories()
+    {
+        $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
+
+        return $this;
+    }
+
+    /**
+     * Restricts the matching to files only.
+     *
+     * @return Finder The current Finder instance
+     *
+     * @api
+     */
+    public function files()
+    {
+        $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
+
+        return $this;
+    }
+
+    /**
+     * Adds tests for the directory depth.
+     *
+     * Usage:
+     *
+     *   $finder->depth('> 1') // the Finder will start matching at level 1.
+     *   $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
+     *
+     * @param int $level The depth level expression
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see DepthRangeFilterIterator
+     * @see NumberComparator
+     *
+     * @api
+     */
+    public function depth($level)
+    {
+        $this->depths[] = new Comparator\NumberComparator($level);
+
+        return $this;
+    }
+
+    /**
+     * Adds tests for file dates (last modified).
+     *
+     * The date must be something that strtotime() is able to parse:
+     *
+     *   $finder->date('since yesterday');
+     *   $finder->date('until 2 days ago');
+     *   $finder->date('> now - 2 hours');
+     *   $finder->date('>= 2005-10-15');
+     *
+     * @param string $date A date rage string
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see strtotime
+     * @see DateRangeFilterIterator
+     * @see DateComparator
+     *
+     * @api
+     */
+    public function date($date)
+    {
+        $this->dates[] = new Comparator\DateComparator($date);
+
+        return $this;
+    }
+
+    /**
+     * Adds rules that files must match.
+     *
+     * You can use patterns (delimited with / sign), globs or simple strings.
+     *
+     * $finder->name('*.php')
+     * $finder->name('/\.php$/') // same as above
+     * $finder->name('test.php')
+     *
+     * @param string $pattern A pattern (a regexp, a glob, or a string)
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see FilenameFilterIterator
+     *
+     * @api
+     */
+    public function name($pattern)
+    {
+        $this->names[] = $pattern;
+
+        return $this;
+    }
+
+    /**
+     * Adds rules that files must not match.
+     *
+     * @param string $pattern A pattern (a regexp, a glob, or a string)
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see FilenameFilterIterator
+     *
+     * @api
+     */
+    public function notName($pattern)
+    {
+        $this->notNames[] = $pattern;
+
+        return $this;
+    }
+
+    /**
+     * Adds tests that file contents must match.
+     *
+     * Strings or PCRE patterns can be used:
+     *
+     * $finder->contains('Lorem ipsum')
+     * $finder->contains('/Lorem ipsum/i')
+     *
+     * @param string $pattern A pattern (string or regexp)
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see FilecontentFilterIterator
+     */
+    public function contains($pattern)
+    {
+        $this->contains[] = $pattern;
+
+        return $this;
+    }
+
+    /**
+     * Adds tests that file contents must not match.
+     *
+     * Strings or PCRE patterns can be used:
+     *
+     * $finder->notContains('Lorem ipsum')
+     * $finder->notContains('/Lorem ipsum/i')
+     *
+     * @param string $pattern A pattern (string or regexp)
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see FilecontentFilterIterator
+     */
+    public function notContains($pattern)
+    {
+        $this->notContains[] = $pattern;
+
+        return $this;
+    }
+
+    /**
+     * Adds rules that filenames must match.
+     *
+     * You can use patterns (delimited with / sign) or simple strings.
+     *
+     * $finder->path('some/special/dir')
+     * $finder->path('/some\/special\/dir/') // same as above
+     *
+     * Use only / as dirname separator.
+     *
+     * @param string $pattern A pattern (a regexp or a string)
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see FilenameFilterIterator
+     */
+    public function path($pattern)
+    {
+        $this->paths[] = $pattern;
+
+        return $this;
+    }
+
+    /**
+     * Adds rules that filenames must not match.
+     *
+     * You can use patterns (delimited with / sign) or simple strings.
+     *
+     * $finder->notPath('some/special/dir')
+     * $finder->notPath('/some\/special\/dir/') // same as above
+     *
+     * Use only / as dirname separator.
+     *
+     * @param string $pattern A pattern (a regexp or a string)
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see FilenameFilterIterator
+     */
+    public function notPath($pattern)
+    {
+        $this->notPaths[] = $pattern;
+
+        return $this;
+    }
+
+    /**
+     * Adds tests for file sizes.
+     *
+     * $finder->size('> 10K');
+     * $finder->size('<= 1Ki');
+     * $finder->size(4);
+     *
+     * @param string $size A size range string
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see SizeRangeFilterIterator
+     * @see NumberComparator
+     *
+     * @api
+     */
+    public function size($size)
+    {
+        $this->sizes[] = new Comparator\NumberComparator($size);
+
+        return $this;
+    }
+
+    /**
+     * Excludes directories.
+     *
+     * @param string|array $dirs A directory path or an array of directories
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see ExcludeDirectoryFilterIterator
+     *
+     * @api
+     */
+    public function exclude($dirs)
+    {
+        $this->exclude = array_merge($this->exclude, (array) $dirs);
+
+        return $this;
+    }
+
+    /**
+     * Excludes "hidden" directories and files (starting with a dot).
+     *
+     * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see ExcludeDirectoryFilterIterator
+     *
+     * @api
+     */
+    public function ignoreDotFiles($ignoreDotFiles)
+    {
+        if ($ignoreDotFiles) {
+            $this->ignore = $this->ignore | static::IGNORE_DOT_FILES;
+        } else {
+            $this->ignore = $this->ignore & ~static::IGNORE_DOT_FILES;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Forces the finder to ignore version control directories.
+     *
+     * @param bool $ignoreVCS Whether to exclude VCS files or not
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see ExcludeDirectoryFilterIterator
+     *
+     * @api
+     */
+    public function ignoreVCS($ignoreVCS)
+    {
+        if ($ignoreVCS) {
+            $this->ignore = $this->ignore | static::IGNORE_VCS_FILES;
+        } else {
+            $this->ignore = $this->ignore & ~static::IGNORE_VCS_FILES;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Adds VCS patterns.
+     *
+     * @see ignoreVCS()
+     *
+     * @param string|string[] $pattern VCS patterns to ignore
+     */
+    public static function addVCSPattern($pattern)
+    {
+        foreach ((array) $pattern as $p) {
+            self::$vcsPatterns[] = $p;
+        }
+
+        self::$vcsPatterns = array_unique(self::$vcsPatterns);
+    }
+
+    /**
+     * Sorts files and directories by an anonymous function.
+     *
+     * The anonymous function receives two \SplFileInfo instances to compare.
+     *
+     * This can be slow as all the matching files and directories must be retrieved for comparison.
+     *
+     * @param \Closure $closure An anonymous function
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see SortableIterator
+     *
+     * @api
+     */
+    public function sort(\Closure $closure)
+    {
+        $this->sort = $closure;
+
+        return $this;
+    }
+
+    /**
+     * Sorts files and directories by name.
+     *
+     * This can be slow as all the matching files and directories must be retrieved for comparison.
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see SortableIterator
+     *
+     * @api
+     */
+    public function sortByName()
+    {
+        $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
+
+        return $this;
+    }
+
+    /**
+     * Sorts files and directories by type (directories before files), then by name.
+     *
+     * This can be slow as all the matching files and directories must be retrieved for comparison.
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see SortableIterator
+     *
+     * @api
+     */
+    public function sortByType()
+    {
+        $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
+
+        return $this;
+    }
+
+    /**
+     * Sorts files and directories by the last accessed time.
+     *
+     * This is the time that the file was last accessed, read or written to.
+     *
+     * This can be slow as all the matching files and directories must be retrieved for comparison.
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see SortableIterator
+     *
+     * @api
+     */
+    public function sortByAccessedTime()
+    {
+        $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
+
+        return $this;
+    }
+
+    /**
+     * Sorts files and directories by the last inode changed time.
+     *
+     * This is the time that the inode information was last modified (permissions, owner, group or other metadata).
+     *
+     * On Windows, since inode is not available, changed time is actually the file creation time.
+     *
+     * This can be slow as all the matching files and directories must be retrieved for comparison.
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see SortableIterator
+     *
+     * @api
+     */
+    public function sortByChangedTime()
+    {
+        $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
+
+        return $this;
+    }
+
+    /**
+     * Sorts files and directories by the last modified time.
+     *
+     * This is the last time the actual contents of the file were last modified.
+     *
+     * This can be slow as all the matching files and directories must be retrieved for comparison.
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see SortableIterator
+     *
+     * @api
+     */
+    public function sortByModifiedTime()
+    {
+        $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
+
+        return $this;
+    }
+
+    /**
+     * Filters the iterator with an anonymous function.
+     *
+     * The anonymous function receives a \SplFileInfo and must return false
+     * to remove files.
+     *
+     * @param \Closure $closure An anonymous function
+     *
+     * @return Finder The current Finder instance
+     *
+     * @see CustomFilterIterator
+     *
+     * @api
+     */
+    public function filter(\Closure $closure)
+    {
+        $this->filters[] = $closure;
+
+        return $this;
+    }
+
+    /**
+     * Forces the following of symlinks.
+     *
+     * @return Finder The current Finder instance
+     *
+     * @api
+     */
+    public function followLinks()
+    {
+        $this->followLinks = true;
+
+        return $this;
+    }
+
+    /**
+     * Tells finder to ignore unreadable directories.
+     *
+     * By default, scanning unreadable directories content throws an AccessDeniedException.
+     *
+     * @param bool $ignore
+     *
+     * @return Finder The current Finder instance
+     */
+    public function ignoreUnreadableDirs($ignore = true)
+    {
+        $this->ignoreUnreadableDirs = (bool) $ignore;
+
+        return $this;
+    }
+
+    /**
+     * Searches files and directories which match defined rules.
+     *
+     * @param string|array $dirs A directory path or an array of directories
+     *
+     * @return Finder The current Finder instance
+     *
+     * @throws \InvalidArgumentException if one of the directories does not exist
+     *
+     * @api
+     */
+    public function in($dirs)
+    {
+        $resolvedDirs = array();
+
+        foreach ((array) $dirs as $dir) {
+            if (is_dir($dir)) {
+                $resolvedDirs[] = $dir;
+            } elseif ($glob = glob($dir, GLOB_BRACE | GLOB_ONLYDIR)) {
+                $resolvedDirs = array_merge($resolvedDirs, $glob);
+            } else {
+                throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
+            }
+        }
+
+        $this->dirs = array_merge($this->dirs, $resolvedDirs);
+
+        return $this;
+    }
+
+    /**
+     * Returns an Iterator for the current Finder configuration.
+     *
+     * This method implements the IteratorAggregate interface.
+     *
+     * @return \Iterator An iterator
+     *
+     * @throws \LogicException if the in() method has not been called
+     */
+    public function getIterator()
+    {
+        if (0 === count($this->dirs) && 0 === count($this->iterators)) {
+            throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
+        }
+
+        if (1 === count($this->dirs) && 0 === count($this->iterators)) {
+            return $this->searchInDirectory($this->dirs[0]);
+        }
+
+        $iterator = new \AppendIterator();
+        foreach ($this->dirs as $dir) {
+            $iterator->append($this->searchInDirectory($dir));
+        }
+
+        foreach ($this->iterators as $it) {
+            $iterator->append($it);
+        }
+
+        return $iterator;
+    }
+
+    /**
+     * Appends an existing set of files/directories to the finder.
+     *
+     * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
+     *
+     * @param mixed $iterator
+     *
+     * @return Finder The finder
+     *
+     * @throws \InvalidArgumentException When the given argument is not iterable.
+     */
+    public function append($iterator)
+    {
+        if ($iterator instanceof \IteratorAggregate) {
+            $this->iterators[] = $iterator->getIterator();
+        } elseif ($iterator instanceof \Iterator) {
+            $this->iterators[] = $iterator;
+        } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
+            $it = new \ArrayIterator();
+            foreach ($iterator as $file) {
+                $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
+            }
+            $this->iterators[] = $it;
+        } else {
+            throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
+        }
+
+        return $this;
+    }
+
+    /**
+     * Counts all the results collected by the iterators.
+     *
+     * @return int
+     */
+    public function count()
+    {
+        return iterator_count($this->getIterator());
+    }
+
+    /**
+     * @return Finder The current Finder instance
+     */
+    private function sortAdapters()
+    {
+        uasort($this->adapters, function (array $a, array $b) {
+            if ($a['selected'] || $b['selected']) {
+                return $a['selected'] ? -1 : 1;
+            }
+
+            return $a['priority'] > $b['priority'] ? -1 : 1;
+        });
+
+        return $this;
+    }
+
+    /**
+     * @param $dir
+     *
+     * @return \Iterator
+     *
+     * @throws \RuntimeException When none of the adapters are supported
+     */
+    private function searchInDirectory($dir)
+    {
+        if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
+            $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
+        }
+
+        if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
+            $this->notPaths[] = '#(^|/)\..+(/|$)#';
+        }
+
+        foreach ($this->adapters as $adapter) {
+            if ($adapter['adapter']->isSupported()) {
+                try {
+                    return $this
+                        ->buildAdapter($adapter['adapter'])
+                        ->searchInDirectory($dir);
+                } catch (ExceptionInterface $e) {
+                }
+            }
+        }
+
+        throw new \RuntimeException('No supported adapter found.');
+    }
+
+    /**
+     * @param AdapterInterface $adapter
+     *
+     * @return AdapterInterface
+     */
+    private function buildAdapter(AdapterInterface $adapter)
+    {
+        return $adapter
+            ->setFollowLinks($this->followLinks)
+            ->setDepths($this->depths)
+            ->setMode($this->mode)
+            ->setExclude($this->exclude)
+            ->setNames($this->names)
+            ->setNotNames($this->notNames)
+            ->setContains($this->contains)
+            ->setNotContains($this->notContains)
+            ->setSizes($this->sizes)
+            ->setDates($this->dates)
+            ->setFilters($this->filters)
+            ->setSort($this->sort)
+            ->setPath($this->paths)
+            ->setNotPath($this->notPaths)
+            ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
+    }
+
+    /**
+     * Unselects all adapters.
+     */
+    private function resetAdapterSelection()
+    {
+        $this->adapters = array_map(function (array $properties) {
+            $properties['selected'] = false;
+
+            return $properties;
+        }, $this->adapters);
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Glob.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Glob.php
new file mode 100644
index 0000000..c2030c9
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Glob.php
@@ -0,0 +1,103 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder;
+
+/**
+ * Glob matches globbing patterns against text.
+ *
+ *   if match_glob("foo.*", "foo.bar") echo "matched\n";
+ *
+ * // prints foo.bar and foo.baz
+ * $regex = glob_to_regex("foo.*");
+ * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t)
+ * {
+ *   if (/$regex/) echo "matched: $car\n";
+ * }
+ *
+ * Glob implements glob(3) style matching that can be used to match
+ * against text, rather than fetching names from a filesystem.
+ *
+ * Based on the Perl Text::Glob module.
+ *
+ * @author Fabien Potencier <fabien@symfony.com> PHP port
+ * @author     Richard Clamp <richardc@unixbeard.net> Perl version
+ * @copyright  2004-2005 Fabien Potencier <fabien@symfony.com>
+ * @copyright  2002 Richard Clamp <richardc@unixbeard.net>
+ */
+class Glob
+{
+    /**
+     * Returns a regexp which is the equivalent of the glob pattern.
+     *
+     * @param string $glob                The glob pattern
+     * @param bool   $strictLeadingDot
+     * @param bool   $strictWildcardSlash
+     *
+     * @return string regex The regexp
+     */
+    public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true)
+    {
+        $firstByte = true;
+        $escaping = false;
+        $inCurlies = 0;
+        $regex = '';
+        $sizeGlob = strlen($glob);
+        for ($i = 0; $i < $sizeGlob; $i++) {
+            $car = $glob[$i];
+            if ($firstByte) {
+                if ($strictLeadingDot && '.' !== $car) {
+                    $regex .= '(?=[^\.])';
+                }
+
+                $firstByte = false;
+            }
+
+            if ('/' === $car) {
+                $firstByte = true;
+            }
+
+            if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
+                $regex .= "\\$car";
+            } elseif ('*' === $car) {
+                $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
+            } elseif ('?' === $car) {
+                $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
+            } elseif ('{' === $car) {
+                $regex .= $escaping ? '\\{' : '(';
+                if (!$escaping) {
+                    ++$inCurlies;
+                }
+            } elseif ('}' === $car && $inCurlies) {
+                $regex .= $escaping ? '}' : ')';
+                if (!$escaping) {
+                    --$inCurlies;
+                }
+            } elseif (',' === $car && $inCurlies) {
+                $regex .= $escaping ? ',' : '|';
+            } elseif ('\\' === $car) {
+                if ($escaping) {
+                    $regex .= '\\\\';
+                    $escaping = false;
+                } else {
+                    $escaping = true;
+                }
+
+                continue;
+            } else {
+                $regex .= $car;
+            }
+            $escaping = false;
+        }
+
+        return '#^'.$regex.'$#';
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php
new file mode 100644
index 0000000..24b15d9
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * CustomFilterIterator filters files by applying anonymous functions.
+ *
+ * The anonymous function receives a \SplFileInfo and must return false
+ * to remove files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class CustomFilterIterator extends FilterIterator
+{
+    private $filters = array();
+
+    /**
+     * Constructor.
+     *
+     * @param \Iterator $iterator The Iterator to filter
+     * @param array     $filters  An array of PHP callbacks
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function __construct(\Iterator $iterator, array $filters)
+    {
+        foreach ($filters as $filter) {
+            if (!is_callable($filter)) {
+                throw new \InvalidArgumentException('Invalid PHP callback.');
+            }
+        }
+        $this->filters = $filters;
+
+        parent::__construct($iterator);
+    }
+
+    /**
+     * Filters the iterator values.
+     *
+     * @return bool true if the value should be kept, false otherwise
+     */
+    public function accept()
+    {
+        $fileinfo = $this->current();
+
+        foreach ($this->filters as $filter) {
+            if (false === call_user_func($filter, $fileinfo)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php
new file mode 100644
index 0000000..4d5ef9a
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\Comparator\DateComparator;
+
+/**
+ * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class DateRangeFilterIterator extends FilterIterator
+{
+    private $comparators = array();
+
+    /**
+     * Constructor.
+     *
+     * @param \Iterator        $iterator    The Iterator to filter
+     * @param DateComparator[] $comparators An array of DateComparator instances
+     */
+    public function __construct(\Iterator $iterator, array $comparators)
+    {
+        $this->comparators = $comparators;
+
+        parent::__construct($iterator);
+    }
+
+    /**
+     * Filters the iterator values.
+     *
+     * @return bool true if the value should be kept, false otherwise
+     */
+    public function accept()
+    {
+        $fileinfo = $this->current();
+
+        if (!file_exists($fileinfo->getRealPath())) {
+            return false;
+        }
+
+        $filedate = $fileinfo->getMTime();
+        foreach ($this->comparators as $compare) {
+            if (!$compare->test($filedate)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php
new file mode 100644
index 0000000..f78c71e
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * DepthRangeFilterIterator limits the directory depth.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class DepthRangeFilterIterator extends FilterIterator
+{
+    private $minDepth = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param \RecursiveIteratorIterator $iterator The Iterator to filter
+     * @param int                        $minDepth The min depth
+     * @param int                        $maxDepth The max depth
+     */
+    public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
+    {
+        $this->minDepth = $minDepth;
+        $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
+
+        parent::__construct($iterator);
+    }
+
+    /**
+     * Filters the iterator values.
+     *
+     * @return bool true if the value should be kept, false otherwise
+     */
+    public function accept()
+    {
+        return $this->getInnerIterator()->getDepth() >= $this->minDepth;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php
new file mode 100644
index 0000000..1ddde85
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * ExcludeDirectoryFilterIterator filters out directories.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ExcludeDirectoryFilterIterator extends FilterIterator
+{
+    private $patterns = array();
+
+    /**
+     * Constructor.
+     *
+     * @param \Iterator $iterator    The Iterator to filter
+     * @param array     $directories An array of directories to exclude
+     */
+    public function __construct(\Iterator $iterator, array $directories)
+    {
+        foreach ($directories as $directory) {
+            $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#';
+        }
+
+        parent::__construct($iterator);
+    }
+
+    /**
+     * Filters the iterator values.
+     *
+     * @return bool true if the value should be kept, false otherwise
+     */
+    public function accept()
+    {
+        $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
+        $path = strtr($path, '\\', '/');
+        foreach ($this->patterns as $pattern) {
+            if (preg_match($pattern, $path)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php
new file mode 100644
index 0000000..4da2f5b
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php
@@ -0,0 +1,131 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\SplFileInfo;
+
+/**
+ * Iterate over shell command result.
+ *
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class FilePathsIterator extends \ArrayIterator
+{
+    /**
+     * @var string
+     */
+    private $baseDir;
+
+    /**
+     * @var int
+     */
+    private $baseDirLength;
+
+    /**
+     * @var string
+     */
+    private $subPath;
+
+    /**
+     * @var string
+     */
+    private $subPathname;
+
+    /**
+     * @var SplFileInfo
+     */
+    private $current;
+
+    /**
+     * @param array  $paths   List of paths returned by shell command
+     * @param string $baseDir Base dir for relative path building
+     */
+    public function __construct(array $paths, $baseDir)
+    {
+        $this->baseDir = $baseDir;
+        $this->baseDirLength = strlen($baseDir);
+
+        parent::__construct($paths);
+    }
+
+    /**
+     * @param string $name
+     * @param array  $arguments
+     *
+     * @return mixed
+     */
+    public function __call($name, array $arguments)
+    {
+        return call_user_func_array(array($this->current(), $name), $arguments);
+    }
+
+    /**
+     * Return an instance of SplFileInfo with support for relative paths.
+     *
+     * @return SplFileInfo File information
+     */
+    public function current()
+    {
+        return $this->current;
+    }
+
+    /**
+     * @return string
+     */
+    public function key()
+    {
+        return $this->current->getPathname();
+    }
+
+    public function next()
+    {
+        parent::next();
+        $this->buildProperties();
+    }
+
+    public function rewind()
+    {
+        parent::rewind();
+        $this->buildProperties();
+    }
+
+    /**
+     * @return string
+     */
+    public function getSubPath()
+    {
+        return $this->subPath;
+    }
+
+    /**
+     * @return string
+     */
+    public function getSubPathname()
+    {
+        return $this->subPathname;
+    }
+
+    private function buildProperties()
+    {
+        $absolutePath = parent::current();
+
+        if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
+            $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
+            $dir = dirname($this->subPathname);
+            $this->subPath = '.' === $dir ? '' : $dir;
+        } else {
+            $this->subPath = $this->subPathname = '';
+        }
+
+        $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php
new file mode 100644
index 0000000..f50fd82
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * FileTypeFilterIterator only keeps files, directories, or both.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class FileTypeFilterIterator extends FilterIterator
+{
+    const ONLY_FILES = 1;
+    const ONLY_DIRECTORIES = 2;
+
+    private $mode;
+
+    /**
+     * Constructor.
+     *
+     * @param \Iterator $iterator The Iterator to filter
+     * @param int       $mode     The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES)
+     */
+    public function __construct(\Iterator $iterator, $mode)
+    {
+        $this->mode = $mode;
+
+        parent::__construct($iterator);
+    }
+
+    /**
+     * Filters the iterator values.
+     *
+     * @return bool true if the value should be kept, false otherwise
+     */
+    public function accept()
+    {
+        $fileinfo = $this->current();
+        if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
+            return false;
+        } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
+            return false;
+        }
+
+        return true;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php
new file mode 100644
index 0000000..28cf770
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php
@@ -0,0 +1,76 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings).
+ *
+ * @author Fabien Potencier  <fabien@symfony.com>
+ * @author WÅ‚odzimierz Gajda <gajdaw@gajdaw.pl>
+ */
+class FilecontentFilterIterator extends MultiplePcreFilterIterator
+{
+    /**
+     * Filters the iterator values.
+     *
+     * @return bool true if the value should be kept, false otherwise
+     */
+    public function accept()
+    {
+        if (!$this->matchRegexps && !$this->noMatchRegexps) {
+            return true;
+        }
+
+        $fileinfo = $this->current();
+
+        if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
+            return false;
+        }
+
+        $content = $fileinfo->getContents();
+        if (!$content) {
+            return false;
+        }
+
+        // should at least not match one rule to exclude
+        foreach ($this->noMatchRegexps as $regex) {
+            if (preg_match($regex, $content)) {
+                return false;
+            }
+        }
+
+        // should at least match one rule
+        $match = true;
+        if ($this->matchRegexps) {
+            $match = false;
+            foreach ($this->matchRegexps as $regex) {
+                if (preg_match($regex, $content)) {
+                    return true;
+                }
+            }
+        }
+
+        return $match;
+    }
+
+    /**
+     * Converts string to regexp if necessary.
+     *
+     * @param string $str Pattern: string or regexp
+     *
+     * @return string regexp corresponding to a given string or regexp
+     */
+    protected function toRegex($str)
+    {
+        return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php
new file mode 100644
index 0000000..f1cd391
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\Expression\Expression;
+
+/**
+ * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class FilenameFilterIterator extends MultiplePcreFilterIterator
+{
+    /**
+     * Filters the iterator values.
+     *
+     * @return bool true if the value should be kept, false otherwise
+     */
+    public function accept()
+    {
+        $filename = $this->current()->getFilename();
+
+        // should at least not match one rule to exclude
+        foreach ($this->noMatchRegexps as $regex) {
+            if (preg_match($regex, $filename)) {
+                return false;
+            }
+        }
+
+        // should at least match one rule
+        $match = true;
+        if ($this->matchRegexps) {
+            $match = false;
+            foreach ($this->matchRegexps as $regex) {
+                if (preg_match($regex, $filename)) {
+                    return true;
+                }
+            }
+        }
+
+        return $match;
+    }
+
+    /**
+     * Converts glob to regexp.
+     *
+     * PCRE patterns are left unchanged.
+     * Glob strings are transformed with Glob::toRegex().
+     *
+     * @param string $str Pattern: glob or regexp
+     *
+     * @return string regexp corresponding to a given glob or regexp
+     */
+    protected function toRegex($str)
+    {
+        return Expression::create($str)->getRegex()->render();
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php
new file mode 100644
index 0000000..f4da44c
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * This iterator just overrides the rewind method in order to correct a PHP bug.
+ *
+ * @see https://bugs.php.net/bug.php?id=49104
+ *
+ * @author Alex Bogomazov
+ */
+abstract class FilterIterator extends \FilterIterator
+{
+    /**
+     * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after
+     * rewind in some cases.
+     *
+     * @see FilterIterator::rewind()
+     */
+    public function rewind()
+    {
+        $iterator = $this;
+        while ($iterator instanceof \OuterIterator) {
+            $innerIterator = $iterator->getInnerIterator();
+
+            if ($innerIterator instanceof RecursiveDirectoryIterator) {
+                if ($innerIterator->isRewindable()) {
+                    $innerIterator->next();
+                    $innerIterator->rewind();
+                }
+            } elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) {
+                $iterator->getInnerIterator()->next();
+                $iterator->getInnerIterator()->rewind();
+            }
+            $iterator = $iterator->getInnerIterator();
+        }
+
+        parent::rewind();
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php
new file mode 100644
index 0000000..068a7ef
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\Expression\Expression;
+
+/**
+ * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class MultiplePcreFilterIterator extends FilterIterator
+{
+    protected $matchRegexps = array();
+    protected $noMatchRegexps = array();
+
+    /**
+     * Constructor.
+     *
+     * @param \Iterator $iterator        The Iterator to filter
+     * @param array     $matchPatterns   An array of patterns that need to match
+     * @param array     $noMatchPatterns An array of patterns that need to not match
+     */
+    public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
+    {
+        foreach ($matchPatterns as $pattern) {
+            $this->matchRegexps[] = $this->toRegex($pattern);
+        }
+
+        foreach ($noMatchPatterns as $pattern) {
+            $this->noMatchRegexps[] = $this->toRegex($pattern);
+        }
+
+        parent::__construct($iterator);
+    }
+
+    /**
+     * Checks whether the string is a regex.
+     *
+     * @param string $str
+     *
+     * @return bool Whether the given string is a regex
+     */
+    protected function isRegex($str)
+    {
+        return Expression::create($str)->isRegex();
+    }
+
+    /**
+     * Converts string into regexp.
+     *
+     * @param string $str Pattern
+     *
+     * @return string regexp corresponding to a given string
+     */
+    abstract protected function toRegex($str);
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php
new file mode 100644
index 0000000..2bb8ebd
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * PathFilterIterator filters files by path patterns (e.g. some/special/dir).
+ *
+ * @author Fabien Potencier  <fabien@symfony.com>
+ * @author WÅ‚odzimierz Gajda <gajdaw@gajdaw.pl>
+ */
+class PathFilterIterator extends MultiplePcreFilterIterator
+{
+    /**
+     * Filters the iterator values.
+     *
+     * @return bool true if the value should be kept, false otherwise
+     */
+    public function accept()
+    {
+        $filename = $this->current()->getRelativePathname();
+
+        if ('\\' === DIRECTORY_SEPARATOR) {
+            $filename = strtr($filename, '\\', '/');
+        }
+
+        // should at least not match one rule to exclude
+        foreach ($this->noMatchRegexps as $regex) {
+            if (preg_match($regex, $filename)) {
+                return false;
+            }
+        }
+
+        // should at least match one rule
+        $match = true;
+        if ($this->matchRegexps) {
+            $match = false;
+            foreach ($this->matchRegexps as $regex) {
+                if (preg_match($regex, $filename)) {
+                    return true;
+                }
+            }
+        }
+
+        return $match;
+    }
+
+    /**
+     * Converts strings to regexp.
+     *
+     * PCRE patterns are left unchanged.
+     *
+     * Default conversion:
+     *     'lorem/ipsum/dolor' ==>  'lorem\/ipsum\/dolor/'
+     *
+     * Use only / as directory separator (on Windows also).
+     *
+     * @param string $str Pattern: regexp or dirname.
+     *
+     * @return string regexp corresponding to a given string or regexp
+     */
+    protected function toRegex($str)
+    {
+        return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php
new file mode 100644
index 0000000..af824d0
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php
@@ -0,0 +1,126 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\Exception\AccessDeniedException;
+use Symfony\Component\Finder\SplFileInfo;
+
+/**
+ * Extends the \RecursiveDirectoryIterator to support relative paths.
+ *
+ * @author Victor Berchet <victor@suumit.com>
+ */
+class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
+{
+    /**
+     * @var bool
+     */
+    private $ignoreUnreadableDirs;
+
+    /**
+     * @var bool
+     */
+    private $rewindable;
+
+    /**
+     * Constructor.
+     *
+     * @param string $path
+     * @param int    $flags
+     * @param bool   $ignoreUnreadableDirs
+     *
+     * @throws \RuntimeException
+     */
+    public function __construct($path, $flags, $ignoreUnreadableDirs = false)
+    {
+        if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
+            throw new \RuntimeException('This iterator only support returning current as fileinfo.');
+        }
+
+        parent::__construct($path, $flags);
+        $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
+    }
+
+    /**
+     * Return an instance of SplFileInfo with support for relative paths.
+     *
+     * @return SplFileInfo File information
+     */
+    public function current()
+    {
+        return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname());
+    }
+
+    /**
+     * @return \RecursiveIterator
+     *
+     * @throws AccessDeniedException
+     */
+    public function getChildren()
+    {
+        try {
+            $children = parent::getChildren();
+
+            if ($children instanceof self) {
+                // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore
+                $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
+            }
+
+            return $children;
+        } catch (\UnexpectedValueException $e) {
+            if ($this->ignoreUnreadableDirs) {
+                // If directory is unreadable and finder is set to ignore it, a fake empty content is returned.
+                return new \RecursiveArrayIterator(array());
+            } else {
+                throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
+            }
+        }
+    }
+
+    /**
+     * Do nothing for non rewindable stream.
+     */
+    public function rewind()
+    {
+        if (false === $this->isRewindable()) {
+            return;
+        }
+
+        // @see https://bugs.php.net/bug.php?id=49104
+        parent::next();
+
+        parent::rewind();
+    }
+
+    /**
+     * Checks if the stream is rewindable.
+     *
+     * @return bool true when the stream is rewindable, false otherwise
+     */
+    public function isRewindable()
+    {
+        if (null !== $this->rewindable) {
+            return $this->rewindable;
+        }
+
+        if (false !== $stream = @opendir($this->getPath())) {
+            $infos = stream_get_meta_data($stream);
+            closedir($stream);
+
+            if ($infos['seekable']) {
+                return $this->rewindable = true;
+            }
+        }
+
+        return $this->rewindable = false;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php
new file mode 100644
index 0000000..3d3140a
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\Comparator\NumberComparator;
+
+/**
+ * SizeRangeFilterIterator filters out files that are not in the given size range.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class SizeRangeFilterIterator extends FilterIterator
+{
+    private $comparators = array();
+
+    /**
+     * Constructor.
+     *
+     * @param \Iterator          $iterator    The Iterator to filter
+     * @param NumberComparator[] $comparators An array of NumberComparator instances
+     */
+    public function __construct(\Iterator $iterator, array $comparators)
+    {
+        $this->comparators = $comparators;
+
+        parent::__construct($iterator);
+    }
+
+    /**
+     * Filters the iterator values.
+     *
+     * @return bool true if the value should be kept, false otherwise
+     */
+    public function accept()
+    {
+        $fileinfo = $this->current();
+        if (!$fileinfo->isFile()) {
+            return true;
+        }
+
+        $filesize = $fileinfo->getSize();
+        foreach ($this->comparators as $compare) {
+            if (!$compare->test($filesize)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.php
new file mode 100644
index 0000000..b32ac8d
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * SortableIterator applies a sort on a given Iterator.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class SortableIterator implements \IteratorAggregate
+{
+    const SORT_BY_NAME = 1;
+    const SORT_BY_TYPE = 2;
+    const SORT_BY_ACCESSED_TIME = 3;
+    const SORT_BY_CHANGED_TIME = 4;
+    const SORT_BY_MODIFIED_TIME = 5;
+
+    private $iterator;
+    private $sort;
+
+    /**
+     * Constructor.
+     *
+     * @param \Traversable $iterator The Iterator to filter
+     * @param int|callable $sort     The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function __construct(\Traversable $iterator, $sort)
+    {
+        $this->iterator = $iterator;
+
+        if (self::SORT_BY_NAME === $sort) {
+            $this->sort = function ($a, $b) {
+                return strcmp($a->getRealpath(), $b->getRealpath());
+            };
+        } elseif (self::SORT_BY_TYPE === $sort) {
+            $this->sort = function ($a, $b) {
+                if ($a->isDir() && $b->isFile()) {
+                    return -1;
+                } elseif ($a->isFile() && $b->isDir()) {
+                    return 1;
+                }
+
+                return strcmp($a->getRealpath(), $b->getRealpath());
+            };
+        } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
+            $this->sort = function ($a, $b) {
+                return ($a->getATime() - $b->getATime());
+            };
+        } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
+            $this->sort = function ($a, $b) {
+                return ($a->getCTime() - $b->getCTime());
+            };
+        } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
+            $this->sort = function ($a, $b) {
+                return ($a->getMTime() - $b->getMTime());
+            };
+        } elseif (is_callable($sort)) {
+            $this->sort = $sort;
+        } else {
+            throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
+        }
+    }
+
+    public function getIterator()
+    {
+        $array = iterator_to_array($this->iterator, true);
+        uasort($array, $this->sort);
+
+        return new \ArrayIterator($array);
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/LICENSE b/core/vendor/symfony/finder/Symfony/Component/Finder/LICENSE
new file mode 100644
index 0000000..43028bc
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2015 Fabien Potencier
+
+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:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+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.
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/README.md b/core/vendor/symfony/finder/Symfony/Component/Finder/README.md
new file mode 100644
index 0000000..7a96219
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/README.md
@@ -0,0 +1,53 @@
+Finder Component
+================
+
+Finder finds files and directories via an intuitive fluent interface.
+
+```php
+use Symfony\Component\Finder\Finder;
+
+$finder = new Finder();
+
+$iterator = $finder
+  ->files()
+  ->name('*.php')
+  ->depth(0)
+  ->size('>= 1K')
+  ->in(__DIR__);
+
+foreach ($iterator as $file) {
+    print $file->getRealpath()."\n";
+}
+```
+
+The iterator returns instances of [Symfony\Component\Finder\SplFileInfo\SplFileInfo][1].
+Besides the build-in methods inherited from [\SplFileInfo][2] (`getPerms()`, `getSize()`, ...),
+you can also use `getRelativePath()` and `getRelativePathname()`. Read the
+[official documentation][3] for more information.
+
+But you can also use it to find files stored remotely like in this example where
+we are looking for files on Amazon S3:
+
+```php
+$s3 = new \Zend_Service_Amazon_S3($key, $secret);
+$s3->registerStreamWrapper("s3");
+
+$finder = new Finder();
+$finder->name('photos*')->size('< 100K')->date('since 1 hour ago');
+foreach ($finder->in('s3://bucket-name') as $file) {
+    print $file->getFilename()."\n";
+}
+```
+
+Resources
+---------
+
+You can run the unit tests with the following command:
+
+    $ cd path/to/Symfony/Component/Finder/
+    $ composer.phar install
+    $ phpunit
+
+[1]: http://api.symfony.com/2.5/Symfony/Component/Finder/SplFileInfo.html
+[2]: http://php.net/splfileinfo
+[3]: http://symfony.com/doc/current/components/finder.html#usage
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Shell/Command.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Shell/Command.php
new file mode 100644
index 0000000..1f69afb
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Shell/Command.php
@@ -0,0 +1,294 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Shell;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class Command
+{
+    /**
+     * @var Command|null
+     */
+    private $parent;
+
+    /**
+     * @var array
+     */
+    private $bits = array();
+
+    /**
+     * @var array
+     */
+    private $labels = array();
+
+    /**
+     * @var \Closure|null
+     */
+    private $errorHandler;
+
+    /**
+     * Constructor.
+     *
+     * @param Command|null $parent Parent command
+     */
+    public function __construct(Command $parent = null)
+    {
+        $this->parent = $parent;
+    }
+
+    /**
+     * Returns command as string.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->join();
+    }
+
+    /**
+     * Creates a new Command instance.
+     *
+     * @param Command|null $parent Parent command
+     *
+     * @return Command New Command instance
+     */
+    public static function create(Command $parent = null)
+    {
+        return new self($parent);
+    }
+
+    /**
+     * Escapes special chars from input.
+     *
+     * @param string $input A string to escape
+     *
+     * @return string The escaped string
+     */
+    public static function escape($input)
+    {
+        return escapeshellcmd($input);
+    }
+
+    /**
+     * Quotes input.
+     *
+     * @param string $input An argument string
+     *
+     * @return string The quoted string
+     */
+    public static function quote($input)
+    {
+        return escapeshellarg($input);
+    }
+
+    /**
+     * Appends a string or a Command instance.
+     *
+     * @param string|Command $bit
+     *
+     * @return Command The current Command instance
+     */
+    public function add($bit)
+    {
+        $this->bits[] = $bit;
+
+        return $this;
+    }
+
+    /**
+     * Prepends a string or a command instance.
+     *
+     * @param string|Command $bit
+     *
+     * @return Command The current Command instance
+     */
+    public function top($bit)
+    {
+        array_unshift($this->bits, $bit);
+
+        foreach ($this->labels as $label => $index) {
+            $this->labels[$label] += 1;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Appends an argument, will be quoted.
+     *
+     * @param string $arg
+     *
+     * @return Command The current Command instance
+     */
+    public function arg($arg)
+    {
+        $this->bits[] = self::quote($arg);
+
+        return $this;
+    }
+
+    /**
+     * Appends escaped special command chars.
+     *
+     * @param string $esc
+     *
+     * @return Command The current Command instance
+     */
+    public function cmd($esc)
+    {
+        $this->bits[] = self::escape($esc);
+
+        return $this;
+    }
+
+    /**
+     * Inserts a labeled command to feed later.
+     *
+     * @param string $label The unique label
+     *
+     * @return Command The current Command instance
+     *
+     * @throws \RuntimeException If label already exists
+     */
+    public function ins($label)
+    {
+        if (isset($this->labels[$label])) {
+            throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
+        }
+
+        $this->bits[] = self::create($this);
+        $this->labels[$label] = count($this->bits)-1;
+
+        return $this->bits[$this->labels[$label]];
+    }
+
+    /**
+     * Retrieves a previously labeled command.
+     *
+     * @param string $label
+     *
+     * @return Command The labeled command
+     *
+     * @throws \RuntimeException
+     */
+    public function get($label)
+    {
+        if (!isset($this->labels[$label])) {
+            throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
+        }
+
+        return $this->bits[$this->labels[$label]];
+    }
+
+    /**
+     * Returns parent command (if any).
+     *
+     * @return Command Parent command
+     *
+     * @throws \RuntimeException If command has no parent
+     */
+    public function end()
+    {
+        if (null === $this->parent) {
+            throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
+        }
+
+        return $this->parent;
+    }
+
+    /**
+     * Counts bits stored in command.
+     *
+     * @return int The bits count
+     */
+    public function length()
+    {
+        return count($this->bits);
+    }
+
+    /**
+     * @param \Closure $errorHandler
+     *
+     * @return Command
+     */
+    public function setErrorHandler(\Closure $errorHandler)
+    {
+        $this->errorHandler = $errorHandler;
+
+        return $this;
+    }
+
+    /**
+     * @return \Closure|null
+     */
+    public function getErrorHandler()
+    {
+        return $this->errorHandler;
+    }
+
+    /**
+     * Executes current command.
+     *
+     * @return array The command result
+     *
+     * @throws \RuntimeException
+     */
+    public function execute()
+    {
+        if (null === $errorHandler = $this->errorHandler) {
+            exec($this->join(), $output);
+        } else {
+            $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
+            $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
+
+            if ($error = stream_get_contents($pipes[2])) {
+                $errorHandler($error);
+            }
+
+            proc_close($process);
+        }
+
+        return $output ?: array();
+    }
+
+    /**
+     * Joins bits.
+     *
+     * @return string
+     */
+    public function join()
+    {
+        return implode(' ', array_filter(
+            array_map(function ($bit) {
+                return $bit instanceof Command ? $bit->join() : ($bit ?: null);
+            }, $this->bits),
+            function ($bit) { return null !== $bit; }
+        ));
+    }
+
+    /**
+     * Insert a string or a Command instance before the bit at given position $index (index starts from 0).
+     *
+     * @param string|Command $bit
+     * @param int            $index
+     *
+     * @return Command The current Command instance
+     */
+    public function addAtIndex($bit, $index)
+    {
+        array_splice($this->bits, $index, 0, $bit);
+
+        return $this;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Shell/Shell.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Shell/Shell.php
new file mode 100644
index 0000000..6d7bff3
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Shell/Shell.php
@@ -0,0 +1,97 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Shell;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class Shell
+{
+    const TYPE_UNIX = 1;
+    const TYPE_DARWIN = 2;
+    const TYPE_CYGWIN = 3;
+    const TYPE_WINDOWS = 4;
+    const TYPE_BSD = 5;
+
+    /**
+     * @var string|null
+     */
+    private $type;
+
+    /**
+     * Returns guessed OS type.
+     *
+     * @return int
+     */
+    public function getType()
+    {
+        if (null === $this->type) {
+            $this->type = $this->guessType();
+        }
+
+        return $this->type;
+    }
+
+    /**
+     * Tests if a command is available.
+     *
+     * @param string $command
+     *
+     * @return bool
+     */
+    public function testCommand($command)
+    {
+        if (!function_exists('exec')) {
+            return false;
+        }
+
+        // todo: find a better way (command could not be available)
+        $testCommand = 'which ';
+        if (self::TYPE_WINDOWS === $this->type) {
+            $testCommand = 'where ';
+        }
+
+        $command = escapeshellcmd($command);
+
+        exec($testCommand.$command, $output, $code);
+
+        return 0 === $code && count($output) > 0;
+    }
+
+    /**
+     * Guesses OS type.
+     *
+     * @return int
+     */
+    private function guessType()
+    {
+        $os = strtolower(PHP_OS);
+
+        if (false !== strpos($os, 'cygwin')) {
+            return self::TYPE_CYGWIN;
+        }
+
+        if (false !== strpos($os, 'darwin')) {
+            return self::TYPE_DARWIN;
+        }
+
+        if (false !== strpos($os, 'bsd')) {
+            return self::TYPE_BSD;
+        }
+
+        if (0 === strpos($os, 'win')) {
+            return self::TYPE_WINDOWS;
+        }
+
+        return self::TYPE_UNIX;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/SplFileInfo.php b/core/vendor/symfony/finder/Symfony/Component/Finder/SplFileInfo.php
new file mode 100644
index 0000000..c7fbe02
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/SplFileInfo.php
@@ -0,0 +1,77 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder;
+
+/**
+ * Extends \SplFileInfo to support relative paths.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class SplFileInfo extends \SplFileInfo
+{
+    private $relativePath;
+    private $relativePathname;
+
+    /**
+     * Constructor.
+     *
+     * @param string $file             The file name
+     * @param string $relativePath     The relative path
+     * @param string $relativePathname The relative path name
+     */
+    public function __construct($file, $relativePath, $relativePathname)
+    {
+        parent::__construct($file);
+        $this->relativePath = $relativePath;
+        $this->relativePathname = $relativePathname;
+    }
+
+    /**
+     * Returns the relative path.
+     *
+     * @return string the relative path
+     */
+    public function getRelativePath()
+    {
+        return $this->relativePath;
+    }
+
+    /**
+     * Returns the relative path name.
+     *
+     * @return string the relative path name
+     */
+    public function getRelativePathname()
+    {
+        return $this->relativePathname;
+    }
+
+    /**
+     * Returns the contents of the file.
+     *
+     * @return string the contents of the file
+     *
+     * @throws \RuntimeException
+     */
+    public function getContents()
+    {
+        $level = error_reporting(0);
+        $content = file_get_contents($this->getPathname());
+        error_reporting($level);
+        if (false === $content) {
+            $error = error_get_last();
+            throw new \RuntimeException($error['message']);
+        }
+
+        return $content;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/ComparatorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/ComparatorTest.php
new file mode 100644
index 0000000..bf59844
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/ComparatorTest.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Comparator;
+
+use Symfony\Component\Finder\Comparator\Comparator;
+
+class ComparatorTest extends \PHPUnit_Framework_TestCase
+{
+    public function testGetSetOperator()
+    {
+        $comparator = new Comparator();
+        try {
+            $comparator->setOperator('foo');
+            $this->fail('->setOperator() throws an \InvalidArgumentException if the operator is not valid.');
+        } catch (\Exception $e) {
+            $this->assertInstanceOf('InvalidArgumentException', $e, '->setOperator() throws an \InvalidArgumentException if the operator is not valid.');
+        }
+
+        $comparator = new Comparator();
+        $comparator->setOperator('>');
+        $this->assertEquals('>', $comparator->getOperator(), '->getOperator() returns the current operator');
+    }
+
+    public function testGetSetTarget()
+    {
+        $comparator = new Comparator();
+        $comparator->setTarget(8);
+        $this->assertEquals(8, $comparator->getTarget(), '->getTarget() returns the target');
+    }
+
+    /**
+     * @dataProvider getTestData
+     */
+    public function testTest($operator, $target, $match, $noMatch)
+    {
+        $c = new Comparator();
+        $c->setOperator($operator);
+        $c->setTarget($target);
+
+        foreach ($match as $m) {
+            $this->assertTrue($c->test($m), '->test() tests a string against the expression');
+        }
+
+        foreach ($noMatch as $m) {
+            $this->assertFalse($c->test($m), '->test() tests a string against the expression');
+        }
+    }
+
+    public function getTestData()
+    {
+        return array(
+            array('<', '1000', array('500', '999'), array('1000', '1500')),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.php
new file mode 100644
index 0000000..2739126
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Comparator;
+
+use Symfony\Component\Finder\Comparator\DateComparator;
+
+class DateComparatorTest extends \PHPUnit_Framework_TestCase
+{
+    public function testConstructor()
+    {
+        try {
+            new DateComparator('foobar');
+            $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+        } catch (\Exception $e) {
+            $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+        }
+
+        try {
+            new DateComparator('');
+            $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+        } catch (\Exception $e) {
+            $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+        }
+    }
+
+    /**
+     * @dataProvider getTestData
+     */
+    public function testTest($test, $match, $noMatch)
+    {
+        $c = new DateComparator($test);
+
+        foreach ($match as $m) {
+            $this->assertTrue($c->test($m), '->test() tests a string against the expression');
+        }
+
+        foreach ($noMatch as $m) {
+            $this->assertFalse($c->test($m), '->test() tests a string against the expression');
+        }
+    }
+
+    public function getTestData()
+    {
+        return array(
+            array('< 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
+            array('until 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
+            array('before 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
+            array('> 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
+            array('after 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
+            array('since 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
+            array('!= 2005-10-10', array(strtotime('2005-10-11')), array(strtotime('2005-10-10'))),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.php
new file mode 100644
index 0000000..d8cef1b
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.php
@@ -0,0 +1,107 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Comparator;
+
+use Symfony\Component\Finder\Comparator\NumberComparator;
+
+class NumberComparatorTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider getConstructorTestData
+     */
+    public function testConstructor($successes, $failures)
+    {
+        foreach ($successes as $s) {
+            new NumberComparator($s);
+        }
+
+        foreach ($failures as $f) {
+            try {
+                new NumberComparator($f);
+                $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+            } catch (\Exception $e) {
+                $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+            }
+        }
+    }
+
+    /**
+     * @dataProvider getTestData
+     */
+    public function testTest($test, $match, $noMatch)
+    {
+        $c = new NumberComparator($test);
+
+        foreach ($match as $m) {
+            $this->assertTrue($c->test($m), '->test() tests a string against the expression');
+        }
+
+        foreach ($noMatch as $m) {
+            $this->assertFalse($c->test($m), '->test() tests a string against the expression');
+        }
+    }
+
+    public function getTestData()
+    {
+        return array(
+            array('< 1000', array('500', '999'), array('1000', '1500')),
+
+            array('< 1K', array('500', '999'), array('1000', '1500')),
+            array('<1k', array('500', '999'), array('1000', '1500')),
+            array('  < 1 K ', array('500', '999'), array('1000', '1500')),
+            array('<= 1K', array('1000'), array('1001')),
+            array('> 1K', array('1001'), array('1000')),
+            array('>= 1K', array('1000'), array('999')),
+
+            array('< 1KI', array('500', '1023'), array('1024', '1500')),
+            array('<= 1KI', array('1024'), array('1025')),
+            array('> 1KI', array('1025'), array('1024')),
+            array('>= 1KI', array('1024'), array('1023')),
+
+            array('1KI', array('1024'), array('1023', '1025')),
+            array('==1KI', array('1024'), array('1023', '1025')),
+
+            array('==1m', array('1000000'), array('999999', '1000001')),
+            array('==1mi', array(1024*1024), array(1024*1024-1, 1024*1024+1)),
+
+            array('==1g', array('1000000000'), array('999999999', '1000000001')),
+            array('==1gi', array(1024*1024*1024), array(1024*1024*1024-1, 1024*1024*1024+1)),
+
+            array('!= 1000', array('500', '999'), array('1000')),
+        );
+    }
+
+    public function getConstructorTestData()
+    {
+        return array(
+            array(
+                array(
+                    '1', '0',
+                    '3.5', '33.55', '123.456', '123456.78',
+                    '.1', '.123',
+                    '.0', '0.0',
+                    '1.', '0.', '123.',
+                    '==1', '!=1', '<1', '>1', '<=1', '>=1',
+                    '==1k', '==1ki', '==1m', '==1mi', '==1g', '==1gi',
+                    '1k', '1ki', '1m', '1mi', '1g', '1gi',
+                ),
+                array(
+                    false, null, '',
+                    ' ', 'foobar',
+                    '=1', '===1',
+                    '0 . 1', '123 .45', '234. 567',
+                    '..', '.0.', '0.1.2',
+                ),
+            ),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/ExpressionTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/ExpressionTest.php
new file mode 100644
index 0000000..4254a45
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/ExpressionTest.php
@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Expression;
+
+use Symfony\Component\Finder\Expression\Expression;
+
+class ExpressionTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider getTypeGuesserData
+     */
+    public function testTypeGuesser($expr, $type)
+    {
+        $this->assertEquals($type, Expression::create($expr)->getType());
+    }
+
+    /**
+     * @dataProvider getCaseSensitiveData
+     */
+    public function testCaseSensitive($expr, $isCaseSensitive)
+    {
+        $this->assertEquals($isCaseSensitive, Expression::create($expr)->isCaseSensitive());
+    }
+
+    /**
+     * @dataProvider getRegexRenderingData
+     */
+    public function testRegexRendering($expr, $body)
+    {
+        $this->assertEquals($body, Expression::create($expr)->renderPattern());
+    }
+
+    public function getTypeGuesserData()
+    {
+        return array(
+            array('{foo}', Expression::TYPE_REGEX),
+            array('/foo/', Expression::TYPE_REGEX),
+            array('foo',   Expression::TYPE_GLOB),
+            array('foo*',  Expression::TYPE_GLOB),
+        );
+    }
+
+    public function getCaseSensitiveData()
+    {
+        return array(
+            array('{foo}m', true),
+            array('/foo/i', false),
+            array('foo*',   true),
+        );
+    }
+
+    public function getRegexRenderingData()
+    {
+        return array(
+            array('{foo}m', 'foo'),
+            array('/foo/i', 'foo'),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/GlobTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/GlobTest.php
new file mode 100644
index 0000000..9d4c3e5
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/GlobTest.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Expression;
+
+use Symfony\Component\Finder\Expression\Expression;
+
+class GlobTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider getToRegexData
+     */
+    public function testGlobToRegex($glob, $match, $noMatch)
+    {
+        foreach ($match as $m) {
+            $this->assertRegExp(Expression::create($glob)->getRegex()->render(), $m, '::toRegex() converts a glob to a regexp');
+        }
+
+        foreach ($noMatch as $m) {
+            $this->assertNotRegExp(Expression::create($glob)->getRegex()->render(), $m, '::toRegex() converts a glob to a regexp');
+        }
+    }
+
+    public function getToRegexData()
+    {
+        return array(
+            array('', array(''), array('f', '/')),
+            array('*', array('foo'), array('foo/', '/foo')),
+            array('foo.*', array('foo.php', 'foo.a', 'foo.'), array('fooo.php', 'foo.php/foo')),
+            array('fo?', array('foo', 'fot'), array('fooo', 'ffoo', 'fo/')),
+            array('fo{o,t}', array('foo', 'fot'), array('fob', 'fo/')),
+            array('foo(bar|foo)', array('foo(bar|foo)'), array('foobar', 'foofoo')),
+            array('foo,bar', array('foo,bar'), array('foo', 'bar')),
+            array('fo{o,\\,}', array('foo', 'fo,'), array()),
+            array('fo{o,\\\\}', array('foo', 'fo\\'), array()),
+            array('/foo', array('/foo'), array('foo')),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/RegexTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/RegexTest.php
new file mode 100644
index 0000000..620ba10
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/RegexTest.php
@@ -0,0 +1,143 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Expression;
+
+use Symfony\Component\Finder\Expression\Expression;
+
+class RegexTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider getHasFlagsData
+     */
+    public function testHasFlags($regex, $start, $end)
+    {
+        $expr = new Expression($regex);
+
+        $this->assertEquals($start, $expr->getRegex()->hasStartFlag());
+        $this->assertEquals($end, $expr->getRegex()->hasEndFlag());
+    }
+
+    /**
+     * @dataProvider getHasJokersData
+     */
+    public function testHasJokers($regex, $start, $end)
+    {
+        $expr = new Expression($regex);
+
+        $this->assertEquals($start, $expr->getRegex()->hasStartJoker());
+        $this->assertEquals($end, $expr->getRegex()->hasEndJoker());
+    }
+
+    /**
+     * @dataProvider getSetFlagsData
+     */
+    public function testSetFlags($regex, $start, $end, $expected)
+    {
+        $expr = new Expression($regex);
+        $expr->getRegex()->setStartFlag($start)->setEndFlag($end);
+
+        $this->assertEquals($expected, $expr->render());
+    }
+
+    /**
+     * @dataProvider getSetJokersData
+     */
+    public function testSetJokers($regex, $start, $end, $expected)
+    {
+        $expr = new Expression($regex);
+        $expr->getRegex()->setStartJoker($start)->setEndJoker($end);
+
+        $this->assertEquals($expected, $expr->render());
+    }
+
+    public function testOptions()
+    {
+        $expr = new Expression('~abc~is');
+        $expr->getRegex()->removeOption('i')->addOption('m');
+
+        $this->assertEquals('~abc~sm', $expr->render());
+    }
+
+    public function testMixFlagsAndJokers()
+    {
+        $expr = new Expression('~^.*abc.*$~is');
+
+        $expr->getRegex()->setStartFlag(false)->setEndFlag(false)->setStartJoker(false)->setEndJoker(false);
+        $this->assertEquals('~abc~is', $expr->render());
+
+        $expr->getRegex()->setStartFlag(true)->setEndFlag(true)->setStartJoker(true)->setEndJoker(true);
+        $this->assertEquals('~^.*abc.*$~is', $expr->render());
+    }
+
+    /**
+     * @dataProvider getReplaceJokersTestData
+     */
+    public function testReplaceJokers($regex, $expected)
+    {
+        $expr = new Expression($regex);
+        $expr = $expr->getRegex()->replaceJokers('@');
+
+        $this->assertEquals($expected, $expr->renderPattern());
+    }
+
+    public function getHasFlagsData()
+    {
+        return array(
+            array('~^abc~', true, false),
+            array('~abc$~', false, true),
+            array('~abc~', false, false),
+            array('~^abc$~', true, true),
+            array('~^abc\\$~', true, false),
+        );
+    }
+
+    public function getHasJokersData()
+    {
+        return array(
+            array('~.*abc~', true, false),
+            array('~abc.*~', false, true),
+            array('~abc~', false, false),
+            array('~.*abc.*~', true, true),
+            array('~.*abc\\.*~', true, false),
+        );
+    }
+
+    public function getSetFlagsData()
+    {
+        return array(
+            array('~abc~', true, false, '~^abc~'),
+            array('~abc~', false, true, '~abc$~'),
+            array('~abc~', false, false, '~abc~'),
+            array('~abc~', true, true, '~^abc$~'),
+        );
+    }
+
+    public function getSetJokersData()
+    {
+        return array(
+            array('~abc~', true, false, '~.*abc~'),
+            array('~abc~', false, true, '~abc.*~'),
+            array('~abc~', false, false, '~abc~'),
+            array('~abc~', true, true, '~.*abc.*~'),
+        );
+    }
+
+    public function getReplaceJokersTestData()
+    {
+        return array(
+            array('~.abc~', '@abc'),
+            array('~\\.abc~', '\\.abc'),
+            array('~\\\\.abc~', '\\\\@abc'),
+            array('~\\\\\\.abc~', '\\\\\\.abc'),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php
new file mode 100644
index 0000000..0cbae14
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\FakeAdapter;
+
+use Symfony\Component\Finder\Adapter\AbstractAdapter;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class DummyAdapter extends AbstractAdapter
+{
+    /**
+     * @var \Iterator
+     */
+    private $iterator;
+
+    /**
+     * @param \Iterator $iterator
+     */
+    public function __construct(\Iterator $iterator)
+    {
+        $this->iterator = $iterator;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function searchInDirectory($dir)
+    {
+        return $this->iterator;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'yes';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function canBeUsed()
+    {
+        return true;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php
new file mode 100644
index 0000000..6e6ed24
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\FakeAdapter;
+
+use Symfony\Component\Finder\Adapter\AbstractAdapter;
+use Symfony\Component\Finder\Exception\AdapterFailureException;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class FailingAdapter extends AbstractAdapter
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function searchInDirectory($dir)
+    {
+        throw new AdapterFailureException($this);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'failing';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function canBeUsed()
+    {
+        return true;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php
new file mode 100644
index 0000000..5a260b0
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\FakeAdapter;
+
+use Symfony\Component\Finder\Adapter\AbstractAdapter;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class NamedAdapter extends AbstractAdapter
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @param string $name
+     */
+    public function __construct($name)
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function searchInDirectory($dir)
+    {
+        return new \ArrayIterator(array());
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function canBeUsed()
+    {
+        return true;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php
new file mode 100644
index 0000000..1f91b98
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\FakeAdapter;
+
+use Symfony\Component\Finder\Adapter\AbstractAdapter;
+
+/**
+ * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
+ */
+class UnsupportedAdapter extends AbstractAdapter
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function searchInDirectory($dir)
+    {
+        return new \ArrayIterator(array());
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'unsupported';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function canBeUsed()
+    {
+        return false;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FinderTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FinderTest.php
new file mode 100644
index 0000000..12f0678
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/FinderTest.php
@@ -0,0 +1,869 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests;
+
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Finder\Adapter;
+
+class FinderTest extends Iterator\RealIteratorTestCase
+{
+    public function testCreate()
+    {
+        $this->assertInstanceOf('Symfony\Component\Finder\Finder', Finder::create());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testDirectories($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->directories());
+        $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->directories();
+        $finder->files();
+        $finder->directories();
+        $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testFiles($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->files());
+        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->files();
+        $finder->directories();
+        $finder->files();
+        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testDepth($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->depth('< 1'));
+        $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->depth('<= 0'));
+        $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->depth('>= 1'));
+        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->depth('< 1')->depth('>= 1');
+        $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testName($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->name('*.php'));
+        $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->name('test.ph*');
+        $finder->name('test.py');
+        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->name('~^test~i');
+        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->name('~\\.php$~i');
+        $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->name('test.p{hp,y}');
+        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testNotName($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->notName('*.php'));
+        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->notName('*.php');
+        $finder->notName('*.py');
+        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->name('test.ph*');
+        $finder->name('test.py');
+        $finder->notName('*.php');
+        $finder->notName('*.py');
+        $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->name('test.ph*');
+        $finder->name('test.py');
+        $finder->notName('*.p{hp,y}');
+        $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getRegexNameTestData
+     *
+     * @group regexName
+     */
+    public function testRegexName($adapter, $regex)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->name($regex);
+        $this->assertIterator($this->toAbsolute(array('test.py', 'test.php')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testSize($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->files()->size('< 1K')->size('> 500'));
+        $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testDate($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->files()->date('until last month'));
+        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testExclude($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->exclude('foo'));
+        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testIgnoreVCS($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false));
+        $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false);
+        $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false));
+        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testIgnoreDotFiles($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false));
+        $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false);
+        $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false));
+        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testSortByName($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->sortByName());
+        $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testSortByType($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->sortByType());
+        $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'toto', 'foo/bar.tmp', 'test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testSortByAccessedTime($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->sortByAccessedTime());
+        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testSortByChangedTime($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->sortByChangedTime());
+        $this->assertIterator($this->toAbsolute(array('toto', 'test.py', 'test.php', 'foo/bar.tmp', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testSortByModifiedTime($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->sortByModifiedTime());
+        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testSort($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }));
+        $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testFilter($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->filter(function (\SplFileInfo $f) { return preg_match('/test/', $f) > 0; }));
+        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testFollowLinks($adapter)
+    {
+        if ('\\' == DIRECTORY_SEPARATOR) {
+            return;
+        }
+
+        $finder = $this->buildFinder($adapter);
+        $this->assertSame($finder, $finder->followLinks());
+        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testIn($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        try {
+            $finder->in('foobar');
+            $this->fail('->in() throws a \InvalidArgumentException if the directory does not exist');
+        } catch (\Exception $e) {
+            $this->assertInstanceOf('InvalidArgumentException', $e, '->in() throws a \InvalidArgumentException if the directory does not exist');
+        }
+
+        $finder = $this->buildFinder($adapter);
+        $iterator = $finder->files()->name('*.php')->depth('< 1')->in(array(self::$tmpDir, __DIR__))->getIterator();
+
+        $this->assertIterator(array(self::$tmpDir.DIRECTORY_SEPARATOR.'test.php', __DIR__.DIRECTORY_SEPARATOR.'FinderTest.php'), $iterator);
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testInWithGlob($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->in(array(__DIR__.'/Fixtures/*/B/C', __DIR__.'/Fixtures/*/*/B/C'))->getIterator();
+
+        $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder);
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     * @expectedException \InvalidArgumentException
+     */
+    public function testInWithNonDirectoryGlob($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->in(__DIR__.'/Fixtures/A/a*');
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testInWithGlobBrace($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->in(array(__DIR__.'/Fixtures/{A,copy/A}/B/C'))->getIterator();
+
+        $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder);
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testGetIterator($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        try {
+            $finder->getIterator();
+            $this->fail('->getIterator() throws a \LogicException if the in() method has not been called');
+        } catch (\Exception $e) {
+            $this->assertInstanceOf('LogicException', $e, '->getIterator() throws a \LogicException if the in() method has not been called');
+        }
+
+        $finder = $this->buildFinder($adapter);
+        $dirs = array();
+        foreach ($finder->directories()->in(self::$tmpDir) as $dir) {
+            $dirs[] = (string) $dir;
+        }
+
+        $expected = $this->toAbsolute(array('foo', 'toto'));
+
+        sort($dirs);
+        sort($expected);
+
+        $this->assertEquals($expected, $dirs, 'implements the \IteratorAggregate interface');
+
+        $finder = $this->buildFinder($adapter);
+        $this->assertEquals(2, iterator_count($finder->directories()->in(self::$tmpDir)), 'implements the \IteratorAggregate interface');
+
+        $finder = $this->buildFinder($adapter);
+        $a = iterator_to_array($finder->directories()->in(self::$tmpDir));
+        $a = array_values(array_map(function ($a) { return (string) $a; }, $a));
+        sort($a);
+        $this->assertEquals($expected, $a, 'implements the \IteratorAggregate interface');
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testRelativePath($adapter)
+    {
+        $finder = $this->buildFinder($adapter)->in(self::$tmpDir);
+
+        $paths = array();
+
+        foreach ($finder as $file) {
+            $paths[] = $file->getRelativePath();
+        }
+
+        $ref = array("", "", "", "", "foo", "");
+
+        sort($ref);
+        sort($paths);
+
+        $this->assertEquals($ref, $paths);
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testRelativePathname($adapter)
+    {
+        $finder = $this->buildFinder($adapter)->in(self::$tmpDir)->sortByName();
+
+        $paths = array();
+
+        foreach ($finder as $file) {
+            $paths[] = $file->getRelativePathname();
+        }
+
+        $ref = array("test.php", "toto", "test.py", "foo", "foo".DIRECTORY_SEPARATOR."bar.tmp", "foo bar");
+
+        sort($paths);
+        sort($ref);
+
+        $this->assertEquals($ref, $paths);
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testAppendWithAFinder($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');
+
+        $finder1 = $this->buildFinder($adapter);
+        $finder1->directories()->in(self::$tmpDir);
+
+        $finder = $finder->append($finder1);
+
+        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testAppendWithAnArray($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');
+
+        $finder->append($this->toAbsolute(array('foo', 'toto')));
+
+        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator());
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testAppendReturnsAFinder($adapter)
+    {
+        $this->assertInstanceOf('Symfony\\Component\\Finder\\Finder', $this->buildFinder($adapter)->append(array()));
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testAppendDoesNotRequireIn($adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');
+
+        $finder1 = Finder::create()->append($finder);
+
+        $this->assertIterator(iterator_to_array($finder->getIterator()), $finder1->getIterator());
+    }
+
+    public function testCountDirectories()
+    {
+        $directory = Finder::create()->directories()->in(self::$tmpDir);
+        $i = 0;
+
+        foreach ($directory as $dir) {
+            $i++;
+        }
+
+        $this->assertCount($i, $directory);
+    }
+
+    public function testCountFiles()
+    {
+        $files = Finder::create()->files()->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures');
+        $i = 0;
+
+        foreach ($files as $file) {
+            $i++;
+        }
+
+        $this->assertCount($i, $files);
+    }
+
+    /**
+     * @expectedException \LogicException
+     */
+    public function testCountWithoutIn()
+    {
+        $finder = Finder::create()->files();
+        count($finder);
+    }
+
+    /**
+     * @dataProvider getContainsTestData
+     * @group grep
+     */
+    public function testContains($adapter, $matchPatterns, $noMatchPatterns, $expected)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
+            ->name('*.txt')->sortByName()
+            ->contains($matchPatterns)
+            ->notContains($noMatchPatterns);
+
+        $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testContainsOnDirectory(Adapter\AdapterInterface $adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->in(__DIR__)
+            ->directories()
+            ->name('Fixtures')
+            ->contains('abc');
+        $this->assertIterator(array(), $finder);
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testNotContainsOnDirectory(Adapter\AdapterInterface $adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->in(__DIR__)
+            ->directories()
+            ->name('Fixtures')
+            ->notContains('abc');
+        $this->assertIterator(array(), $finder);
+    }
+
+    /**
+     * Searching in multiple locations involves AppendIterator which does an unnecessary rewind which leaves FilterIterator
+     * with inner FilesystemIterator in an invalid state.
+     *
+     * @see https://bugs.php.net/bug.php?id=49104
+     *
+     * @dataProvider getAdaptersTestData
+     */
+    public function testMultipleLocations(Adapter\AdapterInterface $adapter)
+    {
+        $locations = array(
+            self::$tmpDir.'/',
+            self::$tmpDir.'/toto/',
+        );
+
+        // it is expected that there are test.py test.php in the tmpDir
+        $finder = $this->buildFinder($adapter);
+        $finder->in($locations)->depth('< 1')->name('test.php');
+
+        $this->assertCount(1, $finder);
+    }
+
+    /**
+     * Iterator keys must be the file pathname.
+     *
+     * @dataProvider getAdaptersTestData
+     */
+    public function testIteratorKeys(Adapter\AdapterInterface $adapter)
+    {
+        $finder = $this->buildFinder($adapter)->in(self::$tmpDir);
+        foreach ($finder as $key => $file) {
+            $this->assertEquals($file->getPathname(), $key);
+        }
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testRegexSpecialCharsLocationWithPathRestrictionContainingStartFlag(Adapter\AdapterInterface $adapter)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'r+e.gex[c]a(r)s')
+            ->path('/^dir/');
+
+        $expected = array('r+e.gex[c]a(r)s'.DIRECTORY_SEPARATOR.'dir',
+                          'r+e.gex[c]a(r)s'.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'bar.dat',);
+        $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
+    }
+
+    public function testAdaptersOrdering()
+    {
+        $finder = Finder::create()
+            ->removeAdapters()
+            ->addAdapter(new FakeAdapter\NamedAdapter('a'), 0)
+            ->addAdapter(new FakeAdapter\NamedAdapter('b'), -50)
+            ->addAdapter(new FakeAdapter\NamedAdapter('c'), 50)
+            ->addAdapter(new FakeAdapter\NamedAdapter('d'), -25)
+            ->addAdapter(new FakeAdapter\NamedAdapter('e'), 25);
+
+        $this->assertEquals(
+            array('c', 'e', 'a', 'd', 'b'),
+            array_map(function (Adapter\AdapterInterface $adapter) {
+                return $adapter->getName();
+            }, $finder->getAdapters())
+        );
+    }
+
+    public function testAdaptersChaining()
+    {
+        $iterator = new \ArrayIterator(array());
+        $filenames = $this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto'));
+        foreach ($filenames as $file) {
+            $iterator->append(new \Symfony\Component\Finder\SplFileInfo($file, null, null));
+        }
+
+        $finder = Finder::create()
+            ->removeAdapters()
+            ->addAdapter(new FakeAdapter\UnsupportedAdapter(), 3)
+            ->addAdapter(new FakeAdapter\FailingAdapter(), 2)
+            ->addAdapter(new FakeAdapter\DummyAdapter($iterator), 1);
+
+        $this->assertIterator($filenames, $finder->in(sys_get_temp_dir())->getIterator());
+    }
+
+    public function getAdaptersTestData()
+    {
+        return array_map(
+            function ($adapter) { return array($adapter); },
+            $this->getValidAdapters()
+        );
+    }
+
+    public function getContainsTestData()
+    {
+        $tests = array(
+            array('', '', array()),
+            array('foo', 'bar', array()),
+            array('', 'foobar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')),
+            array('lorem ipsum dolor sit amet', 'foobar', array('lorem.txt')),
+            array('sit', 'bar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')),
+            array('dolor sit amet', '@^L@m', array('dolor.txt', 'ipsum.txt')),
+            array('/^lorem ipsum dolor sit amet$/m', 'foobar', array('lorem.txt')),
+            array('lorem', 'foobar', array('lorem.txt')),
+            array('', 'lorem', array('dolor.txt', 'ipsum.txt')),
+            array('ipsum dolor sit amet', '/^IPSUM/m', array('lorem.txt')),
+        );
+
+        return $this->buildTestData($tests);
+    }
+
+    public function getRegexNameTestData()
+    {
+        $tests = array(
+            array('~.+\\.p.+~i'),
+            array('~t.*s~i'),
+        );
+
+        return $this->buildTestData($tests);
+    }
+
+    /**
+     * @dataProvider getTestPathData
+     */
+    public function testPath(Adapter\AdapterInterface $adapter, $matchPatterns, $noMatchPatterns, array $expected)
+    {
+        $finder = $this->buildFinder($adapter);
+        $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
+            ->path($matchPatterns)
+            ->notPath($noMatchPatterns);
+
+        $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
+    }
+
+    public function testAdapterSelection()
+    {
+        // test that by default, PhpAdapter is selected
+        $adapters = Finder::create()->getAdapters();
+        $this->assertTrue($adapters[0] instanceof Adapter\PhpAdapter);
+
+        // test another adapter selection
+        $adapters = Finder::create()->setAdapter('gnu_find')->getAdapters();
+        $this->assertTrue($adapters[0] instanceof Adapter\GnuFindAdapter);
+
+        // test that useBestAdapter method removes selection
+        $adapters = Finder::create()->useBestAdapter()->getAdapters();
+        $this->assertFalse($adapters[0] instanceof Adapter\PhpAdapter);
+    }
+
+    public function getTestPathData()
+    {
+        $tests = array(
+            array('', '', array()),
+            array('/^A\/B\/C/', '/C$/',
+                array('A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat'),
+            ),
+            array('/^A\/B/', 'foobar',
+                array(
+                    'A'.DIRECTORY_SEPARATOR.'B',
+                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
+                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
+                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
+                ),
+            ),
+            array('A/B/C', 'foobar',
+                array(
+                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
+                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
+                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
+                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat.copy',
+                ),
+            ),
+            array('A/B', 'foobar',
+                array(
+                    //dirs
+                    'A'.DIRECTORY_SEPARATOR.'B',
+                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
+                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B',
+                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
+                    //files
+                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
+                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
+                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat.copy',
+                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat.copy',
+                ),
+            ),
+            array('/^with space\//', 'foobar',
+                array(
+                    'with space'.DIRECTORY_SEPARATOR.'foo.txt',
+                ),
+            ),
+        );
+
+        return $this->buildTestData($tests);
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testAccessDeniedException(Adapter\AdapterInterface $adapter)
+    {
+        if ('\\' === DIRECTORY_SEPARATOR) {
+            $this->markTestSkipped('chmod is not supported on Windows');
+        }
+
+        $finder = $this->buildFinder($adapter);
+        $finder->files()->in(self::$tmpDir);
+
+        // make 'foo' directory non-readable
+        $testDir = self::$tmpDir.DIRECTORY_SEPARATOR.'foo';
+        chmod($testDir, 0333);
+
+        if (false === $couldRead = is_readable($testDir)) {
+            try {
+                $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
+                $this->fail('Finder should throw an exception when opening a non-readable directory.');
+            } catch (\Exception $e) {
+                $expectedExceptionClass = 'Symfony\\Component\\Finder\\Exception\\AccessDeniedException';
+                if ($e instanceof \PHPUnit_Framework_ExpectationFailedException) {
+                    $this->fail(sprintf("Expected exception:\n%s\nGot:\n%s\nWith comparison failure:\n%s", $expectedExceptionClass, 'PHPUnit_Framework_ExpectationFailedException', $e->getComparisonFailure()->getExpectedAsString()));
+                }
+
+                $this->assertInstanceOf($expectedExceptionClass, $e);
+            }
+        }
+
+        // restore original permissions
+        chmod($testDir, 0777);
+        clearstatcache($testDir);
+
+        if ($couldRead) {
+            $this->markTestSkipped('could read test files while test requires unreadable');
+        }
+    }
+
+    /**
+     * @dataProvider getAdaptersTestData
+     */
+    public function testIgnoredAccessDeniedException(Adapter\AdapterInterface $adapter)
+    {
+        if ('\\' === DIRECTORY_SEPARATOR) {
+            $this->markTestSkipped('chmod is not supported on Windows');
+        }
+
+        $finder = $this->buildFinder($adapter);
+        $finder->files()->ignoreUnreadableDirs()->in(self::$tmpDir);
+
+        // make 'foo' directory non-readable
+        $testDir = self::$tmpDir.DIRECTORY_SEPARATOR.'foo';
+        chmod($testDir, 0333);
+
+        if (false === ($couldRead = is_readable($testDir))) {
+            $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
+        }
+
+        // restore original permissions
+        chmod($testDir, 0777);
+        clearstatcache($testDir);
+
+        if ($couldRead) {
+            $this->markTestSkipped('could read test files while test requires unreadable');
+        }
+    }
+
+    private function buildTestData(array $tests)
+    {
+        $data = array();
+        foreach ($this->getValidAdapters() as $adapter) {
+            foreach ($tests as $test) {
+                $data[] = array_merge(array($adapter), $test);
+            }
+        }
+
+        return $data;
+    }
+
+    private function buildFinder(Adapter\AdapterInterface $adapter)
+    {
+        return Finder::create()
+            ->removeAdapters()
+            ->addAdapter($adapter);
+    }
+
+    private function getValidAdapters()
+    {
+        return array_filter(
+            array(
+                new Adapter\BsdFindAdapter(),
+                new Adapter\GnuFindAdapter(),
+                new Adapter\PhpAdapter(),
+            ),
+            function (Adapter\AdapterInterface $adapter) {
+                return $adapter->isSupported();
+            }
+        );
+    }
+
+    /**
+     * Searching in multiple locations with sub directories involves
+     * AppendIterator which does an unnecessary rewind which leaves
+     * FilterIterator with inner FilesystemIterator in an invalid state.
+     *
+     * @see https://bugs.php.net/bug.php?id=49104
+     */
+    public function testMultipleLocationsWithSubDirectories()
+    {
+        $locations = array(
+            __DIR__.'/Fixtures/one',
+            self::$tmpDir.DIRECTORY_SEPARATOR.'toto',
+        );
+
+        $finder = new Finder();
+        $finder->in($locations)->depth('< 10')->name('*.neon');
+
+        $expected = array(
+            __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'c.neon',
+            __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'d.neon',
+        );
+
+        $this->assertIterator($expected, $finder);
+        $this->assertIteratorInForeach($expected, $finder);
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.dat b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.dat
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/A/B/ab.dat b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/A/B/ab.dat
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/A/a.dat b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/A/a.dat
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copy b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copy
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copy b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copy
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/dolor.txt b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/dolor.txt
new file mode 100644
index 0000000..658bec6
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/dolor.txt
@@ -0,0 +1,2 @@
+dolor sit amet
+DOLOR SIT AMET
\ No newline at end of file
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/ipsum.txt b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/ipsum.txt
new file mode 100644
index 0000000..c7f392d
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/ipsum.txt
@@ -0,0 +1,2 @@
+ipsum dolor sit amet
+IPSUM DOLOR SIT AMET
\ No newline at end of file
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/lorem.txt b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/lorem.txt
new file mode 100644
index 0000000..2991a2c
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/lorem.txt
@@ -0,0 +1,2 @@
+lorem ipsum dolor sit amet
+LOREM IPSUM DOLOR SIT AMET
\ No newline at end of file
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/one/a b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/one/a
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/one/b/c.neon b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/one/b/c.neon
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/one/b/d.neon b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/one/b/d.neon
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/r+e.gex[c]a(r)s/dir/bar.dat b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/r+e.gex[c]a(r)s/dir/bar.dat
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/with space/foo.txt b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/with space/foo.txt
new file mode 100644
index 0000000..e69de29
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.php
new file mode 100644
index 0000000..62629b1
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\CustomFilterIterator;
+
+class CustomFilterIteratorTest extends IteratorTestCase
+{
+    /**
+     * @expectedException \InvalidArgumentException
+     */
+    public function testWithInvalidFilter()
+    {
+        new CustomFilterIterator(new Iterator(), array('foo'));
+    }
+
+    /**
+     * @dataProvider getAcceptData
+     */
+    public function testAccept($filters, $expected)
+    {
+        $inner = new Iterator(array('test.php', 'test.py', 'foo.php'));
+
+        $iterator = new CustomFilterIterator($inner, $filters);
+
+        $this->assertIterator($expected, $iterator);
+    }
+
+    public function getAcceptData()
+    {
+        return array(
+            array(array(function (\SplFileInfo $fileinfo) { return false; }), array()),
+            array(array(function (\SplFileInfo $fileinfo) { return preg_match('/^test/', $fileinfo) > 0; }), array('test.php', 'test.py')),
+            array(array('is_dir'), array()),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php
new file mode 100644
index 0000000..709d5fe
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php
@@ -0,0 +1,72 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
+use Symfony\Component\Finder\Comparator\DateComparator;
+
+class DateRangeFilterIteratorTest extends RealIteratorTestCase
+{
+    /**
+     * @dataProvider getAcceptData
+     */
+    public function testAccept($size, $expected)
+    {
+        $files = self::$files;
+        $files[] = self::toAbsolute('doesnotexist');
+        $inner = new Iterator($files);
+
+        $iterator = new DateRangeFilterIterator($inner, $size);
+
+        $this->assertIterator($expected, $iterator);
+    }
+
+    public function getAcceptData()
+    {
+        $since20YearsAgo = array(
+            '.git',
+            'test.py',
+            'foo',
+            'foo/bar.tmp',
+            'test.php',
+            'toto',
+            '.bar',
+            '.foo',
+            '.foo/.bar',
+            'foo bar',
+            '.foo/bar',
+        );
+
+        $since2MonthsAgo = array(
+            '.git',
+            'test.py',
+            'foo',
+            'toto',
+            '.bar',
+            '.foo',
+            '.foo/.bar',
+            'foo bar',
+            '.foo/bar',
+        );
+
+        $untilLastMonth = array(
+            'foo/bar.tmp',
+            'test.php',
+        );
+
+        return array(
+            array(array(new DateComparator('since 20 years ago')), $this->toAbsolute($since20YearsAgo)),
+            array(array(new DateComparator('since 2 months ago')), $this->toAbsolute($since2MonthsAgo)),
+            array(array(new DateComparator('until last month')), $this->toAbsolute($untilLastMonth)),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php
new file mode 100644
index 0000000..5ec9832
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php
@@ -0,0 +1,80 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
+
+class DepthRangeFilterIteratorTest extends RealIteratorTestCase
+{
+    /**
+     * @dataProvider getAcceptData
+     */
+    public function testAccept($minDepth, $maxDepth, $expected)
+    {
+        $inner = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->toAbsolute(), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);
+
+        $iterator = new DepthRangeFilterIterator($inner, $minDepth, $maxDepth);
+
+        $actual = array_keys(iterator_to_array($iterator));
+        sort($expected);
+        sort($actual);
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function getAcceptData()
+    {
+        $lessThan1 = array(
+            '.git',
+            'test.py',
+            'foo',
+            'test.php',
+            'toto',
+            '.foo',
+            '.bar',
+            'foo bar',
+        );
+
+        $lessThanOrEqualTo1 = array(
+            '.git',
+            'test.py',
+            'foo',
+            'foo/bar.tmp',
+            'test.php',
+            'toto',
+            '.foo',
+            '.foo/.bar',
+            '.bar',
+            'foo bar',
+            '.foo/bar',
+        );
+
+        $graterThanOrEqualTo1 = array(
+            'foo/bar.tmp',
+            '.foo/.bar',
+            '.foo/bar',
+        );
+
+        $equalTo1 = array(
+            'foo/bar.tmp',
+            '.foo/.bar',
+            '.foo/bar',
+        );
+
+        return array(
+            array(0, 0, $this->toAbsolute($lessThan1)),
+            array(0, 1, $this->toAbsolute($lessThanOrEqualTo1)),
+            array(2, PHP_INT_MAX, array()),
+            array(1, PHP_INT_MAX, $this->toAbsolute($graterThanOrEqualTo1)),
+            array(1, 1, $this->toAbsolute($equalTo1)),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php
new file mode 100644
index 0000000..693b733
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
+use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
+
+class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase
+{
+    /**
+     * @dataProvider getAcceptData
+     */
+    public function testAccept($directories, $expected)
+    {
+        $inner = new \RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->toAbsolute(), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);
+
+        $iterator = new ExcludeDirectoryFilterIterator($inner, $directories);
+
+        $this->assertIterator($expected, $iterator);
+    }
+
+    public function getAcceptData()
+    {
+        $foo = array(
+            '.bar',
+            '.foo',
+            '.foo/.bar',
+            '.foo/bar',
+            '.git',
+            'test.py',
+            'test.php',
+            'toto',
+            'foo bar',
+        );
+
+        $fo = array(
+            '.bar',
+            '.foo',
+            '.foo/.bar',
+            '.foo/bar',
+            '.git',
+            'test.py',
+            'foo',
+            'foo/bar.tmp',
+            'test.php',
+            'toto',
+            'foo bar',
+        );
+
+        return array(
+            array(array('foo'), $this->toAbsolute($foo)),
+            array(array('fo'), $this->toAbsolute($fo)),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.php
new file mode 100644
index 0000000..89853a8
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.php
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\FilePathsIterator;
+
+class FilePathsIteratorTest extends RealIteratorTestCase
+{
+    /**
+     * @dataProvider getSubPathData
+     */
+    public function testSubPath($baseDir, array $paths, array $subPaths, array $subPathnames)
+    {
+        $iterator = new FilePathsIterator($paths, $baseDir);
+
+        foreach ($iterator as $index => $file) {
+            $this->assertEquals($paths[$index], $file->getPathname());
+            $this->assertEquals($subPaths[$index], $iterator->getSubPath());
+            $this->assertEquals($subPathnames[$index], $iterator->getSubPathname());
+        }
+    }
+
+    public function getSubPathData()
+    {
+        $tmpDir = sys_get_temp_dir().'/symfony_finder';
+
+        return array(
+            array(
+                $tmpDir,
+                array( // paths
+                    $tmpDir.DIRECTORY_SEPARATOR.'.git' => $tmpDir.DIRECTORY_SEPARATOR.'.git',
+                    $tmpDir.DIRECTORY_SEPARATOR.'test.py' => $tmpDir.DIRECTORY_SEPARATOR.'test.py',
+                    $tmpDir.DIRECTORY_SEPARATOR.'foo' => $tmpDir.DIRECTORY_SEPARATOR.'foo',
+                    $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp',
+                    $tmpDir.DIRECTORY_SEPARATOR.'test.php' => $tmpDir.DIRECTORY_SEPARATOR.'test.php',
+                    $tmpDir.DIRECTORY_SEPARATOR.'toto' => $tmpDir.DIRECTORY_SEPARATOR.'toto',
+                ),
+                array( // subPaths
+                    $tmpDir.DIRECTORY_SEPARATOR.'.git' => '',
+                    $tmpDir.DIRECTORY_SEPARATOR.'test.py' => '',
+                    $tmpDir.DIRECTORY_SEPARATOR.'foo' => '',
+                    $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => 'foo',
+                    $tmpDir.DIRECTORY_SEPARATOR.'test.php' => '',
+                    $tmpDir.DIRECTORY_SEPARATOR.'toto' => '',
+                ),
+                array( // subPathnames
+                    $tmpDir.DIRECTORY_SEPARATOR.'.git' => '.git',
+                    $tmpDir.DIRECTORY_SEPARATOR.'test.py' => 'test.py',
+                    $tmpDir.DIRECTORY_SEPARATOR.'foo' => 'foo',
+                    $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => 'foo'.DIRECTORY_SEPARATOR.'bar.tmp',
+                    $tmpDir.DIRECTORY_SEPARATOR.'test.php' => 'test.php',
+                    $tmpDir.DIRECTORY_SEPARATOR.'toto' => 'toto',
+                ),
+            ),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php
new file mode 100644
index 0000000..cfa8684
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php
@@ -0,0 +1,72 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\FileTypeFilterIterator;
+
+class FileTypeFilterIteratorTest extends RealIteratorTestCase
+{
+    /**
+     * @dataProvider getAcceptData
+     */
+    public function testAccept($mode, $expected)
+    {
+        $inner = new InnerTypeIterator(self::$files);
+
+        $iterator = new FileTypeFilterIterator($inner, $mode);
+
+        $this->assertIterator($expected, $iterator);
+    }
+
+    public function getAcceptData()
+    {
+        $onlyFiles = array(
+            'test.py',
+            'foo/bar.tmp',
+            'test.php',
+            '.bar',
+            '.foo/.bar',
+            '.foo/bar',
+            'foo bar',
+        );
+
+        $onlyDirectories = array(
+            '.git',
+            'foo',
+            'toto',
+            '.foo',
+        );
+
+        return array(
+            array(FileTypeFilterIterator::ONLY_FILES, $this->toAbsolute($onlyFiles)),
+            array(FileTypeFilterIterator::ONLY_DIRECTORIES, $this->toAbsolute($onlyDirectories)),
+        );
+    }
+}
+
+class InnerTypeIterator extends \ArrayIterator
+{
+    public function current()
+    {
+        return new \SplFileInfo(parent::current());
+    }
+
+    public function isFile()
+    {
+        return $this->current()->isFile();
+    }
+
+    public function isDir()
+    {
+        return $this->current()->isDir();
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php
new file mode 100644
index 0000000..744bdae
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
+
+class FilecontentFilterIteratorTest extends IteratorTestCase
+{
+    public function testAccept()
+    {
+        $inner = new MockFileListIterator(array('test.txt'));
+        $iterator = new FilecontentFilterIterator($inner, array(), array());
+        $this->assertIterator(array('test.txt'), $iterator);
+    }
+
+    public function testDirectory()
+    {
+        $inner = new MockFileListIterator(array('directory'));
+        $iterator = new FilecontentFilterIterator($inner, array('directory'), array());
+        $this->assertIterator(array(), $iterator);
+    }
+
+    public function testUnreadableFile()
+    {
+        $inner = new MockFileListIterator(array('file r-'));
+        $iterator = new FilecontentFilterIterator($inner, array('file r-'), array());
+        $this->assertIterator(array(), $iterator);
+    }
+
+    /**
+     * @dataProvider getTestFilterData
+     */
+    public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray)
+    {
+        $iterator = new FilecontentFilterIterator($inner, $matchPatterns, $noMatchPatterns);
+        $this->assertIterator($resultArray, $iterator);
+    }
+
+    public function getTestFilterData()
+    {
+        $inner = new MockFileListIterator();
+
+        $inner[] = new MockSplFileInfo(array(
+            'name' => 'a.txt',
+            'contents' => 'Lorem ipsum...',
+            'type' => 'file',
+            'mode' => 'r+', )
+        );
+
+        $inner[] = new MockSplFileInfo(array(
+            'name' => 'b.yml',
+            'contents' => 'dolor sit...',
+            'type' => 'file',
+            'mode' => 'r+', )
+        );
+
+        $inner[] = new MockSplFileInfo(array(
+            'name' => 'some/other/dir/third.php',
+            'contents' => 'amet...',
+            'type' => 'file',
+            'mode' => 'r+', )
+        );
+
+        $inner[] = new MockSplFileInfo(array(
+            'name' => 'unreadable-file.txt',
+            'contents' => false,
+            'type' => 'file',
+            'mode' => 'r+', )
+        );
+
+        return array(
+            array($inner, array('.'), array(), array('a.txt', 'b.yml', 'some/other/dir/third.php')),
+            array($inner, array('ipsum'), array(), array('a.txt')),
+            array($inner, array('i', 'amet'), array('Lorem', 'amet'), array('b.yml')),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.php
new file mode 100644
index 0000000..c4b9795
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
+
+class FilenameFilterIteratorTest extends IteratorTestCase
+{
+    /**
+     * @dataProvider getAcceptData
+     */
+    public function testAccept($matchPatterns, $noMatchPatterns, $expected)
+    {
+        $inner = new InnerNameIterator(array('test.php', 'test.py', 'foo.php'));
+
+        $iterator = new FilenameFilterIterator($inner, $matchPatterns, $noMatchPatterns);
+
+        $this->assertIterator($expected, $iterator);
+    }
+
+    public function getAcceptData()
+    {
+        return array(
+            array(array('test.*'), array(), array('test.php', 'test.py')),
+            array(array(), array('test.*'), array('foo.php')),
+            array(array('*.php'), array('test.*'), array('foo.php')),
+            array(array('*.php', '*.py'), array('foo.*'), array('test.php', 'test.py')),
+            array(array('/\.php$/'), array(), array('test.php', 'foo.php')),
+            array(array(), array('/\.php$/'), array('test.py')),
+        );
+    }
+}
+
+class InnerNameIterator extends \ArrayIterator
+{
+    public function current()
+    {
+        return new \SplFileInfo(parent::current());
+    }
+
+    public function getFilename()
+    {
+        return parent::current();
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php
new file mode 100644
index 0000000..029a266
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+/**
+ * @author Alex Bogomazov
+ */
+class FilterIteratorTest extends RealIteratorTestCase
+{
+    public function testFilterFilesystemIterators()
+    {
+        $i = new \FilesystemIterator($this->toAbsolute());
+
+        // it is expected that there are test.py test.php in the tmpDir
+        $i = $this->getMockForAbstractClass('Symfony\Component\Finder\Iterator\FilterIterator', array($i));
+        $i->expects($this->any())
+            ->method('accept')
+            ->will($this->returnCallback(function () use ($i) {
+                return (bool) preg_match('/\.php/', (string) $i->current());
+            })
+        );
+
+        $c = 0;
+        foreach ($i as $item) {
+            $c++;
+        }
+
+        $this->assertEquals(1, $c);
+
+        $i->rewind();
+
+        $c = 0;
+        foreach ($i as $item) {
+            $c++;
+        }
+
+        // This would fail with \FilterIterator but works with Symfony\Component\Finder\Iterator\FilterIterator
+        // see https://bugs.php.net/bug.php?id=49104
+        $this->assertEquals(1, $c);
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/Iterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/Iterator.php
new file mode 100644
index 0000000..849bf08
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/Iterator.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+class Iterator implements \Iterator
+{
+    protected $values = array();
+
+    public function __construct(array $values = array())
+    {
+        foreach ($values as $value) {
+            $this->attach(new \SplFileInfo($value));
+        }
+        $this->rewind();
+    }
+
+    public function attach(\SplFileInfo $fileinfo)
+    {
+        $this->values[] = $fileinfo;
+    }
+
+    public function rewind()
+    {
+        reset($this->values);
+    }
+
+    public function valid()
+    {
+        return false !== $this->current();
+    }
+
+    public function next()
+    {
+        next($this->values);
+    }
+
+    public function current()
+    {
+        return current($this->values);
+    }
+
+    public function key()
+    {
+        return key($this->values);
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php
new file mode 100644
index 0000000..ae7388e
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php
@@ -0,0 +1,98 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+abstract class IteratorTestCase extends \PHPUnit_Framework_TestCase
+{
+    protected function assertIterator($expected, \Traversable $iterator)
+    {
+        // set iterator_to_array $use_key to false to avoid values merge
+        // this made FinderTest::testAppendWithAnArray() failed with GnuFinderAdapter
+        $values = array_map(function (\SplFileInfo $fileinfo) { return str_replace('/', DIRECTORY_SEPARATOR, $fileinfo->getPathname()); }, iterator_to_array($iterator, false));
+
+        $expected = array_map(function ($path) { return str_replace('/', DIRECTORY_SEPARATOR, $path); }, $expected);
+
+        sort($values);
+        sort($expected);
+
+        $this->assertEquals($expected, array_values($values));
+    }
+
+    protected function assertOrderedIterator($expected, \Traversable $iterator)
+    {
+        $values = array_map(function (\SplFileInfo $fileinfo) { return $fileinfo->getPathname(); }, iterator_to_array($iterator));
+
+        $this->assertEquals($expected, array_values($values));
+    }
+
+    /**
+     *  Same as assertOrderedIterator, but checks the order of groups of
+     *  array elements.
+     *
+     *  @param array $expected - an array of arrays. For any two subarrays
+     *      $a and $b such that $a goes before $b in $expected, the method
+     *      asserts that any element of $a goes before any element of $b
+     *      in the sequence generated by $iterator
+     *  @param \Traversable $iterator
+     */
+    protected function assertOrderedIteratorForGroups($expected, \Traversable $iterator)
+    {
+        $values = array_values(array_map(function (\SplFileInfo $fileinfo) { return $fileinfo->getPathname(); }, iterator_to_array($iterator)));
+
+        foreach ($expected as $subarray) {
+            $temp = array();
+            while (count($values) && count($temp) < count($subarray)) {
+                array_push($temp, array_shift($values));
+            }
+            sort($temp);
+            sort($subarray);
+            $this->assertEquals($subarray, $temp);
+        }
+    }
+
+    /**
+     * Same as IteratorTestCase::assertIterator with foreach usage.
+     *
+     * @param array        $expected
+     * @param \Traversable $iterator
+     */
+    protected function assertIteratorInForeach($expected, \Traversable $iterator)
+    {
+        $values = array();
+        foreach ($iterator as $file) {
+            $this->assertInstanceOf('Symfony\\Component\\Finder\\SplFileInfo', $file);
+            $values[] = $file->getPathname();
+        }
+
+        sort($values);
+        sort($expected);
+
+        $this->assertEquals($expected, array_values($values));
+    }
+
+    /**
+     * Same as IteratorTestCase::assertOrderedIterator with foreach usage.
+     *
+     * @param array        $expected
+     * @param \Traversable $iterator
+     */
+    protected function assertOrderedIteratorInForeach($expected, \Traversable $iterator)
+    {
+        $values = array();
+        foreach ($iterator as $file) {
+            $this->assertInstanceOf('Symfony\\Component\\Finder\\SplFileInfo', $file);
+            $values[] = $file->getPathname();
+        }
+
+        $this->assertEquals($expected, array_values($values));
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.php
new file mode 100644
index 0000000..eb0adfa
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+class MockFileListIterator extends \ArrayIterator
+{
+    public function __construct(array $filesArray = array())
+    {
+        $files = array_map(function ($file) { return new MockSplFileInfo($file); }, $filesArray);
+        parent::__construct($files);
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.php
new file mode 100644
index 0000000..f2e8f8e
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.php
@@ -0,0 +1,134 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+class MockSplFileInfo extends \SplFileInfo
+{
+    const   TYPE_DIRECTORY = 1;
+    const   TYPE_FILE = 2;
+    const   TYPE_UNKNOWN = 3;
+
+    private $contents = null;
+    private $mode = null;
+    private $type = null;
+    private $relativePath = null;
+    private $relativePathname = null;
+
+    public function __construct($param)
+    {
+        if (is_string($param)) {
+            parent::__construct($param);
+        } elseif (is_array($param)) {
+            $defaults = array(
+              'name' => 'file.txt',
+              'contents' => null,
+              'mode' => null,
+              'type' => null,
+              'relativePath' => null,
+              'relativePathname' => null,
+            );
+            $defaults = array_merge($defaults, $param);
+            parent::__construct($defaults['name']);
+            $this->setContents($defaults['contents']);
+            $this->setMode($defaults['mode']);
+            $this->setType($defaults['type']);
+            $this->setRelativePath($defaults['relativePath']);
+            $this->setRelativePathname($defaults['relativePathname']);
+        } else {
+            throw new \RuntimeException(sprintf('Incorrect parameter "%s"', $param));
+        }
+    }
+
+    public function isFile()
+    {
+        if (null === $this->type) {
+            return preg_match('/file/', $this->getFilename());
+        };
+
+        return self::TYPE_FILE === $this->type;
+    }
+
+    public function isDir()
+    {
+        if (null === $this->type) {
+            return preg_match('/directory/', $this->getFilename());
+        }
+
+        return self::TYPE_DIRECTORY === $this->type;
+    }
+
+    public function isReadable()
+    {
+        if (null === $this->mode) {
+            return preg_match('/r\+/', $this->getFilename());
+        }
+
+        return preg_match('/r\+/', $this->mode);
+    }
+
+    public function getContents()
+    {
+        return $this->contents;
+    }
+
+    public function setContents($contents)
+    {
+        $this->contents = $contents;
+    }
+
+    public function setMode($mode)
+    {
+        $this->mode = $mode;
+    }
+
+    public function setType($type)
+    {
+        if (is_string($type)) {
+            switch ($type) {
+                case 'directory':
+                    $this->type = self::TYPE_DIRECTORY;
+                case 'd':
+                    $this->type = self::TYPE_DIRECTORY;
+                    break;
+                case 'file':
+                    $this->type = self::TYPE_FILE;
+                case 'f':
+                    $this->type = self::TYPE_FILE;
+                    break;
+                default:
+                    $this->type = self::TYPE_UNKNOWN;
+            }
+        } else {
+            $this->type = $type;
+        }
+    }
+
+    public function setRelativePath($relativePath)
+    {
+        $this->relativePath = $relativePath;
+    }
+
+    public function setRelativePathname($relativePathname)
+    {
+        $this->relativePathname = $relativePathname;
+    }
+
+    public function getRelativePath()
+    {
+        return $this->relativePath;
+    }
+
+    public function getRelativePathname()
+    {
+        return $this->relativePathname;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php
new file mode 100644
index 0000000..89d8edb
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\MultiplePcreFilterIterator;
+
+class MultiplePcreFilterIteratorTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider getIsRegexFixtures
+     */
+    public function testIsRegex($string, $isRegex, $message)
+    {
+        $testIterator = new TestMultiplePcreFilterIterator();
+        $this->assertEquals($isRegex, $testIterator->isRegex($string), $message);
+    }
+
+    public function getIsRegexFixtures()
+    {
+        return array(
+            array('foo', false, 'string'),
+            array(' foo ', false, '" " is not a valid delimiter'),
+            array('\\foo\\', false, '"\\" is not a valid delimiter'),
+            array('afooa', false, '"a" is not a valid delimiter'),
+            array('//', false, 'the pattern should contain at least 1 character'),
+            array('/a/', true, 'valid regex'),
+            array('/foo/', true, 'valid regex'),
+            array('/foo/i', true, 'valid regex with a single modifier'),
+            array('/foo/imsxu', true, 'valid regex with multiple modifiers'),
+            array('#foo#', true, '"#" is a valid delimiter'),
+            array('{foo}', true, '"{,}" is a valid delimiter pair'),
+            array('*foo.*', false, '"*" is not considered as a valid delimiter'),
+            array('?foo.?', false, '"?" is not considered as a valid delimiter'),
+        );
+    }
+}
+
+class TestMultiplePcreFilterIterator extends MultiplePcreFilterIterator
+{
+    public function __construct()
+    {
+    }
+
+    public function accept()
+    {
+        throw new \BadFunctionCallException('Not implemented');
+    }
+
+    public function isRegex($str)
+    {
+        return parent::isRegex($str);
+    }
+
+    public function toRegex($str)
+    {
+        throw new \BadFunctionCallException('Not implemented');
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.php
new file mode 100644
index 0000000..579beed
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\PathFilterIterator;
+
+class PathFilterIteratorTest extends IteratorTestCase
+{
+    /**
+     * @dataProvider getTestFilterData
+     */
+    public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray)
+    {
+        $iterator = new PathFilterIterator($inner, $matchPatterns, $noMatchPatterns);
+        $this->assertIterator($resultArray, $iterator);
+    }
+
+    public function getTestFilterData()
+    {
+        $inner = new MockFileListIterator();
+
+        //PATH:   A/B/C/abc.dat
+        $inner[] = new MockSplFileInfo(array(
+            'name' => 'abc.dat',
+            'relativePathname' => 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
+        ));
+
+        //PATH:   A/B/ab.dat
+        $inner[] = new MockSplFileInfo(array(
+            'name' => 'ab.dat',
+            'relativePathname' => 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
+        ));
+
+        //PATH:   A/a.dat
+        $inner[] = new MockSplFileInfo(array(
+            'name' => 'a.dat',
+            'relativePathname' => 'A'.DIRECTORY_SEPARATOR.'a.dat',
+        ));
+
+        //PATH:   copy/A/B/C/abc.dat.copy
+        $inner[] = new MockSplFileInfo(array(
+            'name' => 'abc.dat.copy',
+            'relativePathname' => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
+        ));
+
+        //PATH:   copy/A/B/ab.dat.copy
+        $inner[] = new MockSplFileInfo(array(
+            'name' => 'ab.dat.copy',
+            'relativePathname' => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
+        ));
+
+        //PATH:   copy/A/a.dat.copy
+        $inner[] = new MockSplFileInfo(array(
+            'name' => 'a.dat.copy',
+            'relativePathname' => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'a.dat',
+        ));
+
+        return array(
+            array($inner, array('/^A/'),       array(), array('abc.dat', 'ab.dat', 'a.dat')),
+            array($inner, array('/^A\/B/'),    array(), array('abc.dat', 'ab.dat')),
+            array($inner, array('/^A\/B\/C/'), array(), array('abc.dat')),
+            array($inner, array('/A\/B\/C/'),  array(), array('abc.dat', 'abc.dat.copy')),
+
+            array($inner, array('A'),      array(), array('abc.dat', 'ab.dat', 'a.dat', 'abc.dat.copy', 'ab.dat.copy', 'a.dat.copy')),
+            array($inner, array('A/B'),    array(), array('abc.dat', 'ab.dat', 'abc.dat.copy', 'ab.dat.copy')),
+            array($inner, array('A/B/C'),  array(), array('abc.dat', 'abc.dat.copy')),
+
+            array($inner, array('copy/A'),      array(), array('abc.dat.copy', 'ab.dat.copy', 'a.dat.copy')),
+            array($inner, array('copy/A/B'),    array(), array('abc.dat.copy', 'ab.dat.copy')),
+            array($inner, array('copy/A/B/C'),  array(), array('abc.dat.copy')),
+
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php
new file mode 100644
index 0000000..e22476d
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php
@@ -0,0 +1,109 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+abstract class RealIteratorTestCase extends IteratorTestCase
+{
+    protected static $tmpDir;
+    protected static $files;
+
+    public static function setUpBeforeClass()
+    {
+        self::$tmpDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'symfony_finder';
+
+        self::$files = array(
+            '.git/',
+            '.foo/',
+            '.foo/.bar',
+            '.foo/bar',
+            '.bar',
+            'test.py',
+            'foo/',
+            'foo/bar.tmp',
+            'test.php',
+            'toto/',
+            'foo bar',
+        );
+
+        self::$files = self::toAbsolute(self::$files);
+
+        if (is_dir(self::$tmpDir)) {
+            self::tearDownAfterClass();
+        } else {
+            mkdir(self::$tmpDir);
+        }
+
+        foreach (self::$files as $file) {
+            if (DIRECTORY_SEPARATOR === $file[strlen($file) - 1]) {
+                mkdir($file);
+            } else {
+                touch($file);
+            }
+        }
+
+        file_put_contents(self::toAbsolute('test.php'), str_repeat(' ', 800));
+        file_put_contents(self::toAbsolute('test.py'), str_repeat(' ', 2000));
+
+        touch(self::toAbsolute('foo/bar.tmp'), strtotime('2005-10-15'));
+        touch(self::toAbsolute('test.php'), strtotime('2005-10-15'));
+    }
+
+    public static function tearDownAfterClass()
+    {
+        foreach (array_reverse(self::$files) as $file) {
+            if (DIRECTORY_SEPARATOR === $file[strlen($file) - 1]) {
+                @rmdir($file);
+            } else {
+                @unlink($file);
+            }
+        }
+    }
+
+    protected static function toAbsolute($files = null)
+    {
+        /*
+         * Without the call to setUpBeforeClass() property can be null.
+         */
+        if (!self::$tmpDir) {
+            self::$tmpDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'symfony_finder';
+        }
+
+        if (is_array($files)) {
+            $f = array();
+            foreach ($files as $file) {
+                if (is_array($file)) {
+                    $f[] = self::toAbsolute($file);
+                } else {
+                    $f[] = self::$tmpDir.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $file);
+                }
+            }
+
+            return $f;
+        }
+
+        if (is_string($files)) {
+            return self::$tmpDir.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $files);
+        }
+
+        return self::$tmpDir;
+    }
+
+    protected static function toAbsoluteFixtures($files)
+    {
+        $f = array();
+        foreach ($files as $file) {
+            $f[] = realpath(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.$file);
+        }
+
+        return $f;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php
new file mode 100644
index 0000000..412054b
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+*
+* (c) Fabien Potencier <fabien@symfony.com>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
+
+class RecursiveDirectoryIteratorTest extends IteratorTestCase
+{
+    /**
+     * @dataProvider getPaths
+     *
+     * @param string $path
+     * @param bool   $seekable
+     * @param array  $contains
+     * @param string $message
+     */
+    public function testRewind($path, $seekable, $contains, $message = null)
+    {
+        try {
+            $i = new RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
+        } catch (\UnexpectedValueException $e) {
+            $this->markTestSkipped(sprintf('Unsupported stream "%s".', $path));
+        }
+
+        $i->rewind();
+
+        $this->assertTrue(true, $message);
+    }
+
+    /**
+     * @dataProvider getPaths
+     *
+     * @param string $path
+     * @param bool   $seekable
+     * @param array  $contains
+     * @param string $message
+     */
+    public function testSeek($path, $seekable, $contains, $message = null)
+    {
+        try {
+            $i = new RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
+        } catch (\UnexpectedValueException $e) {
+            $this->markTestSkipped(sprintf('Unsupported stream "%s".', $path));
+        }
+
+        $actual = array();
+
+        $i->seek(0);
+        $actual[] = $i->getPathname();
+
+        $i->seek(1);
+        $actual[] = $i->getPathname();
+
+        $i->seek(2);
+        $actual[] = $i->getPathname();
+
+        $this->assertEquals($contains, $actual);
+    }
+
+    public function getPaths()
+    {
+        $data = array();
+
+        // ftp
+        $contains = array(
+            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'README',
+            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'index.html',
+            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'pub',
+        );
+        $data[] = array('ftp://ftp.mozilla.org/', false, $contains);
+
+        return $data;
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php
new file mode 100644
index 0000000..8780db4
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php
@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
+use Symfony\Component\Finder\Comparator\NumberComparator;
+
+class SizeRangeFilterIteratorTest extends RealIteratorTestCase
+{
+    /**
+     * @dataProvider getAcceptData
+     */
+    public function testAccept($size, $expected)
+    {
+        $inner = new InnerSizeIterator(self::$files);
+
+        $iterator = new SizeRangeFilterIterator($inner, $size);
+
+        $this->assertIterator($expected, $iterator);
+    }
+
+    public function getAcceptData()
+    {
+        $lessThan1KGreaterThan05K = array(
+            '.foo',
+            '.git',
+            'foo',
+            'test.php',
+            'toto',
+        );
+
+        return array(
+            array(array(new NumberComparator('< 1K'), new NumberComparator('> 0.5K')), $this->toAbsolute($lessThan1KGreaterThan05K)),
+        );
+    }
+}
+
+class InnerSizeIterator extends \ArrayIterator
+{
+    public function current()
+    {
+        return new \SplFileInfo(parent::current());
+    }
+
+    public function getFilename()
+    {
+        return parent::current();
+    }
+
+    public function isFile()
+    {
+        return $this->current()->isFile();
+    }
+
+    public function getSize()
+    {
+        return $this->current()->getSize();
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php
new file mode 100644
index 0000000..e2f433f
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php
@@ -0,0 +1,169 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\SortableIterator;
+
+class SortableIteratorTest extends RealIteratorTestCase
+{
+    public function testConstructor()
+    {
+        try {
+            new SortableIterator(new Iterator(array()), 'foobar');
+            $this->fail('__construct() throws an \InvalidArgumentException exception if the mode is not valid');
+        } catch (\Exception $e) {
+            $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException exception if the mode is not valid');
+        }
+    }
+
+    /**
+     * @dataProvider getAcceptData
+     */
+    public function testAccept($mode, $expected)
+    {
+        if (!is_callable($mode)) {
+            switch ($mode) {
+                case SortableIterator::SORT_BY_ACCESSED_TIME :
+                    file_get_contents(self::toAbsolute('.git'));
+                    sleep(1);
+                    file_get_contents(self::toAbsolute('.bar'));
+                    break;
+                case SortableIterator::SORT_BY_CHANGED_TIME :
+                    file_put_contents(self::toAbsolute('test.php'), 'foo');
+                    sleep(1);
+                    file_put_contents(self::toAbsolute('test.py'), 'foo');
+                    break;
+                case SortableIterator::SORT_BY_MODIFIED_TIME :
+                    file_put_contents(self::toAbsolute('test.php'), 'foo');
+                    sleep(1);
+                    file_put_contents(self::toAbsolute('test.py'), 'foo');
+                    break;
+            }
+        }
+
+        $inner = new Iterator(self::$files);
+
+        $iterator = new SortableIterator($inner, $mode);
+
+        if ($mode === SortableIterator::SORT_BY_ACCESSED_TIME
+            || $mode === SortableIterator::SORT_BY_CHANGED_TIME
+            || $mode === SortableIterator::SORT_BY_MODIFIED_TIME) {
+            $this->assertOrderedIteratorForGroups($expected, $iterator);
+        } else {
+            $this->assertOrderedIterator($expected, $iterator);
+        }
+    }
+
+    public function getAcceptData()
+    {
+        $sortByName = array(
+            '.bar',
+            '.foo',
+            '.foo/.bar',
+            '.foo/bar',
+            '.git',
+            'foo',
+            'foo bar',
+            'foo/bar.tmp',
+            'test.php',
+            'test.py',
+            'toto',
+        );
+
+        $sortByType = array(
+            '.foo',
+            '.git',
+            'foo',
+            'toto',
+            '.bar',
+            '.foo/.bar',
+            '.foo/bar',
+            'foo bar',
+            'foo/bar.tmp',
+            'test.php',
+            'test.py',
+        );
+
+        $customComparison = array(
+            '.bar',
+            '.foo',
+            '.foo/.bar',
+            '.foo/bar',
+            '.git',
+            'foo',
+            'foo bar',
+            'foo/bar.tmp',
+            'test.php',
+            'test.py',
+            'toto',
+        );
+
+        $sortByAccessedTime = array(
+            // For these two files the access time was set to 2005-10-15
+            array('foo/bar.tmp', 'test.php'),
+            // These files were created more or less at the same time
+            array(
+                '.git',
+                '.foo',
+                '.foo/.bar',
+                '.foo/bar',
+                'test.py',
+                'foo',
+                'toto',
+                'foo bar',
+            ),
+            // This file was accessed after sleeping for 1 sec
+            array('.bar'),
+        );
+
+        $sortByChangedTime = array(
+            array(
+                '.git',
+                '.foo',
+                '.foo/.bar',
+                '.foo/bar',
+                '.bar',
+                'foo',
+                'foo/bar.tmp',
+                'toto',
+                'foo bar',
+            ),
+            array('test.php'),
+            array('test.py'),
+        );
+
+        $sortByModifiedTime = array(
+            array(
+                '.git',
+                '.foo',
+                '.foo/.bar',
+                '.foo/bar',
+                '.bar',
+                'foo',
+                'foo/bar.tmp',
+                'toto',
+                'foo bar',
+            ),
+            array('test.php'),
+            array('test.py'),
+        );
+
+        return array(
+            array(SortableIterator::SORT_BY_NAME, $this->toAbsolute($sortByName)),
+            array(SortableIterator::SORT_BY_TYPE, $this->toAbsolute($sortByType)),
+            array(SortableIterator::SORT_BY_ACCESSED_TIME, $this->toAbsolute($sortByAccessedTime)),
+            array(SortableIterator::SORT_BY_CHANGED_TIME, $this->toAbsolute($sortByChangedTime)),
+            array(SortableIterator::SORT_BY_MODIFIED_TIME, $this->toAbsolute($sortByModifiedTime)),
+            array(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }, $this->toAbsolute($customComparison)),
+        );
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/composer.json b/core/vendor/symfony/finder/Symfony/Component/Finder/composer.json
new file mode 100644
index 0000000..a91b470
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/composer.json
@@ -0,0 +1,31 @@
+{
+    "name": "symfony/finder",
+    "type": "library",
+    "description": "Symfony Finder Component",
+    "keywords": [],
+    "homepage": "http://symfony.com",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Fabien Potencier",
+            "email": "fabien@symfony.com"
+        },
+        {
+            "name": "Symfony Community",
+            "homepage": "http://symfony.com/contributors"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.3"
+    },
+    "autoload": {
+        "psr-0": { "Symfony\\Component\\Finder\\": "" }
+    },
+    "target-dir": "Symfony/Component/Finder",
+    "minimum-stability": "dev",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.6-dev"
+        }
+    }
+}
diff --git a/core/vendor/symfony/finder/Symfony/Component/Finder/phpunit.xml.dist b/core/vendor/symfony/finder/Symfony/Component/Finder/phpunit.xml.dist
new file mode 100644
index 0000000..0ed1223
--- /dev/null
+++ b/core/vendor/symfony/finder/Symfony/Component/Finder/phpunit.xml.dist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
+         backupGlobals="false"
+         colors="true"
+         bootstrap="vendor/autoload.php"
+>
+    <php>
+        <!-- Silence E_USER_DEPRECATED (-16385 == -1 & ~E_USER_DEPRECATED) -->
+        <ini name="error_reporting" value="-16385"/>
+    </php>
+    <testsuites>
+        <testsuite name="Symfony Finder Component Test Suite">
+            <directory>./Tests/</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory>./</directory>
+            <exclude>
+                <directory>./Tests</directory>
+                <directory>./vendor</directory>
+            </exclude>
+        </whitelist>
+    </filter>
+</phpunit>
